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 Character Level v1.0.1
plugins/CharacterLevel.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Text; 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: AssemblyDescription("Character level from the sum of skill levels and a shared server ranking.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("Character Level by BenjSammy")] [assembly: AssemblyTitle("CharacterLevel")] [assembly: AssemblyVersion("1.0.1.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 BenjSammy.CharacterLevel { [BepInPlugin("benjsammy.characterlevel", "Character Level by BenjSammy", "1.0.1")] public sealed class CharacterLevelPlugin : BaseUnityPlugin { public const string PluginGuid = "benjsammy.characterlevel"; public const string PluginName = "Character Level by BenjSammy"; public const string PluginVersion = "1.0.1"; private GameApi _api; private RankingEngine _engine; private RankingPanel _panel; private ConfigEntry<bool> _visible; private ConfigEntry<KeyCode> _toggleKey; private ConfigEntry<float> _scale; private ConfigEntry<float> _width; private ConfigEntry<float> _top; private ConfigEntry<float> _margin; private ConfigEntry<int> _rows; private ConfigEntry<float> _backgroundOpacity; private float _nextError; private void Awake() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown _visible = ((BaseUnityPlugin)this).Config.Bind<bool>("Affichage", "Afficher", true, "Afficher le classement à droite du jeu."); _toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Affichage", "Touche", (KeyCode)289, "Touche pour afficher ou masquer le cadre."); _scale = ((BaseUnityPlugin)this).Config.Bind<float>("Affichage", "Echelle", 1f, new ConfigDescription("Taille du cadre, adaptée automatiquement à la hauteur de l'écran.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.7f, 2f), Array.Empty<object>())); _width = ((BaseUnityPlugin)this).Config.Bind<float>("Affichage", "Largeur", 330f, new ConfigDescription("Largeur maximale à 1080 pixels de haut. Le cadre se resserre autour de la liste.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(260f, 600f), Array.Empty<object>())); _top = ((BaseUnityPlugin)this).Config.Bind<float>("Affichage", "PositionVerticale", 0.33f, new ConfigDescription("Position depuis le haut de l'écran : 0,33 = 33 %, sous la mini-carte.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.7f), Array.Empty<object>())); _margin = ((BaseUnityPlugin)this).Config.Bind<float>("Affichage", "MargeDroite", 20f, new ConfigDescription("Marge depuis le bord droit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); _rows = ((BaseUnityPlugin)this).Config.Bind<int>("Affichage", "LignesVisibles", 10, new ConfigDescription("Nombre de lignes visibles avant défilement.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 20), Array.Empty<object>())); _backgroundOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Affichage", "OpaciteFond", 0.25f, new ConfigDescription("Opacité du fond : 0.25 correspond à 75 % de transparence.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); try { _api = new GameApi(); _engine = new RankingEngine(); _panel = new RankingPanel(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Character Level 1.0.1 by BenjSammy active. Simple Connecté panel, 75% transparent background. Level = sum of current integer skill levels."); } catch (Exception ex) { ((Behaviour)this).enabled = false; ((BaseUnityPlugin)this).Logger.LogError((object)("Character Level could not start: incompatible Valheim API. " + ex)); } } private void Update() { if (_engine == null) { return; } try { _engine.Tick(_api, Time.realtimeSinceStartup); } catch (Exception exception) { Report(exception); } } private void OnGUI() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (_engine == null || _api.NetworkToken == null || _api.IsDedicated || !_api.HasLocalPlayer) { return; } try { if (RankingPanel.TogglePressed(_toggleKey.Value)) { _visible.Value = !_visible.Value; } if (_visible.Value) { _panel.Draw(_engine, _scale.Value, _width.Value, _top.Value, _margin.Value, _rows.Value, _backgroundOpacity.Value); } } catch (Exception exception) { Report(exception); } } private void Report(Exception exception) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!(realtimeSinceStartup < _nextError)) { _nextError = realtimeSinceStartup + 15f; ((BaseUnityPlugin)this).Logger.LogWarning((object)("Character Level: " + exception)); } } private void OnDestroy() { _engine?.Close(); } } internal sealed class OnlinePeer { internal long Id; internal string Name; } internal interface IGameApi { object NetworkToken { get; } bool IsServer { get; } bool IsDedicated { get; } bool HasLocalPlayer { get; } long LocalPeerId { get; } long ServerPeerId { get; } bool TryGetLocalSkills(out float[] levels, out string name); List<OnlinePeer> GetPeers(); void Register(string method, Action<long, string> handler); void Send(long destination, string method, string payload); } internal static class LevelMath { internal const int MaxSkills = 512; internal const int MaxTotal = 1000000; internal static bool TrySum(float[] levels, out int total) { total = 0; if (levels == null || levels.Length > 512) { return false; } foreach (float num in levels) { if (float.IsNaN(num) || float.IsInfinity(num) || num < 0f || num > 10000f) { return false; } int num2 = (int)Math.Floor(num); if (total > 1000000 - num2) { return false; } total += num2; } return true; } } [DataContract] internal sealed class SkillReport { [DataMember(Name = "v", IsRequired = true)] public int Version = 1; [DataMember(Name = "s", IsRequired = true)] public float[] Skills; } [DataContract] internal sealed class RankRow { [DataMember(Name = "id", IsRequired = true)] public long PeerId; [DataMember(Name = "n", IsRequired = true)] public string Name; [DataMember(Name = "l", IsRequired = true)] public int? Level; } [DataContract] internal sealed class RankingPacket { [DataMember(Name = "v", IsRequired = true)] public int Version = 1; [DataMember(Name = "p", IsRequired = true)] public RankRow[] Rows; } internal static class PacketCodec { private const int MaximumBytes = 48000; internal const int MaximumPlayers = 256; internal static string Encode<T>(T packet) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) using MemoryStream memoryStream = new MemoryStream(); ((XmlObjectSerializer)new DataContractJsonSerializer(typeof(T))).WriteObject((Stream)memoryStream, (object)packet); if (memoryStream.Length > 48000) { throw new SerializationException("Ranking packet too large."); } return Encoding.UTF8.GetString(memoryStream.ToArray()); } internal static bool TryDecode<T>(string payload, out T packet) where T : class { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) packet = null; if (string.IsNullOrEmpty(payload) || payload.Length > 48000 || Encoding.UTF8.GetByteCount(payload) > 48000) { return false; } try { using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(payload))) { packet = ((XmlObjectSerializer)new DataContractJsonSerializer(typeof(T), new DataContractJsonSerializerSettings { MaxItemsInObjectGraph = 5000 })).ReadObject((Stream)memoryStream) as T; } return packet != null; } catch (Exception) { return false; } } internal static string CleanName(string name) { if (string.IsNullOrWhiteSpace(name)) { return "Personnage"; } StringBuilder stringBuilder = new StringBuilder(); foreach (char c in name) { stringBuilder.Append(char.IsControl(c) ? ' ' : c); } string text = stringBuilder.ToString().Trim(); if (text.Length > 48) { text = text[..(char.IsHighSurrogate(text[47]) ? 47 : 48)]; } if (text.Length != 0) { return text; } return "Personnage"; } internal static RankRow[] Sort(IEnumerable<RankRow> rows) { return rows.OrderByDescending((RankRow row) => row.Level ?? (-1)).ThenBy<RankRow, string>((RankRow row) => row.Name, StringComparer.OrdinalIgnoreCase).ThenBy((RankRow row) => row.PeerId) .ToArray(); } internal static bool TryReadRanking(string payload, out RankRow[] rows) { rows = null; if (!TryDecode<RankingPacket>(payload, out var packet) || packet.Version != 1 || packet.Rows == null || packet.Rows.Length > 256) { return false; } HashSet<long> hashSet = new HashSet<long>(); RankRow[] rows2 = packet.Rows; foreach (RankRow rankRow in rows2) { if (rankRow == null || rankRow.PeerId == 0L || !hashSet.Add(rankRow.PeerId) || (rankRow.Level.HasValue && (rankRow.Level.Value < 0 || rankRow.Level.Value > 1000000))) { return false; } rankRow.Name = CleanName(rankRow.Name); } rows = Sort(packet.Rows); return true; } } internal sealed class RankingEngine { internal const string ReportRpc = "benjsammy.characterlevel.v1.skills"; internal const string RankingRpc = "benjsammy.characterlevel.v1.ranking"; private const double RefreshSeconds = 5.0; private readonly Dictionary<long, int> _totals = new Dictionary<long, int>(); private readonly Dictionary<long, double> _lastReport = new Dictionary<long, double>(); private IGameApi _game; private object _networkToken; private double _now; private double _nextReport; private double _nextSnapshot; private double _lastSnapshot = -1.0; private double _lastBroadcast = -1.0; private bool _dirty; private bool _closed; internal RankRow[] Rows { get; private set; } = new RankRow[0]; internal int LocalLevel { get; private set; } internal string LocalName { get; private set; } = ""; internal bool HasLocalLevel { get; private set; } internal bool Synchronized { get { if (_lastSnapshot >= 0.0) { return _now - _lastSnapshot <= 20.0; } return false; } } internal void Tick(IGameApi game, double now) { if (_closed) { return; } _now = now; object token = game.NetworkToken; if (token == null) { if (_networkToken != null) { ResetSession(); } return; } if (token != _networkToken) { ResetSession(); _game = game; _networkToken = token; game.Register("benjsammy.characterlevel.v1.skills", delegate(long sender, string text) { if (_networkToken == token && !_closed) { ReceiveReport(sender, text); } }); game.Register("benjsammy.characterlevel.v1.ranking", delegate(long sender, string text) { if (_networkToken == token && !_closed) { ReceiveRanking(sender, text); } }); } if (now >= _nextReport && game.HasLocalPlayer) { _nextReport = now + 5.0; if (game.TryGetLocalSkills(out var levels, out var name) && LevelMath.TrySum(levels, out var total)) { LocalLevel = total; LocalName = PacketCodec.CleanName(name); HasLocalLevel = true; if (game.IsServer) { _totals[game.LocalPeerId] = total; _dirty = true; } else if (game.ServerPeerId != 0L) { game.Send(game.ServerPeerId, "benjsammy.characterlevel.v1.skills", PacketCodec.Encode(new SkillReport { Skills = levels })); } } } if (game.IsServer && (now >= _nextSnapshot || (_dirty && now - _lastBroadcast >= 0.5))) { PublishRanking(); } } private void ReceiveReport(long sender, string payload) { if (_game != null && _game.IsServer && _game.GetPeers().FirstOrDefault((OnlinePeer player) => player.Id == sender) != null && (!_lastReport.TryGetValue(sender, out var value) || !(_now - value < 0.5)) && PacketCodec.TryDecode<SkillReport>(payload, out var packet) && packet.Version == 1 && LevelMath.TrySum(packet.Skills, out var total)) { _totals[sender] = total; _lastReport[sender] = _now; _dirty = true; } } private void PublishRanking() { List<OnlinePeer> list = (from peer in _game.GetPeers() where peer.Id != 0 group peer by peer.Id into @group select @group.First()).ToList(); if (!_game.IsDedicated && _game.HasLocalPlayer && _game.TryGetLocalSkills(out var _, out var name)) { list.Add(new OnlinePeer { Id = _game.LocalPeerId, Name = name }); } list = (from peer in list where peer.Id != 0 group peer by peer.Id into @group select @group.First()).Take(256).ToList(); HashSet<long> activeIds = new HashSet<long>(list.Select((OnlinePeer peer) => peer.Id)); long[] array = _totals.Keys.Where((long id) => !activeIds.Contains(id)).ToArray(); foreach (long key in array) { _totals.Remove(key); } array = _lastReport.Keys.Where((long id) => !activeIds.Contains(id)).ToArray(); foreach (long key2 in array) { _lastReport.Remove(key2); } Rows = PacketCodec.Sort(list.Select((OnlinePeer peer) => new RankRow { PeerId = peer.Id, Name = PacketCodec.CleanName(peer.Name), Level = (_totals.TryGetValue(peer.Id, out var value) ? new int?(value) : ((int?)null)) })); _lastSnapshot = _now; _lastBroadcast = _now; _nextSnapshot = _now + 5.0; _dirty = false; string payload = PacketCodec.Encode(new RankingPacket { Rows = Rows }); foreach (OnlinePeer item in list) { if (item.Id != _game.LocalPeerId && _totals.ContainsKey(item.Id)) { _game.Send(item.Id, "benjsammy.characterlevel.v1.ranking", payload); } } } private void ReceiveRanking(long sender, string payload) { if (_game != null && !_game.IsServer && sender == _game.ServerPeerId && PacketCodec.TryReadRanking(payload, out var rows)) { Rows = rows; _lastSnapshot = _now; } } internal RankRow[] DisplayRows() { if (Synchronized) { return Rows; } if (HasLocalLevel && _game != null && _game.HasLocalPlayer) { return new RankRow[1] { new RankRow { PeerId = _game.LocalPeerId, Name = LocalName, Level = LocalLevel } }; } return new RankRow[0]; } private void ResetSession() { _game = null; _networkToken = null; _totals.Clear(); _lastReport.Clear(); Rows = new RankRow[0]; LocalLevel = 0; LocalName = ""; HasLocalLevel = false; _nextReport = 0.0; _nextSnapshot = 0.0; _lastSnapshot = -1.0; _lastBroadcast = -1.0; _dirty = false; } internal void Close() { ResetSession(); _closed = true; } } internal sealed class GameApi : IGameApi { private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private readonly MemberInfo _netInstance; private readonly MemberInfo _rpcInstance; private readonly MemberInfo _localPlayer; private readonly MethodInfo _isServer; private readonly MethodInfo _isDedicated; private readonly MethodInfo _getPeers; private readonly MethodInfo _getServerPeer; private readonly MethodInfo _serverPeerId; private readonly FieldInfo _routerId; private readonly FieldInfo _peerId; private readonly FieldInfo _peerName; private readonly MethodInfo _peerReady; private readonly MethodInfo _getSkills; private readonly MethodInfo _getSkillList; private readonly FieldInfo _skillLevel; private readonly MethodInfo _getPlayerName; private readonly MethodInfo _register; private readonly MethodInfo _send; private object Net => Read(_netInstance, null); private object Router => Read(_rpcInstance, null); private object LocalPlayer => Read(_localPlayer, null); public object NetworkToken { get { if (Net != null) { return Router; } return null; } } public bool IsServer { get { if (Net != null) { return (bool)_isServer.Invoke(Net, null); } return false; } } public bool IsDedicated { get { if (Net != null) { return (bool)_isDedicated.Invoke(Net, null); } return false; } } public bool HasLocalPlayer => LocalPlayer != null; public long LocalPeerId { get { if (Router != null) { return (long)_routerId.GetValue(Router); } return 0L; } } public long ServerPeerId { get { if (Net == null || Router == null) { return 0L; } if (IsServer) { return LocalPeerId; } object obj = _getServerPeer.Invoke(Net, null); if (obj != null) { return (long)_peerId.GetValue(obj); } return (long)_serverPeerId.Invoke(Router, null); } } internal GameApi() { Type type = RequireType("ZNet"); Type type2 = RequireType("ZRoutedRpc"); Type type3 = RequireType("ZNetPeer"); Type type4 = RequireType("Player"); Type type5 = RequireType("Skills"); Type nestedType = type5.GetNestedType("Skill", BindingFlags.Public | BindingFlags.NonPublic); if (nestedType == null) { throw new TypeLoadException("Skills.Skill was not found."); } _netInstance = RequireMember(type, "instance"); _rpcInstance = RequireMember(type2, "instance"); _localPlayer = RequireMember(type4, "m_localPlayer"); _isServer = RequireMethod(type, "IsServer", Type.EmptyTypes, typeof(bool)); _isDedicated = RequireMethod(type, "IsDedicated", Type.EmptyTypes, typeof(bool)); _getPeers = RequireMethod(type, "GetPeers", Type.EmptyTypes); _getServerPeer = RequireMethod(type, "GetServerPeer", Type.EmptyTypes); _serverPeerId = RequireMethod(type2, "GetServerPeerID", Type.EmptyTypes, typeof(long)); _routerId = RequireField(type2, "m_id", typeof(long)); _peerId = RequireField(type3, "m_uid", typeof(long)); _peerName = RequireField(type3, "m_playerName", typeof(string)); _peerReady = type3.GetMethod("IsReady", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); _getSkills = RequireMethod(type4, "GetSkills", Type.EmptyTypes); _getSkillList = RequireMethod(type5, "GetSkillList", Type.EmptyTypes); _skillLevel = RequireField(nestedType, "m_level", typeof(float)); _getPlayerName = RequireMethod(type4, "GetPlayerName", Type.EmptyTypes, typeof(string)); _send = RequireMethod(type2, "InvokeRoutedRPC", new Type[3] { typeof(long), typeof(string), typeof(object[]) }); _register = (from method in type2.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where method.Name == "Register" && method.IsGenericMethodDefinition && method.GetGenericArguments().Length == 1 select method.MakeGenericMethod(typeof(string))).FirstOrDefault(delegate(MethodInfo method) { ParameterInfo[] parameters = method.GetParameters(); return parameters.Length == 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(Action<long, string>); }); if (_register == null) { throw new MissingMethodException("ZRoutedRpc.Register<string>(string, Action<long,string>)"); } } public bool TryGetLocalSkills(out float[] levels, out string name) { levels = null; name = ""; object localPlayer = LocalPlayer; if (localPlayer == null) { return false; } object obj = _getSkills.Invoke(localPlayer, null); if (obj == null) { return false; } if (!(_getSkillList.Invoke(obj, null) is IEnumerable enumerable)) { return false; } List<float> list = new List<float>(); foreach (object item in enumerable) { if (item != null) { if (list.Count >= 512) { return false; } list.Add((float)_skillLevel.GetValue(item)); } } levels = list.ToArray(); name = (string)_getPlayerName.Invoke(localPlayer, null); return true; } public List<OnlinePeer> GetPeers() { List<OnlinePeer> list = new List<OnlinePeer>(); if (Net == null || !IsServer) { return list; } if (!(_getPeers.Invoke(Net, null) is IEnumerable enumerable)) { return list; } foreach (object item in enumerable) { if (item != null && (!(_peerReady != null) || !(_peerReady.ReturnType == typeof(bool)) || (bool)_peerReady.Invoke(item, null))) { string text = (string)_peerName.GetValue(item); long num = (long)_peerId.GetValue(item); if (num != 0L && !string.IsNullOrWhiteSpace(text)) { list.Add(new OnlinePeer { Id = num, Name = text }); } } } return list; } public void Register(string method, Action<long, string> handler) { object router = Router; if (router == null) { throw new InvalidOperationException("Valheim network is not ready."); } _register.Invoke(router, new object[2] { method, handler }); } public void Send(long destination, string method, string payload) { object router = Router; if (router != null) { _send.Invoke(router, new object[3] { destination, method, new object[1] { payload } }); } } private static Type RequireType(string name) { 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; } } throw new TypeLoadException("Valheim type was not found: " + name); } private static MemberInfo RequireMember(Type type, string name) { object obj = ((object)type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); if (obj == null) { throw new MissingMemberException(type.FullName, name); } return (MemberInfo)obj; } private static FieldInfo RequireField(Type type, string name, Type expected) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != expected) { throw new MissingFieldException(type.FullName, name); } return field; } private static MethodInfo RequireMethod(Type type, string name, Type[] parameters, Type expected = null) { MethodInfo method = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameters, null); if (method == null || (expected != null && method.ReturnType != expected)) { throw new MissingMethodException(type.FullName, name); } return method; } private static object Read(MemberInfo member, object instance) { FieldInfo fieldInfo = member as FieldInfo; if (!(fieldInfo != null)) { return ((PropertyInfo)member).GetValue(instance, null); } return fieldInfo.GetValue(instance); } } internal sealed class RankingPanel { private Vector2 _scroll; private GUIStyle _line; private GUIStyle _title; private int _fontSize; internal static bool TogglePressed(KeyCode key) { //IL_0006: 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) Event current = Event.current; if ((int)key != 0 && current != null && (int)current.type == 4 && current.keyCode == key) { current.Use(); return true; } return false; } internal void Draw(RankingEngine engine, float customScale, float referenceWidth, float topFraction, float marginRight, int maximumRows, float backgroundOpacity) { //IL_0328: 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_0067: 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_009b: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) if (Screen.height < 240) { return; } RankRow[] array = engine.DisplayRows(); float num = Mathf.Clamp((float)Screen.height / 1080f, 0.65f, 1.8f) * customScale; EnsureStyles(num); float num2 = 12f * num; float num3 = Mathf.Min(marginRight * num, (float)Screen.width * 0.2f); float num4 = _title.CalcSize(new GUIContent("Connecté")).x; RankRow[] array2 = array; foreach (RankRow row in array2) { num4 = Mathf.Max(num4, _line.CalcSize(new GUIContent(RowLabel(row))).x); } float num5 = Mathf.Min(Mathf.Clamp(num4 + num2 * 2f + 18f * num, 160f * num, referenceWidth * num), (float)Screen.width - num3 - 12f); if (num5 < 100f) { return; } float num6 = 34f * num; float num7 = 8f * num; float num8 = 28f * num; float num9 = Mathf.Clamp((float)Screen.height * topFraction, 8f, (float)Screen.height - 120f); int num10 = Mathf.Max(1, Mathf.FloorToInt(((float)Screen.height - num9 - 16f - num6 - num7) / num8)); int num11 = Mathf.Min(Mathf.Max(1, array.Length), Mathf.Min(maximumRows, num10)); float num12 = (float)num11 * num8; float num13 = num6 + num12 + num7; if (num13 > (float)Screen.height - 16f) { num12 = Mathf.Max(16f, (float)Screen.height - 16f - num6 - num7); num13 = num6 + num12 + num7; } num9 = Mathf.Min(num9, Mathf.Max(8f, (float)Screen.height - num13 - 8f)); float num14 = Mathf.Max(6f, (float)Screen.width - num5 - num3); Color color = GUI.color; int depth = GUI.depth; try { GUI.depth = -100; GUI.color = new Color(0.035f, 0.04f, 0.05f, Mathf.Clamp01(backgroundOpacity)); GUI.DrawTexture(new Rect(num14, num9, num5, num13), (Texture)(object)Texture2D.whiteTexture); Label(new Rect(num14 + num2, num9 + 5f * num, num5 - num2 * 2f, 25f * num), "Connecté", _title, num); Rect val = default(Rect); ((Rect)(ref val))..ctor(num14 + num2, num9 + num6, num5 - num2 * 2f, num12); if (array.Length > num11) { Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, 0f, Mathf.Max(1f, ((Rect)(ref val)).width - 18f * num), (float)array.Length * num8); _scroll = GUI.BeginScrollView(val, _scroll, val2, false, false); try { DrawRows(array, new Rect(0f, 0f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), num8, num); return; } finally { GUI.EndScrollView(); } } _scroll = Vector2.zero; DrawRows(array, val, num8, num); } finally { GUI.color = color; GUI.depth = depth; } } private void DrawRows(RankRow[] rows, Rect area, float rowHeight, float scale) { //IL_001f: 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) for (int i = 0; i < rows.Length; i++) { Label(new Rect(((Rect)(ref area)).x, ((Rect)(ref area)).y + (float)i * rowHeight, ((Rect)(ref area)).width, rowHeight), RowLabel(rows[i]), _line, scale); } if (rows.Length == 0) { Label(new Rect(((Rect)(ref area)).x, ((Rect)(ref area)).y, ((Rect)(ref area)).width, rowHeight), "…", _line, scale); } } private static string RowLabel(RankRow row) { return row.Name + " " + (row.Level.HasValue ? row.Level.Value.ToString() : "…") + " lvl."; } private void EnsureStyles(float scale) { int num = Mathf.RoundToInt(17f * scale); if (_line == null || _fontSize != num) { _fontSize = num; _line = Style(num, (FontStyle)0); _title = Style(Mathf.RoundToInt(18f * scale), (FontStyle)1); } } private static GUIStyle Style(int size, FontStyle fontStyle) { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_002b: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_004f: 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_0060: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = Mathf.Max(9, size), fontStyle = fontStyle, alignment = (TextAnchor)3, richText = false, wordWrap = false, clipping = (TextClipping)1, padding = new RectOffset(0, 0, 0, 0) }; val.normal.textColor = Color.white; return val; } private static void Label(Rect rectangle, string text, GUIStyle style, float scale) { //IL_0014: 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_004a: 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) GUI.color = new Color(0f, 0f, 0f, 0.65f); GUI.Label(new Rect(((Rect)(ref rectangle)).x + scale, ((Rect)(ref rectangle)).y + scale, ((Rect)(ref rectangle)).width, ((Rect)(ref rectangle)).height), text, style); GUI.color = Color.white; GUI.Label(rectangle, text, style); } } }