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 Biome Borders v1.0.0
plugins/BiomeBorders.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("BenjSammy")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Biome Borders by BenjSammy")] [assembly: AssemblyTitle("BiomeBorders")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [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 BenjSammy.BiomeBorders { internal readonly struct PixelBounds { internal readonly int Left; internal readonly int Bottom; internal readonly int Right; internal readonly int Top; internal PixelBounds(int left, int bottom, int right, int top) { Left = left; Bottom = bottom; Right = right; Top = top; } } internal readonly struct BiomeEdge { internal readonly int X; internal readonly int Y; internal readonly bool Vertical; internal BiomeEdge(int x, int y, bool vertical) { X = x; Y = y; Vertical = vertical; } } internal readonly struct BiomeLabel { internal readonly int X; internal readonly int Y; internal readonly int Area; internal readonly byte Biome; internal BiomeLabel(int x, int y, byte biome, int area) { X = x; Y = y; Biome = biome; Area = area; } } internal readonly struct ExploredPixels { private readonly bool[] _ownArray; private readonly bool[] _sharedArray; private readonly BitArray _ownBits; private readonly BitArray _sharedBits; internal readonly bool Valid; internal ExploredPixels(object own, object shared, int size) { _ownArray = own as bool[]; _ownBits = own as BitArray; _sharedArray = ((shared is bool[] array && array.Length == size) ? array : null); _sharedBits = ((shared is BitArray bitArray && bitArray.Length == size) ? bitArray : null); bool[] ownArray = _ownArray; int valid; if (ownArray == null || ownArray.Length != size) { BitArray ownBits = _ownBits; valid = ((ownBits != null && ownBits.Length == size) ? 1 : 0); } else { valid = 1; } Valid = (byte)valid != 0; } internal bool Contains(int pixel) { if (Valid) { bool[] ownArray = _ownArray; if (!((ownArray != null) ? ownArray[pixel] : _ownBits[pixel])) { bool[] sharedArray = _sharedArray; if (sharedArray == null) { return _sharedBits?[pixel] ?? false; } return sharedArray[pixel]; } return true; } return false; } } internal sealed class BiomeAtlas { private readonly byte[] _biomes; private readonly BiomeEdge[] _edges; private readonly int[] _rows; internal int Width { get; } internal int Height { get; } internal int KnownPixels { get; } internal BiomeAtlas(int width, int height, byte[] biomes, CancellationToken stop = default(CancellationToken)) { if (width < 1 || height < 1 || biomes.Length != checked(width * height)) { throw new ArgumentException("The biome grid dimensions do not match its data."); } Width = width; Height = height; _biomes = biomes; _rows = new int[height + 1]; List<BiomeEdge> list = new List<BiomeEdge>(); int num = 0; for (int i = 0; i < height; i++) { stop.ThrowIfCancellationRequested(); _rows[i] = list.Count; for (int j = 0; j < width; j++) { int num2 = i * width + j; byte b = biomes[num2]; if (b != 0) { num++; if (j > 0 && IsDifferent(b, biomes[num2 - 1])) { list.Add(new BiomeEdge(j, i, vertical: true)); } if (i > 0 && IsDifferent(b, biomes[num2 - width])) { list.Add(new BiomeEdge(j, i, vertical: false)); } } } } _rows[height] = list.Count; _edges = list.ToArray(); KnownPixels = num; } private static bool IsDifferent(byte a, byte b) { if (b != 0) { return a != b; } return false; } internal void VisibleEdges(PixelBounds view, ExploredPixels explored, List<BiomeEdge> result) { result.Clear(); if (!explored.Valid || view.Right <= view.Left || view.Top <= view.Bottom) { return; } int num = Math.Max(0, view.Bottom); int num2 = Math.Min(Height, view.Top + 1); for (int i = num; i < num2; i++) { for (int j = _rows[i]; j < _rows[i + 1]; j++) { BiomeEdge item = _edges[j]; if (item.X >= view.Left && item.X <= view.Right && !(item.Vertical ? (i == view.Top) : (item.X == view.Right))) { int num3 = i * Width + item.X; int pixel = num3 - (item.Vertical ? 1 : Width); if (explored.Contains(num3) && explored.Contains(pixel)) { result.Add(item); } } } } } internal void VisibleLabels(PixelBounds view, ExploredPixels explored, List<BiomeLabel> result) { result.Clear(); if (!explored.Valid) { return; } int num = 1; while ((view.Right - view.Left) / num > 70 || (view.Top - view.Bottom) / num > 50) { num *= 2; } int num2 = SampleStart(Math.Max(0, view.Left), num); int num3 = SampleStart(Math.Max(0, view.Bottom), num); int num4 = Math.Min(Width, view.Right); int num5 = Math.Min(Height, view.Top); if (num2 >= num4 || num3 >= num5) { return; } int num6 = (num4 - 1 - num2) / num + 1; int num7 = (num5 - 1 - num3) / num + 1; byte[] array = new byte[num6 * num7]; bool[] array2 = new bool[array.Length]; int[] array3 = new int[array.Length]; for (int i = 0; i < num7; i++) { for (int j = 0; j < num6; j++) { int num8 = (num3 + i * num) * Width + num2 + j * num; if (explored.Contains(num8)) { array[i * num6 + j] = _biomes[num8]; } } } for (int k = 0; k < array.Length; k++) { byte b = array[k]; if (b == 0 || array2[k]) { continue; } int count = 1; int num9 = 0; int num10 = 0; array3[0] = k; array2[k] = true; for (int l = 0; l < count; l++) { int num11 = array3[l]; int num12 = num11 % num6; int num13 = num11 / num6; num9 += num12; num10 += num13; if (num12 > 0) { Visit(num11 - 1, b, array, array2, array3, ref count); } if (num12 + 1 < num6) { Visit(num11 + 1, b, array, array2, array3, ref count); } if (num13 > 0) { Visit(num11 - num6, b, array, array2, array3, ref count); } if (num13 + 1 < num7) { Visit(num11 + num6, b, array, array2, array3, ref count); } } if (count < 4) { continue; } float num14 = (float)num9 / (float)count; float num15 = (float)num10 / (float)count; int num16 = array3[0]; int num17 = -1; float num18 = float.MaxValue; for (int m = 0; m < count; m++) { int num19 = array3[m]; int num20 = num19 % num6; int num21 = num19 / num6; int num22 = 0; if (num20 > 0 && array[num19 - 1] == b) { num22++; } if (num20 + 1 < num6 && array[num19 + 1] == b) { num22++; } if (num21 > 0 && array[num19 - num6] == b) { num22++; } if (num21 + 1 < num7 && array[num19 + num6] == b) { num22++; } float num23 = (float)num20 - num14; float num24 = (float)num21 - num15; float num25 = num23 * num23 + num24 * num24; if (num22 >= num17 && (num22 != num17 || !(num25 >= num18))) { num16 = num19; num17 = num22; num18 = num25; } } result.Add(new BiomeLabel(num2 + num16 % num6 * num, num3 + num16 / num6 * num, b, count * num * num)); } result.Sort(delegate(BiomeLabel a, BiomeLabel biomeLabel) { int area = biomeLabel.Area; return area.CompareTo(a.Area); }); } private static int SampleStart(int minimum, int step) { int num = minimum / step * step + step / 2; if (num >= minimum) { return num; } return num + step; } private static void Visit(int pixel, byte biome, byte[] samples, bool[] visited, int[] queue, ref int count) { if (!visited[pixel] && samples[pixel] == biome) { visited[pixel] = true; queue[count++] = pixel; } } } internal readonly struct PixelProjection { private readonly float _pixelLeft; private readonly float _pixelBottom; private readonly float _localLeft; private readonly float _localBottom; internal readonly float ScaleX; internal readonly float ScaleY; internal readonly PixelBounds Bounds; internal PixelProjection(int width, int height, float u, float v, float uSize, float vSize, float localLeft, float localBottom, float localWidth, float localHeight) { _pixelLeft = u * (float)width; _pixelBottom = v * (float)height; _localLeft = localLeft; _localBottom = localBottom; ScaleX = localWidth / (uSize * (float)width); ScaleY = localHeight / (vSize * (float)height); Bounds = new PixelBounds((int)Math.Floor(Clamp(_pixelLeft, width)), (int)Math.Floor(Clamp(_pixelBottom, height)), (int)Math.Ceiling(Clamp((u + uSize) * (float)width, width)), (int)Math.Ceiling(Clamp((v + vSize) * (float)height, height))); } internal float X(float pixel) { return _localLeft + (pixel - _pixelLeft) * ScaleX; } internal float Y(float pixel) { return _localBottom + (pixel - _pixelBottom) * ScaleY; } private static float Clamp(float value, int limit) { return Math.Max(0f, Math.Min(limit, value)); } } [BepInPlugin("benjsammy.biomeborders", "Biome Borders by BenjSammy", "1.0.0")] public sealed class BiomeBordersPlugin : BaseUnityPlugin { private ConfigEntry<bool> _showCurrent; private ConfigEntry<bool> _showBorders; private ConfigEntry<bool> _showNames; private GameMap _game; private MapOverlay _overlay; private Component _map; private Texture2D _source; private Task<BiomeAtlas> _building; private CancellationTokenSource _buildStop; private BiomeAtlas _atlas; private string[] _names; private readonly List<BiomeEdge> _edges = new List<BiomeEdge>(); private readonly List<BiomeLabel> _labels = new List<BiomeLabel>(); private RectTransform _mini; private RectTransform _large; private string _current = string.Empty; private PixelProjection _projection; private Rect _lastUv; private Rect _lastRect; private int _lastWidth; private int _lastHeight; private bool _mapOpen; private bool _shared; private bool _bordersVisible; private bool _namesVisible; private bool _failedAtlas; private float _nextHud; private float _nextFog; private float _nextNames; private float _nextWarning; private void Awake() { if (Application.isBatchMode) { return; } _showCurrent = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowCurrentBiome", true, "Show the current biome below the minimap."); _showBorders = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowBorders", true, "Draw biome boundaries on the explored world map."); _showNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowBiomeNames", true, "Label the larger visible biome regions."); try { _game = new GameMap(); _overlay = new MapOverlay(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Biome Borders 1.0.0 ready. Client only."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Biome Borders could not bind the Valheim map API. " + ex)); } } private void LateUpdate() { if (_game == null || _overlay == null) { return; } try { Component minimap = _game.Minimap; Component player = _game.Player; if ((Object)(object)_map != (Object)(object)minimap) { ResetAtlas(); _map = minimap; _nextHud = 0f; } if (!Object.op_Implicit((Object)(object)minimap) || !Object.op_Implicit((Object)(object)player)) { _mini = null; HideLargeMap(); return; } float unscaledTime = Time.unscaledTime; _mini = ((_showCurrent.Value && _game.IsSmall(minimap)) ? _game.SmallRect(minimap) : null); if (Object.op_Implicit((Object)(object)_mini) && unscaledTime >= _nextHud) { _nextHud = unscaledTime + 0.25f; _current = _game.CurrentBiome(player); } if (!_game.IsLarge(minimap) || (!_showBorders.Value && !_showNames.Value) || !_game.Ready(minimap)) { HideLargeMap(); } else { UpdateLargeMap(minimap, unscaledTime); } } catch (Exception error) { HideLargeMap(); Report(error); } } private void UpdateLargeMap(Component map, float now) { //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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0194: 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_019c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = _game.Texture(map); if ((Object)(object)_source != (Object)(object)val) { ResetAtlas(); _source = val; } if (!Object.op_Implicit((Object)(object)val) || _failedAtlas || !_game.TryReadLargeView(map, out var transform, out var uv)) { HideLargeMap(); return; } bool flag = _game.SharedVisible(map); ExploredPixels explored = _game.Exploration(map, flag, ((Texture)val).width * ((Texture)val).height); if (!explored.Valid) { HideLargeMap(); return; } if (!EnsureAtlas(map, val)) { return; } Rect rect = transform.rect; if (((Rect)(ref rect)).width < 1f || ((Rect)(ref rect)).height < 1f) { HideLargeMap(); return; } int num; int num2; if (_mapOpen) { num = (((Object)(object)_large != (Object)(object)transform) ? 1 : 0); if (num == 0 && !(uv != _lastUv) && !(rect != _lastRect) && Screen.width == _lastWidth) { num2 = ((Screen.height != _lastHeight) ? 1 : 0); goto IL_0117; } } else { num = 1; } num2 = 1; goto IL_0117; IL_0117: bool flag2 = (byte)num2 != 0; bool flag3 = num != 0 || now >= _nextFog || flag != _shared; if (flag2) { _projection = new PixelProjection(_atlas.Width, _atlas.Height, ((Rect)(ref uv)).xMin, ((Rect)(ref uv)).yMin, ((Rect)(ref uv)).width, ((Rect)(ref uv)).height, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height); _lastUv = uv; _lastRect = rect; _lastWidth = Screen.width; _lastHeight = Screen.height; } if (flag3) { _nextFog = now + 0.6f; _shared = flag; } _large = transform; _mapOpen = true; if (_showBorders.Value) { if (!_bordersVisible || flag2 || flag3) { _atlas.VisibleEdges(_projection.Bounds, explored, _edges); _overlay.DrawBorders(transform, _projection, _edges); _bordersVisible = true; } } else if (_bordersVisible) { _overlay.HideBorders(); _bordersVisible = false; } if (_showNames.Value) { if (!_namesVisible || flag3 || now >= _nextNames) { _atlas.VisibleLabels(_projection.Bounds, explored, _labels); _nextNames = now + 0.3f; _namesVisible = true; } } else { _labels.Clear(); _namesVisible = false; } } private bool EnsureAtlas(Component map, Texture2D texture) { if (_atlas != null) { return true; } try { if (_building == null) { int width = ((Texture)texture).width; int height = ((Texture)texture).height; if (width < 2 || height < 2 || width > 4096 || height > 4096) { throw new InvalidOperationException("Unsupported world map texture dimensions."); } string[] names; Dictionary<int, byte> palette = _game.ReadPalette(map, out names); _names = new string[names.Length]; for (int i = 1; i < names.Length; i++) { _names[i] = _game.LocalizedBiome(names[i]); } Color32[] pixels = texture.GetPixels32(); _buildStop = new CancellationTokenSource(); CancellationToken stop = _buildStop.Token; _building = Task.Run(() => CreateAtlas(width, height, pixels, palette, stop), stop); return false; } if (!_building.IsCompleted) { return false; } _atlas = _building.GetAwaiter().GetResult(); StopBuilding(); if (_atlas.KnownPixels == 0) { throw new InvalidOperationException("The map texture does not contain the known biome palette."); } return true; } catch (Exception error) { StopBuilding(); _atlas = null; _failedAtlas = true; Report(error); return false; } } private static BiomeAtlas CreateAtlas(int width, int height, Color32[] pixels, Dictionary<int, byte> palette, CancellationToken stop) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0036: Unknown result type (might be due to invalid IL or missing references) byte[] array = new byte[pixels.Length]; for (int i = 0; i < height; i++) { stop.ThrowIfCancellationRequested(); for (int j = 0; j < width; j++) { int num = i * width + j; Color32 val = pixels[num]; palette.TryGetValue(GameMap.ColorKey(val.r, val.g, val.b), out array[num]); } } return new BiomeAtlas(width, height, array, stop); } private void OnGUI() { //IL_00c7: 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) //IL_0013: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (_overlay == null || (int)Event.current.type != 7) { return; } Color color = GUI.color; int depth = GUI.depth; try { GUI.color = Color.white; GUI.depth = -90; if (Object.op_Implicit((Object)(object)_mini) && ((Component)_mini).gameObject.activeInHierarchy) { _overlay.DrawCurrentBiome(_mini, _current); } if (_mapOpen && Object.op_Implicit((Object)(object)_large) && ((Component)_large).gameObject.activeInHierarchy && _namesVisible) { _overlay.DrawNames(_large, _projection, _labels, _names); } } catch (Exception error) { Report(error); } finally { GUI.color = color; GUI.depth = depth; } } private void HideLargeMap() { _overlay?.HideBorders(); _mapOpen = false; _large = null; _bordersVisible = false; _namesVisible = false; } private void StopBuilding() { _buildStop?.Cancel(); _buildStop?.Dispose(); _buildStop = null; _building = null; } private void ResetAtlas() { HideLargeMap(); StopBuilding(); _overlay?.ClearMap(); _atlas = null; _source = null; _names = null; _failedAtlas = false; _labels.Clear(); _edges.Clear(); } private void Report(Exception error) { if (!(Time.unscaledTime < _nextWarning)) { _nextWarning = Time.unscaledTime + 15f; ((BaseUnityPlugin)this).Logger.LogWarning((object)("Biome Borders: " + error)); } } private void OnDestroy() { StopBuilding(); _overlay?.Dispose(); } } internal sealed class GameMap { private const BindingFlags Members = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private readonly MemberInfo _mapInstance; private readonly MemberInfo _localizationInstance; private readonly FieldInfo _localPlayer; private readonly FieldInfo _mode; private readonly FieldInfo _smallImage; private readonly FieldInfo _largeImage; private readonly FieldInfo _texture; private readonly FieldInfo _explored; private readonly FieldInfo _others; private readonly FieldInfo _showShared; private readonly FieldInfo _generated; private readonly MethodInfo _currentBiome; private readonly MethodInfo _pixelColor; private readonly MethodInfo _localize; private readonly PropertyInfo _uvRect; private readonly object _small; private readonly object _large; private readonly Array _biomeValues; internal Component Minimap { get { object obj = ReadSingleton(_mapInstance); return (Component)((obj is Component) ? obj : null); } } internal Component Player { get { object? value = _localPlayer.GetValue(null); return (Component)((value is Component) ? value : null); } } internal GameMap() { Type type = FindType("Minimap"); Type type2 = FindType("Player"); Type type3 = FindType("Heightmap+Biome"); Type type4 = FindType("Localization", required: false); _mapInstance = FindSingleton(type); _localPlayer = RequireField(type2, "m_localPlayer"); _mode = RequireField(type, "m_mode"); _small = Enum.Parse(_mode.FieldType, "Small"); _large = Enum.Parse(_mode.FieldType, "Large"); _smallImage = RequireField(type, "m_mapImageSmall"); _largeImage = RequireField(type, "m_mapImageLarge"); _texture = RequireField(type, "m_mapTexture"); _explored = RequireField(type, "m_explored"); _others = type.GetField("m_exploredOthers", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _showShared = type.GetField("m_showSharedMapData", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _generated = type.GetField("m_hasGenerated", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _uvRect = _largeImage.FieldType.GetProperty("uvRect", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new MissingMemberException("RawImage.uvRect"); _pixelColor = RequireMethod(type, "GetPixelColor", type3); _currentBiome = RequireMethod(type2, "GetCurrentBiome"); _biomeValues = Enum.GetValues(type3); if (type4 != null) { _localizationInstance = FindSingleton(type4, required: false); _localize = type4.GetMethod("Localize", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null) ?? type4.GetMethod("Localize", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(string), typeof(string[]) }, null); } } internal bool IsSmall(Component map) { return _small.Equals(_mode.GetValue(map)); } internal bool IsLarge(Component map) { return _large.Equals(_mode.GetValue(map)); } internal bool Ready(Component map) { if (!(_generated == null)) { return (bool)_generated.GetValue(map); } return true; } internal RectTransform SmallRect(Component map) { return ImageRect(_smallImage.GetValue(map)); } internal Texture2D Texture(Component map) { object? value = _texture.GetValue(map); return (Texture2D)((value is Texture2D) ? value : null); } internal bool SharedVisible(Component map) { if (_showShared != null) { return (bool)_showShared.GetValue(map); } return false; } private static RectTransform ImageRect(object image) { Component val = (Component)((image is Component) ? image : null); if (!Object.op_Implicit((Object)(object)val) || !val.gameObject.activeInHierarchy) { return null; } Transform transform = val.transform; return (RectTransform)(object)((transform is RectTransform) ? transform : null); } internal bool TryReadLargeView(Component map, out RectTransform transform, out Rect uv) { //IL_0037: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) object value = _largeImage.GetValue(map); transform = ImageRect(value); uv = (Object.op_Implicit((Object)(object)transform) ? ((Rect)_uvRect.GetValue(value, null)) : default(Rect)); if (Object.op_Implicit((Object)(object)transform) && ((Rect)(ref uv)).width > 1E-05f && ((Rect)(ref uv)).height > 1E-05f && IsFinite(((Rect)(ref uv)).xMin) && IsFinite(((Rect)(ref uv)).yMin) && IsFinite(((Rect)(ref uv)).xMax)) { return IsFinite(((Rect)(ref uv)).yMax); } return false; } internal ExploredPixels Exploration(Component map, bool showShared, int length) { return new ExploredPixels(_explored.GetValue(map), (!showShared) ? null : _others?.GetValue(map), length); } internal string CurrentBiome(Component player) { object obj = _currentBiome.Invoke(player, null); if (obj == null || Convert.ToInt64(obj) == 0L) { return string.Empty; } return LocalizedBiome(obj.ToString()); } internal string LocalizedBiome(string biome) { object obj = ReadSingleton(_localizationInstance); if (_localize != null && obj != null) { string text = "biome_" + biome.ToLowerInvariant(); string text2 = "$" + text; object[] parameters = ((_localize.GetParameters().Length != 1) ? new object[2] { text2, Array.Empty<string>() } : new object[1] { text2 }); string text3 = _localize.Invoke(obj, parameters) as string; if (!string.IsNullOrWhiteSpace(text3) && text3 != text2 && text3 != text && text3 != "[" + text + "]") { return text3; } } if (biome == "AshLands") { return "Ashlands"; } StringBuilder stringBuilder = new StringBuilder(biome.Length + 6); for (int i = 0; i < biome.Length; i++) { if (i > 0 && char.IsUpper(biome[i]) && char.IsLower(biome[i - 1])) { stringBuilder.Append(' '); } stringBuilder.Append(biome[i]); } return stringBuilder.ToString(); } internal Dictionary<int, byte> ReadPalette(Component map, out string[] names) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_008a: Unknown result type (might be due to invalid IL or missing references) Dictionary<int, byte> dictionary = new Dictionary<int, byte>(); List<string> list = new List<string> { string.Empty }; foreach (object biomeValue in _biomeValues) { long num = Convert.ToInt64(biomeValue); if (num > 0 && (num & (num - 1)) == 0L && list.Count < 256) { Color32 val = Color32.op_Implicit((Color)_pixelColor.Invoke(map, new object[1] { biomeValue })); int key = ColorKey(val.r, val.g, val.b); byte b = (byte)list.Count; list.Add(biomeValue.ToString()); dictionary[key] = (byte)((!dictionary.ContainsKey(key)) ? b : 0); } } names = list.ToArray(); Dictionary<int, byte> dictionary2 = new Dictionary<int, byte>(); foreach (KeyValuePair<int, byte> item in dictionary) { if (item.Value == 0) { continue; } int num2 = item.Key & 0xFF; int num3 = (item.Key >> 8) & 0xFF; int num4 = item.Key >> 16; for (int i = Math.Max(0, num2 - 1); i <= Math.Min(255, num2 + 1); i++) { for (int j = Math.Max(0, num3 - 1); j <= Math.Min(255, num3 + 1); j++) { for (int k = Math.Max(0, num4 - 1); k <= Math.Min(255, num4 + 1); k++) { int key2 = ColorKey(i, j, k); if (dictionary2.TryGetValue(key2, out var value) && value != item.Value) { dictionary2[key2] = 0; } else { dictionary2[key2] = item.Value; } } } } } foreach (KeyValuePair<int, byte> item2 in dictionary) { dictionary2[item2.Key] = item2.Value; } return dictionary2; } internal static int ColorKey(int r, int g, int b) { return r | (g << 8) | (b << 16); } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static Type FindType(string name, bool required = true) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(name, throwOnError: false); if (type != null) { return type; } } if (required) { throw new TypeLoadException(name); } return null; } private static FieldInfo RequireField(Type type, string name) { return type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new MissingFieldException(type.Name, name); } private static MethodInfo RequireMethod(Type type, string name, params Type[] args) { return type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, args, null) ?? throw new MissingMethodException(type.Name, name); } private static MemberInfo FindSingleton(Type type, bool required = true) { MemberInfo memberInfo = (MemberInfo)(((object)type.GetProperty("instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)(type.GetField("instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("m_instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)))); if (required && memberInfo == null) { throw new MissingMemberException(type.Name, "instance"); } return memberInfo; } private static object ReadSingleton(MemberInfo member) { if (member is PropertyInfo propertyInfo) { return propertyInfo.GetValue(null, null); } return (member as FieldInfo)?.GetValue(null); } } internal sealed class MapOverlay : IDisposable { private sealed class Layer { internal readonly CanvasRenderer Renderer; internal readonly Mesh Mesh; internal Layer(RectTransform parent, Material material) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0062: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown GameObject val = new GameObject("Biome Borders", new Type[2] { typeof(RectTransform), typeof(CanvasRenderer) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)parent, false); ((Transform)val2).SetAsFirstSibling(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.pivot = parent.pivot; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; Renderer = val.GetComponent<CanvasRenderer>(); Renderer.SetMaterial(material, (Texture)(object)Texture2D.whiteTexture); Mesh = new Mesh { name = "Biome Borders mesh" }; Mesh.MarkDynamic(); } } private const int EdgesPerMesh = 7000; private static readonly Color32 HaloColor = new Color32((byte)238, (byte)228, (byte)195, (byte)210); private static readonly Color32 LineColor = new Color32((byte)30, (byte)28, (byte)24, (byte)242); private readonly List<Layer> _layers = new List<Layer>(); private readonly List<Vector3> _vertices = new List<Vector3>(); private readonly List<Color32> _colors = new List<Color32>(); private readonly List<int> _triangles = new List<int>(); private readonly List<Rect> _occupied = new List<Rect>(); private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4]; private RectTransform _parent; private Material _material; private GUIStyle _label; private GUIStyle _shadow; private int _fontSize; private static float UiScale => Mathf.Clamp((float)Screen.height / 1080f, 0.75f, 1.75f); internal void DrawBorders(RectTransform map, PixelProjection projection, List<BiomeEdge> edges) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_parent != (Object)(object)map) { ClearMap(); _parent = map; } if (edges.Count == 0) { HideBorders(); return; } if (!Object.op_Implicit((Object)(object)_material)) { Shader val = Shader.Find("UI/Default"); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Valheim's UI shader is unavailable."); } _material = new Material(val) { name = "Biome Borders UI", hideFlags = (HideFlags)61 }; } Rect rect = map.rect; Rect val2 = ScreenRect(map); float height = ((Rect)(ref val2)).height; float num = ((height > 1f) ? (((Rect)(ref rect)).height / height) : 1f) * UiScale; int num2 = 0; for (int i = 0; i < edges.Count; i += 7000) { int end = Math.Min(i + 7000, edges.Count); if (num2 == _layers.Count) { _layers.Add(new Layer(map, _material)); } Layer layer = _layers[num2++]; _vertices.Clear(); _colors.Clear(); _triangles.Clear(); AddStroke(edges, i, end, projection, rect, 1.6f * num, HaloColor); AddStroke(edges, i, end, projection, rect, 0.75f * num, LineColor); layer.Mesh.Clear(); layer.Mesh.SetVertices(_vertices); layer.Mesh.SetColors(_colors); layer.Mesh.SetTriangles(_triangles, 0); if (!((Component)layer.Renderer).gameObject.activeSelf) { ((Component)layer.Renderer).gameObject.SetActive(true); } layer.Renderer.SetMesh(layer.Mesh); } for (int j = num2; j < _layers.Count; j++) { ((Component)_layers[j].Renderer).gameObject.SetActive(false); } } private void AddStroke(List<BiomeEdge> edges, int start, int end, PixelProjection projection, Rect clip, float halfWidth, Color32 color) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) for (int i = start; i < end; i++) { BiomeEdge biomeEdge = edges[i]; float num = projection.X(biomeEdge.X); float num2 = projection.Y(biomeEdge.Y); float num3 = num + (biomeEdge.Vertical ? 0f : projection.ScaleX); float num4 = num2 + (biomeEdge.Vertical ? projection.ScaleY : 0f); AddQuad(Mathf.Max(((Rect)(ref clip)).xMin, num - halfWidth), Mathf.Max(((Rect)(ref clip)).yMin, num2 - halfWidth), Mathf.Min(((Rect)(ref clip)).xMax, num3 + halfWidth), Mathf.Min(((Rect)(ref clip)).yMax, num4 + halfWidth), color); } } private void AddQuad(float x0, float y0, float x1, float y1, Color32 color) { //IL_001e: 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_0044: 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_006a: Unknown result type (might be due to invalid IL or missing references) if (!(x0 >= x1) && !(y0 >= y1)) { int count = _vertices.Count; _vertices.Add(new Vector3(x0, y0)); _vertices.Add(new Vector3(x0, y1)); _vertices.Add(new Vector3(x1, y1)); _vertices.Add(new Vector3(x1, y0)); for (int i = 0; i < 4; i++) { _colors.Add(color); } _triangles.Add(count); _triangles.Add(count + 1); _triangles.Add(count + 2); _triangles.Add(count + 2); _triangles.Add(count + 3); _triangles.Add(count); } } internal void DrawNames(RectTransform map, PixelProjection projection, List<BiomeLabel> labels, string[] names) { //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_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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_0101: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) if (labels.Count == 0) { return; } EnsureStyles(); Rect val = ScreenRect(map); Camera canvasCamera = GetCanvasCamera(map); float uiScale = UiScale; float num = ((Rect)(ref val)).width * ((Rect)(ref val)).height; Rect rect = map.rect; float width = ((Rect)(ref rect)).width; rect = map.rect; float num2 = num / (width * ((Rect)(ref rect)).height) * projection.ScaleX * projection.ScaleY; _occupied.Clear(); Rect rect2 = default(Rect); foreach (BiomeLabel label in labels) { if (_occupied.Count >= 12) { break; } if ((float)label.Area * num2 < 950f * uiScale * uiScale) { continue; } Vector3 val2 = ((Transform)map).TransformPoint(new Vector3(projection.X((float)label.X + 0.5f), projection.Y((float)label.Y + 0.5f))); Vector2 val3 = RectTransformUtility.WorldToScreenPoint(canvasCamera, val2); GUIContent val4 = new GUIContent(names[label.Biome]); Vector2 val5 = _label.CalcSize(val4); ((Rect)(ref rect2))..ctor(val3.x - val5.x / 2f, (float)Screen.height - val3.y - val5.y / 2f, val5.x, val5.y); Rect val6 = Rect.MinMaxRect(((Rect)(ref rect2)).xMin - 9f * uiScale, ((Rect)(ref rect2)).yMin - 5f * uiScale, ((Rect)(ref rect2)).xMax + 9f * uiScale, ((Rect)(ref rect2)).yMax + 5f * uiScale); if (((Rect)(ref val6)).xMin < ((Rect)(ref val)).xMin || ((Rect)(ref val6)).xMax > ((Rect)(ref val)).xMax || ((Rect)(ref val6)).yMin < ((Rect)(ref val)).yMin || ((Rect)(ref val6)).yMax > ((Rect)(ref val)).yMax) { continue; } bool flag = false; foreach (Rect item in _occupied) { Rect current2 = item; if (((Rect)(ref current2)).Overlaps(val6)) { flag = true; break; } } if (!flag) { _occupied.Add(val6); DrawLabel(rect2, val4); } } } internal void DrawCurrentBiome(RectTransform miniMap, string name) { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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) if (!string.IsNullOrEmpty(name)) { EnsureStyles(); Rect val = ScreenRect(miniMap); float uiScale = UiScale; GUIContent val2 = new GUIContent("Biome · " + name); Vector2 val3 = _label.CalcSize(val2); float num = Mathf.Min(val3.x + 20f * uiScale, (float)Screen.width - 8f); float num2 = val3.y + 8f * uiScale; float num3 = Mathf.Clamp(((Rect)(ref val)).center.x - num / 2f, 4f, (float)Screen.width - num - 4f); float num4 = Mathf.Clamp(((Rect)(ref val)).yMax + 6f * uiScale, 4f, (float)Screen.height - num2 - 4f); Rect val4 = default(Rect); ((Rect)(ref val4))..ctor(num3, num4, num, num2); GUI.color = new Color(0.04f, 0.04f, 0.04f, 0.72f); GUI.DrawTexture(val4, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; DrawLabel(val4, val2); } } private void EnsureStyles() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_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_006c: Expected O, but got Unknown //IL_0071: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.RoundToInt(15f * UiScale); if (_label == null || num != _fontSize) { _fontSize = num; _label = new GUIStyle(GUI.skin.label) { fontSize = num, alignment = (TextAnchor)4, fontStyle = (FontStyle)1, richText = false, wordWrap = false, padding = new RectOffset(0, 0, 0, 0) }; _label.normal.textColor = new Color(1f, 0.97f, 0.89f); _shadow = new GUIStyle(_label); _shadow.normal.textColor = new Color(0.065f, 0.055f, 0.04f, 0.95f); } } private void DrawLabel(Rect rect, GUIContent content) { //IL_0024: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) float uiScale = UiScale; GUI.Label(new Rect(((Rect)(ref rect)).x - uiScale, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), content, _shadow); GUI.Label(new Rect(((Rect)(ref rect)).x + uiScale, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), content, _shadow); GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y - uiScale, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), content, _shadow); GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + uiScale, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), content, _shadow); GUI.Label(rect, content, _label); } private Rect ScreenRect(RectTransform transform) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) transform.GetWorldCorners(_corners); Camera canvasCamera = GetCanvasCamera(transform); float num = float.PositiveInfinity; float num2 = float.PositiveInfinity; float num3 = float.NegativeInfinity; float num4 = float.NegativeInfinity; Vector3[] corners = _corners; foreach (Vector3 val in corners) { Vector2 val2 = RectTransformUtility.WorldToScreenPoint(canvasCamera, val); float num5 = (float)Screen.height - val2.y; num = Mathf.Min(num, val2.x); num2 = Mathf.Min(num2, num5); num3 = Mathf.Max(num3, val2.x); num4 = Mathf.Max(num4, num5); } return Rect.MinMaxRect(num, num2, num3, num4); } private static Camera GetCanvasCamera(RectTransform transform) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Canvas componentInParent = ((Component)transform).GetComponentInParent<Canvas>(); if (!Object.op_Implicit((Object)(object)componentInParent) || (int)componentInParent.renderMode == 0) { return null; } if (!Object.op_Implicit((Object)(object)componentInParent.worldCamera)) { return Camera.main; } return componentInParent.worldCamera; } internal void HideBorders() { foreach (Layer layer in _layers) { if (Object.op_Implicit((Object)(object)layer.Renderer) && ((Component)layer.Renderer).gameObject.activeSelf) { ((Component)layer.Renderer).gameObject.SetActive(false); } } } internal void ClearMap() { foreach (Layer layer in _layers) { if (Object.op_Implicit((Object)(object)layer.Renderer)) { Object.Destroy((Object)(object)((Component)layer.Renderer).gameObject); } Object.Destroy((Object)(object)layer.Mesh); } _layers.Clear(); _parent = null; } public void Dispose() { ClearMap(); if (Object.op_Implicit((Object)(object)_material)) { Object.Destroy((Object)(object)_material); } } } }