using System; using System.Buffers; using System.Buffers.Binary; using System.Buffers.Text; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.Tracing; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Numerics; using System.Numerics.Hashing; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.AccessControl; using System.Security.Cryptography; using System.Security.Principal; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FxResources.System.Buffers; using FxResources.System.Memory; using HarmonyLib; using JetBrains.Annotations; using LiteDB; using LiteDB.Engine; using LiteDB.Utils; using LiteDB.Utils.Extensions; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: Guid("72b7e2b4-c4d2-4b2f-91db-99d0311d97bc")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyProduct("GlitnirRanking")] [assembly: AssemblyCompany("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("GlitnirRanking")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace Glitnir.Ranking { internal static class GlitnirRankingServerSync { internal static readonly ConfigSync ConfigSync = new ConfigSync("com.glitnir.ranking") { DisplayName = "Glitnir Ranking", CurrentVersion = "0.7.55", MinimumRequiredVersion = "0.7.55" }; internal static ConfigEntry BindConfig(this ConfigFile config, string group, string name, T value, string description, bool synced = true) { ConfigEntry val = config.Bind(group, name, value, description); if (synced) { ConfigSync.AddConfigEntry(val); } return val; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.glitnir.ranking", "Glitnir Ranking", "0.7.55")] public class GlitnirRankingPlugin : BaseUnityPlugin { private enum DebugCategory { General, Hit, Kill, Skill, PendingKill, Snapshot, Points } private sealed class SnapshotTopEntryData { public int Position; public string PlayerName = ""; public int Points; public bool IsLocalPlayer; public int TotalKillsPontuadas; public int TotalBossesPontuadas; public int TotalSkillLevelUpsPontuados; public int TotalFishingPontuadas; public int TotalCraftPontuadas; public int TotalFarmJackpotsPontuados; public int TotalUniqueCraftJackpotsPontuados; public int TotalDeaths; public int KillPointsTotal; public int BossPointsTotal; public int SkillPointsTotal; public int FishingPointsTotal; public int CraftPointsTotal; public int FarmJackpotPointsTotal; public int UniqueCraftJackpotPointsTotal; public int DeathPenaltyPointsTotal; public int TotalPointsExchanges; public int PointsExchangePenaltyTotal; public int PointsExchangeCoinsTotal; public int ExplorationMapJackpotPointsTotal; public string LastReason = ""; public string LastUpdateUtc = ""; } private sealed class SnapshotPlayerData { public bool HasData; public int Position; public string PlayerName = ""; public int Points; public int TotalKillsPontuadas; public int TotalBossesPontuadas; public int TotalSkillLevelUpsPontuados; public int KillPointsTotal; public int BossPointsTotal; public int SkillPointsTotal; public int TotalFishingPontuadas; public int TotalCraftPontuadas; public int TotalFarmJackpotsPontuados; public int TotalUniqueCraftJackpotsPontuados; public int TotalDeaths; public int FishingPointsTotal; public int CraftPointsTotal; public int FarmJackpotPointsTotal; public int UniqueCraftJackpotPointsTotal; public int DeathPenaltyPointsTotal; public int TotalPointsExchanges; public int PointsExchangePenaltyTotal; public int PointsExchangeCoinsTotal; public int ExplorationMapJackpotPointsTotal; public string LastReason = ""; public string LastUpdateUtc = ""; public bool RankingEnabled; public bool EnableKillPoints; public bool EnableBossPoints; public bool EnableSkillPoints; public bool EnableMarketplaceQuestPoints; public int TopCount; public bool RewardClaimsEnabled; public bool RewardCanClaim; public bool RewardAlreadyClaimed; public int RewardRank; public int RewardMinPoints; public string RewardLabel = ""; public string RewardPrefabName = ""; public int RewardAmount; public string RewardBlockReason = ""; public string RewardClaimCycleId = ""; public string HudKillRules = ""; public string HudBossRules = ""; public string HudSkillJackpotRules = ""; public string HudMarketplaceQuestRules = ""; public string HudFishingRules = ""; public string HudCraftRules = ""; public string HudFarmJackpotRules = ""; public string HudUniqueCraftJackpotRules = ""; public string HudDeathPenaltyRules = ""; public bool EnableDeathPenalty; public bool DeathPenaltyUseMultiplier; public int DeathPenaltyPerDeath; public string HudExplorationMapJackpotRules = ""; public Dictionary ProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary FloatProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); } private sealed class PendingKillCheck { public string PrefabName = ""; public float FirstSeenTime; public float LastHitTime; } private sealed class RankRewardInfo { public int Rank; public int MinPoints; public string Label = ""; public string PrefabName = ""; public int Amount; } private sealed class RuleGuideGroup { public readonly string Name; public readonly List Rows = new List(); public RuleGuideGroup(string name) { Name = (string.IsNullOrWhiteSpace(name) ? "Outros" : name); } } private class SkillGuideGroup { public string Name; public List Milestones; public SkillGuideGroup(string name) { Name = (string.IsNullOrWhiteSpace(name) ? "Habilidade" : name); Milestones = new List(); } } private class SkillGuideMilestone { public string Level; public string Points; public SkillGuideMilestone(string level, string points) { Level = (string.IsNullOrWhiteSpace(level) ? "?" : level); Points = (string.IsNullOrWhiteSpace(points) ? "0" : points); } } public const string ModGuid = "com.glitnir.ranking"; public const string ModName = "Glitnir Ranking"; public const string ModVersion = "0.7.55"; internal static GlitnirRankingPlugin Instance; internal static ManualLogSource Log; private const string RpcRequestSnapshot = "glitnir.ranking.requestsnapshot"; private const string RpcReceiveSnapshot = "glitnir.ranking.receivesnapshot"; private const string RpcReportHit = "glitnir.ranking.reporthit"; private const string RpcReportKill = "glitnir.ranking.reportkill"; private const string RpcReportSkillGain = "glitnir.ranking.reportskillgain"; private const string RpcRequestRewardClaim = "glitnir.ranking.requestrewardclaim"; private const string RpcGrantRewardItem = "glitnir.ranking.grantrewarditem"; private const string RpcFinalizeRewardClaim = "glitnir.ranking.finalizerewardclaim"; private const string RpcRewardClaimFeedback = "glitnir.ranking.rewardclaimfeedback"; private const string RpcRequestPointsExchange = "glitnir.ranking.requestpointsexchange"; private const string RpcGrantExchangeCoins = "glitnir.ranking.grantexchangecoins"; private const string RpcFinalizePointsExchange = "glitnir.ranking.finalizepointsexchange"; private const string RpcPointsExchangeFeedback = "glitnir.ranking.pointsexchangefeedback"; private const string RpcReportMarketplaceQuestComplete = "glitnir.ranking.marketquestcomplete"; private const string RpcReportFishCaught = "glitnir.ranking.reportfishcaught"; private const string RpcReportCraftedItem = "glitnir.ranking.reportcrafteditem"; private const string RpcReportFarmHarvest = "glitnir.ranking.reportfarmharvest"; private const string RpcReportPlayerDeath = "glitnir.ranking.reportplayerdeath"; private const string RpcReportExplorationMap = "glitnir.ranking.reportexplorationmap"; private const float DamageCreditLifetimeSeconds = 180f; private const float ProcessedKillLifetimeSeconds = 180f; private const float LocalRecentHitLifetimeSeconds = 15f; private const float ServerPendingKillDelaySeconds = 0.25f; private const float ServerPendingKillTimeoutSeconds = 12f; private const float ServerPendingKillCheckInterval = 0.25f; private const int MaxHudChars = 3000; private const int MaxPlayerNameLength = 32; private const int MaxReasonLength = 64; private const float ClientRefreshInterval = 1f; private readonly Dictionary _hudPrefabDisplayNameCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _hudPrefabObjectCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private int _hudObjectDbItemCountCached = -1; private int _hudZNetScenePrefabCountCached = -1; private Type _hudLocalizationType; private FieldInfo _hudLocalizationInstanceField; private MethodInfo _hudLocalizationLocalizeMethod; private bool _hudLocalizationReflectionReady; private Harmony _harmony; private bool _rpcsRegistered = false; private string _rulesFilePath; private string _uiFolderPath; private string _uiFilePath; private string _databaseFilePath; private string _legacyDatabaseFilePath; private ConfigFile _rulesConfig; private FileSystemWatcher _rulesConfigWatcher; private bool _rulesConfigReloadQueued; private float _rulesConfigReloadAt; private float _rulesConfigApplyAt; private const float RulesConfigApplyInterval = 1f; private ConfigEntry _cfgRankingEnabled; private ConfigEntry _cfgEnableKillPoints; private ConfigEntry _cfgEnableBossPoints; private ConfigEntry _cfgDefaultKillPoints; private ConfigEntry _cfgTopCount; private ConfigEntry _cfgAllowRepeatedBossPoints; private ConfigEntry _cfgDebugLogging; private ConfigEntry _cfgLogHitReports; private ConfigEntry _cfgLogKillReports; private ConfigEntry _cfgLogSkillReports; private ConfigEntry _cfgLogPendingKillReports; private ConfigEntry _cfgLogSnapshotRequests; private ConfigEntry _cfgLogPointsChanges; private ConfigEntry _cfgEnableSkillPoints; private ConfigEntry _cfgIgnoreTamedKills; private ConfigEntry _cfgEnableMarketplaceQuestPoints; private ConfigEntry _cfgEnableFishingPoints; private ConfigEntry _cfgEnableDeathPenalty; private ConfigEntry _cfgEnableExplorationJackpots; private ConfigEntry _cfgExplorationMapJackpotRules; private ConfigEntry _cfgDeathPenaltyRules; private ConfigEntry _cfgDeathPenaltyUseMultiplier; private ConfigEntry _cfgDeathPenaltyPerDeath; private readonly Dictionary> _cfgCombatBiomeRuleEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private ConfigEntry _cfgProductionCategoryRules; private ConfigEntry _cfgMarketplaceQuestPointMap; private ConfigEntry _cfgFarmJackpotRules; private ConfigEntry _cfgUniqueCraftJackpotRules; private ConfigEntry _cfgRewardClaimsEnabled; private ConfigEntry _cfgRewardClaimCycleId; private ConfigEntry _cfgRewardTop1MinPoints; private ConfigEntry _cfgRewardTop1Label; private ConfigEntry _cfgRewardTop1Prefab; private ConfigEntry _cfgRewardTop1Amount; private ConfigEntry _cfgRewardTop2MinPoints; private ConfigEntry _cfgRewardTop2Label; private ConfigEntry _cfgRewardTop2Prefab; private ConfigEntry _cfgRewardTop2Amount; private ConfigEntry _cfgRewardTop3MinPoints; private ConfigEntry _cfgRewardTop3Label; private ConfigEntry _cfgRewardTop3Prefab; private ConfigEntry _cfgRewardTop3Amount; private ConfigEntry _cfgPointsExchangeEnabled; private ConfigEntry _cfgPointsExchangePrefab; private ConfigEntry _cfgPointsExchangeCoinsPerPoint; private ConfigEntry _cfgPointsExchangeMinPoints; private ConfigEntry _cfgPointsExchangeMaxPointsPerRequest; private ConfigEntry _cfgDiscordTop3WebhookEnabled; private ConfigEntry _cfgDiscordTop3WebhookUrl; private ConfigEntry _cfgIgnoreAdminsInRanking; private ConfigEntry _cfgIgnoredAdminNames; private readonly Dictionary> _cfgKillPointEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _cfgBossPointEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _cfgFishingPointEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _cfgCraftPointEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _cfgFarmJackpotEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _cfgUniqueCraftJackpotEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _cfgSkillMilestoneJackpotPointEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private RankingDatabase _database = new RankingDatabase(); private RankingRules _rules = new RankingRules(); private readonly Dictionary _marketplaceQuestPointsByUid = new Dictionary(); private readonly Dictionary> _damageCredits = new Dictionary>(StringComparer.Ordinal); private readonly Dictionary _processedKills = new Dictionary(StringComparer.Ordinal); private readonly Dictionary _ignoredTamedKills = new Dictionary(StringComparer.Ordinal); private readonly Dictionary _localRecentHits = new Dictionary(StringComparer.Ordinal); private readonly Dictionary _pendingKillChecks = new Dictionary(StringComparer.Ordinal); private float _serverPendingKillCheckAt; private bool _hudVisible; private float _hudOpenTime; private Rect _windowRect = new Rect(660f, 56f, 548f, 804f); private Rect _iconRect = new Rect(24f, 180f, 56f, 56f); private GameObject _rankingInputBlockerObject; private Canvas _rankingInputBlockerCanvas; private RectTransform _rankingInputBlockerRect; private Vector2 _rankingScrollPosition = Vector2.zero; private Vector2 _playerInfoScrollPosition = Vector2.zero; private Vector2 _rulesInfoScrollPosition = Vector2.zero; private Vector2 _actionsScrollPosition = Vector2.zero; private readonly HashSet _expandedActionPlayers = new HashSet(StringComparer.OrdinalIgnoreCase); private int _hudTabIndex = 0; private float _hudTabSwitchTime = 0f; private readonly HashSet _expandedRuleCategories = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _expandedGuideSkillRows = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _expandedRuleSubCategories = new HashSet(StringComparer.OrdinalIgnoreCase); private bool _ruleCategoriesInitialized; private readonly HashSet _expandedPerformanceCategories = new HashSet(StringComparer.OrdinalIgnoreCase); private bool _performanceCategoriesInitialized; private float _clientRefreshTimer; private float _explorationReportTimer; private float _lastReportedMapExplorePercent = -1f; private long _lastKnownServerPeerUid; private bool _requestedInitialServerSnapshot; private string _cachedTopText = "Carregando ranking..."; private string _cachedPlayerText = "Aguardando dados do servidor..."; private string _statusText = "Sincronizando..."; private float _statusUntil = 0f; private bool _rewardClaimRequestPending; private string _rewardClaimPendingCycleId = ""; private int _rewardClaimPendingRank = 0; private readonly HashSet _pendingRewardClaims = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _pendingPointsExchanges = new HashSet(StringComparer.OrdinalIgnoreCase); private bool _pointsExchangeRequestPending; private string _pointsExchangeAmountInput = ""; private bool _iconDragging; private Vector2 _iconDragOffset = Vector2.zero; private Vector2 _iconMouseDownPosition = Vector2.zero; private bool _iconMovedDuringDrag; private readonly List _cachedTopEntries = new List(); private SnapshotPlayerData _cachedPlayerData = new SnapshotPlayerData(); private GUIStyle _windowStyle; private GUIStyle _headerStyle; private GUIStyle _sectionTitleStyle; private GUIStyle _rankingTextStyle; private GUIStyle _playerTextStyle; private GUIStyle _footerStyle; private GUIStyle _statusStyle; private GUIStyle _iconButtonStyle; private GUIStyle _panelHeadingStyle; private GUIStyle _cardLabelStyle; private GUIStyle _cardValueStyle; private GUIStyle _bodyRowStyle; private GUIStyle _bodyValueStyle; private GUIStyle _mutedBodyStyle; private GUIStyle _rankIndexStyle; private GUIStyle _rankNameStyle; private GUIStyle _rankPointsStyle; private GUIStyle _youTagStyle; private GUIStyle _emptyStateStyle; private GUIStyle _configStyle; private bool _stylesReady; private string _uiTitleFontNames = "Cinzel Decorative|Cinzel|Trajan Pro|Palatino Linotype|Georgia|Times New Roman"; private string _uiBodyFontNames = "Cormorant Garamond|Cormorant SC|Palatino Linotype|Georgia|Garamond|Arial"; private string _uiAccentFontNames = "Cinzel|Palatino Linotype|Georgia|Arial"; private bool _uiUseSystemFonts = false; private KeyCode _uiToggleKey = (KeyCode)121; private float _uiIconZoom = 0.96f; private Font _uiTitleFont; private Font _uiBodyFont; private Font _uiAccentFont; private Texture2D _uiTransparentTexture; private Texture2D _uiWhiteTexture; private Texture2D _uiPanelTexture; private Texture2D _uiBackgroundTexture; private Texture2D _uiRankingIconTexture; private Texture2D _uiTitleRankingTexture; private Texture2D _uiTitleTopTexture; private Texture2D _uiTitleGuideTexture; private Texture2D _uiTitlePlayerTexture; private Texture2D _uiTitleActionsTexture; private readonly Dictionary _uiRuleCategoryIcons = new Dictionary(StringComparer.OrdinalIgnoreCase); private const float RuleCategoryIconSize = 24f; private Texture2D _uiRank1IconTexture; private Texture2D _uiRank2IconTexture; private Texture2D _uiRank3IconTexture; private bool _uiTexturesLoaded; private readonly HashSet _missingUiTextureWarnings = new HashSet(StringComparer.OrdinalIgnoreCase); private const string DefaultKillPointRules = "Boar:1"; private const string DefaultCombatCategoryRules = "Prados:Boar:1,Deer:1,Neck:1;Floresta Negra:Greydwarf:1,Greydwarf_Elite:2,Greydwarf_Shaman:2,Troll:5;Pântano:Draugr:2,Draugr_Elite:3,Blob:2,Abomination:8;Montanha:Wolf:2,Hatchling:2,StoneGolem:8;Planícies:Goblin:3,GoblinBrute:5,Lox:6,Deathsquito:3;Oceano:Serpent:6;Mistlands:Seeker:4,SeekerBrute:8,Gjall:10;Ashlands:Charred_Melee:4,Charred_Archer:4,Volture:4;Especiais:Haldor:0"; private const string DefaultProductionCategoryRules = "Armas:SwordIron=800;Armaduras:HelmetBronze=800;Comidas:DeerStew=25"; private static readonly Dictionary ManualPortuguesePrefabNames = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "deerstew", "Ensopado de cervo" }, { "honeysglazedchicken", "Frango glaceado com mel" }, { "mushroomjotun", "Cogumelo Jotun" }, { "helmetbronze", "Elmo de bronze" }, { "helmetcarapace", "Elmo de carapaça" }, { "helmetdrake", "Elmo de draco" }, { "helmetdverger", "Tiara Dvergr" }, { "helmetfenris", "Capuz de Fenris" }, { "helmetiron", "Elmo de ferro" }, { "helmetleather", "Elmo de couro" }, { "helmetmage", "Capuz de mago" }, { "helmetpadded", "Elmo acolchoado" }, { "helmetroot", "Máscara de raiz" }, { "helmettrollleather", "Capuz de couro de troll" }, { "helmetflametal", "Elmo de flametal" }, { "armorbronzechest", "Peitoral de bronze" }, { "armorbronzelegs", "Perneiras de bronze" }, { "armorcarapacechest", "Peitoral de carapaça" }, { "armorcarapacelegs", "Perneiras de carapaça" }, { "armorfenringchest", "Peitoral de Fenris" }, { "armorfenringlegs", "Perneiras de Fenris" }, { "armorironchest", "Peitoral de ferro" }, { "armorironlegs", "Perneiras de ferro" }, { "armorleatherchest", "Túnica de couro" }, { "armorleatherlegs", "Calças de couro" }, { "armormagechest", "Manto de mago" }, { "armormagelegs", "Calças de mago" }, { "armorpaddedcuirass", "Couraça acolchoada" }, { "armorpaddedgreaves", "Grevas acolchoadas" }, { "armorragschest", "Túnica de trapos" }, { "armorragslegs", "Calças de trapos" }, { "armorrootchest", "Armadura de raiz" }, { "armorrootlegs", "Perneiras de raiz" }, { "armortrollleatherchest", "Túnica de couro de troll" }, { "armortrollleatherlegs", "Calças de couro de troll" }, { "knifeblackmetal", "Faca de metal negro" }, { "knifecopper", "Faca de cobre" }, { "knifeflint", "Faca de sílex" }, { "knifesilver", "Faca de prata" }, { "swordiron", "Espada de ferro" }, { "swordsilver", "Espada de prata" }, { "swordblackmetal", "Espada de metal negro" }, { "swordbronze", "Espada de bronze" }, { "swordmistwalker", "Mistwalker" }, { "swordflametal", "Espada de flametal" }, { "axeiron", "Machado de ferro" }, { "axebronze", "Machado de bronze" }, { "axeblackmetal", "Machado de metal negro" }, { "maceiron", "Maça de ferro" }, { "macebronze", "Maça de bronze" }, { "macesilver", "Frostner" }, { "sledgeiron", "Marreta de ferro" }, { "sledge_demolisher", "Demolidor" }, { "bow", "Arco bruto" }, { "bowfinewood", "Arco de madeira fina" }, { "bowhuntsman", "Arco do caçador" }, { "bowdraugrfang", "Presa de Draugr" }, { "bowspine", "Estilhaçador de espinha" }, { "crossbowarbalest", "Arbalest" }, { "crossbowripper", "Ripper" }, { "shieldwood", "Escudo de madeira" }, { "shieldbronze buckler", "Broquel de bronze" }, { "shieldironbuckler", "Broquel de ferro" }, { "shieldblackmetal", "Escudo de metal negro" }, { "shieldcarapace", "Escudo de carapaça" }, { "shieldflametal", "Escudo de flametal" }, { "atgierbronze", "Atgeir de bronze" }, { "atgieriron", "Atgeir de ferro" }, { "atgierblackmetal", "Atgeir de metal negro" }, { "spearflint", "Lança de sílex" }, { "spearbronze", "Lança de bronze" }, { "spearwolffang", "Lança de presas" }, { "carrot", "Cenoura" }, { "turnip", "Nabo" }, { "onion", "Cebola" }, { "barley", "Cevada" }, { "flax", "Linho" }, { "sap", "Seiva" }, { "jotunpuffs", "Cogumelo Jotun" }, { "magecap", "Chapéu de Mago" }, { "vineberry", "Baga de Videira" } }; private static readonly Dictionary BossDisplayNamesPtBr = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Eikthyr", "Eikthyr" }, { "gd_king", "O Ancião" }, { "Bonemass", "Massa Óssea" }, { "Dragon", "Moder" }, { "GoblinKing", "Yagluth" }, { "SeekerQueen", "Rainha Seeker" }, { "Fader", "Fader" }, { "Charred_Melee_Dyrnwyn", "Guerreiro Carbonizado Dyrnwyn" }, { "Fenring_Cultist_Hildir", "Cultista Fenring da Hildir" }, { "GoblinBruteBros", "Irmãos Berserker Fuling" }, { "GoblinBrute_Hildir", "Berserker Fuling da Hildir" }, { "GoblinShaman_Hildir", "Xamã Fuling da Hildir" }, { "Skeleton_Hildir", "Esqueleto da Hildir" } }; private static readonly Dictionary BossPortugueseToPrefab = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Eikthyr", "Eikthyr" }, { "O Ancião", "gd_king" }, { "Ancião", "gd_king" }, { "O Anciao", "gd_king" }, { "Anciao", "gd_king" }, { "Massa Óssea", "Bonemass" }, { "Massa Ossea", "Bonemass" }, { "Bonemass", "Bonemass" }, { "Moder", "Dragon" }, { "Yagluth", "GoblinKing" }, { "Rainha Seeker", "SeekerQueen" }, { "Rainha dos Seeker", "SeekerQueen" }, { "Seeker Queen", "SeekerQueen" }, { "Fader", "Fader" }, { "Guerreiro Carbonizado Dyrnwyn", "Charred_Melee_Dyrnwyn" }, { "Dyrnwyn", "Charred_Melee_Dyrnwyn" }, { "Cultista Fenring da Hildir", "Fenring_Cultist_Hildir" }, { "Irmãos Berserker Fuling", "GoblinBruteBros" }, { "Irmaos Berserker Fuling", "GoblinBruteBros" }, { "Berserker Fuling da Hildir", "GoblinBrute_Hildir" }, { "Xamã Fuling da Hildir", "GoblinShaman_Hildir" }, { "Xama Fuling da Hildir", "GoblinShaman_Hildir" }, { "Esqueleto da Hildir", "Skeleton_Hildir" } }; private static readonly Dictionary FishDisplayNamesPtBr = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Fish1", "Perca" }, { "Fish2", "Lúcio" }, { "Fish3", "Fish3" }, { "Fish4_cave", "Tetra" }, { "Fish5", "Peixe Troll" }, { "Fish6", "Arenque gigante" }, { "Fish7", "Garoupa" }, { "Fish8", "Garoupa estrelada" }, { "Fish9", "Peixe-pescador" }, { "Fish10", "Salmão do norte" }, { "Fish11", "Peixe magma" }, { "Fish12", "Baiacu" } }; private static readonly Dictionary FishPortugueseToPrefab = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Perca", "Fish1" }, { "Lúcio", "Fish2" }, { "Lucio", "Fish2" }, { "Fish3", "Fish3" }, { "Tetra", "Fish4_cave" }, { "Peixe Troll", "Fish5" }, { "Arenque gigante", "Fish6" }, { "Garoupa", "Fish7" }, { "Garoupa estrelada", "Fish8" }, { "Peixe-pescador", "Fish9" }, { "Peixe pescador", "Fish9" }, { "Salmão do norte", "Fish10" }, { "Salmao do norte", "Fish10" }, { "Peixe magma", "Fish11" }, { "Baiacu", "Fish12" } }; private static readonly Dictionary HudFriendlyNames = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Boar", "Javali" }, { "Neck", "Nixe" }, { "Greyling", "Greydwarf Jovem" }, { "Greydwarf", "Greydwarf" }, { "Greydwarf_Elite", "Greydwarf Elite" }, { "Greydwarf_Shaman", "Xamã Greydwarf" }, { "Troll", "Troll" }, { "Skeleton", "Esqueleto" }, { "Skeleton_Poison", "Esqueleto Venenoso" }, { "Draugr", "Draugr" }, { "Draugr_Elite", "Draugr Elite" }, { "Blob", "Gosma" }, { "BlobElite", "Gosma Elite" }, { "Leech", "Sanguessuga" }, { "Surtling", "Surtling" }, { "Abomination", "Abominação" }, { "Wolf", "Lobo" }, { "Hatchling", "Draco" }, { "Fenring", "Fenring" }, { "StoneGolem", "Golem de Pedra" }, { "Goblin", "Fuling" }, { "GoblinArcher", "Fuling Arqueiro" }, { "GoblinBrute", "Fuling Berserker" }, { "GoblinShaman", "Xamã Fuling" }, { "Lox", "Lox" }, { "Deathsquito", "Mosquito da Morte" }, { "Serpent", "Serpente Marinha" }, { "Bat", "Morcego" }, { "Ulv", "Ulv" }, { "Hare", "Lebre" }, { "Tick", "Carrapato" }, { "Seeker", "Seeker" }, { "SeekerBrute", "Seeker Brutamontes" }, { "Gjall", "Gjall" }, { "Dverger", "Dvergr" }, { "Charred_Melee", "Carbonizado Guerreiro" }, { "Charred_Archer", "Carbonizado Arqueiro" }, { "Charred_Mage", "Carbonizado Mago" }, { "Morgen", "Morgen" }, { "Asksvin", "Asksvin" }, { "Volture", "Abutre das Cinzas" }, { "Eikthyr", "Eikthyr" }, { "gd_king", "O Ancião" }, { "Bonemass", "Massa Óssea" }, { "Dragon", "Moder" }, { "GoblinKing", "Yagluth" }, { "SeekerQueen", "Rainha Seeker" }, { "Fader", "Fader" }, { "Fish1", "Perca" }, { "Fish2", "Lúcio" }, { "Fish3", "Fish3" }, { "Fish4_cave", "Tetra" }, { "Fish5", "Peixe Troll" }, { "Fish6", "Arenque gigante" }, { "Fish7", "Garoupa" }, { "Fish8", "Garoupa estrelada" }, { "Fish9", "Peixe-pescador" }, { "Fish10", "Salmão do norte" }, { "Fish11", "Peixe magma" }, { "Fish12", "Baiacu" }, { "Carrot", "Cenoura" }, { "Turnip", "Nabo" }, { "Onion", "Cebola" }, { "Barley", "Cevada" }, { "Flax", "Linho" }, { "Sap", "Seiva" }, { "JotunPuffs", "Cogumelo Jotun" }, { "Magecap", "Chapéu de Mago" }, { "Vineberry", "Baga de Videira" }, { "Fiddleheadfern", "Samambaia" }, { "Run", "Corrida" }, { "Jump", "Salto" }, { "Swords", "Espadas" }, { "Knives", "Facas" }, { "Clubs", "Porretes" }, { "Polearms", "Armas de Haste" }, { "Spears", "Lanças" }, { "Blocking", "Bloqueio" }, { "Axes", "Machados" }, { "Bows", "Arcos" }, { "Crossbows", "Bestas" }, { "ElementalMagic", "Magia Elemental" }, { "BloodMagic", "Magia de Sangue" }, { "Fishing", "Pesca" }, { "Cooking", "Culinária" }, { "Deer", "Cervo" }, { "EvilHeart_Forest", "Coração Maligno da Floresta" }, { "Ghost", "Fantasma" }, { "Wraith", "Aparição" }, { "Fenring_Cultist", "Cultista Fenring" }, { "SeekerBrood", "Cria de Seeker" }, { "DvergerMage", "Mago Dvergr" }, { "DvergerMageFire", "Mago Dvergr de Fogo" }, { "DvergerMageIce", "Mago Dvergr de Gelo" }, { "DvergerMageSupport", "Mago Dvergr de Suporte" }, { "DvergerRogue", "Ladino Dvergr" }, { "Charred_Twitcher", "Carbonizado Retorcido" }, { "Charred_Melee_Dyrnwyn", "Guerreiro Carbonizado Dyrnwyn" }, { "GoblinBruteBros", "Irmãos Berserker Fuling" }, { "GoblinBrute_Hildir", "Berserker Fuling da Hildir" }, { "GoblinShaman_Hildir", "Xamã Fuling da Hildir" }, { "Fenring_Cultist_Hildir", "Cultista Fenring da Hildir" }, { "Skeleton_Hildir", "Esqueleto da Hildir" }, { "ExploreBlackForest", "Explorador da Floresta Negra" }, { "ExploreSwamp", "Explorador do Pântano" }, { "ExploreMountain", "Explorador das Montanhas" }, { "ExplorePlains", "Explorador das Planícies" }, { "ExploreMistlands", "Explorador das Terras Nebulosas" }, { "ExploreAshlands", "Explorador das Terras das Cinzas" }, { "Kill100Enemies", "Exterminador" }, { "CraftMaster", "Mestre Artesão" }, { "Mapa 5%", "Mapa 5%" } }; private const float ActionPlayerCollapsedHeight = 58f; private const float ActionPlayerExpandedHeight = 650f; private const string HudColorPoints = "#00FF7F"; private const string HudColorDanger = "#FF5555"; private const string HudColorProgress = "#4FC3F7"; private const string HudColorHighlight = "#FFD700"; private const string HudColorMuted = "#D7DCE5"; private const string HudColorName = "#FFFFFF"; private const string HudColorSeparator = "#8F6E38"; private void EnsureRulesFileExists() { try { if (!File.Exists(_rulesFilePath)) { File.WriteAllText(_rulesFilePath, BuildDefaultRulesFileContents(), Encoding.UTF8); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao criar arquivo de regras: " + ex)); } } private string BuildDefaultRulesFileContents() { StringBuilder stringBuilder = new StringBuilder(16384); stringBuilder.AppendLine("# ======================================================================="); stringBuilder.AppendLine("# GLITNIR RANKING - CONFIGURACAO DE PONTUACAO"); stringBuilder.AppendLine("# ======================================================================="); stringBuilder.AppendLine("# Este arquivo controla as regras do ranking do servidor Glitnir."); stringBuilder.AppendLine("# Prefab = nome interno do item/criatura/colheita no Valheim."); stringBuilder.AppendLine("# Pontos = valor entregue ao jogador quando a regra for validada."); stringBuilder.AppendLine("#"); stringBuilder.AppendLine("# Organizacao principal:"); stringBuilder.AppendLine("# - KillPoints: pontos por criatura normal. Peixes NAO ficam aqui."); stringBuilder.AppendLine("# - FishingPoints: somente pontos por peixe realmente pescado."); stringBuilder.AppendLine("# - BossPoints: pontos por bosses e minibosses."); stringBuilder.AppendLine("# - CraftPoints.Rules: pontos por craft, em uma linha limpa separada por ponto e virgula."); stringBuilder.AppendLine("# - FarmJackpots.Rules: jackpots de colheita, em uma linha limpa separada por ponto e virgula."); stringBuilder.AppendLine("# - UniqueCraftJackpots.Rules: jackpots unicos por craft, em uma linha limpa separada por ponto e virgula."); stringBuilder.AppendLine("#"); stringBuilder.AppendLine("# Nao use virgulas nas listas de producao/jackpot. Use ;"); stringBuilder.AppendLine("# Exemplos:"); stringBuilder.AppendLine("# CraftPoints.Rules=MeadHealthMinor:20;ArrowNeedle:2"); stringBuilder.AppendLine("# FarmJackpots.Rules=Carrot:200:1000"); stringBuilder.AppendLine("# UniqueCraftJackpots.Rules=IronSword:1:800"); stringBuilder.AppendLine("# ======================================================================="); stringBuilder.AppendLine(); stringBuilder.AppendLine("RankingEnabled=true"); stringBuilder.AppendLine("EnableKillPoints=true"); stringBuilder.AppendLine("EnableBossPoints=true"); stringBuilder.AppendLine("DefaultKillPoints=1"); stringBuilder.AppendLine("TopCount=10"); stringBuilder.AppendLine("AllowRepeatedBossPoints=false"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Logging"); stringBuilder.AppendLine("DebugLogging=false"); stringBuilder.AppendLine("LogHitReports=false"); stringBuilder.AppendLine("LogKillReports=false"); stringBuilder.AppendLine("LogSkillReports=false"); stringBuilder.AppendLine("LogPendingKillReports=false"); stringBuilder.AppendLine("LogSnapshotRequests=false"); stringBuilder.AppendLine("LogPointsChanges=false"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Skill milestone jackpot points"); stringBuilder.AppendLine("EnableSkillPoints=true"); stringBuilder.AppendLine("IgnoreTamedKills=true"); stringBuilder.AppendLine("EnableMarketplaceQuestPoints=true"); stringBuilder.AppendLine("EnableFishingPoints=true"); stringBuilder.AppendLine("EnableDeathPenalty=true"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Marketplace quest points"); stringBuilder.AppendLine("[MarketplaceQuestPoints]"); stringBuilder.AppendLine("QuestPointMap=ccq_b21:450,ccq_b22:150"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Penalidade por morte"); stringBuilder.AppendLine("[DeathPenalty]"); stringBuilder.AppendLine("# UseMultiplierMode=false usa a tabela Rules abaixo."); stringBuilder.AppendLine("# UseMultiplierMode=true ignora Rules e usa PenaltyPerDeath por morte."); stringBuilder.AppendLine("# Exemplo multiplicador: PenaltyPerDeath=100 e 15 mortes = -1500."); stringBuilder.AppendLine("UseMultiplierMode=false"); stringBuilder.AppendLine("PenaltyPerDeath=100"); stringBuilder.AppendLine("# Formato do modo tabela: quantidadeDeMortes:pontosPerdidos,quantidadeDeMortes:pontosPerdidos"); stringBuilder.AppendLine("# Exemplo: 1:0,2:100,5:300,10:800"); stringBuilder.AppendLine("Rules=1:0,2:100,5:300,10:800"); stringBuilder.AppendLine(); stringBuilder.AppendLine("# Reward claims"); stringBuilder.AppendLine("RewardClaimsEnabled=true"); stringBuilder.AppendLine("RewardClaimCycleId=temporada_001"); stringBuilder.AppendLine("RewardTop1MinPoints=300"); stringBuilder.AppendLine("RewardTop1Label=Recompensa do 1 lugar"); stringBuilder.AppendLine("RewardTop1Prefab=Coins"); stringBuilder.AppendLine("RewardTop1Amount=500"); stringBuilder.AppendLine("RewardTop2MinPoints=200"); stringBuilder.AppendLine("RewardTop2Label=Recompensa do 2 lugar"); stringBuilder.AppendLine("RewardTop2Prefab=AmberPearl"); stringBuilder.AppendLine("RewardTop2Amount=10"); stringBuilder.AppendLine("RewardTop3MinPoints=100"); stringBuilder.AppendLine("RewardTop3Label=Recompensa do 3 lugar"); stringBuilder.AppendLine("RewardTop3Prefab=Ruby"); stringBuilder.AppendLine("RewardTop3Amount=5"); stringBuilder.AppendLine(); AppendBossPoints(stringBuilder); AppendKillPoints(stringBuilder); AppendFishingPoints(stringBuilder); AppendSkillMilestoneJackpotPoints(stringBuilder); AppendProductionRankingRules(stringBuilder); return stringBuilder.ToString(); } private void AppendBossPoints(StringBuilder sb) { sb.AppendLine("# ========================="); sb.AppendLine("# BOSS POINTS"); sb.AppendLine("# ========================="); sb.AppendLine("# Cada boss/miniboss fica em uma chave própria."); sb.AppendLine("BossPoints.Bonemass=2200"); sb.AppendLine("BossPoints.Charred_Melee_Dyrnwyn=40"); sb.AppendLine("BossPoints.Dragon=3000"); sb.AppendLine("BossPoints.Eikthyr=1200"); sb.AppendLine("BossPoints.Fader=10000"); sb.AppendLine("BossPoints.Fenring_Cultist_Hildir=30"); sb.AppendLine("BossPoints.gd_king=4200"); sb.AppendLine("BossPoints.GoblinBruteBros=35"); sb.AppendLine("BossPoints.GoblinBrute_Hildir=18"); sb.AppendLine("BossPoints.GoblinKing=6000"); sb.AppendLine("BossPoints.GoblinShaman_Hildir=18"); sb.AppendLine("BossPoints.SeekerQueen=8600"); sb.AppendLine("BossPoints.Skeleton_Hildir=25"); sb.AppendLine(); } private void AppendPoint(StringBuilder sb, string section, string key, int points) { sb.AppendLine(section + "." + key + "=" + points); } private void AppendKillPoint(StringBuilder sb, string prefabName, int points, string comment = null) { } private void AppendKillPoints(StringBuilder sb) { sb.AppendLine("# ========================="); sb.AppendLine("# KILL POINTS / COMBATE"); sb.AppendLine("# ========================="); sb.AppendLine("# Pontos por criaturas normais. Peixes nao devem ficar aqui; use [FishingPoints]."); sb.AppendLine("# Formato gerado pelo BepInEx: [KillPoints] Prefab = pontos."); sb.AppendLine("# Mantido no modo performance: o mod NAO envia RPC por hit; pontua apenas kill confirmada."); sb.AppendLine("KillPoints.Boar=1"); sb.AppendLine("KillPoints.Neck=1"); sb.AppendLine("KillPoints.Greyling=1"); sb.AppendLine("KillPoints.Greydwarf=1"); sb.AppendLine("KillPoints.Greydwarf_Elite=2"); sb.AppendLine("KillPoints.Greydwarf_Shaman=2"); sb.AppendLine("KillPoints.Skeleton=1"); sb.AppendLine("KillPoints.Troll=5"); sb.AppendLine("KillPoints.Draugr=2"); sb.AppendLine("KillPoints.Draugr_Elite=3"); sb.AppendLine("KillPoints.Blob=2"); sb.AppendLine("KillPoints.Wolf=2"); sb.AppendLine("KillPoints.Hatchling=2"); sb.AppendLine("KillPoints.StoneGolem=8"); sb.AppendLine("KillPoints.Deathsquito=3"); sb.AppendLine("KillPoints.Goblin=3"); sb.AppendLine("KillPoints.GoblinBrute=5"); sb.AppendLine("KillPoints.GoblinShaman=4"); sb.AppendLine("KillPoints.Lox=6"); sb.AppendLine("KillPoints.Serpent=6"); sb.AppendLine("KillPoints.Seeker=4"); sb.AppendLine("KillPoints.SeekerBrute=8"); sb.AppendLine("KillPoints.Gjall=10"); sb.AppendLine("KillPoints.Charred_Melee=4"); sb.AppendLine("KillPoints.Charred_Archer=4"); sb.AppendLine("KillPoints.Morgen=12"); sb.AppendLine(); } private void AppendFishingPoints(StringBuilder sb) { sb.AppendLine("# ========================="); sb.AppendLine("# FISHING POINTS"); sb.AppendLine("# ========================="); sb.AppendLine("# As chaves podem ficar em português; o código converte para o prefab real internamente."); sb.AppendLine("# Mapeamento: Perca=Fish1, Lúcio=Fish2, Fish3=Fish3, Tetra=Fish4_cave, Peixe Troll=Fish5, Arenque gigante=Fish6, Garoupa=Fish7, Garoupa estrelada=Fish8, Peixe-pescador=Fish9, Salmão do norte=Fish10, Peixe magma=Fish11, Baiacu=Fish12"); AppendFishingPoint(sb, "Perca", 1); AppendFishingPoint(sb, "Lúcio", 1); AppendFishingPoint(sb, "Fish3", 2); AppendFishingPoint(sb, "Tetra", 3); AppendFishingPoint(sb, "Peixe Troll", 2); AppendFishingPoint(sb, "Arenque gigante", 3); AppendFishingPoint(sb, "Garoupa", 3000); AppendFishingPoint(sb, "Garoupa estrelada", 4); AppendFishingPoint(sb, "Peixe-pescador", 4); AppendFishingPoint(sb, "Salmão do norte", 5); AppendFishingPoint(sb, "Peixe magma", 5); AppendFishingPoint(sb, "Baiacu", 6); sb.AppendLine(); } private void AppendFishingPoint(StringBuilder sb, string prefabName, int points) { sb.AppendLine("FishingPoints." + prefabName + "=" + points); } private void AppendSkillPoint(StringBuilder sb, string skillKey, int points, string comment = null) { if (!string.IsNullOrWhiteSpace(comment)) { sb.AppendLine(comment); } sb.AppendLine("SkillPoints." + skillKey + "=" + points); } private void AppendSkillMilestoneJackpotPoints(StringBuilder sb) { sb.AppendLine("# ========================="); sb.AppendLine("# SKILL MILESTONE JACKPOT POINTS"); sb.AppendLine("# ========================="); sb.AppendLine("# Pontos únicos por marco de skill. Formato: SkillMilestoneJackpotPoints.Skill=20:pontos,40:pontos,60:pontos,80:pontos,100:pontos"); sb.AppendLine("# Exemplo: Bows 20/40/60/80/100. Cada marco pontua uma única vez por jogador/ciclo."); AppendSkillMilestoneJackpotPoint(sb, "BloodMagic", "20:1500,40:3000,60:5000,80:7500,100:12000"); AppendSkillMilestoneJackpotPoint(sb, "ElementalMagic", "20:1000,40:2000,60:3500,80:5500,100:8000"); AppendSkillMilestoneJackpotPoint(sb, "Bows", "20:500,40:1000,60:2000,80:3000,100:4000"); AppendSkillMilestoneJackpotPoint(sb, "Crossbows", "20:500,40:1000,60:2000,80:3000,100:4000"); AppendSkillMilestoneJackpotPoint(sb, "Swords", "20:500,40:1000,60:2000,80:3000,100:4000"); AppendSkillMilestoneJackpotPoint(sb, "Axes", "20:500,40:1000,60:2000,80:3000,100:4000"); AppendSkillMilestoneJackpotPoint(sb, "Clubs", "20:500,40:1000,60:2000,80:3000,100:4000"); AppendSkillMilestoneJackpotPoint(sb, "Spears", "20:500,40:1000,60:2000,80:3000,100:4000"); AppendSkillMilestoneJackpotPoint(sb, "Polearms", "20:500,40:1000,60:2000,80:3000,100:4000"); AppendSkillMilestoneJackpotPoint(sb, "Knives", "20:500,40:1000,60:2000,80:3000,100:4000"); AppendSkillMilestoneJackpotPoint(sb, "Blocking", "20:400,40:800,60:1500,80:2500,100:3500"); AppendSkillMilestoneJackpotPoint(sb, "Run", "20:300,40:700,60:1200,80:2000,100:3000"); AppendSkillMilestoneJackpotPoint(sb, "Jump", "20:300,40:700,60:1200,80:2000,100:3000"); AppendSkillMilestoneJackpotPoint(sb, "WoodCutting", "20:300,40:700,60:1200,80:1800,100:2500"); AppendSkillMilestoneJackpotPoint(sb, "Pickaxes", "20:300,40:700,60:1200,80:1800,100:2500"); AppendSkillMilestoneJackpotPoint(sb, "Farming", "20:0,40:0,60:0,80:0,100:0"); sb.AppendLine(); } private void AppendSkillMilestoneJackpotPoint(StringBuilder sb, string skillKey, string milestones) { sb.AppendLine("SkillMilestoneJackpotPoints." + skillKey + "=" + milestones); } private void AppendProductionRankingRules(StringBuilder sb) { sb.AppendLine("# ======================================================================="); sb.AppendLine("# PRODUCAO E JACKPOTS - GLITNIR RANKING"); sb.AppendLine("# ======================================================================="); sb.AppendLine("# Estes blocos usam UMA entrada por sistema para manter o arquivo limpo."); sb.AppendLine("# Nao use virgulas. Separe cada regra com ponto e virgula (;)."); sb.AppendLine("# Formatos:"); sb.AppendLine("# CraftPoints.Rules = Prefab:pontos;OutroPrefab:pontos"); sb.AppendLine("# FarmJackpots.Rules = Prefab:quantidade:pontos;OutroPrefab:quantidade:pontos"); sb.AppendLine("# UniqueCraftJackpots.Rules = Prefab:quantidade:pontos;OutroPrefab:quantidade:pontos"); sb.AppendLine("# Exemplos reais:"); sb.AppendLine("# MeadHealthMinor:20"); sb.AppendLine("# Carrot:200:1000"); sb.AppendLine("# IronSword:1:800"); sb.AppendLine("# ======================================================================="); sb.AppendLine(); sb.AppendLine("# ========================="); sb.AppendLine("# CRAFT POINTS"); sb.AppendLine("# ========================="); sb.AppendLine("# Pontos por craft de qualquer prefab configurado."); sb.AppendLine("# Exemplo de item: MeadHealthMinor:20"); sb.AppendLine("CraftPoints.Rules=MeadHealthMinor:20"); sb.AppendLine(); sb.AppendLine("# ========================="); sb.AppendLine("# FARM JACKPOTS"); sb.AppendLine("# ========================="); sb.AppendLine("# Jackpot por colheita. Premia uma vez por jogador/ciclo quando bater a quantidade."); sb.AppendLine("# Exemplo de item: Carrot:200:1000"); sb.AppendLine("FarmJackpots.Rules=Carrot:200:1000"); sb.AppendLine(); sb.AppendLine("# ========================="); sb.AppendLine("# UNIQUE CRAFT JACKPOTS"); sb.AppendLine("# ========================="); sb.AppendLine("# Jackpot unico por craft. Ideal para armas, armaduras e marcos especiais."); sb.AppendLine("# Exemplo de item: IronSword:1:800"); sb.AppendLine("UniqueCraftJackpots.Rules=IronSword:1:800"); sb.AppendLine(); } private void AppendStringPoint(StringBuilder sb, string section, string key, string value) { sb.AppendLine(section + "." + key + "=" + value); } private void LoadRules() { _rules = new RankingRules(); try { if (!File.Exists(_rulesFilePath)) { return; } string[] array = File.ReadAllLines(_rulesFilePath, Encoding.UTF8); foreach (string text in array) { string text2 = text.Trim(); if (string.IsNullOrWhiteSpace(text2) || text2.StartsWith("#") || text2.StartsWith(";") || text2.StartsWith("//")) { continue; } int num = text2.IndexOf('='); if (num <= 0) { continue; } string text3 = text2.Substring(0, num).Trim(); string text4 = text2.Substring(num + 1).Trim(); if (text3.Equals("RankingEnabled", StringComparison.OrdinalIgnoreCase)) { _rules.RankingEnabled = ParseBool(text4, _rules.RankingEnabled); } else if (text3.Equals("EnableKillPoints", StringComparison.OrdinalIgnoreCase)) { _rules.EnableKillPoints = ParseBool(text4, _rules.EnableKillPoints); } else if (text3.Equals("EnableBossPoints", StringComparison.OrdinalIgnoreCase)) { _rules.EnableBossPoints = ParseBool(text4, _rules.EnableBossPoints); } else if (text3.Equals("DefaultKillPoints", StringComparison.OrdinalIgnoreCase)) { _rules.DefaultKillPoints = ParseInt(text4, _rules.DefaultKillPoints); } else if (text3.Equals("TopCount", StringComparison.OrdinalIgnoreCase)) { _rules.TopCount = Mathf.Clamp(ParseInt(text4, _rules.TopCount), 1, 50); } else if (text3.Equals("AllowRepeatedBossPoints", StringComparison.OrdinalIgnoreCase)) { _rules.AllowRepeatedBossPoints = ParseBool(text4, _rules.AllowRepeatedBossPoints); } else if (text3.Equals("DebugLogging", StringComparison.OrdinalIgnoreCase)) { _rules.DebugLogging = ParseBool(text4, _rules.DebugLogging); } else if (text3.Equals("LogHitReports", StringComparison.OrdinalIgnoreCase)) { _rules.LogHitReports = ParseBool(text4, _rules.LogHitReports); } else if (text3.Equals("LogKillReports", StringComparison.OrdinalIgnoreCase)) { _rules.LogKillReports = ParseBool(text4, _rules.LogKillReports); } else if (text3.Equals("LogPendingKillReports", StringComparison.OrdinalIgnoreCase)) { _rules.LogPendingKillReports = ParseBool(text4, _rules.LogPendingKillReports); } else if (text3.Equals("LogSnapshotRequests", StringComparison.OrdinalIgnoreCase)) { _rules.LogSnapshotRequests = ParseBool(text4, _rules.LogSnapshotRequests); } else if (text3.Equals("LogPointsChanges", StringComparison.OrdinalIgnoreCase)) { _rules.LogPointsChanges = ParseBool(text4, _rules.LogPointsChanges); } else if (text3.Equals("EnableSkillPoints", StringComparison.OrdinalIgnoreCase)) { _rules.EnableSkillPoints = ParseBool(text4, _rules.EnableSkillPoints); } else if (text3.Equals("LogSkillReports", StringComparison.OrdinalIgnoreCase)) { _rules.LogSkillReports = ParseBool(text4, _rules.LogSkillReports); } else if (text3.Equals("EnableFishingPoints", StringComparison.OrdinalIgnoreCase)) { _rules.EnableFishingPoints = ParseBool(text4, _rules.EnableFishingPoints); } else if (text3.Equals("EnableDeathPenalty", StringComparison.OrdinalIgnoreCase)) { _rules.EnableDeathPenalty = ParseBool(text4, _rules.EnableDeathPenalty); } else if (text3.Equals("DeathPenalty.UseMultiplierMode", StringComparison.OrdinalIgnoreCase) || text3.Equals("DeathPenaltyUseMultiplier", StringComparison.OrdinalIgnoreCase) || text3.Equals("UseMultiplierMode", StringComparison.OrdinalIgnoreCase)) { _rules.DeathPenaltyUseMultiplier = ParseBool(text4, _rules.DeathPenaltyUseMultiplier); } else if (text3.Equals("DeathPenalty.PenaltyPerDeath", StringComparison.OrdinalIgnoreCase) || text3.Equals("DeathPenaltyPerDeath", StringComparison.OrdinalIgnoreCase) || text3.Equals("PenaltyPerDeath", StringComparison.OrdinalIgnoreCase)) { _rules.DeathPenaltyPerDeath = Mathf.Max(0, ParseInt(text4, _rules.DeathPenaltyPerDeath)); } else if (text3.Equals("DeathPenalty.Rules", StringComparison.OrdinalIgnoreCase) || text3.Equals("DeathPenaltyRules", StringComparison.OrdinalIgnoreCase) || text3.Equals("Rules", StringComparison.OrdinalIgnoreCase)) { _rules.DeathPenaltyRules = ParseDeathPenaltyRules(text4); } else if (text3.Equals("RewardClaimsEnabled", StringComparison.OrdinalIgnoreCase)) { _rules.RewardClaimsEnabled = ParseBool(text4, _rules.RewardClaimsEnabled); } else if (text3.Equals("RewardClaimCycleId", StringComparison.OrdinalIgnoreCase)) { _rules.RewardClaimCycleId = SafeLimit(text4, 64); } else if (text3.Equals("RewardTop1MinPoints", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop1MinPoints = Mathf.Max(0, ParseInt(text4, _rules.RewardTop1MinPoints)); } else if (text3.Equals("RewardTop1Label", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop1Label = SafeLimit(text4, 96); } else if (text3.Equals("RewardTop1Prefab", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop1Prefab = SafeLimit(text4, 96); } else if (text3.Equals("RewardTop1Amount", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop1Amount = Mathf.Max(0, ParseInt(text4, _rules.RewardTop1Amount)); } else if (text3.Equals("RewardTop2MinPoints", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop2MinPoints = Mathf.Max(0, ParseInt(text4, _rules.RewardTop2MinPoints)); } else if (text3.Equals("RewardTop2Label", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop2Label = SafeLimit(text4, 96); } else if (text3.Equals("RewardTop2Prefab", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop2Prefab = SafeLimit(text4, 96); } else if (text3.Equals("RewardTop2Amount", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop2Amount = Mathf.Max(0, ParseInt(text4, _rules.RewardTop2Amount)); } else if (text3.Equals("RewardTop3MinPoints", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop3MinPoints = Mathf.Max(0, ParseInt(text4, _rules.RewardTop3MinPoints)); } else if (text3.Equals("RewardTop3Label", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop3Label = SafeLimit(text4, 96); } else if (text3.Equals("RewardTop3Prefab", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop3Prefab = SafeLimit(text4, 96); } else if (text3.Equals("RewardTop3Amount", StringComparison.OrdinalIgnoreCase)) { _rules.RewardTop3Amount = Mathf.Max(0, ParseInt(text4, _rules.RewardTop3Amount)); } else if (text3.StartsWith("KillPoints.", StringComparison.OrdinalIgnoreCase)) { string text5 = SafeKey(text3.Substring("KillPoints.".Length)); if (!IsFishPrefab(text5)) { _rules.KillPoints[text5] = ParseInt(text4, 0); } } else if (text3.StartsWith("BossPoints.", StringComparison.OrdinalIgnoreCase)) { _rules.BossPoints[NormalizeBossPrefabName(text3.Substring("BossPoints.".Length))] = ParseInt(text4, 0); } else if (text3.StartsWith("FishingPoints.", StringComparison.OrdinalIgnoreCase)) { string text6 = NormalizeFishPrefabName(text3.Substring("FishingPoints.".Length)); if (IsFishPrefab(text6)) { _rules.FishingPoints[text6] = ParseInt(text4, 0); } } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao carregar regras do ranking: " + ex)); } } private bool ParseBool(string raw, bool fallback) { bool result; return bool.TryParse(raw, out result) ? result : fallback; } private int ParseInt(string raw, int fallback) { int result; return int.TryParse(raw, out result) ? result : fallback; } private void InitializeSyncedRulesConfig() { try { string filePath = Path.Combine(Paths.ConfigPath, "glitnir.ranking.rules.cfg"); Dictionary dictionary = LoadLegacyRulesOverrides(filePath); MergeSectionOverrides(dictionary, LoadSectionRulesOverrides(filePath)); _rulesConfig = ((BaseUnityPlugin)this).Config; BindSyncedRulesConfigEntries(dictionary); ApplyRulesFromSyncedConfig(); _rulesConfig.Save(); CleanupFishKillPointConfigEntries(); RewriteRulesConfigHeaderAndGroupedSections(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao inicializar config sincronizada do ranking: " + ex)); EnsureRulesFileExists(); LoadRules(); } } private void SetupRulesConfigWatcher() { try { if (!string.IsNullOrWhiteSpace(_rulesFilePath)) { string directoryName = Path.GetDirectoryName(_rulesFilePath); string fileName = Path.GetFileName(_rulesFilePath); if (!string.IsNullOrWhiteSpace(directoryName) && !string.IsNullOrWhiteSpace(fileName)) { _rulesConfigWatcher = new FileSystemWatcher(directoryName, fileName); _rulesConfigWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime; _rulesConfigWatcher.Changed += OnRulesConfigFileChanged; _rulesConfigWatcher.Created += OnRulesConfigFileChanged; _rulesConfigWatcher.Renamed += OnRulesConfigFileChanged; _rulesConfigWatcher.EnableRaisingEvents = true; } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Não foi possível iniciar watcher da config do ranking: " + ex.Message)); } } private void OnRulesConfigFileChanged(object sender, FileSystemEventArgs args) { _rulesConfigReloadQueued = true; _rulesConfigReloadAt = Time.realtimeSinceStartup + 0.5f; } private void ProcessRulesConfigReloadIfNeeded() { if (!_rulesConfigReloadQueued || Time.realtimeSinceStartup < _rulesConfigReloadAt) { return; } _rulesConfigReloadQueued = false; try { ConfigFile rulesConfig = _rulesConfig; if (rulesConfig != null) { rulesConfig.Reload(); } BindSyncedRulesConfigEntries(null); ApplyRulesFromSyncedConfig(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao recarregar config do ranking: " + ex)); } } private void RefreshRulesFromSyncedConfigIfNeeded() { if (!(Time.realtimeSinceStartup < _rulesConfigApplyAt)) { _rulesConfigApplyAt = Time.realtimeSinceStartup + 1f; ApplyRulesFromSyncedConfig(); } } private Dictionary LoadLegacyRulesOverrides(string filePath) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); try { if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) { return dictionary; } bool flag = false; string[] array = File.ReadAllLines(filePath, Encoding.UTF8); foreach (string text in array) { string text2 = text.Trim(); if (text2.StartsWith("[") && text2.EndsWith("]")) { flag = true; break; } } if (flag) { return dictionary; } string[] array2 = File.ReadAllLines(filePath, Encoding.UTF8); foreach (string text3 in array2) { string text4 = text3.Trim(); if (string.IsNullOrWhiteSpace(text4) || text4.StartsWith("#") || text4.StartsWith(";") || text4.StartsWith("//")) { continue; } int num = text4.IndexOf('='); if (num > 0) { string text5 = text4.Substring(0, num).Trim(); string value = text4.Substring(num + 1).Trim(); if (!string.IsNullOrWhiteSpace(text5)) { dictionary[text5] = value; } } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Falha ao ler overrides legados da config do ranking: " + ex.Message)); } return dictionary; } private void MergeSectionOverrides(Dictionary target, Dictionary source) { if (target == null || source == null) { return; } foreach (KeyValuePair item in source) { if (!string.IsNullOrWhiteSpace(item.Key)) { target[item.Key] = item.Value; } } } private Dictionary LoadSectionRulesOverrides(string filePath) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); try { if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) { return dictionary; } string text = string.Empty; HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase) { "BossPoints", "FishingPoints", "KillPoints", "CraftPoints", "FarmJackpots", "UniqueCraftJackpots", "SkillMilestoneJackpotPoints", "DeathPenalty", "ExplorationMapJackpots" }; string[] array = File.ReadAllLines(filePath, Encoding.UTF8); foreach (string text2 in array) { string text3 = ((text2 != null) ? text2.Trim() : string.Empty); if (string.IsNullOrWhiteSpace(text3) || text3.StartsWith("#") || text3.StartsWith(";") || text3.StartsWith("//")) { continue; } if (text3.StartsWith("[") && text3.EndsWith("]")) { text = SafeKey(text3.Substring(1, text3.Length - 2)); continue; } int num = text3.IndexOf('='); if (num <= 0) { continue; } string text4 = text3.Substring(0, num).Trim(); string value = text3.Substring(num + 1).Trim(); if (string.IsNullOrWhiteSpace(text4)) { continue; } string text5 = text4; if (!text4.Contains(".") && !string.IsNullOrWhiteSpace(text)) { text5 = text + "." + text4; } int num2 = text5.IndexOf('.'); if (num2 > 0) { string text6 = text5.Substring(0, num2).Trim(); string text7 = SafeKey(text5.Substring(num2 + 1)); if (hashSet.Contains(text6) && !string.IsNullOrWhiteSpace(text7) && (!text6.Equals("KillPoints", StringComparison.OrdinalIgnoreCase) || !IsFishPrefab(text7))) { dictionary[text6 + "." + text7] = value; } } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Falha ao ler entradas dinâmicas da config do ranking: " + ex.Message)); } return dictionary; } private bool IsLegacyRulesFileFormat(string filePath) { try { if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) { return false; } string[] array = File.ReadAllLines(filePath, Encoding.UTF8); foreach (string text in array) { string text2 = text.Trim(); if (!string.IsNullOrWhiteSpace(text2) && !text2.StartsWith("#") && !text2.StartsWith(";") && !text2.StartsWith("//")) { return !text2.StartsWith("[") || !text2.EndsWith("]"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Falha ao detectar formato legado da config do ranking: " + ex.Message)); } return false; } private void BindSyncedRulesConfigEntries(Dictionary legacyOverrides) { if (_rulesConfig != null) { legacyOverrides = legacyOverrides ?? new Dictionary(StringComparer.OrdinalIgnoreCase); RankingRules rankingRules = new RankingRules(); _cfgRankingEnabled = _rulesConfig.BindConfig("General", "RankingEnabled", ReadLegacyBool(legacyOverrides, "RankingEnabled", rankingRules.RankingEnabled), "Ativa o sistema de ranking."); _cfgEnableKillPoints = _rulesConfig.BindConfig("General", "EnableKillPoints", ReadLegacyBool(legacyOverrides, "EnableKillPoints", rankingRules.EnableKillPoints), "Ativa a pontuação por criaturas normais."); _cfgEnableBossPoints = _rulesConfig.BindConfig("General", "EnableBossPoints", ReadLegacyBool(legacyOverrides, "EnableBossPoints", rankingRules.EnableBossPoints), "Ativa a pontuação por bosses e minibosses."); _cfgDefaultKillPoints = _rulesConfig.BindConfig("General", "DefaultKillPoints", ReadLegacyInt(legacyOverrides, "DefaultKillPoints", rankingRules.DefaultKillPoints), "Pontos padrão para kills sem regra específica."); _cfgTopCount = _rulesConfig.BindConfig("General", "TopCount", ReadLegacyInt(legacyOverrides, "TopCount", rankingRules.TopCount), "Quantidade de jogadores exibidos no topo do ranking."); _cfgAllowRepeatedBossPoints = _rulesConfig.BindConfig("General", "AllowRepeatedBossPoints", ReadLegacyBool(legacyOverrides, "AllowRepeatedBossPoints", rankingRules.AllowRepeatedBossPoints), "Permite pontuar boss repetido."); _cfgEnableSkillPoints = _rulesConfig.BindConfig("General", "EnableSkillPoints", ReadLegacyBool(legacyOverrides, "EnableSkillPoints", rankingRules.EnableSkillPoints), "Ativa jackpots por marcos de skill."); _cfgIgnoreTamedKills = _rulesConfig.BindConfig("General", "IgnoreTamedKills", ReadLegacyBool(legacyOverrides, "IgnoreTamedKills", rankingRules.IgnoreTamedKills), "Ignora pontos por matar criaturas domadas."); _cfgEnableMarketplaceQuestPoints = _rulesConfig.BindConfig("General", "EnableMarketplaceQuestPoints", ReadLegacyBool(legacyOverrides, "EnableMarketplaceQuestPoints", rankingRules.EnableMarketplaceQuestPoints), "Ativa pontuação por conclusão de quests do Marketplace."); _cfgEnableFishingPoints = _rulesConfig.BindConfig("General", "EnableFishingPoints", ReadLegacyBool(legacyOverrides, "EnableFishingPoints", rankingRules.EnableFishingPoints), "Ativa pontuação própria por pesca."); _cfgEnableDeathPenalty = _rulesConfig.BindConfig("General", "EnableDeathPenalty", ReadLegacyBool(legacyOverrides, "EnableDeathPenalty", rankingRules.EnableDeathPenalty), "Ativa penalidade por morte no ranking."); _cfgDebugLogging = _rulesConfig.BindConfig("Logging", "DebugLogging", ReadLegacyBool(legacyOverrides, "DebugLogging", rankingRules.DebugLogging), "Ativa logs de depuração."); _cfgLogHitReports = _rulesConfig.BindConfig("Logging", "LogHitReports", ReadLegacyBool(legacyOverrides, "LogHitReports", rankingRules.LogHitReports), "Ativa logs de hit reports."); _cfgLogKillReports = _rulesConfig.BindConfig("Logging", "LogKillReports", ReadLegacyBool(legacyOverrides, "LogKillReports", rankingRules.LogKillReports), "Ativa logs de kill reports."); _cfgLogSkillReports = _rulesConfig.BindConfig("Logging", "LogSkillReports", ReadLegacyBool(legacyOverrides, "LogSkillReports", rankingRules.LogSkillReports), "Ativa logs de skill reports."); _cfgLogPendingKillReports = _rulesConfig.BindConfig("Logging", "LogPendingKillReports", ReadLegacyBool(legacyOverrides, "LogPendingKillReports", rankingRules.LogPendingKillReports), "Ativa logs das checagens pendentes de kill."); _cfgLogSnapshotRequests = _rulesConfig.BindConfig("Logging", "LogSnapshotRequests", ReadLegacyBool(legacyOverrides, "LogSnapshotRequests", rankingRules.LogSnapshotRequests), "Ativa logs de snapshots do ranking."); _cfgLogPointsChanges = _rulesConfig.BindConfig("Logging", "LogPointsChanges", ReadLegacyBool(legacyOverrides, "LogPointsChanges", rankingRules.LogPointsChanges), "Ativa logs de alterações de pontos."); _cfgRewardClaimsEnabled = _rulesConfig.BindConfig("Rewards", "RewardClaimsEnabled", ReadLegacyBool(legacyOverrides, "RewardClaimsEnabled", rankingRules.RewardClaimsEnabled), "Ativa o resgate de recompensas no HUD."); _cfgRewardClaimCycleId = _rulesConfig.BindConfig("Rewards", "RewardClaimCycleId", ReadLegacyString(legacyOverrides, "RewardClaimCycleId", rankingRules.RewardClaimCycleId), "Identificador do ciclo atual de recompensas."); _cfgRewardTop1MinPoints = _rulesConfig.BindConfig("Rewards", "RewardTop1MinPoints", ReadLegacyInt(legacyOverrides, "RewardTop1MinPoints", rankingRules.RewardTop1MinPoints), "Pontos mínimos para o Top 1 resgatar."); _cfgRewardTop1Label = _rulesConfig.BindConfig("Rewards", "RewardTop1Label", ReadLegacyString(legacyOverrides, "RewardTop1Label", rankingRules.RewardTop1Label), "Texto exibido para a recompensa do Top 1."); _cfgRewardTop1Prefab = _rulesConfig.BindConfig("Rewards", "RewardTop1Prefab", ReadLegacyString(legacyOverrides, "RewardTop1Prefab", rankingRules.RewardTop1Prefab), "Prefab do item entregue ao Top 1."); _cfgRewardTop1Amount = _rulesConfig.BindConfig("Rewards", "RewardTop1Amount", ReadLegacyInt(legacyOverrides, "RewardTop1Amount", rankingRules.RewardTop1Amount), "Quantidade do item entregue ao Top 1."); _cfgRewardTop2MinPoints = _rulesConfig.BindConfig("Rewards", "RewardTop2MinPoints", ReadLegacyInt(legacyOverrides, "RewardTop2MinPoints", rankingRules.RewardTop2MinPoints), "Pontos mínimos para o Top 2 resgatar."); _cfgRewardTop2Label = _rulesConfig.BindConfig("Rewards", "RewardTop2Label", ReadLegacyString(legacyOverrides, "RewardTop2Label", rankingRules.RewardTop2Label), "Texto exibido para a recompensa do Top 2."); _cfgRewardTop2Prefab = _rulesConfig.BindConfig("Rewards", "RewardTop2Prefab", ReadLegacyString(legacyOverrides, "RewardTop2Prefab", rankingRules.RewardTop2Prefab), "Prefab do item entregue ao Top 2."); _cfgRewardTop2Amount = _rulesConfig.BindConfig("Rewards", "RewardTop2Amount", ReadLegacyInt(legacyOverrides, "RewardTop2Amount", rankingRules.RewardTop2Amount), "Quantidade do item entregue ao Top 2."); _cfgRewardTop3MinPoints = _rulesConfig.BindConfig("Rewards", "RewardTop3MinPoints", ReadLegacyInt(legacyOverrides, "RewardTop3MinPoints", rankingRules.RewardTop3MinPoints), "Pontos mínimos para o Top 3 resgatar."); _cfgRewardTop3Label = _rulesConfig.BindConfig("Rewards", "RewardTop3Label", ReadLegacyString(legacyOverrides, "RewardTop3Label", rankingRules.RewardTop3Label), "Texto exibido para a recompensa do Top 3."); _cfgRewardTop3Prefab = _rulesConfig.BindConfig("Rewards", "RewardTop3Prefab", ReadLegacyString(legacyOverrides, "RewardTop3Prefab", rankingRules.RewardTop3Prefab), "Prefab do item entregue ao Top 3."); _cfgRewardTop3Amount = _rulesConfig.BindConfig("Rewards", "RewardTop3Amount", ReadLegacyInt(legacyOverrides, "RewardTop3Amount", rankingRules.RewardTop3Amount), "Quantidade do item entregue ao Top 3."); _cfgPointsExchangeEnabled = _rulesConfig.BindConfig("PointsExchange", "Enabled", ReadLegacyBool(legacyOverrides, "PointsExchangeEnabled", rankingRules.PointsExchangeEnabled), "Ativa o botão de câmbio de pontos por moedas no HUD."); _cfgPointsExchangePrefab = _rulesConfig.BindConfig("PointsExchange", "Prefab", ReadLegacyString(legacyOverrides, "PointsExchangePrefab", rankingRules.PointsExchangePrefab), "Prefab entregue no câmbio de pontos. Exemplo: Coins."); _cfgPointsExchangeCoinsPerPoint = _rulesConfig.BindConfig("PointsExchange", "CoinsPerPoint", ReadLegacyInt(legacyOverrides, "PointsExchangeCoinsPerPoint", rankingRules.PointsExchangeCoinsPerPoint), "Quantidade de moedas entregues por cada ponto trocado."); _cfgPointsExchangeMinPoints = _rulesConfig.BindConfig("PointsExchange", "MinPoints", ReadLegacyInt(legacyOverrides, "PointsExchangeMinPoints", rankingRules.PointsExchangeMinPoints), "Valor legado. O câmbio não exige requisito mínimo; basta o jogador ter pontos disponíveis."); _cfgPointsExchangeMaxPointsPerRequest = _rulesConfig.BindConfig("PointsExchange", "MaxPointsPerRequest", ReadLegacyInt(legacyOverrides, "PointsExchangeMaxPointsPerRequest", rankingRules.PointsExchangeMaxPointsPerRequest), "Máximo de pontos convertidos por clique. Use 0 para trocar todos."); _cfgMarketplaceQuestPointMap = _rulesConfig.BindConfig("MarketplaceQuestPoints", "QuestPointMap", BuildMarketplaceQuestPointMapDefault(legacyOverrides), "Formato: questId:pontos separados por vírgula. Ex: ccq_b21:450,ccq_b22:150"); _cfgDeathPenaltyRules = _rulesConfig.BindConfig("DeathPenalty", "Rules", ReadLegacyString(legacyOverrides, "DeathPenalty.Rules", ReadLegacyString(legacyOverrides, "DeathPenaltyRules", "1:0,2:100,5:300,10:800")), "Penalidade por morte em marcos. Formato: mortes:pontosPerdidos,mortes:pontosPerdidos. Exemplo: 1:0,2:100,5:300,10:800"); _cfgDeathPenaltyUseMultiplier = _rulesConfig.BindConfig("DeathPenalty", "UseMultiplierMode", ReadLegacyBool(legacyOverrides, "DeathPenalty.UseMultiplierMode", ReadLegacyBool(legacyOverrides, "DeathPenaltyUseMultiplier", fallback: false)), "Se true, ignora a tabela Rules e aplica PenaltyPerDeath a cada morte. Exemplo: 15 mortes x 100 = -1500."); _cfgDeathPenaltyPerDeath = _rulesConfig.BindConfig("DeathPenalty", "PenaltyPerDeath", Mathf.Max(0, ReadLegacyInt(legacyOverrides, "DeathPenalty.PenaltyPerDeath", ReadLegacyInt(legacyOverrides, "DeathPenaltyPerDeath", 100))), "Valor perdido por cada morte quando UseMultiplierMode=true."); _cfgEnableExplorationJackpots = _rulesConfig.BindConfig("ExplorationMapJackpots", "Enabled", ReadLegacyBool(legacyOverrides, "ExplorationMapJackpots.Enabled", fallback: true), "Ativa jackpots por porcentagem de mapa revelado."); _cfgExplorationMapJackpotRules = _rulesConfig.BindConfig("ExplorationMapJackpots", "Rules", ReadLegacyString(legacyOverrides, "ExplorationMapJackpots.Rules", ReadLegacyString(legacyOverrides, "ExplorationMapJackpotRules", "5:25;10:50;25:150;50:400;75:800;100:1500")), "Jackpots por porcentagem do mapa revelado. Formato: porcentagem:pontos;porcentagem:pontos. Exemplo: 5:25;10:50;25:150"); BindCombatBiomeRuleEntries(legacyOverrides); _cfgProductionCategoryRules = _rulesConfig.BindConfig("HudCategories", "Production", ReadLegacyString(legacyOverrides, "HudCategories.Production", "Armas:SwordIron=800;Armaduras:HelmetBronze=800;Comidas:DeerStew=25"), "Producao/Conquistas por categoria COM pontos. O nome da categoria do config vira a aba do HUD. Formato obrigatorio: Categoria:Prefab=pontos,Prefab=pontos;Outra:Prefab=pontos. Exemplo: Armas:SwordIron=800;Armaduras:HelmetBronze=800;Comidas:DeerStew=25. Tambem organiza FarmJackpots e UniqueCraftJackpots."); BindPointSectionEntries("BossPoints", "Pontos por bosses e minibosses.", legacyOverrides, _cfgBossPointEntries); BindPointSectionEntries("FishingPoints", "Pontos por peixe pescado.", legacyOverrides, _cfgFishingPointEntries); BindStringPointSectionEntries("SkillMilestoneJackpotPoints", "Pontos únicos por marco de skill. Formato: 20:500,40:1000,60:2000,80:3000,100:4000.", legacyOverrides, _cfgSkillMilestoneJackpotPointEntries); _cfgFarmJackpotRules = _rulesConfig.BindConfig("FarmJackpots", "Rules", ReadGroupedRulesDefault(legacyOverrides, "FarmJackpots", "Carrot:200:1000;Turnip:200:1200;Onion:200:1500;Barley:500:2000;Flax:500:2000"), "Jackpots de colheita. Edite somente esta linha. Formato: Prefab:quantidade:pontos;Prefab:quantidade:pontos. Exemplo: Carrot:200:1000;Barley:500:2000."); _cfgUniqueCraftJackpotRules = _rulesConfig.BindConfig("UniqueCraftJackpots", "Rules", ReadGroupedRulesDefault(legacyOverrides, "UniqueCraftJackpots", "SwordIron:1:800;SwordSilver:1:1500;SwordBlackmetal:1:2500;ArmorWolfChest:1:2000;ArmorCarapaceChest:1:3500"), "Jackpot único por craft. Edite somente esta linha. Formato: Prefab:quantidade:pontos;Prefab:quantidade:pontos. Exemplo: SwordIron:1:800;ArmorWolfChest:1:2000."); } } private void BindCombatBiomeRuleEntries(Dictionary legacyOverrides) { if (_cfgCombatBiomeRuleEntries != null) { _cfgCombatBiomeRuleEntries.Clear(); Dictionary defaults = ParseCombatBiomeDefaults("Prados:Boar:1,Deer:1,Neck:1;Floresta Negra:Greydwarf:1,Greydwarf_Elite:2,Greydwarf_Shaman:2,Troll:5;Pântano:Draugr:2,Draugr_Elite:3,Blob:2,Abomination:8;Montanha:Wolf:2,Hatchling:2,StoneGolem:8;Planícies:Goblin:3,GoblinBrute:5,Lox:6,Deathsquito:3;Oceano:Serpent:6;Mistlands:Seeker:4,SeekerBrute:8,Gjall:10;Ashlands:Charred_Melee:4,Charred_Archer:4,Volture:4;Especiais:Haldor:0"); BindSingleCombatBiome("Prados", defaults, legacyOverrides); BindSingleCombatBiome("Floresta Negra", defaults, legacyOverrides); BindSingleCombatBiome("Pântano", defaults, legacyOverrides); BindSingleCombatBiome("Montanha", defaults, legacyOverrides); BindSingleCombatBiome("Planícies", defaults, legacyOverrides); BindSingleCombatBiome("Oceano", defaults, legacyOverrides); BindSingleCombatBiome("Mistlands", defaults, legacyOverrides); BindSingleCombatBiome("Ashlands", defaults, legacyOverrides); BindSingleCombatBiome("Especiais", defaults, legacyOverrides); } } private void BindSingleCombatBiome(string category, Dictionary defaults, Dictionary legacyOverrides) { if (defaults == null || !defaults.TryGetValue(category, out var value)) { value = string.Empty; } string value2 = ReadLegacyString(legacyOverrides, "Combat." + category, value); _cfgCombatBiomeRuleEntries[category] = _rulesConfig.BindConfig("Combat", category, value2, "Mobs e pontos para esta aba do HUD. Formato: Prefab;Pontos,OutroPrefab;Pontos. Exemplo: Boar;2,Deer;3. Aceita qualquer prefab, inclusive de mods. O nome desta chave vira a categoria no HUD."); } private Dictionary ParseCombatBiomeDefaults(string raw) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[3] { ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : string.Empty); if (string.IsNullOrWhiteSpace(text2)) { continue; } int num = text2.IndexOf(':'); if (num <= 0 || num >= text2.Length - 1) { continue; } string text3 = NormalizeHudCategoryName(text2.Substring(0, num).Trim()); string text4 = text2.Substring(num + 1).Trim(); if (string.IsNullOrWhiteSpace(text3) || string.IsNullOrWhiteSpace(text4)) { continue; } List list = new List(); string[] array3 = text4.Split(new char[2] { ',', '|' }, StringSplitOptions.RemoveEmptyEntries); string[] array4 = array3; foreach (string itemRaw in array4) { if (TryParseCombatBiomeItem(itemRaw, out var prefab, out var points)) { list.Add(prefab + ";" + Mathf.Max(0, points)); } } dictionary[text3] = string.Join(",", list.ToArray()); } return dictionary; } private string BuildCombatCategoryRulesFromBiomeEntries() { if (_cfgCombatBiomeRuleEntries == null || _cfgCombatBiomeRuleEntries.Count == 0) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair> cfgCombatBiomeRuleEntry in _cfgCombatBiomeRuleEntries) { if (cfgCombatBiomeRuleEntry.Value == null) { continue; } string value = NormalizeHudCategoryName(cfgCombatBiomeRuleEntry.Key); if (string.IsNullOrWhiteSpace(value)) { continue; } string value2 = ConvertCombatBiomeItemsToHudCategoryItems(cfgCombatBiomeRuleEntry.Value.Value); if (!string.IsNullOrWhiteSpace(value2)) { if (stringBuilder.Length > 0) { stringBuilder.Append(';'); } stringBuilder.Append(value); stringBuilder.Append(':'); stringBuilder.Append(value2); } } return stringBuilder.ToString(); } private string ConvertCombatBiomeItemsToHudCategoryItems(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return string.Empty; } List list = new List(); string[] array = raw.Split(new char[4] { ',', '|', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string itemRaw in array2) { if (TryParseCombatBiomeItem(itemRaw, out var prefab, out var points)) { list.Add(prefab + ":" + Mathf.Max(0, points)); } } return string.Join(",", list.ToArray()); } private bool TryParseCombatBiomeItem(string itemRaw, out string prefab, out int points) { prefab = string.Empty; points = 0; if (string.IsNullOrWhiteSpace(itemRaw)) { return false; } string text = itemRaw.Trim(); int num = text.LastIndexOf(';'); if (num <= 0) { num = text.LastIndexOf('='); } if (num <= 0) { num = text.LastIndexOf(':'); } if (num <= 0 || num >= text.Length - 1) { return false; } string value = text.Substring(0, num).Trim(); string s = text.Substring(num + 1).Trim(); if (!int.TryParse(s, out var result)) { return false; } prefab = SafeKey(value); points = Mathf.Max(0, result); return !string.IsNullOrWhiteSpace(prefab); } private void RewriteRulesConfigHeaderAndGroupedSections() { try { if (string.IsNullOrWhiteSpace(_rulesFilePath) || !File.Exists(_rulesFilePath)) { return; } string[] array = File.ReadAllLines(_rulesFilePath, Encoding.UTF8); List list = new List(array.Length + 40); string a = string.Empty; bool flag = false; HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase) { "KillPoints", "CraftPoints", "FarmJackpots", "UniqueCraftJackpots", "DeathPenalty", "ExplorationMapJackpots" }; list.Add("## Glitnir Ranking - Regras de pontuação"); list.Add("##"); list.Add("## Edite este arquivo no servidor. As regras marcadas como synced são enviadas aos clientes."); list.Add("##"); list.Add("## Combate fica em [Combat], uma chave por bioma/categoria, exatamente igual ao HUD."); list.Add("## [Combat]"); list.Add("## Prados = Boar;2,Deer;3"); list.Add("## Floresta Negra = Troll;20,Greydwarf;1"); list.Add("## Pântano = Draugr;2,Blob;2"); list.Add("## [UniqueCraftJackpots] Rules = Prefab:quantidade:pontos;Prefab:quantidade:pontos"); list.Add("## [DeathPenalty] Rules = mortes:pontosPerdidos,mortes:pontosPerdidos"); list.Add("## [ExplorationMapJackpots] Rules = porcentagem:pontos;porcentagem:pontos"); list.Add("##"); list.Add("## Exemplos de prefabs reais comuns:"); list.Add("## Carrot:200:1000"); list.Add("## SwordIron:1:800"); list.Add("## ArmorWolfChest:1:2000"); list.Add("## 1:0,2:100,5:300,10:800"); list.Add("##"); list.Add("## Importante: se um item não pontuar, ative DebugLogging/LogPointsChanges e veja no log"); list.Add("## o prefab detectado pelo ranking no momento do kill, craft ou colheita."); list.Add(""); bool flag2 = false; bool flag3 = false; bool flag4 = false; bool flag5 = false; string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : string.Empty); if (text2.StartsWith("## Glitnir Ranking - Regras de pontuação", StringComparison.OrdinalIgnoreCase) || (string.Equals(a, "HudCategories", StringComparison.OrdinalIgnoreCase) && text2.StartsWith("Combat", StringComparison.OrdinalIgnoreCase) && text2.IndexOf('=') > 0)) { continue; } if (text2.StartsWith("[") && text2.EndsWith("]")) { string text3 = text2.Substring(1, text2.Length - 2).Trim(); flag = hashSet.Contains(text3); a = text3; if (flag) { if (text3.Equals("FarmJackpots", StringComparison.OrdinalIgnoreCase) && !flag2) { AppendGroupedFarmSection(list); flag2 = true; } else if (text3.Equals("UniqueCraftJackpots", StringComparison.OrdinalIgnoreCase) && !flag3) { AppendGroupedUniqueCraftSection(list); flag3 = true; } else if (text3.Equals("DeathPenalty", StringComparison.OrdinalIgnoreCase) && !flag4) { AppendGroupedDeathPenaltySection(list); flag4 = true; } else if (text3.Equals("ExplorationMapJackpots", StringComparison.OrdinalIgnoreCase) && !flag5) { AppendGroupedExplorationMapSection(list); flag5 = true; } } else { list.Add(text); } } else if (!flag) { list.Add(text); } } if (!flag2) { AppendGroupedFarmSection(list); } if (!flag3) { AppendGroupedUniqueCraftSection(list); } if (!flag4) { AppendGroupedDeathPenaltySection(list); } if (!flag5) { AppendGroupedExplorationMapSection(list); } File.WriteAllLines(_rulesFilePath, list.ToArray(), Encoding.UTF8); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao organizar config do ranking: " + ex.Message)); } } private void AppendGroupedFarmSection(List lines) { lines.Add(""); lines.Add("[FarmJackpots]"); lines.Add(""); lines.Add("## Jackpot de colheita por prefab configurado."); lines.Add("## Formato: Prefab:quantidade:pontos;Prefab:quantidade:pontos"); lines.Add("## Exemplo: Carrot:200:1000;Barley:500:2000"); lines.Add("Rules = " + ((_cfgFarmJackpotRules != null) ? SanitizeDelimitedJackpotRules(_cfgFarmJackpotRules.Value) : "Carrot:200:1000;Barley:500:2000")); } private void AppendGroupedUniqueCraftSection(List lines) { lines.Add(""); lines.Add("[UniqueCraftJackpots]"); lines.Add(""); lines.Add("## Jackpot único por craft de qualquer prefab configurado."); lines.Add("## Formato: Prefab:quantidade:pontos;Prefab:quantidade:pontos"); lines.Add("## Exemplo: SwordIron:1:800;ArmorWolfChest:1:2000"); lines.Add("Rules = " + ((_cfgUniqueCraftJackpotRules != null) ? SanitizeDelimitedJackpotRules(_cfgUniqueCraftJackpotRules.Value) : "SwordIron:1:800;ArmorWolfChest:1:2000")); } private void AppendGroupedDeathPenaltySection(List lines) { lines.Add(""); lines.Add("[DeathPenalty]"); lines.Add(""); lines.Add("## Penalidade por morte."); lines.Add("## UseMultiplierMode=false usa a tabela Rules abaixo."); lines.Add("## UseMultiplierMode=true ignora Rules e aplica PenaltyPerDeath para cada morte."); lines.Add("## Exemplo multiplicador: PenaltyPerDeath=100 e 15 mortes = -1500 pontos."); lines.Add("UseMultiplierMode = " + ((_cfgDeathPenaltyUseMultiplier != null) ? _cfgDeathPenaltyUseMultiplier.Value.ToString() : "false")); lines.Add("PenaltyPerDeath = " + ((_cfgDeathPenaltyPerDeath != null) ? Mathf.Max(0, _cfgDeathPenaltyPerDeath.Value).ToString() : "100")); lines.Add(""); lines.Add("## Formato do modo tabela: mortes:pontosPerdidos,mortes:pontosPerdidos"); lines.Add("## Exemplo: 1:0,2:100,5:300,10:800"); lines.Add("Rules = " + ((_cfgDeathPenaltyRules != null) ? SanitizeDeathPenaltyRules(_cfgDeathPenaltyRules.Value) : "1:0,2:100,5:300,10:800")); } private void AppendGroupedExplorationMapSection(List lines) { lines.Add(""); lines.Add("[ExplorationMapJackpots]"); lines.Add(""); lines.Add("## Jackpot por porcentagem de mapa revelado."); lines.Add("## Formato: porcentagem:pontos;porcentagem:pontos"); lines.Add("## Exemplo: 5:25;10:50;25:150;50:400;75:800;100:1500"); lines.Add("Enabled = " + ((_cfgEnableExplorationJackpots != null) ? _cfgEnableExplorationJackpots.Value.ToString() : "true")); lines.Add("Rules = " + ((_cfgExplorationMapJackpotRules != null) ? _cfgExplorationMapJackpotRules.Value : "5:25;10:50;25:150;50:400;75:800;100:1500")); } private void CleanupFishKillPointConfigEntries() { try { if (string.IsNullOrWhiteSpace(_rulesFilePath) || !File.Exists(_rulesFilePath)) { return; } string[] array = File.ReadAllLines(_rulesFilePath, Encoding.UTF8); List list = new List(array.Length); bool flag = false; bool flag2 = false; string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : string.Empty); if (text2.StartsWith("[") && text2.EndsWith("]")) { flag = text2.Equals("[KillPoints]", StringComparison.OrdinalIgnoreCase); } int num = text2.IndexOf('='); if (num > 0) { string text3 = text2.Substring(0, num).Trim(); string text4 = text3; if (text3.StartsWith("KillPoints.", StringComparison.OrdinalIgnoreCase)) { text4 = text3.Substring("KillPoints.".Length).Trim(); } else if (!flag) { text4 = null; } if (!string.IsNullOrWhiteSpace(text4) && IsFishPrefab(text4)) { flag2 = true; continue; } } list.Add(text); } if (flag2) { File.WriteAllLines(_rulesFilePath, list.ToArray(), Encoding.UTF8); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao limpar prefabs de peixe do config: " + ex.Message)); } } private void CleanupGroupedProductionConfigEntries() { try { if (string.IsNullOrWhiteSpace(_rulesFilePath) || !File.Exists(_rulesFilePath)) { return; } string[] array = File.ReadAllLines(_rulesFilePath, Encoding.UTF8); List list = new List(array.Length); string text = string.Empty; bool flag = false; HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase) { "KillPoints", "CraftPoints", "FarmJackpots", "UniqueCraftJackpots", "DeathPenalty", "ExplorationMapJackpots" }; string[] array2 = array; foreach (string text2 in array2) { string text3 = ((text2 != null) ? text2.Trim() : string.Empty); if (text3.StartsWith("[") && text3.EndsWith("]")) { text = text3.Substring(1, text3.Length - 2).Trim(); list.Add(text2); continue; } int num = text3.IndexOf('='); if (num > 0 && hashSet.Contains(text)) { string text4 = text3.Substring(0, num).Trim(); bool flag2 = text4.Equals("Rules", StringComparison.OrdinalIgnoreCase); if (text.Equals("DeathPenalty", StringComparison.OrdinalIgnoreCase)) { flag2 = flag2 || text4.Equals("UseMultiplierMode", StringComparison.OrdinalIgnoreCase) || text4.Equals("PenaltyPerDeath", StringComparison.OrdinalIgnoreCase); } else if (text.Equals("ExplorationMapJackpots", StringComparison.OrdinalIgnoreCase)) { flag2 = flag2 || text4.Equals("Enabled", StringComparison.OrdinalIgnoreCase); } if (!flag2) { flag = true; continue; } } list.Add(text2); } if (flag) { File.WriteAllLines(_rulesFilePath, list.ToArray(), Encoding.UTF8); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao reorganizar config de produção: " + ex.Message)); } } private string BuildMarketplaceQuestPointMapDefault(Dictionary legacyOverrides) { string text = ReadLegacyString(legacyOverrides, "MarketplaceQuestPoints.QuestPointMap", null); if (!string.IsNullOrWhiteSpace(text)) { return SanitizeMarketplaceQuestPointMap(text); } text = ReadLegacyString(legacyOverrides, "QuestPointMap", null); if (!string.IsNullOrWhiteSpace(text)) { return SanitizeMarketplaceQuestPointMap(text); } Dictionary mergedDefaultPointEntries = GetMergedDefaultPointEntries("MarketplaceQuestPoints", legacyOverrides); if (mergedDefaultPointEntries.Count <= 0) { return "ccq_b21:450,ccq_b22:150"; } return string.Join(",", from p in mergedDefaultPointEntries.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase) select SafeMarketplaceQuestKey(p.Key) + ":" + Mathf.Max(0, p.Value)); } private Dictionary ParseMarketplaceQuestPointMap(string raw) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : string.Empty); if (string.IsNullOrWhiteSpace(text2)) { continue; } string[] array3 = text2.Split(new char[1] { ':' }, 2, StringSplitOptions.None); if (array3.Length == 2) { string text3 = SafeMarketplaceQuestKey(array3[0]); if (!string.IsNullOrWhiteSpace(text3) && int.TryParse(array3[1].Trim(), out var result)) { dictionary[text3] = result; } } } return dictionary; } private string SanitizeMarketplaceQuestPointMap(string raw) { Dictionary dictionary = ParseMarketplaceQuestPointMap(raw); if (dictionary.Count <= 0) { return string.Empty; } return string.Join(",", from p in dictionary.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase) select p.Key + ":" + Mathf.Max(0, p.Value)); } private Dictionary ParseSkillMilestoneMap(string raw) { Dictionary dictionary = new Dictionary(); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : string.Empty); if (!string.IsNullOrWhiteSpace(text2)) { string[] array3 = text2.Split(new char[1] { ':' }, 2, StringSplitOptions.None); if (array3.Length == 2 && int.TryParse(array3[0].Trim(), out var result) && int.TryParse(array3[1].Trim(), out var result2)) { result = Mathf.Clamp(result, 1, 100); dictionary[result] = Mathf.Max(0, result2); } } } return dictionary; } private string SanitizeSkillMilestoneMap(string raw) { Dictionary dictionary = ParseSkillMilestoneMap(raw); if (dictionary.Count <= 0) { return string.Empty; } return string.Join(",", from p in dictionary orderby p.Key select p.Key + ":" + Mathf.Max(0, p.Value)); } private JackpotRule ParseJackpotRule(string raw) { JackpotRule jackpotRule = new JackpotRule(); if (string.IsNullOrWhiteSpace(raw)) { return jackpotRule; } string[] array = raw.Split(new char[1] { ':' }, 2, StringSplitOptions.None); if (array.Length != 2) { return jackpotRule; } if (!int.TryParse(array[0].Trim(), out var result)) { return jackpotRule; } if (!int.TryParse(array[1].Trim(), out var result2)) { return jackpotRule; } jackpotRule.RequiredAmount = Mathf.Max(1, result); jackpotRule.Points = Mathf.Max(0, result2); return jackpotRule; } private string SanitizeJackpotRule(string raw) { JackpotRule jackpotRule = ParseJackpotRule(raw); if (jackpotRule == null || jackpotRule.RequiredAmount <= 0) { return "1:0"; } return jackpotRule.RequiredAmount + ":" + Mathf.Max(0, jackpotRule.Points); } private string StripHudCategoryPointPart(string itemRaw) { if (string.IsNullOrWhiteSpace(itemRaw)) { return ""; } string text = itemRaw.Trim(); int num = text.IndexOf('='); if (num > 0) { text = text.Substring(0, num).Trim(); } int num2 = text.LastIndexOf(':'); if (num2 > 0 && num2 < text.Length - 1) { string s = text.Substring(num2 + 1).Trim(); if (int.TryParse(s, out var _)) { text = text.Substring(0, num2).Trim(); } } return SafeKey(text); } private bool TryParseHudCategoryPointItem(string itemRaw, out string prefab, out int points) { prefab = ""; points = 0; if (string.IsNullOrWhiteSpace(itemRaw)) { return false; } string text = itemRaw.Trim(); int num = text.LastIndexOf('='); if (num <= 0) { num = text.LastIndexOf(':'); } if (num <= 0 || num >= text.Length - 1) { return false; } string value = text.Substring(0, num).Trim(); string s = text.Substring(num + 1).Trim(); if (!int.TryParse(s, out var result)) { return false; } prefab = SafeKey(value); points = Mathf.Max(0, result); return !string.IsNullOrWhiteSpace(prefab); } private Dictionary ParseHudCategoryRules(string raw) { ParseHudCategorizedPointRules(raw, out var categories); return categories; } private static string NormalizeHudCategoryName(string category) { if (string.IsNullOrWhiteSpace(category)) { return category; } string text = category.Trim(); if (text.Equals("Arcos e Munições", StringComparison.OrdinalIgnoreCase) || text.Equals("Arcos e Municoes", StringComparison.OrdinalIgnoreCase) || text.Equals("Armas, Armaduras e Munições", StringComparison.OrdinalIgnoreCase) || text.Equals("Armas, Armaduras e Municoes", StringComparison.OrdinalIgnoreCase)) { return "Armas"; } if (text.Equals("Comidas e Consumíveis", StringComparison.OrdinalIgnoreCase) || text.Equals("Comidas e Consumiveis", StringComparison.OrdinalIgnoreCase) || text.Equals("Comidas e bebidas", StringComparison.OrdinalIgnoreCase)) { return "Comidas"; } return text; } private Dictionary ParseHudCategorizedPointRules(string raw, out Dictionary categories) { categories = new Dictionary(StringComparer.OrdinalIgnoreCase); Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[3] { ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : ""); if (string.IsNullOrWhiteSpace(text2)) { continue; } int num = text2.IndexOf(':'); if (num <= 0 || num >= text2.Length - 1) { continue; } string value = NormalizeHudCategoryName(text2.Substring(0, num).Trim()); if (string.IsNullOrWhiteSpace(value)) { continue; } string text3 = text2.Substring(num + 1); string[] array3 = text3.Split(new char[2] { ',', '|' }, StringSplitOptions.RemoveEmptyEntries); string[] array4 = array3; foreach (string itemRaw in array4) { string text4 = StripHudCategoryPointPart(itemRaw); if (!string.IsNullOrWhiteSpace(text4)) { categories[text4] = value; if (TryParseHudCategoryPointItem(itemRaw, out var prefab, out var points)) { dictionary[prefab] = points; } } } } return dictionary; } private Dictionary ParseDelimitedPointRules(string raw) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[4] { ';', ',', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : string.Empty); if (string.IsNullOrWhiteSpace(text2)) { continue; } string[] array3 = text2.Split(new char[1] { ':' }, 2, StringSplitOptions.None); if (array3.Length == 2) { string text3 = SafeKey(array3[0]); if (!string.IsNullOrWhiteSpace(text3) && int.TryParse(array3[1].Trim(), out var result)) { dictionary[text3] = Mathf.Max(0, result); } } } return dictionary; } private Dictionary ParseDelimitedJackpotRules(string raw) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[4] { ';', ',', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : string.Empty); if (string.IsNullOrWhiteSpace(text2)) { continue; } string[] array3 = text2.Split(new char[1] { ':' }, 3, StringSplitOptions.None); if (array3.Length == 3) { string text3 = SafeKey(array3[0]); if (!string.IsNullOrWhiteSpace(text3) && int.TryParse(array3[1].Trim(), out var result) && int.TryParse(array3[2].Trim(), out var result2)) { dictionary[text3] = new JackpotRule { RequiredAmount = Mathf.Max(1, result), Points = Mathf.Max(0, result2) }; } } } return dictionary; } private Dictionary ParseDeathPenaltyRules(string raw) { Dictionary dictionary = new Dictionary(); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[4] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = ((text != null) ? text.Trim() : string.Empty); if (!string.IsNullOrWhiteSpace(text2)) { string[] array3 = text2.Split(new char[1] { ':' }, 2, StringSplitOptions.None); if (array3.Length == 2 && int.TryParse(array3[0].Trim(), out var result) && int.TryParse(array3[1].Trim(), out var result2)) { result = Mathf.Max(1, result); result2 = (dictionary[result] = Mathf.Max(0, result2)); } } } return dictionary; } private string SanitizeDeathPenaltyRules(string raw) { Dictionary dictionary = ParseDeathPenaltyRules(raw); if (dictionary.Count <= 0) { return string.Empty; } return string.Join(",", from p in dictionary orderby p.Key select Mathf.Max(1, p.Key) + ":" + Mathf.Max(0, p.Value)); } private string SanitizeDelimitedPointRules(string raw) { return SanitizeDelimitedPointRules(raw, ";"); } private string SanitizeDelimitedPointRules(string raw, string delimiter) { Dictionary dictionary = ParseDelimitedPointRules(raw); if (dictionary.Count <= 0) { return string.Empty; } if (string.IsNullOrEmpty(delimiter)) { delimiter = ";"; } return string.Join(delimiter, from p in dictionary.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase) where !IsFishPrefab(p.Key) select p.Key + ":" + Mathf.Max(0, p.Value)); } private string SanitizeDelimitedJackpotRules(string raw) { Dictionary dictionary = ParseDelimitedJackpotRules(raw); if (dictionary.Count <= 0) { return string.Empty; } return string.Join(";", from p in dictionary.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase) select p.Key + ":" + Mathf.Max(1, p.Value.RequiredAmount) + ":" + Mathf.Max(0, p.Value.Points)); } private string ReadGroupedRulesDefault(Dictionary legacyOverrides, string section, string fallback) { string text = ReadLegacyString(legacyOverrides, section + ".Rules", null); if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } text = ReadLegacyString(legacyOverrides, "Rules", null); if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } return fallback; } private string BuildDelimitedPointRulesDefault(string section, Dictionary legacyOverrides, string fallback) { string text = ReadLegacyString(legacyOverrides, section + ".Rules", null); if (!string.IsNullOrWhiteSpace(text)) { return SanitizeDelimitedPointRules(text); } Dictionary mergedDefaultPointEntries = GetMergedDefaultPointEntries(section, legacyOverrides); if (mergedDefaultPointEntries.Count <= 0) { return fallback; } return string.Join(";", from p in mergedDefaultPointEntries.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase) select SafeKey(p.Key) + ":" + Mathf.Max(0, p.Value)); } private string BuildDelimitedJackpotRulesDefault(string section, Dictionary legacyOverrides, string fallback) { string text = ReadLegacyString(legacyOverrides, section + ".Rules", null); if (!string.IsNullOrWhiteSpace(text)) { return SanitizeDelimitedJackpotRules(text); } Dictionary mergedDefaultStringEntries = GetMergedDefaultStringEntries(section, legacyOverrides); if (mergedDefaultStringEntries.Count <= 0) { return fallback; } List list = new List(); foreach (KeyValuePair item in mergedDefaultStringEntries.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase)) { if (!item.Key.Equals("Rules", StringComparison.OrdinalIgnoreCase)) { JackpotRule jackpotRule = ParseJackpotRule(item.Value); if (jackpotRule != null && jackpotRule.RequiredAmount > 0) { list.Add(SafeKey(item.Key) + ":" + Mathf.Max(1, jackpotRule.RequiredAmount) + ":" + Mathf.Max(0, jackpotRule.Points)); } } } return (list.Count > 0) ? string.Join(";", list) : fallback; } private void BindPointSectionEntries(string prefix, string descriptionPrefix, Dictionary legacyOverrides, Dictionary> target) { Dictionary mergedDefaultPointEntries = GetMergedDefaultPointEntries(prefix, legacyOverrides); List list = new List(target.Keys); foreach (string item in list) { if (!mergedDefaultPointEntries.ContainsKey(item)) { mergedDefaultPointEntries[item] = target[item].Value; } } foreach (KeyValuePair item2 in mergedDefaultPointEntries.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase)) { string text = SafeKey(item2.Key); if (!string.IsNullOrWhiteSpace(text) && (!prefix.Equals("KillPoints", StringComparison.OrdinalIgnoreCase) || !IsFishPrefab(text)) && (!prefix.Equals("FishingPoints", StringComparison.OrdinalIgnoreCase) || IsFishPrefab(text)) && !target.TryGetValue(text, out var value)) { value = (target[text] = _rulesConfig.BindConfig(prefix, text, item2.Value, descriptionPrefix + " Chave: " + text)); } } } private void BindStringPointSectionEntries(string prefix, string descriptionPrefix, Dictionary legacyOverrides, Dictionary> target) { Dictionary mergedDefaultStringEntries = GetMergedDefaultStringEntries(prefix, legacyOverrides); List list = new List(target.Keys); foreach (string item in list) { if (!mergedDefaultStringEntries.ContainsKey(item)) { mergedDefaultStringEntries[item] = target[item].Value; } } foreach (KeyValuePair item2 in mergedDefaultStringEntries.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase)) { string text = SafeKey(item2.Key); if (!string.IsNullOrWhiteSpace(text) && !target.TryGetValue(text, out var value)) { value = (target[text] = _rulesConfig.BindConfig(prefix, text, SanitizeSkillMilestoneMap(item2.Value), descriptionPrefix + " Chave: " + text)); } } } private void BindGenericJackpotSectionEntries(string prefix, string descriptionPrefix, Dictionary legacyOverrides, Dictionary> target) { Dictionary mergedDefaultStringEntries = GetMergedDefaultStringEntries(prefix, legacyOverrides); List list = new List(target.Keys); foreach (string item in list) { if (!mergedDefaultStringEntries.ContainsKey(item)) { mergedDefaultStringEntries[item] = target[item].Value; } } foreach (KeyValuePair item2 in mergedDefaultStringEntries.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.OrdinalIgnoreCase)) { string text = SafeKey(item2.Key); if (!string.IsNullOrWhiteSpace(text) && !target.TryGetValue(text, out var value)) { value = (target[text] = _rulesConfig.BindConfig(prefix, text, SanitizeJackpotRule(item2.Value), descriptionPrefix + " Chave: " + text)); } } } private Dictionary GetMergedDefaultStringEntries(string prefix, Dictionary legacyOverrides) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair item in ParseRuleTemplate(BuildDefaultRulesFileContents())) { if (item.Key.StartsWith(prefix + ".", StringComparison.OrdinalIgnoreCase)) { string text = SafeKey(item.Key.Substring(prefix.Length + 1)); if (!string.IsNullOrWhiteSpace(text)) { dictionary[text] = item.Value; } } } foreach (KeyValuePair legacyOverride in legacyOverrides) { if (legacyOverride.Key.StartsWith(prefix + ".", StringComparison.OrdinalIgnoreCase)) { string text2 = SafeKey(legacyOverride.Key.Substring(prefix.Length + 1)); if (!string.IsNullOrWhiteSpace(text2)) { dictionary[text2] = legacyOverride.Value; } } } return dictionary; } private Dictionary GetMergedDefaultPointEntries(string prefix, Dictionary legacyOverrides) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair item in ParseRuleTemplate(BuildDefaultRulesFileContents())) { if (!item.Key.StartsWith(prefix + ".", StringComparison.OrdinalIgnoreCase)) { continue; } string text = SafeKey(item.Key.Substring(prefix.Length + 1)); if (!string.IsNullOrWhiteSpace(text) && (!prefix.Equals("KillPoints", StringComparison.OrdinalIgnoreCase) || !IsFishPrefab(text)) && (!prefix.Equals("FishingPoints", StringComparison.OrdinalIgnoreCase) || IsFishPrefab(text))) { if (!int.TryParse(item.Value, out var result)) { result = 0; } dictionary[text] = result; } } foreach (KeyValuePair legacyOverride in legacyOverrides) { if (legacyOverride.Key.StartsWith(prefix + ".", StringComparison.OrdinalIgnoreCase)) { string text2 = SafeKey(legacyOverride.Key.Substring(prefix.Length + 1)); if (!string.IsNullOrWhiteSpace(text2) && (!prefix.Equals("KillPoints", StringComparison.OrdinalIgnoreCase) || !IsFishPrefab(text2)) && (!prefix.Equals("FishingPoints", StringComparison.OrdinalIgnoreCase) || IsFishPrefab(text2)) && int.TryParse(legacyOverride.Value, out var result2)) { dictionary[text2] = result2; } } } return dictionary; } private Dictionary ParseRuleTemplate(string contents) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(contents)) { return dictionary; } using (StringReader stringReader = new StringReader(contents)) { string text; while ((text = stringReader.ReadLine()) != null) { string text2 = text.Trim(); if (string.IsNullOrWhiteSpace(text2) || text2.StartsWith("#") || text2.StartsWith(";") || text2.StartsWith("//")) { continue; } int num = text2.IndexOf('='); if (num > 0) { string text3 = text2.Substring(0, num).Trim(); string value = text2.Substring(num + 1).Trim(); if (!string.IsNullOrWhiteSpace(text3)) { dictionary[text3] = value; } } } } return dictionary; } private bool ReadLegacyBool(Dictionary values, string key, bool fallback) { string value; return (values != null && values.TryGetValue(key, out value)) ? ParseBool(value, fallback) : fallback; } private int ReadLegacyInt(Dictionary values, string key, int fallback) { string value; return (values != null && values.TryGetValue(key, out value)) ? ParseInt(value, fallback) : fallback; } private string ReadLegacyString(Dictionary values, string key, string fallback) { if (values != null && values.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value)) { return value; } return fallback; } private void ApplyRulesFromSyncedConfig() { if (_rulesConfig == null) { return; } RankingRules rankingRules = new RankingRules(); if (_cfgRankingEnabled != null) { rankingRules.RankingEnabled = _cfgRankingEnabled.Value; } if (_cfgEnableKillPoints != null) { rankingRules.EnableKillPoints = _cfgEnableKillPoints.Value; } if (_cfgEnableBossPoints != null) { rankingRules.EnableBossPoints = _cfgEnableBossPoints.Value; } if (_cfgDefaultKillPoints != null) { rankingRules.DefaultKillPoints = Mathf.Max(0, _cfgDefaultKillPoints.Value); } if (_cfgTopCount != null) { rankingRules.TopCount = Mathf.Clamp(_cfgTopCount.Value, 1, 50); } if (_cfgAllowRepeatedBossPoints != null) { rankingRules.AllowRepeatedBossPoints = _cfgAllowRepeatedBossPoints.Value; } if (_cfgDebugLogging != null) { rankingRules.DebugLogging = _cfgDebugLogging.Value; } if (_cfgLogHitReports != null) { rankingRules.LogHitReports = _cfgLogHitReports.Value; } if (_cfgLogKillReports != null) { rankingRules.LogKillReports = _cfgLogKillReports.Value; } if (_cfgLogSkillReports != null) { rankingRules.LogSkillReports = _cfgLogSkillReports.Value; } if (_cfgLogPendingKillReports != null) { rankingRules.LogPendingKillReports = _cfgLogPendingKillReports.Value; } if (_cfgLogSnapshotRequests != null) { rankingRules.LogSnapshotRequests = _cfgLogSnapshotRequests.Value; } if (_cfgLogPointsChanges != null) { rankingRules.LogPointsChanges = _cfgLogPointsChanges.Value; } if (_cfgEnableSkillPoints != null) { rankingRules.EnableSkillPoints = _cfgEnableSkillPoints.Value; } if (_cfgIgnoreTamedKills != null) { rankingRules.IgnoreTamedKills = _cfgIgnoreTamedKills.Value; } if (_cfgEnableMarketplaceQuestPoints != null) { rankingRules.EnableMarketplaceQuestPoints = _cfgEnableMarketplaceQuestPoints.Value; } if (_cfgEnableFishingPoints != null) { rankingRules.EnableFishingPoints = _cfgEnableFishingPoints.Value; } if (_cfgEnableDeathPenalty != null) { rankingRules.EnableDeathPenalty = _cfgEnableDeathPenalty.Value; } if (_cfgDeathPenaltyUseMultiplier != null) { rankingRules.DeathPenaltyUseMultiplier = _cfgDeathPenaltyUseMultiplier.Value; } if (_cfgDeathPenaltyPerDeath != null) { rankingRules.DeathPenaltyPerDeath = Mathf.Max(0, _cfgDeathPenaltyPerDeath.Value); } if (_cfgEnableExplorationJackpots != null) { rankingRules.EnableExplorationJackpots = _cfgEnableExplorationJackpots.Value; } if (_cfgRewardClaimsEnabled != null) { rankingRules.RewardClaimsEnabled = _cfgRewardClaimsEnabled.Value; } if (_cfgRewardClaimCycleId != null) { rankingRules.RewardClaimCycleId = SafeLimit(_cfgRewardClaimCycleId.Value, 64); } if (_cfgRewardTop1MinPoints != null) { rankingRules.RewardTop1MinPoints = Mathf.Max(0, _cfgRewardTop1MinPoints.Value); } if (_cfgRewardTop1Label != null) { rankingRules.RewardTop1Label = SafeLimit(_cfgRewardTop1Label.Value, 96); } if (_cfgRewardTop1Prefab != null) { rankingRules.RewardTop1Prefab = SafeLimit(_cfgRewardTop1Prefab.Value, 96); } if (_cfgRewardTop1Amount != null) { rankingRules.RewardTop1Amount = Mathf.Max(0, _cfgRewardTop1Amount.Value); } if (_cfgRewardTop2MinPoints != null) { rankingRules.RewardTop2MinPoints = Mathf.Max(0, _cfgRewardTop2MinPoints.Value); } if (_cfgRewardTop2Label != null) { rankingRules.RewardTop2Label = SafeLimit(_cfgRewardTop2Label.Value, 96); } if (_cfgRewardTop2Prefab != null) { rankingRules.RewardTop2Prefab = SafeLimit(_cfgRewardTop2Prefab.Value, 96); } if (_cfgRewardTop2Amount != null) { rankingRules.RewardTop2Amount = Mathf.Max(0, _cfgRewardTop2Amount.Value); } if (_cfgRewardTop3MinPoints != null) { rankingRules.RewardTop3MinPoints = Mathf.Max(0, _cfgRewardTop3MinPoints.Value); } if (_cfgRewardTop3Label != null) { rankingRules.RewardTop3Label = SafeLimit(_cfgRewardTop3Label.Value, 96); } if (_cfgRewardTop3Prefab != null) { rankingRules.RewardTop3Prefab = SafeLimit(_cfgRewardTop3Prefab.Value, 96); } if (_cfgRewardTop3Amount != null) { rankingRules.RewardTop3Amount = Mathf.Max(0, _cfgRewardTop3Amount.Value); } if (_cfgPointsExchangeEnabled != null) { rankingRules.PointsExchangeEnabled = _cfgPointsExchangeEnabled.Value; } if (_cfgPointsExchangePrefab != null) { rankingRules.PointsExchangePrefab = SafeLimit(_cfgPointsExchangePrefab.Value, 96); } if (_cfgPointsExchangeCoinsPerPoint != null) { rankingRules.PointsExchangeCoinsPerPoint = Mathf.Max(1, _cfgPointsExchangeCoinsPerPoint.Value); } if (_cfgPointsExchangeMinPoints != null) { rankingRules.PointsExchangeMinPoints = Mathf.Max(0, _cfgPointsExchangeMinPoints.Value); } if (_cfgPointsExchangeMaxPointsPerRequest != null) { rankingRules.PointsExchangeMaxPointsPerRequest = Mathf.Max(0, _cfgPointsExchangeMaxPointsPerRequest.Value); } string raw = BuildCombatCategoryRulesFromBiomeEntries(); string raw2 = ((_cfgProductionCategoryRules != null) ? _cfgProductionCategoryRules.Value : "Armas:SwordIron=800;Armaduras:HelmetBronze=800;Comidas:DeerStew=25"); Dictionary categories; foreach (KeyValuePair item in ParseHudCategorizedPointRules(raw, out categories)) { if (!IsFishPrefab(item.Key)) { rankingRules.KillPoints[item.Key] = Mathf.Max(0, item.Value); } } Dictionary categories2; foreach (KeyValuePair item2 in ParseHudCategorizedPointRules(raw2, out categories2)) { rankingRules.CraftPoints[item2.Key] = Mathf.Max(0, item2.Value); } rankingRules.CombatHudCategories = categories; rankingRules.ProductionHudCategories = categories2; foreach (KeyValuePair> cfgKillPointEntry in _cfgKillPointEntries) { if (cfgKillPointEntry.Value != null) { string text = SafeKey(cfgKillPointEntry.Key); if (!string.IsNullOrWhiteSpace(text) && !IsFishPrefab(text)) { rankingRules.KillPoints[text] = Mathf.Max(0, cfgKillPointEntry.Value.Value); } } } foreach (KeyValuePair> cfgBossPointEntry in _cfgBossPointEntries) { rankingRules.BossPoints[cfgBossPointEntry.Key] = ((cfgBossPointEntry.Value != null) ? cfgBossPointEntry.Value.Value : 0); } foreach (KeyValuePair> cfgFishingPointEntry in _cfgFishingPointEntries) { string text2 = NormalizeFishPrefabName(cfgFishingPointEntry.Key); if (IsFishPrefab(text2)) { rankingRules.FishingPoints[text2] = ((cfgFishingPointEntry.Value != null) ? cfgFishingPointEntry.Value.Value : 0); } } foreach (KeyValuePair> cfgSkillMilestoneJackpotPointEntry in _cfgSkillMilestoneJackpotPointEntries) { rankingRules.SkillMilestoneJackpotPoints[cfgSkillMilestoneJackpotPointEntry.Key] = ((cfgSkillMilestoneJackpotPointEntry.Value != null) ? ParseSkillMilestoneMap(cfgSkillMilestoneJackpotPointEntry.Value.Value) : new Dictionary()); } if (_cfgFarmJackpotRules != null) { foreach (KeyValuePair item3 in ParseDelimitedJackpotRules(_cfgFarmJackpotRules.Value)) { rankingRules.FarmJackpots[item3.Key] = item3.Value; } } if (_cfgUniqueCraftJackpotRules != null) { foreach (KeyValuePair item4 in ParseDelimitedJackpotRules(_cfgUniqueCraftJackpotRules.Value)) { rankingRules.UniqueCraftJackpots[item4.Key] = item4.Value; } } if (_cfgMarketplaceQuestPointMap != null) { foreach (KeyValuePair item5 in ParseMarketplaceQuestPointMap(_cfgMarketplaceQuestPointMap.Value)) { rankingRules.MarketplaceQuestPoints[item5.Key] = item5.Value; } } if (_cfgDeathPenaltyRules != null) { rankingRules.DeathPenaltyRules = ParseDeathPenaltyRules(_cfgDeathPenaltyRules.Value); } if (_cfgExplorationMapJackpotRules != null) { rankingRules.ExplorationMapJackpots = ParseDeathPenaltyRules(_cfgExplorationMapJackpotRules.Value); } _rules = rankingRules; RebuildMarketplaceQuestPointCache(); } private void RebuildMarketplaceQuestPointCache() { _marketplaceQuestPointsByUid.Clear(); if (_rules == null || _rules.MarketplaceQuestPoints == null) { return; } foreach (KeyValuePair marketplaceQuestPoint in _rules.MarketplaceQuestPoints) { string text = SafeMarketplaceQuestKey(marketplaceQuestPoint.Key); int value = marketplaceQuestPoint.Value; if (!string.IsNullOrWhiteSpace(text) && value != 0) { int num = MarketplaceQuestKeyToUid(text); if (num != 0) { _marketplaceQuestPointsByUid[num] = new MarketplaceQuestPointRule { QuestKey = text, Points = value }; } } } } private string SafeMarketplaceQuestKey(string questKey) { questKey = SafeLimit(questKey, 128).Trim().ToLowerInvariant(); questKey = questKey.Replace("|", "/"); return questKey; } private int MarketplaceQuestKeyToUid(string questKey) { questKey = SafeMarketplaceQuestKey(questKey); if (string.IsNullOrWhiteSpace(questKey)) { return 0; } try { return StringExtensionMethods.GetStableHashCode(questKey); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao converter quest key do Marketplace em UID: " + questKey + " erro=" + ex.Message)); return 0; } } private bool TryGetMarketplaceQuestRule(int questUid, out MarketplaceQuestPointRule rule) { rule = null; if (_rules == null || !_rules.EnableMarketplaceQuestPoints) { return false; } return _marketplaceQuestPointsByUid.TryGetValue(questUid, out rule) && rule != null && rule.Points != 0; } private void LoadDatabase() { _database = new RankingDatabase(); if (!IsDedicatedServerInstance()) { DebugLog(DebugCategory.General, "LoadDatabase ignorado fora do servidor dedicado. Banco LiteDB fica somente no servidor."); return; } try { if (string.IsNullOrWhiteSpace(_databaseFilePath)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[Ranking] Caminho do banco LiteDB nao definido."); return; } EnsureDatabaseDirectoryExists(); using LiteDatabase liteDatabase = new LiteDatabase(_databaseFilePath); ILiteCollection collection = liteDatabase.GetCollection("ranking_entries"); ILiteCollection collection2 = liteDatabase.GetCollection("reward_claims"); ILiteCollection collection3 = liteDatabase.GetCollection("marketplace_quest_credits"); ILiteCollection collection4 = liteDatabase.GetCollection("fishing_catch_credits"); collection.EnsureIndex((RankingEntryDocument x) => x.PlayerName, unique: true); collection2.EnsureIndex((RewardClaimDocument x) => x.Key, unique: true); collection3.EnsureIndex((MarketplaceQuestCreditDocument x) => x.Key, unique: true); collection4.EnsureIndex((FishingCatchCreditDocument x) => x.ZdoKey, unique: true); RankingDatabase rankingDatabase = new RankingDatabase(); foreach (RankingEntryDocument item in collection.FindAll()) { RankingEntry rankingEntry = ConvertFromDocument(item); if (rankingEntry != null && !string.IsNullOrWhiteSpace(rankingEntry.PlayerName)) { rankingDatabase.Entries.Add(rankingEntry); } } foreach (RewardClaimDocument item2 in collection2.FindAll()) { RewardClaimRecord rewardClaimRecord = ConvertFromDocument(item2); if (rewardClaimRecord != null && !string.IsNullOrWhiteSpace(rewardClaimRecord.PlayerName)) { rankingDatabase.Claims.Add(rewardClaimRecord); } } foreach (MarketplaceQuestCreditDocument item3 in collection3.FindAll()) { MarketplaceQuestCreditRecord marketplaceQuestCreditRecord = ConvertFromDocument(item3); if (marketplaceQuestCreditRecord != null && !string.IsNullOrWhiteSpace(marketplaceQuestCreditRecord.PlayerName) && !string.IsNullOrWhiteSpace(marketplaceQuestCreditRecord.QuestKey)) { rankingDatabase.MarketplaceQuestCredits.Add(marketplaceQuestCreditRecord); } } foreach (FishingCatchCreditDocument item4 in collection4.FindAll()) { FishingCatchCreditRecord fishingCatchCreditRecord = ConvertFromDocument(item4); if (fishingCatchCreditRecord != null && !string.IsNullOrWhiteSpace(fishingCatchCreditRecord.ZdoKey)) { rankingDatabase.FishingCatchCredits.Add(fishingCatchCreditRecord); } } _database = NormalizeDatabase(rankingDatabase); } catch (Exception ex) { _database = new RankingDatabase(); ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao carregar banco LiteDB do ranking: " + ex)); } } private void EnsureDatabaseDirectoryExists() { if (!IsDedicatedServerInstance()) { return; } try { if (!string.IsNullOrWhiteSpace(_databaseFilePath)) { string directoryName = Path.GetDirectoryName(_databaseFilePath); if (!string.IsNullOrWhiteSpace(directoryName) && !Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Nao foi possivel preparar pasta do banco LiteDB: " + ex.Message)); } } private RankingDatabase LoadLegacyDatabaseFile(string filePath) { RankingDatabase result = new RankingDatabase(); try { if (string.IsNullOrWhiteSpace(filePath)) { return result; } if (!File.Exists(filePath)) { return result; } RankingDatabase rankingDatabase = new RankingDatabase(); string[] array = File.ReadAllLines(filePath, Encoding.UTF8); string[] array2 = array; foreach (string text in array2) { string text2 = ((text == null) ? "" : text.Trim()); if (string.IsNullOrWhiteSpace(text2) || text2.StartsWith("#")) { continue; } if (text2.StartsWith("Claim|", StringComparison.Ordinal)) { string[] array3 = text2.Split(new char[1] { '|' }); if (array3.Length < 5) { continue; } RewardClaimRecord rewardClaimRecord = new RewardClaimRecord(); rewardClaimRecord.CycleId = SafeLimit(DecodeDatabaseField(array3[1]), 64); rewardClaimRecord.PlayerName = SanitizePlayerName(DecodeDatabaseField(array3[2])); rewardClaimRecord.Rank = Mathf.Clamp(ParseInt(array3[3], 0), 0, int.MaxValue); rewardClaimRecord.ClaimedAtUtc = SafeLimit(DecodeDatabaseField(array3[4]), 64); rewardClaimRecord.Status = ((array3.Length >= 6) ? SafeLimit(DecodeDatabaseField(array3[5]), 16) : "claimed"); if (!string.IsNullOrWhiteSpace(rewardClaimRecord.CycleId) && !string.IsNullOrWhiteSpace(rewardClaimRecord.PlayerName) && rewardClaimRecord.Rank > 0) { string claimKey = BuildRewardClaimKey(rewardClaimRecord.CycleId, rewardClaimRecord.PlayerName, rewardClaimRecord.Rank); if (!rankingDatabase.Claims.Any((RewardClaimRecord x) => string.Equals(BuildRewardClaimKey(x.CycleId, x.PlayerName, x.Rank), claimKey, StringComparison.OrdinalIgnoreCase))) { rankingDatabase.Claims.Add(rewardClaimRecord); } } } else if (text2.StartsWith("QuestCredit|", StringComparison.Ordinal)) { string[] array4 = text2.Split(new char[1] { '|' }); if (array4.Length < 4) { continue; } MarketplaceQuestCreditRecord marketplaceQuestCreditRecord = new MarketplaceQuestCreditRecord(); marketplaceQuestCreditRecord.PlayerName = SanitizePlayerName(DecodeDatabaseField(array4[1])); marketplaceQuestCreditRecord.QuestKey = SafeKey(DecodeDatabaseField(array4[2])); marketplaceQuestCreditRecord.GrantedAtUtc = ((array4.Length >= 4) ? SafeLimit(DecodeDatabaseField(array4[3]), 64) : ""); if (!string.IsNullOrWhiteSpace(marketplaceQuestCreditRecord.PlayerName) && !string.IsNullOrWhiteSpace(marketplaceQuestCreditRecord.QuestKey)) { string creditKey = BuildMarketplaceQuestCreditKey(marketplaceQuestCreditRecord.PlayerName, marketplaceQuestCreditRecord.QuestKey); if (!rankingDatabase.MarketplaceQuestCredits.Any((MarketplaceQuestCreditRecord x) => string.Equals(BuildMarketplaceQuestCreditKey(x.PlayerName, x.QuestKey), creditKey, StringComparison.OrdinalIgnoreCase))) { rankingDatabase.MarketplaceQuestCredits.Add(marketplaceQuestCreditRecord); } } } else { if (!text2.StartsWith("Entry|", StringComparison.Ordinal)) { continue; } string[] array5 = text2.Split(new char[1] { '|' }); if (array5.Length < 10) { continue; } RankingEntry entry = new RankingEntry(); entry.PlayerName = SanitizePlayerName(DecodeDatabaseField(array5[1])); entry.Points = Mathf.Clamp(ParseInt(array5[2], 0), -2147483647, int.MaxValue); entry.LastReason = SafeReason(DecodeDatabaseField(array5[3])); entry.LastUpdateUtc = SafeLimit(DecodeDatabaseField(array5[4]), 64); entry.TotalKillsPontuadas = Mathf.Clamp(ParseInt(array5[5], 0), 0, int.MaxValue); entry.TotalBossesPontuadas = Mathf.Clamp(ParseInt(array5[6], 0), 0, int.MaxValue); entry.KillPointsTotal = Mathf.Clamp(ParseInt(array5[7], 0), -2147483647, int.MaxValue); entry.BossPointsTotal = Mathf.Clamp(ParseInt(array5[8], 0), -2147483647, int.MaxValue); entry.BossCredits = new HashSet(StringComparer.OrdinalIgnoreCase); string text3 = DecodeDatabaseField(array5[9]); if (!string.IsNullOrWhiteSpace(text3)) { string[] array6 = text3.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); string[] array7 = array6; foreach (string value in array7) { string text4 = SafeKey(value); if (!string.IsNullOrWhiteSpace(text4)) { entry.BossCredits.Add(text4); } } } if (array5.Length >= 11) { entry.TotalSkillLevelUpsPontuados = Mathf.Clamp(ParseInt(array5[10], 0), 0, int.MaxValue); } if (array5.Length >= 12) { entry.SkillPointsTotal = Mathf.Clamp(ParseInt(array5[11], 0), -2147483647, int.MaxValue); } if (array5.Length >= 13) { entry.TotalCraftPontuadas = Mathf.Clamp(ParseInt(array5[12], 0), 0, int.MaxValue); } if (array5.Length >= 14) { entry.CraftPointsTotal = Mathf.Clamp(ParseInt(array5[13], 0), -2147483647, int.MaxValue); } if (array5.Length >= 15) { entry.TotalFarmJackpotsPontuados = Mathf.Clamp(ParseInt(array5[14], 0), 0, int.MaxValue); } if (array5.Length >= 16) { entry.FarmJackpotPointsTotal = Mathf.Clamp(ParseInt(array5[15], 0), -2147483647, int.MaxValue); } if (array5.Length >= 17) { entry.TotalUniqueCraftJackpotsPontuados = Mathf.Clamp(ParseInt(array5[16], 0), 0, int.MaxValue); } if (array5.Length >= 18) { entry.UniqueCraftJackpotPointsTotal = Mathf.Clamp(ParseInt(array5[17], 0), -2147483647, int.MaxValue); } if (array5.Length >= 19) { entry.ProgressCounters = DeserializeStringIntDictionary(DecodeDatabaseField(array5[18])); } if (array5.Length >= 20) { entry.GenericJackpotCredits = DeserializeStringSet(DecodeDatabaseField(array5[19])); } if (array5.Length >= 21) { entry.TotalDeaths = Mathf.Clamp(ParseInt(array5[20], 0), 0, int.MaxValue); } if (array5.Length >= 22) { entry.DeathPenaltyPointsTotal = Mathf.Clamp(ParseInt(array5[21], 0), 0, int.MaxValue); } if (array5.Length >= 23) { entry.TotalPointsExchanges = Mathf.Clamp(ParseInt(array5[22], 0), 0, int.MaxValue); } if (array5.Length >= 24) { entry.PointsExchangePenaltyTotal = Mathf.Clamp(ParseInt(array5[23], 0), 0, int.MaxValue); } if (array5.Length >= 25) { entry.PointsExchangeCoinsTotal = Mathf.Clamp(ParseInt(array5[24], 0), 0, int.MaxValue); } if (array5.Length >= 26) { entry.ExplorationMapJackpotPointsTotal = Mathf.Clamp(ParseInt(array5[25], 0), 0, int.MaxValue); } if (!string.IsNullOrWhiteSpace(entry.PlayerName)) { RankingEntry rankingEntry = rankingDatabase.Entries.FirstOrDefault((RankingEntry x) => string.Equals(x.PlayerName, entry.PlayerName, StringComparison.OrdinalIgnoreCase)); if (rankingEntry != null) { rankingEntry.Points = entry.Points; rankingEntry.LastReason = entry.LastReason; rankingEntry.LastUpdateUtc = entry.LastUpdateUtc; rankingEntry.TotalKillsPontuadas = entry.TotalKillsPontuadas; rankingEntry.TotalBossesPontuadas = entry.TotalBossesPontuadas; rankingEntry.KillPointsTotal = entry.KillPointsTotal; rankingEntry.BossPointsTotal = entry.BossPointsTotal; rankingEntry.BossCredits = entry.BossCredits; rankingEntry.TotalSkillLevelUpsPontuados = entry.TotalSkillLevelUpsPontuados; rankingEntry.SkillPointsTotal = entry.SkillPointsTotal; rankingEntry.TotalCraftPontuadas = entry.TotalCraftPontuadas; rankingEntry.CraftPointsTotal = entry.CraftPointsTotal; rankingEntry.TotalFarmJackpotsPontuados = entry.TotalFarmJackpotsPontuados; rankingEntry.FarmJackpotPointsTotal = entry.FarmJackpotPointsTotal; rankingEntry.TotalUniqueCraftJackpotsPontuados = entry.TotalUniqueCraftJackpotsPontuados; rankingEntry.UniqueCraftJackpotPointsTotal = entry.UniqueCraftJackpotPointsTotal; rankingEntry.ProgressCounters = entry.ProgressCounters ?? new Dictionary(StringComparer.OrdinalIgnoreCase); rankingEntry.GenericJackpotCredits = entry.GenericJackpotCredits ?? new HashSet(StringComparer.OrdinalIgnoreCase); rankingEntry.TotalDeaths = entry.TotalDeaths; rankingEntry.DeathPenaltyPointsTotal = entry.DeathPenaltyPointsTotal; rankingEntry.TotalPointsExchanges = entry.TotalPointsExchanges; rankingEntry.PointsExchangePenaltyTotal = entry.PointsExchangePenaltyTotal; rankingEntry.PointsExchangeCoinsTotal = entry.PointsExchangeCoinsTotal; rankingEntry.ExplorationMapJackpotPointsTotal = entry.ExplorationMapJackpotPointsTotal; } else { rankingDatabase.Entries.Add(entry); } } } } return NormalizeDatabase(rankingDatabase); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao importar banco legado do ranking: " + ex)); return result; } } private RankingDatabase NormalizeDatabase(RankingDatabase database) { if (database == null) { database = new RankingDatabase(); } if (database.Entries == null) { database.Entries = new List(); } if (database.Claims == null) { database.Claims = new List(); } if (database.MarketplaceQuestCredits == null) { database.MarketplaceQuestCredits = new List(); } if (database.FishingCatchCredits == null) { database.FishingCatchCredits = new List(); } foreach (RankingEntry entry in database.Entries) { if (entry != null) { entry.PlayerName = SanitizePlayerName(entry.PlayerName); entry.LastReason = SafeReason(entry.LastReason); entry.LastUpdateUtc = SafeLimit(entry.LastUpdateUtc, 64); entry.Points = Mathf.Clamp(entry.Points, -2147483647, int.MaxValue); entry.TotalKillsPontuadas = Mathf.Clamp(entry.TotalKillsPontuadas, 0, int.MaxValue); entry.TotalBossesPontuadas = Mathf.Clamp(entry.TotalBossesPontuadas, 0, int.MaxValue); entry.KillPointsTotal = Mathf.Clamp(entry.KillPointsTotal, -2147483647, int.MaxValue); entry.BossPointsTotal = Mathf.Clamp(entry.BossPointsTotal, -2147483647, int.MaxValue); entry.TotalSkillLevelUpsPontuados = Mathf.Clamp(entry.TotalSkillLevelUpsPontuados, 0, int.MaxValue); entry.SkillPointsTotal = Mathf.Clamp(entry.SkillPointsTotal, -2147483647, int.MaxValue); entry.TotalFishingPontuadas = Mathf.Clamp(entry.TotalFishingPontuadas, 0, int.MaxValue); entry.FishingPointsTotal = Mathf.Clamp(entry.FishingPointsTotal, -2147483647, int.MaxValue); entry.TotalCraftPontuadas = Mathf.Clamp(entry.TotalCraftPontuadas, 0, int.MaxValue); entry.CraftPointsTotal = Mathf.Clamp(entry.CraftPointsTotal, -2147483647, int.MaxValue); entry.TotalFarmJackpotsPontuados = Mathf.Clamp(entry.TotalFarmJackpotsPontuados, 0, int.MaxValue); entry.FarmJackpotPointsTotal = Mathf.Clamp(entry.FarmJackpotPointsTotal, -2147483647, int.MaxValue); entry.TotalUniqueCraftJackpotsPontuados = Mathf.Clamp(entry.TotalUniqueCraftJackpotsPontuados, 0, int.MaxValue); entry.UniqueCraftJackpotPointsTotal = Mathf.Clamp(entry.UniqueCraftJackpotPointsTotal, -2147483647, int.MaxValue); entry.TotalDeaths = Mathf.Clamp(entry.TotalDeaths, 0, int.MaxValue); entry.DeathPenaltyPointsTotal = Mathf.Clamp(entry.DeathPenaltyPointsTotal, 0, int.MaxValue); entry.TotalPointsExchanges = Mathf.Clamp(entry.TotalPointsExchanges, 0, int.MaxValue); entry.PointsExchangePenaltyTotal = Mathf.Clamp(entry.PointsExchangePenaltyTotal, 0, int.MaxValue); entry.PointsExchangeCoinsTotal = Mathf.Clamp(entry.PointsExchangeCoinsTotal, 0, int.MaxValue); entry.ExplorationMapJackpotPointsTotal = Mathf.Clamp(entry.ExplorationMapJackpotPointsTotal, 0, int.MaxValue); entry.BossCredits = ((entry.BossCredits == null) ? new HashSet(StringComparer.OrdinalIgnoreCase) : new HashSet(entry.BossCredits.Where((string x) => !string.IsNullOrWhiteSpace(x)).Select(SafeKey), StringComparer.OrdinalIgnoreCase)); entry.GenericJackpotCredits = ((entry.GenericJackpotCredits == null) ? new HashSet(StringComparer.OrdinalIgnoreCase) : new HashSet(entry.GenericJackpotCredits.Where((string x) => !string.IsNullOrWhiteSpace(x)).Select(SafeKey), StringComparer.OrdinalIgnoreCase)); entry.SkillLevel100JackpotCredits = ((entry.SkillLevel100JackpotCredits == null) ? new HashSet(StringComparer.OrdinalIgnoreCase) : new HashSet(entry.SkillLevel100JackpotCredits.Where((string x) => !string.IsNullOrWhiteSpace(x)).Select(SafeKey), StringComparer.OrdinalIgnoreCase)); entry.ProgressCounters = ((entry.ProgressCounters == null) ? new Dictionary(StringComparer.OrdinalIgnoreCase) : entry.ProgressCounters.Where((KeyValuePair x) => !string.IsNullOrWhiteSpace(x.Key)).GroupBy, string>((KeyValuePair x) => SafeKey(x.Key), StringComparer.OrdinalIgnoreCase).ToDictionary>, string, int>((IGrouping> x) => x.Key, (IGrouping> x) => Mathf.Clamp(x.Last().Value, 0, int.MaxValue), StringComparer.OrdinalIgnoreCase)); } } database.Entries = (from x in database.Entries.Where((RankingEntry x) => x != null && !string.IsNullOrWhiteSpace(x.PlayerName)).GroupBy((RankingEntry x) => x.PlayerName, StringComparer.OrdinalIgnoreCase) select x.First()).OrderBy((RankingEntry x) => x.PlayerName, StringComparer.OrdinalIgnoreCase).ToList(); database.Claims = (from x in database.Claims.Where((RewardClaimRecord x) => x != null && !string.IsNullOrWhiteSpace(x.CycleId) && !string.IsNullOrWhiteSpace(x.PlayerName) && x.Rank > 0).Select(delegate(RewardClaimRecord x) { x.CycleId = SafeLimit(x.CycleId, 64); x.PlayerName = SanitizePlayerName(x.PlayerName); x.Rank = Mathf.Clamp(x.Rank, 1, int.MaxValue); x.ClaimedAtUtc = SafeLimit(x.ClaimedAtUtc, 64); x.Status = SafeLimit(string.IsNullOrWhiteSpace(x.Status) ? "claimed" : x.Status, 16); return x; }).GroupBy((RewardClaimRecord x) => BuildRewardClaimKey(x.CycleId, x.PlayerName, x.Rank), StringComparer.OrdinalIgnoreCase) select x.First()).ToList(); database.MarketplaceQuestCredits = (from x in database.MarketplaceQuestCredits.Where((MarketplaceQuestCreditRecord x) => x != null && !string.IsNullOrWhiteSpace(x.PlayerName) && !string.IsNullOrWhiteSpace(x.QuestKey)).Select(delegate(MarketplaceQuestCreditRecord x) { x.PlayerName = SanitizePlayerName(x.PlayerName); x.QuestKey = SafeKey(x.QuestKey); x.GrantedAtUtc = SafeLimit(x.GrantedAtUtc, 64); return x; }).GroupBy((MarketplaceQuestCreditRecord x) => BuildMarketplaceQuestCreditKey(x.PlayerName, x.QuestKey), StringComparer.OrdinalIgnoreCase) select x.First()).ToList(); database.FishingCatchCredits = (from x in database.FishingCatchCredits.Where((FishingCatchCreditRecord x) => x != null && !string.IsNullOrWhiteSpace(x.ZdoKey)).Select(delegate(FishingCatchCreditRecord x) { x.PlayerName = SanitizePlayerName(x.PlayerName); x.FishPrefab = SafeKey(x.FishPrefab); x.ZdoKey = SafeKey(x.ZdoKey); x.GrantedAtUtc = SafeLimit(x.GrantedAtUtc, 64); return x; }).GroupBy((FishingCatchCreditRecord x) => x.ZdoKey, StringComparer.OrdinalIgnoreCase) select x.First()).ToList(); return database; } private void SaveDatabase() { try { if (!IsDedicatedServerInstance() || string.IsNullOrWhiteSpace(_databaseFilePath) || _database == null) { return; } EnsureDatabaseDirectoryExists(); RankingDatabase rankingDatabase = NormalizeDatabase(_database); using (LiteDatabase liteDatabase = new LiteDatabase(_databaseFilePath)) { ILiteCollection collection = liteDatabase.GetCollection("ranking_entries"); ILiteCollection collection2 = liteDatabase.GetCollection("reward_claims"); ILiteCollection collection3 = liteDatabase.GetCollection("marketplace_quest_credits"); ILiteCollection collection4 = liteDatabase.GetCollection("fishing_catch_credits"); collection.EnsureIndex((RankingEntryDocument x) => x.PlayerName, unique: true); collection2.EnsureIndex((RewardClaimDocument x) => x.Key, unique: true); collection3.EnsureIndex((MarketplaceQuestCreditDocument x) => x.Key, unique: true); collection4.EnsureIndex((FishingCatchCreditDocument x) => x.ZdoKey, unique: true); collection.DeleteAll(); collection2.DeleteAll(); collection3.DeleteAll(); collection4.DeleteAll(); if (rankingDatabase.Entries != null) { foreach (RankingEntry entry in rankingDatabase.Entries) { RankingEntryDocument rankingEntryDocument = ConvertToDocument(entry); if (rankingEntryDocument != null && !string.IsNullOrWhiteSpace(rankingEntryDocument.PlayerName)) { collection.Upsert(rankingEntryDocument); } } } if (rankingDatabase.Claims != null) { foreach (RewardClaimRecord claim in rankingDatabase.Claims) { RewardClaimDocument rewardClaimDocument = ConvertToDocument(claim); if (rewardClaimDocument != null && !string.IsNullOrWhiteSpace(rewardClaimDocument.Key)) { collection2.Upsert(rewardClaimDocument); } } } if (rankingDatabase.MarketplaceQuestCredits != null) { foreach (MarketplaceQuestCreditRecord marketplaceQuestCredit in rankingDatabase.MarketplaceQuestCredits) { MarketplaceQuestCreditDocument marketplaceQuestCreditDocument = ConvertToDocument(marketplaceQuestCredit); if (marketplaceQuestCreditDocument != null && !string.IsNullOrWhiteSpace(marketplaceQuestCreditDocument.Key)) { collection3.Upsert(marketplaceQuestCreditDocument); } } } if (rankingDatabase.FishingCatchCredits != null) { foreach (FishingCatchCreditRecord fishingCatchCredit in rankingDatabase.FishingCatchCredits) { FishingCatchCreditDocument fishingCatchCreditDocument = ConvertToDocument(fishingCatchCredit); if (fishingCatchCreditDocument != null && !string.IsNullOrWhiteSpace(fishingCatchCreditDocument.ZdoKey)) { collection4.Upsert(fishingCatchCreditDocument); } } } } _database = rankingDatabase; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao salvar banco LiteDB do ranking: " + ex)); } } private RankingEntryDocument ConvertToDocument(RankingEntry entry) { if (entry == null) { return null; } RankingEntryDocument rankingEntryDocument = new RankingEntryDocument(); rankingEntryDocument.PlayerName = SanitizePlayerName(entry.PlayerName); rankingEntryDocument.Points = entry.Points; rankingEntryDocument.LastReason = SafeReason(entry.LastReason); rankingEntryDocument.LastUpdateUtc = SafeLimit(entry.LastUpdateUtc, 64); rankingEntryDocument.TotalKillsPontuadas = entry.TotalKillsPontuadas; rankingEntryDocument.TotalBossesPontuadas = entry.TotalBossesPontuadas; rankingEntryDocument.KillPointsTotal = entry.KillPointsTotal; rankingEntryDocument.BossPointsTotal = entry.BossPointsTotal; rankingEntryDocument.TotalSkillLevelUpsPontuados = entry.TotalSkillLevelUpsPontuados; rankingEntryDocument.SkillPointsTotal = entry.SkillPointsTotal; rankingEntryDocument.TotalFishingPontuadas = entry.TotalFishingPontuadas; rankingEntryDocument.FishingPointsTotal = entry.FishingPointsTotal; rankingEntryDocument.TotalCraftPontuadas = entry.TotalCraftPontuadas; rankingEntryDocument.CraftPointsTotal = entry.CraftPointsTotal; rankingEntryDocument.TotalFarmJackpotsPontuados = entry.TotalFarmJackpotsPontuados; rankingEntryDocument.FarmJackpotPointsTotal = entry.FarmJackpotPointsTotal; rankingEntryDocument.TotalUniqueCraftJackpotsPontuados = entry.TotalUniqueCraftJackpotsPontuados; rankingEntryDocument.UniqueCraftJackpotPointsTotal = entry.UniqueCraftJackpotPointsTotal; rankingEntryDocument.TotalDeaths = entry.TotalDeaths; rankingEntryDocument.DeathPenaltyPointsTotal = entry.DeathPenaltyPointsTotal; rankingEntryDocument.TotalPointsExchanges = entry.TotalPointsExchanges; rankingEntryDocument.PointsExchangePenaltyTotal = entry.PointsExchangePenaltyTotal; rankingEntryDocument.PointsExchangeCoinsTotal = entry.PointsExchangeCoinsTotal; rankingEntryDocument.ExplorationMapJackpotPointsTotal = entry.ExplorationMapJackpotPointsTotal; rankingEntryDocument.ProgressCounters = SerializeStringIntDictionary(entry.ProgressCounters); rankingEntryDocument.FloatProgressCounters = SerializeStringFloatDictionary(entry.FloatProgressCounters); rankingEntryDocument.GenericJackpotCredits = SerializeStringSet(entry.GenericJackpotCredits); rankingEntryDocument.BossCredits = SerializeStringSet(entry.BossCredits); rankingEntryDocument.SkillLevel100JackpotCredits = SerializeStringSet(entry.SkillLevel100JackpotCredits); return rankingEntryDocument; } private RankingEntry ConvertFromDocument(RankingEntryDocument doc) { if (doc == null) { return null; } RankingEntry rankingEntry = new RankingEntry(); rankingEntry.PlayerName = SanitizePlayerName(doc.PlayerName); rankingEntry.Points = doc.Points; rankingEntry.LastReason = SafeReason(doc.LastReason); rankingEntry.LastUpdateUtc = SafeLimit(doc.LastUpdateUtc, 64); rankingEntry.TotalKillsPontuadas = doc.TotalKillsPontuadas; rankingEntry.TotalBossesPontuadas = doc.TotalBossesPontuadas; rankingEntry.KillPointsTotal = doc.KillPointsTotal; rankingEntry.BossPointsTotal = doc.BossPointsTotal; rankingEntry.TotalSkillLevelUpsPontuados = doc.TotalSkillLevelUpsPontuados; rankingEntry.SkillPointsTotal = doc.SkillPointsTotal; rankingEntry.TotalFishingPontuadas = doc.TotalFishingPontuadas; rankingEntry.FishingPointsTotal = doc.FishingPointsTotal; rankingEntry.TotalCraftPontuadas = doc.TotalCraftPontuadas; rankingEntry.CraftPointsTotal = doc.CraftPointsTotal; rankingEntry.TotalFarmJackpotsPontuados = doc.TotalFarmJackpotsPontuados; rankingEntry.FarmJackpotPointsTotal = doc.FarmJackpotPointsTotal; rankingEntry.TotalUniqueCraftJackpotsPontuados = doc.TotalUniqueCraftJackpotsPontuados; rankingEntry.UniqueCraftJackpotPointsTotal = doc.UniqueCraftJackpotPointsTotal; rankingEntry.TotalDeaths = doc.TotalDeaths; rankingEntry.DeathPenaltyPointsTotal = doc.DeathPenaltyPointsTotal; rankingEntry.TotalPointsExchanges = doc.TotalPointsExchanges; rankingEntry.PointsExchangePenaltyTotal = doc.PointsExchangePenaltyTotal; rankingEntry.PointsExchangeCoinsTotal = doc.PointsExchangeCoinsTotal; rankingEntry.ExplorationMapJackpotPointsTotal = doc.ExplorationMapJackpotPointsTotal; rankingEntry.ProgressCounters = DeserializeStringIntDictionary(doc.ProgressCounters); rankingEntry.FloatProgressCounters = DeserializeStringFloatDictionary(doc.FloatProgressCounters); rankingEntry.GenericJackpotCredits = DeserializeStringSet(doc.GenericJackpotCredits); rankingEntry.BossCredits = DeserializeStringSet(doc.BossCredits); rankingEntry.SkillLevel100JackpotCredits = DeserializeStringSet(doc.SkillLevel100JackpotCredits); return rankingEntry; } private RewardClaimDocument ConvertToDocument(RewardClaimRecord claim) { if (claim == null) { return null; } RewardClaimDocument rewardClaimDocument = new RewardClaimDocument(); rewardClaimDocument.CycleId = SafeKey(claim.CycleId); rewardClaimDocument.PlayerName = SanitizePlayerName(claim.PlayerName); rewardClaimDocument.Rank = claim.Rank; rewardClaimDocument.ClaimedAtUtc = SafeLimit(claim.ClaimedAtUtc, 64); rewardClaimDocument.Status = SafeLimit(claim.Status, 32); rewardClaimDocument.Key = BuildRewardClaimKey(rewardClaimDocument.CycleId, rewardClaimDocument.PlayerName, rewardClaimDocument.Rank); return rewardClaimDocument; } private RewardClaimRecord ConvertFromDocument(RewardClaimDocument doc) { if (doc == null) { return null; } RewardClaimRecord rewardClaimRecord = new RewardClaimRecord(); rewardClaimRecord.CycleId = SafeKey(doc.CycleId); rewardClaimRecord.PlayerName = SanitizePlayerName(doc.PlayerName); rewardClaimRecord.Rank = doc.Rank; rewardClaimRecord.ClaimedAtUtc = SafeLimit(doc.ClaimedAtUtc, 64); rewardClaimRecord.Status = SafeLimit(doc.Status, 32); return rewardClaimRecord; } private MarketplaceQuestCreditDocument ConvertToDocument(MarketplaceQuestCreditRecord credit) { if (credit == null) { return null; } MarketplaceQuestCreditDocument marketplaceQuestCreditDocument = new MarketplaceQuestCreditDocument(); marketplaceQuestCreditDocument.PlayerName = SanitizePlayerName(credit.PlayerName); marketplaceQuestCreditDocument.QuestKey = SafeKey(credit.QuestKey); marketplaceQuestCreditDocument.GrantedAtUtc = SafeLimit(credit.GrantedAtUtc, 64); marketplaceQuestCreditDocument.Key = BuildMarketplaceQuestCreditKey(marketplaceQuestCreditDocument.PlayerName, marketplaceQuestCreditDocument.QuestKey); return marketplaceQuestCreditDocument; } private MarketplaceQuestCreditRecord ConvertFromDocument(MarketplaceQuestCreditDocument doc) { if (doc == null) { return null; } MarketplaceQuestCreditRecord marketplaceQuestCreditRecord = new MarketplaceQuestCreditRecord(); marketplaceQuestCreditRecord.PlayerName = SanitizePlayerName(doc.PlayerName); marketplaceQuestCreditRecord.QuestKey = SafeKey(doc.QuestKey); marketplaceQuestCreditRecord.GrantedAtUtc = SafeLimit(doc.GrantedAtUtc, 64); return marketplaceQuestCreditRecord; } private FishingCatchCreditDocument ConvertToDocument(FishingCatchCreditRecord credit) { if (credit == null) { return null; } FishingCatchCreditDocument fishingCatchCreditDocument = new FishingCatchCreditDocument(); fishingCatchCreditDocument.PlayerName = SanitizePlayerName(credit.PlayerName); fishingCatchCreditDocument.FishPrefab = SafeKey(credit.FishPrefab); fishingCatchCreditDocument.ZdoKey = SafeKey(credit.ZdoKey); fishingCatchCreditDocument.GrantedAtUtc = SafeLimit(credit.GrantedAtUtc, 64); return fishingCatchCreditDocument; } private FishingCatchCreditRecord ConvertFromDocument(FishingCatchCreditDocument doc) { if (doc == null) { return null; } FishingCatchCreditRecord fishingCatchCreditRecord = new FishingCatchCreditRecord(); fishingCatchCreditRecord.PlayerName = SanitizePlayerName(doc.PlayerName); fishingCatchCreditRecord.FishPrefab = SafeKey(doc.FishPrefab); fishingCatchCreditRecord.ZdoKey = SafeKey(doc.ZdoKey); fishingCatchCreditRecord.GrantedAtUtc = SafeLimit(doc.GrantedAtUtc, 64); return fishingCatchCreditRecord; } private string SerializeStringSet(HashSet values) { if (values == null || values.Count == 0) { return ""; } return string.Join("\n", values.Where((string x) => !string.IsNullOrWhiteSpace(x)).Select(SafeKey).Distinct(StringComparer.OrdinalIgnoreCase) .OrderBy((string x) => x, StringComparer.OrdinalIgnoreCase) .ToArray()); } private HashSet DeserializeStringSet(string raw) { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return hashSet; } string[] array = raw.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string value in array) { string text = SafeKey(value); if (!string.IsNullOrWhiteSpace(text)) { hashSet.Add(text); } } return hashSet; } private string SerializeStringIntDictionary(Dictionary values) { if (values == null || values.Count == 0) { return ""; } return string.Join("\n", (from p in values where !string.IsNullOrWhiteSpace(p.Key) select EncodeDatabaseField(SafeKey(p.Key)) + ":" + Mathf.Clamp(p.Value, 0, int.MaxValue)).OrderBy((string x) => x, StringComparer.OrdinalIgnoreCase).ToArray()); } private Dictionary DeserializeStringIntDictionary(string raw) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string text2 = ((text == null) ? "" : text.Trim()); if (string.IsNullOrWhiteSpace(text2)) { continue; } int num = text2.LastIndexOf(':'); if (num <= 0 || num >= text2.Length - 1) { continue; } string text3 = text2.Substring(0, num); string s = text2.Substring(num + 1); if (int.TryParse(s, out var result)) { string value = DecodeDatabaseField(text3); if (string.IsNullOrWhiteSpace(value)) { value = text3; } value = SafeKey(value); if (!string.IsNullOrWhiteSpace(value)) { dictionary[value] = Mathf.Clamp(result, 0, int.MaxValue); } } } return dictionary; } private string SerializeStringFloatDictionary(Dictionary values) { if (values == null || values.Count == 0) { return ""; } return string.Join("\n", (from p in values where !string.IsNullOrWhiteSpace(p.Key) select EncodeDatabaseField(SafeKey(p.Key)) + ":" + Mathf.Clamp(p.Value, 0f, 1000000f).ToString("R", CultureInfo.InvariantCulture)).OrderBy((string x) => x, StringComparer.OrdinalIgnoreCase).ToArray()); } private Dictionary DeserializeStringFloatDictionary(string raw) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } string[] array = raw.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string text2 = ((text == null) ? "" : text.Trim()); if (string.IsNullOrWhiteSpace(text2)) { continue; } int num = text2.LastIndexOf(':'); if (num <= 0 || num >= text2.Length - 1) { continue; } string text3 = text2.Substring(0, num); string s = text2.Substring(num + 1); if (float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { string value = DecodeDatabaseField(text3); if (string.IsNullOrWhiteSpace(value)) { value = text3; } value = SafeKey(value); if (!string.IsNullOrWhiteSpace(value)) { dictionary[value] = Mathf.Clamp(result, 0f, 1000000f); } } } return dictionary; } private string EncodeDatabaseField(string value) { try { byte[] bytes = Encoding.UTF8.GetBytes(value ?? ""); return Convert.ToBase64String(bytes); } catch { return ""; } } private string DecodeDatabaseField(string value) { try { if (string.IsNullOrWhiteSpace(value)) { return ""; } byte[] bytes = Convert.FromBase64String(value); return Encoding.UTF8.GetString(bytes); } catch { return ""; } } private void DebugLog(DebugCategory category, string message) { if (_rules == null || !_rules.DebugLogging) { return; } bool flag = false; if (category switch { DebugCategory.Hit => _rules.LogHitReports, DebugCategory.Kill => _rules.LogKillReports, DebugCategory.Skill => _rules.LogSkillReports, DebugCategory.PendingKill => _rules.LogPendingKillReports, DebugCategory.Snapshot => _rules.LogSnapshotRequests, DebugCategory.Points => _rules.LogPointsChanges, _ => true, }) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"[{category}] {message}"); } } } public void AddPoints(string playerName, int amount, string reason) { if (IsServerInstance() && _rules.RankingEnabled && !string.IsNullOrWhiteSpace(playerName)) { playerName = SanitizePlayerName(playerName); if (ShouldIgnorePlayerForRanking(playerName)) { DebugLog(DebugCategory.Points, "Pontuação ignorada para admin: " + playerName + " motivo=" + reason); return; } RankingEntry orCreateEntry = GetOrCreateEntry(playerName); ApplyPointsToEntry(orCreateEntry, amount, reason); } } private void ApplyPointsToEntry(RankingEntry entry, int amount, string reason) { if (entry == null) { return; } if (ShouldIgnorePlayerForRanking(entry.PlayerName)) { DebugLog(DebugCategory.Points, "Pontuação ignorada para admin: " + entry.PlayerName + " motivo=" + reason); return; } Dictionary oldRanks = (IsServerInstance() ? GetRankingSnapshot() : new Dictionary(StringComparer.OrdinalIgnoreCase)); entry.Points = Mathf.Clamp(entry.Points + amount, -2147483647, int.MaxValue); entry.LastReason = SafeReason(reason); entry.LastUpdateUtc = DateTime.UtcNow.ToString("O"); Dictionary newRanks = (IsServerInstance() ? GetRankingSnapshot() : new Dictionary(StringComparer.OrdinalIgnoreCase)); DebugLog(DebugCategory.Points, "Pontuação alterada: player=" + entry.PlayerName + " amount=" + amount + " total=" + entry.Points + " motivo=" + entry.LastReason); if (IsServerInstance()) { TrySendTop3DiscordWebhooks(oldRanks, newRanks, entry.LastReason); SaveDatabase(); } } private void TrySendTop3DiscordWebhooks(Dictionary oldRanks, Dictionary newRanks, string reason) { try { if (!IsServerInstance() || _cfgDiscordTop3WebhookEnabled == null || !_cfgDiscordTop3WebhookEnabled.Value || _cfgDiscordTop3WebhookUrl == null || string.IsNullOrWhiteSpace(_cfgDiscordTop3WebhookUrl.Value)) { return; } if (oldRanks == null) { oldRanks = new Dictionary(StringComparer.OrdinalIgnoreCase); } if (newRanks == null) { newRanks = new Dictionary(StringComparer.OrdinalIgnoreCase); } HashSet hashSet = new HashSet(oldRanks.Keys, StringComparer.OrdinalIgnoreCase); foreach (string key in newRanks.Keys) { hashSet.Add(key); } foreach (string item in hashSet) { if (string.IsNullOrWhiteSpace(item)) { continue; } int value; int num = (oldRanks.TryGetValue(item, out value) ? value : int.MaxValue); int value2; int num2 = (newRanks.TryGetValue(item, out value2) ? value2 : int.MaxValue); bool flag = num > 3 && num2 >= 1 && num2 <= 3; bool flag2 = num >= 1 && num <= 3 && num2 > 3; bool flag3 = num >= 1 && num <= 3 && num2 >= 1 && num2 <= 3 && num2 > num; if (flag || flag2 || flag3) { int points = FindRankingEntryByName(item)?.Points ?? 0; if (flag) { SendDiscordTop3EnteredWebhook(item, num2, points, reason); } else if (flag2) { SendDiscordTop3LostWebhook(item, num, num2, points, reason); } else if (flag3) { SendDiscordTop3DroppedWebhook(item, num, num2, points, reason); } } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Erro ao preparar webhook Top 3 do Discord: " + ex.Message)); } } private RankRewardInfo GetRankRewardInfo(int rank) { return rank switch { 1 => new RankRewardInfo { Rank = 1, MinPoints = Mathf.Max(0, _rules.RewardTop1MinPoints), Label = SafeLimit(_rules.RewardTop1Label, 96), PrefabName = SafeLimit(_rules.RewardTop1Prefab, 96), Amount = Mathf.Max(0, _rules.RewardTop1Amount) }, 2 => new RankRewardInfo { Rank = 2, MinPoints = Mathf.Max(0, _rules.RewardTop2MinPoints), Label = SafeLimit(_rules.RewardTop2Label, 96), PrefabName = SafeLimit(_rules.RewardTop2Prefab, 96), Amount = Mathf.Max(0, _rules.RewardTop2Amount) }, 3 => new RankRewardInfo { Rank = 3, MinPoints = Mathf.Max(0, _rules.RewardTop3MinPoints), Label = SafeLimit(_rules.RewardTop3Label, 96), PrefabName = SafeLimit(_rules.RewardTop3Prefab, 96), Amount = Mathf.Max(0, _rules.RewardTop3Amount) }, _ => null, }; } private string BuildRewardClaimKey(string cycleId, string playerName, int rank) { return SafeLimit(cycleId, 64) + "|" + SanitizePlayerName(playerName) + "|" + Mathf.Clamp(rank, 0, int.MaxValue); } private string BuildPendingRewardKey(long sender, string cycleId, int rank) { return sender + "|" + SafeLimit(cycleId, 64) + "|" + Mathf.Clamp(rank, 0, int.MaxValue); } private bool HasClaimedReward(string cycleId, string playerName, int rank) { if (_database == null || _database.Claims == null) { return false; } string key = BuildRewardClaimKey(cycleId, playerName, rank); return _database.Claims.Any((RewardClaimRecord x) => x != null && string.Equals(BuildRewardClaimKey(x.CycleId, x.PlayerName, x.Rank), key, StringComparison.OrdinalIgnoreCase) && string.Equals(SafeLimit(x.Status, 16), "claimed", StringComparison.OrdinalIgnoreCase)); } private bool HasPendingRewardClaim(string cycleId, string playerName, int rank) { if (_database == null || _database.Claims == null) { return false; } string key = BuildRewardClaimKey(cycleId, playerName, rank); return _database.Claims.Any((RewardClaimRecord x) => x != null && string.Equals(BuildRewardClaimKey(x.CycleId, x.PlayerName, x.Rank), key, StringComparison.OrdinalIgnoreCase) && string.Equals(SafeLimit(x.Status, 16), "pending", StringComparison.OrdinalIgnoreCase)); } private void ReserveRewardClaim(string cycleId, string playerName, int rank) { if (_database == null) { _database = new RankingDatabase(); } if (_database.Claims == null) { _database.Claims = new List(); } string cycleId2 = SafeLimit(cycleId, 64); string playerName2 = SanitizePlayerName(playerName); int rank2 = Mathf.Clamp(rank, 1, int.MaxValue); string key = BuildRewardClaimKey(cycleId2, playerName2, rank2); RewardClaimRecord rewardClaimRecord = _database.Claims.FirstOrDefault((RewardClaimRecord x) => x != null && string.Equals(BuildRewardClaimKey(x.CycleId, x.PlayerName, x.Rank), key, StringComparison.OrdinalIgnoreCase)); if (rewardClaimRecord != null) { rewardClaimRecord.Status = "pending"; rewardClaimRecord.ClaimedAtUtc = ""; return; } _database.Claims.Add(new RewardClaimRecord { CycleId = cycleId2, PlayerName = playerName2, Rank = rank2, ClaimedAtUtc = "", Status = "pending" }); } private void ClearPendingRewardClaim(string cycleId, string playerName, int rank) { if (_database != null && _database.Claims != null) { string key = BuildRewardClaimKey(cycleId, playerName, rank); _database.Claims.RemoveAll((RewardClaimRecord x) => x != null && string.Equals(BuildRewardClaimKey(x.CycleId, x.PlayerName, x.Rank), key, StringComparison.OrdinalIgnoreCase) && string.Equals(SafeLimit(x.Status, 16), "pending", StringComparison.OrdinalIgnoreCase)); } } private void MarkRewardClaimed(string cycleId, string playerName, int rank) { if (_database == null) { _database = new RankingDatabase(); } if (_database.Claims == null) { _database.Claims = new List(); } string cycleId2 = SafeLimit(cycleId, 64); string playerName2 = SanitizePlayerName(playerName); int rank2 = Mathf.Clamp(rank, 1, int.MaxValue); string key = BuildRewardClaimKey(cycleId2, playerName2, rank2); RewardClaimRecord rewardClaimRecord = _database.Claims.FirstOrDefault((RewardClaimRecord x) => x != null && string.Equals(BuildRewardClaimKey(x.CycleId, x.PlayerName, x.Rank), key, StringComparison.OrdinalIgnoreCase)); if (rewardClaimRecord != null) { rewardClaimRecord.Status = "claimed"; rewardClaimRecord.ClaimedAtUtc = DateTime.UtcNow.ToString("O"); return; } _database.Claims.Add(new RewardClaimRecord { CycleId = cycleId2, PlayerName = playerName2, Rank = rank2, ClaimedAtUtc = DateTime.UtcNow.ToString("O"), Status = "claimed" }); } private void FillRewardSnapshotData(SnapshotPlayerData playerData) { if (playerData == null) { return; } playerData.RewardClaimsEnabled = _rules != null && _rules.RewardClaimsEnabled; playerData.RewardCanClaim = false; playerData.RewardAlreadyClaimed = false; playerData.RewardRank = Mathf.Max(0, playerData.Position); playerData.RewardMinPoints = 0; playerData.RewardLabel = ""; playerData.RewardPrefabName = ""; playerData.RewardAmount = 0; playerData.RewardBlockReason = ""; playerData.RewardClaimCycleId = ((_rules != null) ? SafeLimit(_rules.RewardClaimCycleId, 64) : ""); if (_rules == null || !_rules.RewardClaimsEnabled) { playerData.RewardBlockReason = "Resgate de recompensa desativado."; return; } if (!playerData.HasData) { playerData.RewardBlockReason = "Você ainda não possui pontuação no ranking."; return; } RankRewardInfo rankRewardInfo = GetRankRewardInfo(playerData.Position); if (rankRewardInfo == null) { playerData.RewardBlockReason = "Somente Top 1, 2 e 3 podem resgatar."; return; } playerData.RewardRank = rankRewardInfo.Rank; playerData.RewardMinPoints = rankRewardInfo.MinPoints; playerData.RewardLabel = rankRewardInfo.Label ?? ""; playerData.RewardPrefabName = rankRewardInfo.PrefabName ?? ""; playerData.RewardAmount = Mathf.Max(0, rankRewardInfo.Amount); if (string.IsNullOrWhiteSpace(playerData.RewardClaimCycleId)) { playerData.RewardBlockReason = "Ciclo de recompensa não configurado."; } else if (string.IsNullOrWhiteSpace(playerData.RewardPrefabName) || playerData.RewardAmount <= 0) { playerData.RewardBlockReason = "Recompensa não configurada para esta posição."; } else if (playerData.Points < rankRewardInfo.MinPoints) { playerData.RewardBlockReason = "Requer " + rankRewardInfo.MinPoints + " pontos para resgatar."; } else if (HasClaimedReward(playerData.RewardClaimCycleId, playerData.PlayerName, rankRewardInfo.Rank)) { playerData.RewardAlreadyClaimed = true; playerData.RewardBlockReason = "Recompensa já resgatada."; } else { playerData.RewardCanClaim = true; playerData.RewardBlockReason = "Recompensa disponível para resgate."; } } private bool TryAddRewardItemToLocalInventory(string prefabName, int amount, out string message) { message = ""; try { if ((Object)(object)Player.m_localPlayer == (Object)null) { message = "Jogador local não encontrado."; return false; } if (string.IsNullOrWhiteSpace(prefabName)) { message = "Prefab da recompensa não configurado."; return false; } if (amount <= 0) { message = "Quantidade de recompensa inválida."; return false; } GameObject val = null; if ((Object)(object)ObjectDB.instance != (Object)null) { val = ObjectDB.instance.GetItemPrefab(prefabName); } if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { val = ZNetScene.instance.GetPrefab(prefabName); } if ((Object)(object)val == (Object)null) { message = "Prefab '" + prefabName + "' não encontrado."; return false; } ItemDrop component = val.GetComponent(); if ((Object)(object)component == (Object)null) { message = "Prefab '" + prefabName + "' não é um item válido."; return false; } Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (inventory == null) { message = "Inventário não encontrado."; return false; } ItemData val2 = inventory.AddItem(prefabName, Mathf.Max(1, amount), Mathf.Max(1, component.m_itemData.m_quality), Mathf.Max(0, component.m_itemData.m_variant), 0L, "", false); if (val2 == null) { message = "Inventário sem espaço suficiente."; return false; } string text = ((component.m_itemData != null && component.m_itemData.m_shared != null) ? component.m_itemData.m_shared.m_name : prefabName); try { ((Character)Player.m_localPlayer).Message((MessageType)2, "Recompensa recebida: " + text + " x" + amount, 0, (Sprite)null); } catch { } message = "Recompensa recebida: " + text + " x" + amount; return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao adicionar recompensa no inventário: " + ex)); message = "Erro ao adicionar item no inventário."; return false; } } private bool TryAddExchangeItemToLocalInventoryOrDropOverflow(string prefabName, int amount, out string message) { message = ""; try { if ((Object)(object)Player.m_localPlayer == (Object)null) { message = "Jogador local não encontrado."; return false; } if (string.IsNullOrWhiteSpace(prefabName)) { message = "Prefab do câmbio não configurado."; return false; } if (amount <= 0) { message = "Quantidade de câmbio inválida."; return false; } GameObject val = null; if ((Object)(object)ObjectDB.instance != (Object)null) { val = ObjectDB.instance.GetItemPrefab(prefabName); } if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { val = ZNetScene.instance.GetPrefab(prefabName); } if ((Object)(object)val == (Object)null) { message = "Prefab '" + prefabName + "' não encontrado."; return false; } ItemDrop component = val.GetComponent(); if ((Object)(object)component == (Object)null) { message = "Prefab '" + prefabName + "' não é um item válido."; return false; } Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (inventory == null) { message = "Inventário não encontrado."; return false; } int num = Mathf.Max(0, amount); int num2 = 0; int num3 = 0; int num4 = 1; int num5 = 0; int num6 = 1; string text = prefabName; if (component.m_itemData != null) { num4 = Mathf.Max(1, component.m_itemData.m_quality); num5 = Mathf.Max(0, component.m_itemData.m_variant); if (component.m_itemData.m_shared != null) { num6 = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize); if (!string.IsNullOrWhiteSpace(component.m_itemData.m_shared.m_name)) { text = component.m_itemData.m_shared.m_name; } } } while (num > 0) { int num7 = Mathf.Min(num6, num); ItemData val2 = inventory.AddItem(prefabName, num7, num4, num5, 0L, "", false); if (val2 == null) { break; } num2 += num7; num -= num7; } if (num > 0) { num3 = DropExchangeItemOverflowNearPlayer(val, component, num, num6, num4, num5); num -= num3; } if (num > 0) { message = "Não foi possível entregar todo o câmbio."; return false; } try { if (num3 > 0 && num2 > 0) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Câmbio recebido: " + text + " x" + num2 + " no inventário, x" + num3 + " no chão.", 0, (Sprite)null); } else if (num3 > 0) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Inventário cheio. Câmbio caiu no chão: " + text + " x" + num3 + ".", 0, (Sprite)null); } else { ((Character)Player.m_localPlayer).Message((MessageType)2, "Câmbio recebido: " + text + " x" + num2 + ".", 0, (Sprite)null); } } catch { } if (num3 > 0 && num2 > 0) { message = "Parte foi para o inventário e o restante caiu no chão."; } else if (num3 > 0) { message = "Inventário cheio: as moedas caíram no chão."; } else { message = "Moedas adicionadas ao inventário."; } return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao entregar moedas do câmbio: " + ex)); message = "Erro ao entregar moedas do câmbio."; return false; } } private int DropExchangeItemOverflowNearPlayer(GameObject itemPrefab, ItemDrop sourceDrop, int amount, int maxStackSize, int quality, int variant) { //IL_003f: 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: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_00af: 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_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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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_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) if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)itemPrefab == (Object)null || amount <= 0) { return 0; } int num = amount; int num2 = 0; Transform transform = ((Component)Player.m_localPlayer).transform; Vector3 val = transform.position + transform.forward * 1.25f + Vector3.up * 0.65f; Vector3 val2 = default(Vector3); while (num > 0) { int num3 = Mathf.Min(Mathf.Max(1, maxStackSize), num); ((Vector3)(ref val2))..ctor(Random.Range(-0.35f, 0.35f), 0f, Random.Range(-0.35f, 0.35f)); GameObject val3 = Object.Instantiate(itemPrefab, val + val2, Quaternion.identity); ItemDrop val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent() : null); if ((Object)(object)val4 != (Object)null && val4.m_itemData != null) { val4.m_itemData.m_stack = num3; val4.m_itemData.m_quality = Mathf.Max(1, quality); val4.m_itemData.m_variant = Mathf.Max(0, variant); } Rigidbody val5 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent() : null); if ((Object)(object)val5 != (Object)null) { val5.linearVelocity = transform.forward * 1.5f + Vector3.up * 1.25f; } num2 += num3; num -= num3; } return num2; } private void RegisterRpcsIfNeeded() { if (!_rpcsRegistered && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register("glitnir.ranking.requestsnapshot", (Action)RPC_RequestSnapshot); ZRoutedRpc.instance.Register("glitnir.ranking.receivesnapshot", (Action)RPC_ReceiveSnapshot); ZRoutedRpc.instance.Register("glitnir.ranking.reporthit", (Action)RPC_ReportHit); ZRoutedRpc.instance.Register("glitnir.ranking.reportkill", (Action)RPC_ReportKill); ZRoutedRpc.instance.Register("glitnir.ranking.reportskillgain", (Action)RPC_ReportSkillGain); ZRoutedRpc.instance.Register("glitnir.ranking.requestrewardclaim", (Action)RPC_RequestRewardClaim); ZRoutedRpc.instance.Register("glitnir.ranking.grantrewarditem", (Action)RPC_GrantRewardItem); ZRoutedRpc.instance.Register("glitnir.ranking.finalizerewardclaim", (Action)RPC_FinalizeRewardClaim); ZRoutedRpc.instance.Register("glitnir.ranking.rewardclaimfeedback", (Action)RPC_RewardClaimFeedback); ZRoutedRpc.instance.Register("glitnir.ranking.requestpointsexchange", (Action)RPC_RequestPointsExchange); ZRoutedRpc.instance.Register("glitnir.ranking.grantexchangecoins", (Action)RPC_GrantExchangeCoins); ZRoutedRpc.instance.Register("glitnir.ranking.finalizepointsexchange", (Action)RPC_FinalizePointsExchange); ZRoutedRpc.instance.Register("glitnir.ranking.pointsexchangefeedback", (Action)RPC_PointsExchangeFeedback); ZRoutedRpc.instance.Register("glitnir.ranking.marketquestcomplete", (Action)RPC_ReportMarketplaceQuestComplete); ZRoutedRpc.instance.Register("glitnir.ranking.reportfishcaught", (Action)RPC_ReportFishCaught); ZRoutedRpc.instance.Register("glitnir.ranking.reportcrafteditem", (Action)RPC_ReportCraftedItem); ZRoutedRpc.instance.Register("glitnir.ranking.reportfarmharvest", (Action)RPC_ReportFarmHarvest); ZRoutedRpc.instance.Register("glitnir.ranking.reportplayerdeath", (Action)RPC_ReportPlayerDeath); ZRoutedRpc.instance.Register("glitnir.ranking.reportexplorationmap", (Action)RPC_ReportExplorationMap); _rpcsRegistered = true; } } private void Awake() { //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; _rulesFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; _uiFolderPath = string.Empty; _uiFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; _databaseFilePath = Path.Combine(Paths.ConfigPath, "GlitnirRanking", "SavedData", "DB.db"); _legacyDatabaseFilePath = Path.Combine(Paths.ConfigPath, "glitnir.ranking.database.legacy.db"); if (IsDedicatedServerInstance()) { EnsureDatabaseDirectoryExists(); } LoadUiSettings(); _cfgDiscordTop3WebhookEnabled = ((BaseUnityPlugin)this).Config.Bind("Discord", "EnableTop3Webhook", true, "Ativa o webhook do Discord quando um jogador entra no Top 3 do ranking."); _cfgDiscordTop3WebhookUrl = ((BaseUnityPlugin)this).Config.Bind("Discord", "Top3WebhookUrl", "", "URL do webhook do Discord para anunciar ascensão ao Top 3."); _cfgIgnoreAdminsInRanking = ((BaseUnityPlugin)this).Config.Bind("Ranking", "IgnoreAdminsInRanking", true, "Se ativo, jogadores presentes na adminlist do servidor nao pontuam nem aparecem no ranking."); _cfgIgnoredAdminNames = ((BaseUnityPlugin)this).Config.Bind("Ranking", "IgnoredAdminNames", "", "Fallback opcional: nomes ou IDs de admins para ignorar. Separe por virgula, ponto e virgula ou quebra de linha."); InitializeSyncedRulesConfig(); SetupRulesConfigWatcher(); if (IsDedicatedServerInstance()) { LoadDatabase(); } else { _database = new RankingDatabase(); } _harmony = new Harmony("com.glitnir.ranking"); _harmony.PatchAll(); } private void OnDestroy() { try { if (IsDedicatedServerInstance()) { SaveDatabase(); } try { if (_rulesConfigWatcher != null) { _rulesConfigWatcher.EnableRaisingEvents = false; _rulesConfigWatcher.Dispose(); _rulesConfigWatcher = null; } } catch { } DestroyRankingInputBlocker(); SaveUiSettings(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } } private void Update() { //IL_0057: 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) RegisterRpcsIfNeeded(); ProcessRulesConfigReloadIfNeeded(); RefreshRulesFromSyncedConfigIfNeeded(); if (!Application.isBatchMode) { CleanupOldLocalRecentHits(); CheckInitialServerSnapshotRequest(); } if (Application.isBatchMode) { CleanupOldDamageCredits(); CleanupOldProcessedKills(); ProcessPendingKillChecks(); return; } if ((int)_uiToggleKey != 0 && Input.GetKeyDown(_uiToggleKey)) { ToggleRankingHud(); } if (_hudVisible) { if (Input.GetKeyDown((KeyCode)27)) { CloseRankingHudAndCollapseAll(); return; } _clientRefreshTimer += Time.unscaledDeltaTime; if (_clientRefreshTimer >= 1f) { _clientRefreshTimer = 0f; RequestSnapshotFromServer(); } ProcessLocalExplorationMapReport(); } else { SetRankingInputBlockerVisible(visible: false); } if (IsServerInstance()) { CleanupOldDamageCredits(); CleanupOldProcessedKills(); ProcessPendingKillChecks(); } } private bool IsServerInstance() { if (Application.isBatchMode) { return true; } try { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } } catch { } return false; } private bool IsDedicatedServerInstance() { return Application.isBatchMode; } private bool IsConnectedToDedicatedServer() { return !Application.isBatchMode && GetServerPeerUid() != 0; } public void ReportLocalMarketplaceQuestCompletion(int questUid) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown try { if (_rules != null && _rules.RankingEnabled && _rules.EnableMarketplaceQuestPoints && TryGetMarketplaceQuestRule(questUid, out var rule) && !((Object)(object)Player.m_localPlayer == (Object)null) && ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(questUid); val.Write(SafeMarketplaceQuestKey(rule.QuestKey)); val.Write(rule.Points); val.Write(SafeLimit(Player.m_localPlayer.GetPlayerName(), 32)); ZRoutedRpc.instance.InvokeRoutedRPC(GetServerPeerUid(), "glitnir.ranking.marketquestcomplete", new object[1] { val }); DebugLog(DebugCategory.Points, "Quest Marketplace reportada: uid=" + questUid + " key=" + rule.QuestKey + " points=" + rule.Points); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao reportar conclusão de quest do Marketplace: " + ex)); } } private void RPC_ReportMarketplaceQuestComplete(long sender, ZPackage pkg) { try { if (!IsServerInstance() || pkg == null) { return; } int questUid = pkg.ReadInt(); string questKey = SafeMarketplaceQuestKey(pkg.ReadString()); int requestedPoints = Mathf.Clamp(pkg.ReadInt(), -2147483647, int.MaxValue); string text = SanitizePlayerName(pkg.ReadString()); string text2 = ResolvePlayerNameFromSender(sender); if (string.IsNullOrWhiteSpace(text2)) { text2 = text; } if (!string.IsNullOrWhiteSpace(text2)) { if (ShouldIgnoreSenderForRanking(sender, text2)) { DebugLog(DebugCategory.Points, "Quest Marketplace ignorada para admin: " + text2); } else { ProcessMarketplaceQuestReport(text2, questUid, questKey, requestedPoints, "rpc-marketplace-quest"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportMarketplaceQuestComplete: " + ex)); } } private void ProcessMarketplaceQuestReport(string playerName, int questUid, string questKey, int requestedPoints, string source) { try { if (!IsServerInstance() || _rules == null || !_rules.RankingEnabled || !_rules.EnableMarketplaceQuestPoints) { return; } if (!TryGetMarketplaceQuestRule(questUid, out var rule)) { DebugLog(DebugCategory.Points, "Quest do Marketplace ignorada sem regra: uid=" + questUid + " key=" + questKey + " source=" + source); return; } if (!string.IsNullOrWhiteSpace(questKey) && !string.Equals(rule.QuestKey, questKey, StringComparison.OrdinalIgnoreCase)) { DebugLog(DebugCategory.Points, "Quest do Marketplace rejeitada por chave divergente: uid=" + questUid + " key=" + questKey + " esperado=" + rule.QuestKey); return; } playerName = SanitizePlayerName(playerName); if (ShouldIgnorePlayerForRanking(playerName)) { DebugLog(DebugCategory.Points, "Quest Marketplace ignorada para admin: " + playerName); return; } if (HasMarketplaceQuestCredit(playerName, rule.QuestKey)) { DebugLog(DebugCategory.Points, "Quest Marketplace já creditada: player=" + playerName + " key=" + rule.QuestKey); return; } RankingEntry orCreateEntry = GetOrCreateEntry(playerName); if (orCreateEntry != null) { int points = rule.Points; if (requestedPoints != points) { DebugLog(DebugCategory.Points, "Quest Marketplace com pontos normalizados: player=" + playerName + " key=" + rule.QuestKey + " solicitado=" + requestedPoints + " configurado=" + points); } ApplyPointsToEntry(orCreateEntry, points, "Quest Marketplace: " + rule.QuestKey); MarkMarketplaceQuestCredit(playerName, rule.QuestKey); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar conclusão de quest do Marketplace: " + ex)); } } private string BuildMarketplaceQuestCreditKey(string playerName, string questKey) { return SanitizePlayerName(playerName).ToLowerInvariant() + "|" + SafeMarketplaceQuestKey(questKey); } private bool HasMarketplaceQuestCredit(string playerName, string questKey) { if (_database == null || _database.MarketplaceQuestCredits == null) { return false; } string creditKey = BuildMarketplaceQuestCreditKey(playerName, questKey); return _database.MarketplaceQuestCredits.Any((MarketplaceQuestCreditRecord x) => x != null && string.Equals(BuildMarketplaceQuestCreditKey(x.PlayerName, x.QuestKey), creditKey, StringComparison.OrdinalIgnoreCase)); } private void MarkMarketplaceQuestCredit(string playerName, string questKey) { if (_database == null) { _database = new RankingDatabase(); } if (_database.MarketplaceQuestCredits == null) { _database.MarketplaceQuestCredits = new List(); } if (!HasMarketplaceQuestCredit(playerName, questKey)) { _database.MarketplaceQuestCredits.Add(new MarketplaceQuestCreditRecord { PlayerName = SanitizePlayerName(playerName), QuestKey = SafeMarketplaceQuestKey(questKey), GrantedAtUtc = DateTime.UtcNow.ToString("O") }); if (IsServerInstance()) { SaveDatabase(); } } } private void ProcessLocalExplorationMapReport() { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown try { if (_rules == null || !_rules.RankingEnabled || !_rules.EnableExplorationJackpots || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Minimap.instance == (Object)null) { return; } _explorationReportTimer += Time.unscaledDeltaTime; if (_explorationReportTimer < 15f) { return; } _explorationReportTimer = 0f; float localMapExplorationPercent = GetLocalMapExplorationPercent(); if (!(localMapExplorationPercent < 0f) && !(localMapExplorationPercent <= _lastReportedMapExplorePercent + 0.05f)) { _lastReportedMapExplorePercent = localMapExplorationPercent; long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0L && _rpcsRegistered && ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(localMapExplorationPercent); val.Write(SafeLimit(Player.m_localPlayer.GetPlayerName(), 32)); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.reportexplorationmap", new object[1] { val }); DebugLog(DebugCategory.Points, "Exploração de mapa reportada: " + localMapExplorationPercent + "%"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao reportar exploração de mapa: " + ex.Message)); } } private float GetLocalMapExplorationPercent() { try { Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return -1f; } FieldInfo fieldInfo = AccessTools.Field(typeof(Minimap), "m_explored"); if (fieldInfo == null) { return -1f; } if (!(fieldInfo.GetValue(instance) is bool[] array) || array.Length == 0) { return -1f; } int num = 0; for (int i = 0; i < array.Length; i++) { if (array[i]) { num++; } } float num2 = (float)num * 100f / (float)Mathf.Max(1, array.Length); return Mathf.Clamp(num2, 0f, 100f); } catch { return -1f; } } private void RPC_ReportExplorationMap(long sender, ZPackage pkg) { try { if (IsServerInstance() && pkg != null) { float percent = Mathf.Clamp(pkg.ReadSingle(), 0f, 100f); string text = SanitizePlayerName(pkg.ReadString()); string text2 = ResolvePlayerNameFromSender(sender); if (string.IsNullOrWhiteSpace(text2)) { text2 = text; } ProcessExplorationMapReport(text2, percent); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportExplorationMap: " + ex)); } } private void ProcessExplorationMapReport(string playerName, float percent) { try { if (!IsServerInstance() || _rules == null || !_rules.RankingEnabled || !_rules.EnableExplorationJackpots) { return; } playerName = SanitizePlayerName(playerName); if (string.IsNullOrWhiteSpace(playerName) || ShouldIgnorePlayerForRanking(playerName) || _rules.ExplorationMapJackpots == null || _rules.ExplorationMapJackpots.Count == 0) { return; } RankingEntry orCreateEntry = GetOrCreateEntry(playerName); if (orCreateEntry == null) { return; } if (orCreateEntry.ProgressCounters == null) { orCreateEntry.ProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); } if (orCreateEntry.GenericJackpotCredits == null) { orCreateEntry.GenericJackpotCredits = new HashSet(StringComparer.OrdinalIgnoreCase); } if (orCreateEntry.FloatProgressCounters == null) { orCreateEntry.FloatProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); } float num = 0f; int value = 0; if (orCreateEntry.FloatProgressCounters.TryGetValue("ExplorationMap:Percent", out var value2)) { num = value2; } else if (orCreateEntry.ProgressCounters.TryGetValue("ExplorationMap:Percent", out value)) { num = value; } float num2 = Mathf.Clamp(Mathf.Max(num, percent), 0f, 100f); int value3 = Mathf.Clamp(Mathf.FloorToInt(num2), 0, 100); orCreateEntry.FloatProgressCounters["ExplorationMap:Percent"] = num2; orCreateEntry.FloatProgressCounters["Exploration:Map"] = num2; orCreateEntry.FloatProgressCounters["Exploracao:Mapa"] = num2; orCreateEntry.ProgressCounters["ExplorationMap:Percent"] = value3; orCreateEntry.ProgressCounters["Exploration:Map"] = value3; orCreateEntry.ProgressCounters["Exploracao:Mapa"] = value3; string text = SafeLimit(_rules.RewardClaimCycleId, 64); foreach (KeyValuePair item2 in _rules.ExplorationMapJackpots.OrderBy((KeyValuePair p) => p.Key)) { int num3 = Mathf.Clamp(item2.Key, 1, 100); int num4 = Mathf.Max(0, item2.Value); if (!(num2 < (float)num3) && num4 > 0) { string item = text + ":ExplorationMap:" + num3; if (!orCreateEntry.GenericJackpotCredits.Contains(item)) { orCreateEntry.GenericJackpotCredits.Add(item); ApplyPointsToEntry(orCreateEntry, num4, "Exploração do mapa: " + num3 + "%"); orCreateEntry.ExplorationMapJackpotPointsTotal = Mathf.Clamp(orCreateEntry.ExplorationMapJackpotPointsTotal + num4, 0, int.MaxValue); } } } SaveDatabase(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar exploração de mapa: " + ex)); } } private void EnsureUiDirectoryExists() { } private void MigrateLegacyUiSettingsIfNeeded() { try { string text = Path.Combine(Paths.ConfigPath, "glitnir.ranking.ui.cfg"); if (!string.IsNullOrWhiteSpace(_uiFilePath) && !string.Equals(text, _uiFilePath, StringComparison.OrdinalIgnoreCase) && !File.Exists(_uiFilePath) && File.Exists(text)) { File.Copy(text, _uiFilePath, overwrite: true); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao migrar configuração antiga da UI do ranking: " + ex)); } } private void LoadUiSettings() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) try { _uiToggleKey = ((BaseUnityPlugin)this).Config.Bind("UI", "HudShortcutKey", _uiToggleKey, "Tecla para abrir/fechar o HUD. Use nomes do Unity KeyCode, ex.: F, G, Alpha1, None.").Value; _uiUseSystemFonts = ((BaseUnityPlugin)this).Config.Bind("UI", "UseSystemFonts", _uiUseSystemFonts, "Ative apenas se o cliente renderizar bem fontes instaladas no sistema.").Value; _uiTitleFontNames = ((BaseUnityPlugin)this).Config.Bind("UI", "TitleFontNames", _uiTitleFontNames, "Fontes opcionais para titulos, separadas por |.").Value; _uiBodyFontNames = ((BaseUnityPlugin)this).Config.Bind("UI", "BodyFontNames", _uiBodyFontNames, "Fontes opcionais para texto, separadas por |.").Value; _uiAccentFontNames = ((BaseUnityPlugin)this).Config.Bind("UI", "AccentFontNames", _uiAccentFontNames, "Fontes opcionais para detalhes/acento, separadas por |.").Value; ((Rect)(ref _iconRect)).x = ((BaseUnityPlugin)this).Config.Bind("UI", "IconX", ((Rect)(ref _iconRect)).x, "Posição X do botão do ranking.").Value; ((Rect)(ref _iconRect)).y = ((BaseUnityPlugin)this).Config.Bind("UI", "IconY", ((Rect)(ref _iconRect)).y, "Posição Y do botão do ranking.").Value; float value = ((BaseUnityPlugin)this).Config.Bind("UI", "IconSize", ((Rect)(ref _iconRect)).width, "Tamanho do botão do ranking.").Value; ((Rect)(ref _iconRect)).width = Mathf.Clamp(value, 36f, 120f); ((Rect)(ref _iconRect)).height = ((Rect)(ref _iconRect)).width; _uiIconZoom = Mathf.Clamp(((BaseUnityPlugin)this).Config.Bind("UI", "IconZoom", _uiIconZoom, "Zoom interno do ícone do botão.").Value, 0.75f, 1.3f); ((Rect)(ref _windowRect)).x = ((BaseUnityPlugin)this).Config.Bind("UI", "WindowX", ((Rect)(ref _windowRect)).x, "Posição X da janela do ranking.").Value; ((Rect)(ref _windowRect)).y = ((BaseUnityPlugin)this).Config.Bind("UI", "WindowY", ((Rect)(ref _windowRect)).y, "Posição Y da janela do ranking.").Value; ((Rect)(ref _windowRect)).width = Mathf.Max(420f, ((BaseUnityPlugin)this).Config.Bind("UI", "WindowW", ((Rect)(ref _windowRect)).width, "Largura da janela do ranking.").Value); ((Rect)(ref _windowRect)).height = Mathf.Max(760f, ((BaseUnityPlugin)this).Config.Bind("UI", "WindowH", ((Rect)(ref _windowRect)).height, "Altura da janela do ranking.").Value); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao carregar UI do ranking: " + ex)); } } private void SaveUiSettings() { try { ((BaseUnityPlugin)this).Config.Save(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao salvar configuração do ranking: " + ex)); } } private Texture2D LoadTextureFromUiFolder(params string[] fileNames) { if (fileNames == null || fileNames.Length == 0) { return null; } foreach (string text in fileNames) { if (!string.IsNullOrWhiteSpace(text)) { Texture2D val = LoadTextureFromUiFolder(text); if ((Object)(object)val != (Object)null) { return val; } } } return null; } private Texture2D LoadTextureFromUiFolder(string fileName) { Texture2D val = LoadEmbeddedTexture(fileName); if ((Object)(object)val != (Object)null) { return val; } try { if (string.IsNullOrWhiteSpace(_uiFolderPath)) { return null; } string text = Path.Combine(_uiFolderPath, fileName); if (!File.Exists(text)) { return null; } byte[] array = File.ReadAllBytes(text); if (array == null || array.Length == 0) { if (_missingUiTextureWarnings.Add(fileName + ":empty")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking UI] Arquivo vazio ou inválido: " + text)); } return null; } Texture2D val2 = CreateTextureFromBytes(array, fileName); if ((Object)(object)val2 != (Object)null) { return val2; } if (_missingUiTextureWarnings.Add(fileName + ":decoder")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking UI] Não foi possível decodificar a textura: " + text + ". Verifique se o PNG/JPG é válido.")); } } catch (Exception ex) { if (_missingUiTextureWarnings.Add(fileName + ":exception")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking UI] Falha ao carregar textura " + fileName + ": " + ex.Message)); } } return null; } private Texture2D LoadEmbeddedTexture(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) { return null; } try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); if (executingAssembly == null) { return null; } string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); if (manifestResourceNames == null || manifestResourceNames.Length == 0) { return null; } string normalizedFileName = fileName.Replace('/', '.').Replace('\\', '.'); StringComparison comparison = StringComparison.OrdinalIgnoreCase; string text = manifestResourceNames.FirstOrDefault((string name) => !string.IsNullOrWhiteSpace(name) && (name.Equals(normalizedFileName, comparison) || name.EndsWith("." + normalizedFileName, comparison) || name.EndsWith(fileName, comparison) || name.IndexOf(normalizedFileName, comparison) >= 0)); if (string.IsNullOrWhiteSpace(text)) { return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { return null; } byte[] array = ReadAllBytes(stream); if (array == null || array.Length == 0) { return null; } Texture2D val = CreateTextureFromBytes(array, text); if ((Object)(object)val != (Object)null) { return val; } } catch (Exception ex) { if (_missingUiTextureWarnings.Add(fileName + ":embeddedexception")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking UI] Falha ao carregar textura embutida " + fileName + ": " + ex.Message)); } } return null; } private Texture2D CreateTextureFromBytes(byte[] bytes, string textureName) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (bytes == null || bytes.Length == 0) { return null; } Texture2D val = null; try { val = new Texture2D(2, 2, (TextureFormat)5, false); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; ((Object)val).name = textureName; if (TryLoadTextureBytes(val, bytes)) { return val; } } catch (Exception ex) { if (_missingUiTextureWarnings.Add((textureName ?? "texture") + ":createtextureexception")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking UI] Falha ao criar textura " + textureName + ": " + ex.Message)); } } if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } return null; } private byte[] ReadAllBytes(Stream stream) { if (stream == null) { return null; } if (stream is MemoryStream memoryStream) { return memoryStream.ToArray(); } using MemoryStream memoryStream2 = new MemoryStream(); stream.CopyTo(memoryStream2); return memoryStream2.ToArray(); } private bool TryLoadTextureBytes(Texture2D texture, byte[] bytes) { if ((Object)(object)texture == (Object)null || bytes == null || bytes.Length == 0) { return false; } try { Type type = FindTypeInLoadedAssemblies("UnityEngine.ImageConversion"); if (type != null) { MethodInfo method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); if (method != null) { if (!(method.Invoke(null, new object[2] { texture, bytes }) is bool result)) { return true; } return result; } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking UI] Falha no carregamento refletido da textura: " + ex.Message)); } return false; } private Type FindTypeInLoadedAssemblies(string fullTypeName) { if (string.IsNullOrWhiteSpace(fullTypeName)) { return null; } try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!(assembly == null)) { Type type = assembly.GetType(fullTypeName, throwOnError: false); if (type != null) { return type; } } } } catch { } return null; } private Texture2D CreateSolidTexture(Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000e: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(1, 1, (TextureFormat)5, false); val.SetPixel(0, 0, color); val.Apply(false, true); ((Texture)val).wrapMode = (TextureWrapMode)1; return val; } private void EnsureUiTexturesLoaded() { //IL_0026: 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_0070: Unknown result type (might be due to invalid IL or missing references) if (!_uiTexturesLoaded) { _uiTransparentTexture = CreateSolidTexture(new Color(0f, 0f, 0f, 0f)); _uiWhiteTexture = CreateSolidTexture(new Color(1f, 1f, 1f, 1f)); _uiPanelTexture = CreateSolidTexture(new Color(0.05f, 0.04f, 0.03f, 0.72f)); _uiBackgroundTexture = LoadTextureFromUiFolder("background_epic_forest_transparent.png"); _uiRankingIconTexture = LoadTextureFromUiFolder("ranking_icon.png"); _uiTitleRankingTexture = LoadTextureFromUiFolder("title_ranking_glitnir_transparent.png"); _uiTitleTopTexture = LoadTextureFromUiFolder("topRanking.png", "title_top_glitnir_transparent.png", "title_top_glitnir.png", "title_top_ranking.png"); _uiTitleGuideTexture = LoadTextureFromUiFolder("guiaHonra.png", "guideHonor.png", "title_guia_honra_transparent.png", "title_guia_de_honra_transparent.png", "title_guide_honor.png"); _uiTitlePlayerTexture = LoadTextureFromUiFolder("title_seu_desempenho_transparent.png"); _uiTitleActionsTexture = LoadTextureFromUiFolder("title_oraculo_ranking_transparent.png", "title_oraculo_do_ranking_transparent.png", "oraculo_ranking.png", "oraculo_do_ranking.png"); _uiRank1IconTexture = LoadTextureFromUiFolder("icon/rank_1.png", "icons/rank_1.png", "rank_1.png"); _uiRank2IconTexture = LoadTextureFromUiFolder("icon/rank_2.png", "icons/rank_2.png", "rank_2.png"); _uiRank3IconTexture = LoadTextureFromUiFolder("icon/rank_3.png", "icons/rank_3.png", "rank_3.png"); LoadRuleCategoryIcons(); _uiTexturesLoaded = true; } } private void LoadRuleCategoryIcons() { _uiRuleCategoryIcons.Clear(); RegisterRuleCategoryIcon("Combate", "0 (5)"); RegisterRuleCategoryIcon("Bosses", "0 (14)"); RegisterRuleCategoryIcon("Skills", "0 (1)"); RegisterRuleCategoryIcon("Quests", "0 (31)"); RegisterRuleCategoryIcon("Pesca", "0 (32)"); RegisterRuleCategoryIcon("Exploração", "0 (27)"); RegisterRuleCategoryIcon("Exploracao", "0 (27)"); RegisterRuleCategoryIcon("Exploration", "0 (27)"); RegisterRuleCategoryIcon("Exploração", "icon_exploration.png"); RegisterRuleCategoryIcon("Exploracao", "icon_exploration.png"); RegisterRuleCategoryIcon("Exploration", "icon_exploration.png"); RegisterRuleCategoryIcon("Produção", "0 (26)"); RegisterRuleCategoryIcon("Cultivo", "0 (11)"); RegisterRuleCategoryIcon("Conquistas", "0 (29)"); RegisterRuleCategoryIcon("Penalidades", "0 (23)"); RegisterRuleCategoryIcon("Resumo", "0 (29)"); RegisterRuleCategoryIcon("Origem", "0 (12)"); RegisterRuleCategoryIcon("Último registro", "0 (7)"); RegisterRuleCategoryIcon("Recompensa", "0 (29)"); RegisterRuleCategoryIcon("Configuração", "0 (27)"); } private void RegisterRuleCategoryIcon(string categoryKey, string iconFileNameWithoutExtension) { if (!string.IsNullOrWhiteSpace(categoryKey) && !string.IsNullOrWhiteSpace(iconFileNameWithoutExtension)) { string text = (iconFileNameWithoutExtension.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ? iconFileNameWithoutExtension : (iconFileNameWithoutExtension + ".png")); Texture2D val = LoadTextureFromUiFolder("icon/" + text, "icons/" + text, text); if ((Object)(object)val != (Object)null) { _uiRuleCategoryIcons[categoryKey] = val; } } } private bool IsLocalPlayerAttackAuthor(HitData hit) { //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_002b: 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) if (hit == null || (Object)(object)Player.m_localPlayer == (Object)null) { return false; } try { ZDOID attacker = hit.m_attacker; ZDOID zDOID = ((Character)Player.m_localPlayer).GetZDOID(); if (!((ZDOID)(ref attacker)).IsNone() && !((ZDOID)(ref zDOID)).IsNone() && ((ZDOID)(ref attacker)).UserID == ((ZDOID)(ref zDOID)).UserID && ((ZDOID)(ref attacker)).ID == ((ZDOID)(ref zDOID)).ID) { return true; } } catch { } try { Character attacker2 = hit.GetAttacker(); if ((Object)(object)attacker2 == (Object)(object)Player.m_localPlayer) { return true; } } catch { } return false; } private string GetLocalPlayerKey() { try { if ((Object)(object)Player.m_localPlayer != (Object)null) { return GetZdoKey((Character)(object)Player.m_localPlayer); } } catch { } return ""; } internal void ReportLocalPlayerDeathToServer() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown try { if (!((Object)(object)Player.m_localPlayer == (Object)null) && ZRoutedRpc.instance != null) { long serverPeerUid = GetServerPeerUid(); ZPackage val = new ZPackage(); val.Write(SafeLimit(Player.m_localPlayer.GetPlayerName(), 32)); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.reportplayerdeath", new object[1] { val }); DebugLog(DebugCategory.Points, "Cliente reportando morte: player=" + GetLocalPlayerName()); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao enviar morte local: " + ex)); } } private void RPC_ReportPlayerDeath(long sender, ZPackage pkg) { try { if (IsServerInstance() && pkg != null) { string text = SanitizePlayerName(pkg.ReadString()); string text2 = ResolvePlayerNameFromSender(sender); if (string.IsNullOrWhiteSpace(text2)) { text2 = text; } if (ShouldIgnoreSenderForRanking(sender, text2)) { DebugLog(DebugCategory.Points, "Morte ignorada para admin: " + text2); } else { ProcessPlayerDeathReport(text2, "rpc-death"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportPlayerDeath: " + ex)); } } private void ProcessPlayerDeathReport(string playerName, string source) { try { if (!IsServerInstance() || _rules == null || !_rules.RankingEnabled || !_rules.EnableDeathPenalty) { return; } playerName = SanitizePlayerName(playerName); if (string.IsNullOrWhiteSpace(playerName)) { return; } if (ShouldIgnorePlayerForRanking(playerName)) { DebugLog(DebugCategory.Points, "Morte ignorada para admin: " + playerName); return; } RankingEntry orCreateEntry = GetOrCreateEntry(playerName); if (orCreateEntry == null) { return; } if (orCreateEntry.ProgressCounters == null) { orCreateEntry.ProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); } if (orCreateEntry.GenericJackpotCredits == null) { orCreateEntry.GenericJackpotCredits = new HashSet(StringComparer.OrdinalIgnoreCase); } string key = "DeathPenalty:Deaths"; int value = 0; orCreateEntry.ProgressCounters.TryGetValue(key, out value); value = Mathf.Clamp(value + 1, 0, int.MaxValue); orCreateEntry.ProgressCounters[key] = value; orCreateEntry.TotalDeaths = value; DebugLog(DebugCategory.Points, "Morte registrada: player=" + playerName + " deaths=" + value + " source=" + source); if (_rules.DeathPenaltyUseMultiplier) { int num = Mathf.Max(0, _rules.DeathPenaltyPerDeath); if (num > 0) { ApplyPointsToEntry(orCreateEntry, -num, "Penalidade por morte: " + value + "x -" + num); orCreateEntry.DeathPenaltyPointsTotal = Mathf.Clamp(orCreateEntry.DeathPenaltyPointsTotal + num, 0, int.MaxValue); } SaveDatabase(); return; } if (_rules.DeathPenaltyRules != null && _rules.DeathPenaltyRules.Count > 0) { string text = SafeLimit(_rules.RewardClaimCycleId, 64); foreach (KeyValuePair item2 in _rules.DeathPenaltyRules.OrderBy((KeyValuePair p) => p.Key)) { int num2 = Mathf.Max(1, item2.Key); int num3 = Mathf.Max(0, item2.Value); if (value < num2) { continue; } string item = text + ":DeathPenalty:" + num2; if (!orCreateEntry.GenericJackpotCredits.Contains(item)) { orCreateEntry.GenericJackpotCredits.Add(item); if (num3 > 0) { ApplyPointsToEntry(orCreateEntry, -num3, "Penalidade por morte: " + value + " mortes"); orCreateEntry.DeathPenaltyPointsTotal = Mathf.Clamp(orCreateEntry.DeathPenaltyPointsTotal + num3, 0, int.MaxValue); } } } } SaveDatabase(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar penalidade por morte: " + ex)); } } private void IncrementProgressCounter(RankingEntry entry, string category, string key, int amount) { if (entry != null && !string.IsNullOrWhiteSpace(category) && !string.IsNullOrWhiteSpace(key) && amount > 0) { if (entry.ProgressCounters == null) { entry.ProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); } string key2 = SafeKey(category) + ":" + SafeKey(key); int value = 0; entry.ProgressCounters.TryGetValue(key2, out value); entry.ProgressCounters[key2] = Mathf.Clamp(value + amount, 0, int.MaxValue); } } private void IncrementProgressCounterAlias(RankingEntry entry, string category, string key, int amount) { IncrementProgressCounter(entry, category, key, amount); } private void AddProgressAndCheckJackpot(RankingEntry entry, string category, string key, int amount, JackpotRule rule, string reason, bool unique) { if (entry == null || rule == null || rule.RequiredAmount <= 0 || rule.Points <= 0) { return; } if (entry.ProgressCounters == null) { entry.ProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); } if (entry.GenericJackpotCredits == null) { entry.GenericJackpotCredits = new HashSet(StringComparer.OrdinalIgnoreCase); } string text = SafeKey(category) + ":" + SafeKey(key); string item = SafeLimit(_rules.RewardClaimCycleId, 64) + ":" + text + ":" + rule.RequiredAmount; if (entry.GenericJackpotCredits.Contains(item)) { return; } int value = 0; entry.ProgressCounters.TryGetValue(text, out value); value = (unique ? Mathf.Max(value, amount) : Mathf.Clamp(value + amount, 0, int.MaxValue)); entry.ProgressCounters[text] = value; if (value < rule.RequiredAmount) { if (IsDedicatedServerInstance()) { SaveDatabase(); } return; } entry.GenericJackpotCredits.Add(item); ApplyPointsToEntry(entry, rule.Points, reason + " (" + value + "/" + rule.RequiredAmount + ")"); if (category.Equals("Farm", StringComparison.OrdinalIgnoreCase)) { entry.TotalFarmJackpotsPontuados++; entry.FarmJackpotPointsTotal = Mathf.Clamp(entry.FarmJackpotPointsTotal + rule.Points, -2147483647, int.MaxValue); } else if (category.Equals("UniqueCraft", StringComparison.OrdinalIgnoreCase)) { entry.TotalUniqueCraftJackpotsPontuados++; entry.UniqueCraftJackpotPointsTotal = Mathf.Clamp(entry.UniqueCraftJackpotPointsTotal + rule.Points, -2147483647, int.MaxValue); } if (IsServerInstance()) { SaveDatabase(); } } private void SendDiscordTop3EnteredWebhook(string playerName, int rank, int points, string reason) { if (_cfgDiscordTop3WebhookUrl != null && !string.IsNullOrWhiteSpace(_cfgDiscordTop3WebhookUrl.Value)) { string text = rank switch { 2 => "\ud83e\udd48", 1 => "\ud83e\udd47", _ => "\ud83e\udd49", }; string field1Value = (string.IsNullOrWhiteSpace(playerName) ? "Jogador" : playerName.Trim()); string field4Value = (string.IsNullOrWhiteSpace(reason) ? "Ascensão no ranking" : reason.Trim()); string json = BuildDiscordTop3EmbedJson("\ud83c\udfdb\ufe0f ORÁCULO DO RANKING", "✨ Um novo nome ascendeu ao pódio de Glitnir.", 15844367, "\ud83d\udc64 Jogador", field1Value, "\ud83c\udfc6 Posição", text + " #" + rank, "⭐ Pontos", points.ToString(), "\ud83d\udcdc Registro", field4Value, "\ud83c\udf1f Seu nome agora ecoa nos salões de Glitnir."); PostDiscordWebhook(json); } } private void SendDiscordTop3LostWebhook(string playerName, int oldRank, int newRank, int points, string reason) { if (_cfgDiscordTop3WebhookUrl != null && !string.IsNullOrWhiteSpace(_cfgDiscordTop3WebhookUrl.Value)) { string field1Value = (string.IsNullOrWhiteSpace(playerName) ? "Jogador" : playerName.Trim()); string field4Value = (string.IsNullOrWhiteSpace(reason) ? "Movimento no ranking" : reason.Trim()); string text = ((newRank == int.MaxValue) ? "Fora do ranking" : ("#" + newRank)); string json = BuildDiscordTop3EmbedJson("\ud83c\udfdb\ufe0f ORÁCULO DO RANKING", "⚠\ufe0f Um campeão perdeu seu lugar entre os três maiores.", 15158332, "\ud83d\udc64 Jogador", field1Value, "\ud83d\udcc9 Mudança", "#" + oldRank + " → " + text, "⭐ Pontos", points.ToString(), "\ud83d\udcdc Registro", field4Value, "⏳ Os salões de Glitnir aguardam sua retomada."); PostDiscordWebhook(json); } } private void SendDiscordTop3DroppedWebhook(string playerName, int oldRank, int newRank, int points, string reason) { if (_cfgDiscordTop3WebhookUrl != null && !string.IsNullOrWhiteSpace(_cfgDiscordTop3WebhookUrl.Value)) { string field1Value = (string.IsNullOrWhiteSpace(playerName) ? "Jogador" : playerName.Trim()); string field4Value = (string.IsNullOrWhiteSpace(reason) ? "Movimento no ranking" : reason.Trim()); string json = BuildDiscordTop3EmbedJson("\ud83c\udfdb\ufe0f ORÁCULO DO RANKING", "⚖\ufe0f A balança da honra se moveu dentro do Top 3.", 3447003, "\ud83d\udc64 Jogador", field1Value, "\ud83d\udcc9 Posição", "#" + oldRank + " → #" + newRank, "⭐ Pontos", points.ToString(), "\ud83d\udcdc Registro", field4Value, "\ud83d\udd25 A disputa pelo topo continua."); PostDiscordWebhook(json); } } private string BuildDiscordTop3EmbedJson(string title, string description, int color, string field1Name, string field1Value, string field2Name, string field2Value, string field3Name, string field3Value, string field4Name, string field4Value, string footerText) { string value = DateTime.UtcNow.ToString("o"); string value2 = BuildDiscordTop3PodiumValue(); return "{\"username\":\"Glitnir Ranking\",\"embeds\":[{\"title\":\"" + EscapeJson(title) + "\",\"description\":\"" + EscapeJson(description) + "\",\"color\":" + color + ",\"fields\":[{\"name\":\"\ud83c\udfc6 Pódio de Glitnir\",\"value\":\"" + EscapeJson(value2) + "\",\"inline\":false},{\"name\":\"" + EscapeJson(field1Name) + "\",\"value\":\"" + EscapeJson(field1Value) + "\",\"inline\":true},{\"name\":\"" + EscapeJson(field2Name) + "\",\"value\":\"" + EscapeJson(field2Value) + "\",\"inline\":true},{\"name\":\"" + EscapeJson(field3Name) + "\",\"value\":\"" + EscapeJson(field3Value) + "\",\"inline\":true},{\"name\":\"" + EscapeJson(field4Name) + "\",\"value\":\"" + EscapeJson(field4Value) + "\",\"inline\":false}],\"footer\":{\"text\":\"" + EscapeJson(footerText) + "\"},\"timestamp\":\"" + EscapeJson(value) + "\"}]}"; } private string BuildDiscordTop3PodiumValue() { try { if (_database == null || _database.Entries == null) { return "Nenhum nome registrado no pódio ainda."; } List list = (from x in _database.Entries where x != null && !string.IsNullOrWhiteSpace(x.PlayerName) && !ShouldIgnorePlayerForRanking(x.PlayerName) orderby x.Points descending, x.BossPointsTotal descending, x.KillPointsTotal descending, x.SkillPointsTotal descending, x.PlayerName select x).Take(3).ToList(); if (list.Count == 0) { return "Nenhum nome registrado no pódio ainda."; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < list.Count; i++) { RankingEntry rankingEntry = list[i]; string value = i switch { 1 => "\ud83e\udd48", 0 => "\ud83e\udd47", _ => "\ud83e\udd49", }; string value2 = (string.IsNullOrWhiteSpace(rankingEntry.PlayerName) ? "Jogador" : rankingEntry.PlayerName.Trim()); stringBuilder.Append(value).Append(" **#").Append(i + 1) .Append("** — ") .Append(value2) .Append("\n") .Append("⭐ **") .Append(rankingEntry.Points) .Append(" pts**"); if (i < list.Count - 1) { stringBuilder.Append("\n\n"); } } return stringBuilder.ToString(); } catch (Exception ex) { Log.LogWarning((object)("Erro ao montar pódio do webhook: " + ex.Message)); return "Pódio indisponível no momento."; } } private void PostDiscordWebhook(string json) { string url = ((_cfgDiscordTop3WebhookUrl != null) ? _cfgDiscordTop3WebhookUrl.Value : ""); if (string.IsNullOrWhiteSpace(url)) { return; } ThreadPool.QueueUserWorkItem(delegate { try { byte[] bytes = Encoding.UTF8.GetBytes(json); HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url); httpWebRequest.Method = "POST"; httpWebRequest.ContentType = "application/json"; httpWebRequest.ContentLength = bytes.Length; httpWebRequest.Timeout = 10000; using (Stream stream = httpWebRequest.GetRequestStream()) { stream.Write(bytes, 0, bytes.Length); } using HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse(); int statusCode = (int)httpWebResponse.StatusCode; if (statusCode < 200 || statusCode >= 300) { Log.LogWarning((object)("Webhook Top 3 Discord retornou status: " + statusCode)); } } catch (Exception ex) { Log.LogWarning((object)("Webhook Top 3 Discord falhou: " + ex.Message)); } }); } private string EscapeJson(string value) { if (string.IsNullOrEmpty(value)) { return ""; } return value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\r", "\\r") .Replace("\n", "\\n"); } private string SafeLimit(string value, int maxLength) { if (string.IsNullOrEmpty(value)) { return ""; } value = value.Replace("\r", " ").Replace("\n", " ").Replace("\t", " ") .Trim(); if (value.Length > maxLength) { value = value.Substring(0, maxLength); } return value; } private string SafeKey(string value) { value = SafeLimit(value, 128); value = value.Replace("|", "/"); return value; } private string SafeReason(string reason) { reason = SafeLimit(reason, 64); reason = reason.Replace("|", "/"); return reason; } private string SanitizePlayerName(string playerName) { playerName = SafeLimit(playerName, 32); playerName = playerName.Replace("|", "/"); if (string.IsNullOrWhiteSpace(playerName)) { return "Jogador"; } return playerName; } private RankingEntry GetOrCreateEntry(string playerName) { string safeName = SanitizePlayerName(playerName); RankingEntry rankingEntry = _database.Entries.FirstOrDefault((RankingEntry x) => string.Equals(x.PlayerName, safeName, StringComparison.OrdinalIgnoreCase)); if (rankingEntry != null) { return rankingEntry; } rankingEntry = new RankingEntry { PlayerName = safeName, Points = 0, LastReason = "", LastUpdateUtc = DateTime.UtcNow.ToString("O"), TotalSkillLevelUpsPontuados = 0, SkillPointsTotal = 0, BossCredits = new HashSet(StringComparer.OrdinalIgnoreCase), TotalDeaths = 0, DeathPenaltyPointsTotal = 0 }; _database.Entries.Add(rankingEntry); return rankingEntry; } private string GetLocalPlayerName() { try { if ((Object)(object)Player.m_localPlayer != (Object)null) { return SanitizePlayerName(Player.m_localPlayer.GetPlayerName()); } } catch { } return "Jogador"; } private long GetServerPeerUid() { try { if ((Object)(object)ZNet.instance == (Object)null) { return 0L; } if (ZNet.instance.IsServer()) { return ZDOMan.GetSessionID(); } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null) { return serverPeer.m_uid; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao obter peer do servidor: " + ex.Message)); } return 0L; } public string GetPrefabName(GameObject go) { if ((Object)(object)go == (Object)null) { return ""; } try { string text = ((Object)go).name; if (string.IsNullOrWhiteSpace(text)) { return ""; } int num = text.IndexOf('('); if (num > 0) { text = text.Substring(0, num); } return SafeKey(text.Trim()); } catch { } return ""; } private string GetZdoKey(GameObject go) { if ((Object)(object)go == (Object)null) { return ""; } try { ZNetView component = go.GetComponent(); if ((Object)(object)component != (Object)null && component.GetZDO() != null) { ZDO zDO = component.GetZDO(); return ((ZDOID)(ref zDO.m_uid)).UserID + ":" + ((ZDOID)(ref zDO.m_uid)).ID; } } catch { } return ""; } private string GetZdoKey(Character character) { //IL_001a: 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) if ((Object)(object)character == (Object)null) { return ""; } try { ZDOID zDOID = character.GetZDOID(); if (((ZDOID)(ref zDOID)).IsNone()) { return ""; } return ((ZDOID)(ref zDOID)).UserID + ":" + ((ZDOID)(ref zDOID)).ID; } catch { } try { ZNetView component = ((Component)character).GetComponent(); if ((Object)(object)component != (Object)null && component.GetZDO() != null) { ZDO zDO = component.GetZDO(); return ((ZDOID)(ref zDO.m_uid)).UserID + ":" + ((ZDOID)(ref zDO.m_uid)).ID; } } catch { } return ""; } private bool IsLocalPlayerSkillsInstance(Skills skills) { if ((Object)(object)skills == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return false; } try { Player value = Traverse.Create((object)skills).Field("m_player").GetValue(); if ((Object)(object)value != (Object)null && (Object)(object)value == (Object)(object)Player.m_localPlayer) { return true; } } catch { } return false; } private float GetSafeSkillLevel(Skills skills, SkillType skillType) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)skills != (Object)null) { return Mathf.Clamp(skills.GetSkillLevel(skillType), 0f, 100f); } } catch { } return 0f; } private int GetEffectiveSkillLevel(float rawLevel) { return Mathf.Clamp(Mathf.FloorToInt(rawLevel + 0.0001f), 0, 100); } private bool IsTrackableSkill(SkillType skillType) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) string skillKey = GetSkillKey(skillType); if (string.IsNullOrWhiteSpace(skillKey)) { return false; } if (string.Equals(skillKey, "None", StringComparison.OrdinalIgnoreCase)) { return false; } if (string.Equals(skillKey, "All", StringComparison.OrdinalIgnoreCase)) { return false; } return true; } private string GetSkillKey(SkillType skillType) { return SafeKey(((object)(SkillType)(ref skillType)).ToString()); } private string GetSkillDisplayName(string skillKey) { skillKey = SafeKey(skillKey); switch (skillKey) { case "WoodCutting": return "Wood Cutting"; case "BloodMagic": return "Blood Magic"; case "ElementalMagic": return "Elemental Magic"; default: { StringBuilder stringBuilder = new StringBuilder(skillKey.Length + 8); for (int i = 0; i < skillKey.Length; i++) { char c = skillKey[i]; if (i > 0 && char.IsUpper(c) && char.IsLetter(skillKey[i - 1])) { stringBuilder.Append(' '); } stringBuilder.Append(c); } return stringBuilder.ToString().Trim(); } } } public float CaptureLocalSkillLevelBeforeRaise(Skills skills, SkillType skillType) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)skills == (Object)null || !IsTrackableSkill(skillType)) { return 0f; } if (!IsLocalPlayerSkillsInstance(skills)) { return 0f; } return GetSafeSkillLevel(skills, skillType); } public void NotifyLocalSkillGain(Skills skills, SkillType skillType, float oldRawLevel) { //IL_0015: 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_008c: 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_0100: Expected O, but got Unknown try { if ((Object)(object)skills == (Object)null || !IsTrackableSkill(skillType) || (Object)(object)Player.m_localPlayer == (Object)null || !IsLocalPlayerSkillsInstance(skills)) { return; } float safeSkillLevel = GetSafeSkillLevel(skills, skillType); int effectiveSkillLevel = GetEffectiveSkillLevel(oldRawLevel); int effectiveSkillLevel2 = GetEffectiveSkillLevel(safeSkillLevel); int num = Mathf.Clamp(effectiveSkillLevel2 - effectiveSkillLevel, 0, 100); if (num <= 0) { return; } string skillKey = GetSkillKey(skillType); if (string.IsNullOrWhiteSpace(skillKey)) { return; } if (IsServerInstance()) { ProcessSkillGainReport(GetLocalPlayerName(), skillKey, num, effectiveSkillLevel, effectiveSkillLevel2, "local-host"); return; } long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0L && _rpcsRegistered && ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(skillKey); val.Write(num); val.Write(effectiveSkillLevel); val.Write(effectiveSkillLevel2); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.reportskillgain", new object[1] { val }); DebugLog(DebugCategory.Skill, "Cliente reportando SKILL: player=" + GetLocalPlayerName() + " skill=" + skillKey + " gainedLevels=" + num + " oldLevel=" + effectiveSkillLevel + " newLevel=" + effectiveSkillLevel2); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao reportar ganho de skill local do ranking: " + ex)); } } private void RPC_ReportSkillGain(long sender, ZPackage pkg) { try { if (!IsServerInstance() || pkg == null) { return; } string text = SafeKey(pkg.ReadString()); int num = Mathf.Clamp(pkg.ReadInt(), 0, 100); int oldLevel = Mathf.Clamp(pkg.ReadInt(), 0, 100); int newLevel = Mathf.Clamp(pkg.ReadInt(), 0, 100); string text2 = ResolvePlayerNameFromSender(sender); DebugLog(DebugCategory.Skill, "Servidor recebeu SKILL: sender=" + sender + " player=" + text2 + " skill=" + text + " gainedLevels=" + num + " oldLevel=" + oldLevel + " newLevel=" + newLevel); if (!string.IsNullOrWhiteSpace(text2) && !string.IsNullOrWhiteSpace(text) && num > 0) { if (ShouldIgnoreSenderForRanking(sender, text2)) { DebugLog(DebugCategory.Skill, "Skill ignorada para admin: " + text2); } else { ProcessSkillGainReport(text2, text, num, oldLevel, newLevel, "rpc-skill"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportSkillGain: " + ex)); } } private void ProcessSkillGainReport(string playerName, string skillKey, int gainedLevels, int oldLevel, int newLevel, string source) { try { if (!IsServerInstance() || !_rules.RankingEnabled || !_rules.EnableSkillPoints) { return; } playerName = SanitizePlayerName(playerName); skillKey = SafeKey(skillKey); gainedLevels = Mathf.Clamp(gainedLevels, 0, 100); if (string.IsNullOrWhiteSpace(playerName) || string.IsNullOrWhiteSpace(skillKey) || gainedLevels <= 0) { return; } if (ShouldIgnorePlayerForRanking(playerName)) { DebugLog(DebugCategory.Skill, "Skill ignorada para admin: " + playerName); return; } RankingEntry orCreateEntry = GetOrCreateEntry(playerName); int num = 0; int num2 = 0; List list = new List(); Dictionary value = null; if (_rules.SkillMilestoneJackpotPoints != null) { _rules.SkillMilestoneJackpotPoints.TryGetValue(skillKey, out value); } if (value != null && value.Count > 0) { foreach (KeyValuePair item2 in value.OrderBy((KeyValuePair p) => p.Key)) { int num3 = Mathf.Clamp(item2.Key, 1, 100); int num4 = Mathf.Max(0, item2.Value); if (oldLevel < num3 && newLevel >= num3) { string item = skillKey + ":" + num3; if (!orCreateEntry.SkillLevel100JackpotCredits.Contains(item)) { orCreateEntry.SkillLevel100JackpotCredits.Add(item); num2++; list.Add(num3); num = Mathf.Clamp(num + num4, -2147483647, int.MaxValue); } } } if (num > 0) { orCreateEntry.TotalSkillLevelUpsPontuados = Mathf.Clamp(orCreateEntry.TotalSkillLevelUpsPontuados + num2, 0, int.MaxValue); orCreateEntry.SkillPointsTotal = Mathf.Clamp(orCreateEntry.SkillPointsTotal + num, -2147483647, int.MaxValue); string reason = "Jackpot Skill: " + GetSkillDisplayName(skillKey) + " " + string.Join("/", list.Select((int l) => l.ToString()).ToArray()); ApplyPointsToEntry(orCreateEntry, num, reason); return; } } DebugLog(DebugCategory.Skill, "Skill ignorada fora dos jackpots de marco: player=" + playerName + " skill=" + skillKey + " oldLevel=" + oldLevel + " newLevel=" + newLevel + " source=" + source); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar skill reportado: " + ex)); } } private string FormatHudLastUpdate(string rawUtc) { if (string.IsNullOrWhiteSpace(rawUtc)) { return "sem registro"; } try { return DateTime.Parse(rawUtc, null, DateTimeStyles.RoundtripKind).ToLocalTime().ToString("dd/MM/yyyy HH:mm"); } catch { return rawUtc; } } private string FormatIntRulesForHud(Dictionary rules) { if (rules == null || rules.Count == 0) { return ""; } return string.Join(",", (from x in rules orderby x.Key select FriendlyRuleNameForHud(x.Key) + ":" + x.Value).ToArray()); } private string FormatCategorizedIntRulesForHud(Dictionary rules, Dictionary manualCategories = null, bool combatMode = false) { if (rules == null || rules.Count == 0) { return ""; } List list = new List(); foreach (IGrouping> item in from x in rules orderby GetHudRuleCategoryOrder(x.Key, manualCategories, combatMode), combatMode ? SafeKey(x.Key) : FriendlyRuleNameForHud(x.Key) group x by GetHudRuleCategoryName(x.Key, manualCategories, combatMode)) { list.Add(BuildHudCategoryHeader(item.Key)); foreach (KeyValuePair item2 in item) { string text = (combatMode ? SafeKey(item2.Key) : item2.Key); list.Add(text + ":" + item2.Value); } } return string.Join(",", list.ToArray()); } private string FormatCategorizedJackpotRulesForHud(Dictionary rules, Dictionary manualCategories = null, bool combatMode = false) { if (rules == null || rules.Count == 0) { return ""; } List list = new List(); foreach (IGrouping> item in from x in rules orderby GetHudRuleCategoryOrder(x.Key, manualCategories, combatMode), FriendlyRuleNameForHud(x.Key) group x by GetHudRuleCategoryName(x.Key, manualCategories, combatMode)) { list.Add(BuildHudCategoryHeader(item.Key)); foreach (KeyValuePair item2 in item) { JackpotRule jackpotRule = item2.Value ?? new JackpotRule(); list.Add(item2.Key + ":" + Mathf.Max(1, jackpotRule.RequiredAmount) + ":" + jackpotRule.Points); } } return string.Join(",", list.ToArray()); } private string BuildHudCategoryHeader(string categoryName) { return "__GLITNIR_CAT__|" + (string.IsNullOrWhiteSpace(categoryName) ? "Outros" : categoryName.Trim()); } private bool IsHudCategoryHeader(string row) { return !string.IsNullOrWhiteSpace(row) && row.StartsWith("__GLITNIR_CAT__|", StringComparison.Ordinal); } private string GetHudCategoryHeaderTitle(string row) { if (!IsHudCategoryHeader(row)) { return ""; } return row.Substring("__GLITNIR_CAT__|".Length).Trim(); } private string GetHudRuleCategoryName(string prefabName, Dictionary manualCategories, bool combatMode) { if (manualCategories != null && manualCategories.TryGetValue(SafeKey(prefabName), out var value) && !string.IsNullOrWhiteSpace(value)) { return NormalizeHudCategoryName(value.Trim(), prefabName, combatMode); } return combatMode ? GetHudCombatCategoryName(prefabName) : GetHudPrefabCategoryName(prefabName); } private string NormalizeHudCategoryName(string category, string prefabName, bool combatMode) { if (combatMode || string.IsNullOrWhiteSpace(category)) { return category; } string text = category.Trim(); if (text.Equals("Arcos e Munições", StringComparison.OrdinalIgnoreCase) || text.Equals("Arcos e munições", StringComparison.OrdinalIgnoreCase) || text.Equals("Armas e escudos", StringComparison.OrdinalIgnoreCase)) { return GetHudPrefabCategoryName(prefabName); } return text; } private int GetHudRuleCategoryOrder(string prefabName, Dictionary manualCategories, bool combatMode) { string hudRuleCategoryName = GetHudRuleCategoryName(prefabName, manualCategories, combatMode); return combatMode ? GetHudCombatCategoryOrder(hudRuleCategoryName) : GetHudProductionCategoryOrder(hudRuleCategoryName); } private int GetHudProductionCategoryOrder(string category) { return category switch { "Armas, armaduras e munições" => 10, "Armaduras" => 10, "Armas" => 10, "Escudos" => 10, "Munições" => 10, "Comidas" => 40, "Comidas e bebidas" => 40, "Ferramentas" => 50, "Materiais" => 60, "Troféus" => 70, "Cultivo" => 80, _ => 999, }; } private int GetHudCombatCategoryOrder(string category) { switch (category) { case "Prados": return 10; case "Floresta Negra": return 20; case "Pântano": return 30; case "Montanha": return 40; case "Planícies": return 50; case "Oceano": return 60; case "Mistlands": return 70; case "Ashlands": return 80; default: if (!(category == "Criaturas Especiais")) { return 999; } goto case "Especiais"; case "Especiais": return 90; } } private string GetHudCombatCategoryName(string prefabName) { string text = SafeKey(prefabName).ToLowerInvariant().Replace("_", "").Replace("-", "") .Replace(" ", ""); if (text.Contains("boar") || text.Contains("deer") || text.Contains("greyling") || text.Contains("neck") || text.Contains("crow") || text.Contains("hen") || text.Contains("chicken")) { return "Prados"; } if (text.Contains("greydwarf") || text.Contains("skeleton") || text.Contains("ghost") || text.Contains("troll")) { return "Floresta Negra"; } if (text.Contains("blob") || text.Contains("abomination") || text.Contains("draugr") || text.Contains("leech") || text.Contains("surtling") || text.Contains("wraith")) { return "Pântano"; } if (text.Contains("hatchling") || text.Contains("fenring") || text.Contains("stonegolem") || text.Contains("ulv") || text.Contains("wolf") || text.Contains("bat")) { return "Montanha"; } if (text.Contains("deathsquito") || text.Contains("goblin") || text.Contains("fuling") || text.Contains("lox")) { return "Planícies"; } if (text.Contains("serpent") || text.Contains("bonemaw") || text.Contains("leviathan") || text.Contains("seagal")) { return "Oceano"; } if (text.Contains("seeker") || text.Contains("gjall") || text.Contains("tick") || text.Contains("hare") || text.Contains("dverger")) { return "Mistlands"; } if (text.Contains("asksvin") || text.Contains("charred") || text.Contains("morgen") || text.Contains("valkyrie") || text.Contains("volture") || text.Contains("tentaroot") || text.Contains("bloblava")) { return "Ashlands"; } if (text.Contains("haldor") || text.Contains("hildir") || text.Contains("odin") || text.Contains("wisp") || text.Contains("trainingdummy")) { return "Especiais"; } return "Outros"; } private int GetHudPrefabCategoryOrder(string prefabName) { return GetHudPrefabCategoryName(prefabName) switch { "Armaduras" => 10, "Armas" => 20, "Escudos" => 25, "Munições" => 30, "Comidas" => 40, "Comidas e bebidas" => 40, "Ferramentas" => 50, "Materiais" => 60, "Troféus" => 70, "Cultivo" => 80, _ => 999, }; } private string GetHudPrefabCategoryName(string prefabName) { string text = SafeKey(prefabName).ToLowerInvariant().Replace("_", "").Replace("-", "") .Replace(" ", ""); if (text.Contains("helmet") || text.Contains("armor") || text.Contains("cape") || text.Contains("chest") || text.Contains("legs") || text.Contains("greaves")) { return "Armaduras"; } if (text.Contains("shield")) { return "Escudos"; } if (text.Contains("arrow") || text.Contains("bolt") || text.Contains("bomb") || text.Contains("oozebomb") || text.Contains("missile")) { return "Munições"; } if (text.Contains("sword") || text.Contains("knife") || text.Contains("axe") || text.Contains("mace") || text.Contains("spear") || text.Contains("atgeir") || text.Contains("bow") || text.Contains("crossbow") || text.Contains("staff") || text.Contains("club") || text.Contains("pickaxe")) { return "Armas"; } if (text.Contains("stew") || text.Contains("soup") || text.Contains("mead") || text.Contains("wine") || text.Contains("cooked") || text.Contains("jerky") || text.Contains("honey") || text.Contains("chicken") || text.Contains("fish") || text.Contains("meat") || text.Contains("mushroom") || text.Contains("bread") || text.Contains("pie") || text.Contains("pudding") || text.Contains("sausages") || text.Contains("eyescream") || text.Contains("salad") || text.Contains("omelette") || text.Contains("seekeraspic") || text.Contains("wolfskewer") || text.Contains("mincemeatsauce") || text.Contains("bloodpudding")) { return "Comidas e bebidas"; } if (text.Contains("hoe") || text.Contains("hammer") || text.Contains("cultivator") || text.Contains("fishingrod") || text.Contains("torch") || text.Contains("wishbone")) { return "Ferramentas"; } if (text.Contains("trophy")) { return "Troféus"; } if (text.Contains("seed") || text.Contains("sapling") || text.Contains("barley") || text.Contains("flax") || text.Contains("carrot") || text.Contains("turnip") || text.Contains("onion") || text.Contains("jotunpuffs") || text.Contains("magecap") || text.Contains("vineberry")) { return "Cultivo"; } if (text.Contains("wood") || text.Contains("stone") || text.Contains("ore") || text.Contains("metal") || text.Contains("bar") || text.Contains("ingot") || text.Contains("hide") || text.Contains("leather") || text.Contains("scale") || text.Contains("chitin") || text.Contains("thread") || text.Contains("linen") || text.Contains("resin") || text.Contains("coal") || text.Contains("core") || text.Contains("crystal") || text.Contains("bone") || text.Contains("fang") || text.Contains("feather") || text.Contains("needle") || text.Contains("claw") || text.Contains("carapace") || text.Contains("mandible") || text.Contains("bloodbag")) { return "Materiais"; } return "Outros"; } private string FormatJackpotRulesForHud(Dictionary rules) { if (rules == null || rules.Count == 0) { return ""; } return string.Join(",", rules.OrderBy((KeyValuePair x) => x.Key).Select(delegate(KeyValuePair x) { JackpotRule jackpotRule = x.Value ?? new JackpotRule(); return FriendlyRuleNameForHud(x.Key) + ":" + Mathf.Max(1, jackpotRule.RequiredAmount) + ":" + jackpotRule.Points; }).ToArray()); } private string FriendlyRuleNameForHud(string rawKey) { string text = SafeKey(rawKey); if (string.IsNullOrWhiteSpace(text)) { return "Regra"; } if (BossDisplayNamesPtBr.TryGetValue(text, out var value) && !string.IsNullOrWhiteSpace(value)) { return value; } if (BossPortugueseToPrefab.TryGetValue(text, out var value2) && BossDisplayNamesPtBr.TryGetValue(value2, out value) && !string.IsNullOrWhiteSpace(value)) { return value; } if (FishDisplayNamesPtBr.TryGetValue(text, out var value3) && !string.IsNullOrWhiteSpace(value3)) { return value3; } if (FishPortugueseToPrefab.TryGetValue(text, out var value4) && FishDisplayNamesPtBr.TryGetValue(value4, out value3) && !string.IsNullOrWhiteSpace(value3)) { return value3; } if (HudFriendlyNames.TryGetValue(text, out var value5) && !string.IsNullOrWhiteSpace(value5)) { return value5; } string text2 = TryManualPortugueseNameForHud(text); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } string prefabDisplayNameForHud = GetPrefabDisplayNameForHud(text); if (!string.IsNullOrWhiteSpace(prefabDisplayNameForHud)) { return prefabDisplayNameForHud; } return HumanizePrefabNamePt(text); } private string GetPrefabDisplayNameForHud(string prefabName) { if (string.IsNullOrWhiteSpace(prefabName)) { return ""; } string text = CleanPrefabNameForHud(prefabName); if (string.IsNullOrWhiteSpace(text)) { return ""; } if (BossDisplayNamesPtBr.TryGetValue(text, out var value) && !string.IsNullOrWhiteSpace(value)) { return value; } if (BossPortugueseToPrefab.TryGetValue(text, out var value2) && BossDisplayNamesPtBr.TryGetValue(value2, out value) && !string.IsNullOrWhiteSpace(value)) { return value; } if (FishDisplayNamesPtBr.TryGetValue(text, out var value3) && !string.IsNullOrWhiteSpace(value3)) { return value3; } if (FishPortugueseToPrefab.TryGetValue(text, out var value4) && FishDisplayNamesPtBr.TryGetValue(value4, out value3) && !string.IsNullOrWhiteSpace(value3)) { return value3; } if (_hudPrefabDisplayNameCache.TryGetValue(text, out var value5)) { return value5; } string text2 = ""; try { GameObject val = ResolvePrefabForHud(text); if ((Object)(object)val != (Object)null) { ItemDrop component = val.GetComponent(); if ((Object)(object)component != (Object)null && component.m_itemData.m_shared != null) { string name = component.m_itemData.m_shared.m_name; if (!string.IsNullOrWhiteSpace(name)) { string text3 = TryManualPortugueseNameForHud(name); if (string.IsNullOrWhiteSpace(text3)) { text3 = TryManualPortugueseNameForHud(text); } if (!string.IsNullOrWhiteSpace(text3)) { text2 = text3; } else { string value6 = TryLocalizeTokenForHud(name); value6 = StripRichText(value6).Trim(); text2 = ((string.IsNullOrWhiteSpace(value6) || !(value6 != name)) ? HumanizePrefabNamePt(text) : value6); } } } } } catch (Exception ex) { if (_rules != null && _rules.DebugLogging) { Log.LogWarning((object)("[Glitnir Ranking] Falha ao localizar nome do prefab '" + prefabName + "': " + ex.Message)); } } if (string.IsNullOrWhiteSpace(text2)) { string text4 = TryManualPortugueseNameForHud(text); text2 = ((!string.IsNullOrWhiteSpace(text4)) ? text4 : HumanizePrefabNamePt(text)); } _hudPrefabDisplayNameCache[text] = text2; return text2; } private GameObject ResolvePrefabForHud(string cleanName) { if (string.IsNullOrWhiteSpace(cleanName)) { return null; } if (_hudPrefabObjectCache.TryGetValue(cleanName, out var value)) { return value; } RebuildHudPrefabObjectCacheIfNeeded(); if (_hudPrefabObjectCache.TryGetValue(cleanName, out value)) { return value; } GameObject val = null; if ((Object)(object)ObjectDB.instance != (Object)null) { val = ObjectDB.instance.GetItemPrefab(cleanName); } if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { val = ZNetScene.instance.GetPrefab(cleanName); } if ((Object)(object)val != (Object)null) { _hudPrefabObjectCache[cleanName] = val; } return val; } private void RebuildHudPrefabObjectCacheIfNeeded() { int num = (((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items != null) ? ObjectDB.instance.m_items.Count : (-1)); int num2 = (((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null) ? ZNetScene.instance.m_prefabs.Count : (-1)); if (_hudObjectDbItemCountCached == num && _hudZNetScenePrefabCountCached == num2 && _hudPrefabObjectCache.Count > 0) { return; } _hudPrefabObjectCache.Clear(); if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items != null) { for (int i = 0; i < ObjectDB.instance.m_items.Count; i++) { GameObject val = ObjectDB.instance.m_items[i]; if (!((Object)(object)val == (Object)null) && !string.IsNullOrWhiteSpace(((Object)val).name) && !_hudPrefabObjectCache.ContainsKey(((Object)val).name)) { _hudPrefabObjectCache[((Object)val).name] = val; } } } if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null) { for (int j = 0; j < ZNetScene.instance.m_prefabs.Count; j++) { GameObject val2 = ZNetScene.instance.m_prefabs[j]; if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrWhiteSpace(((Object)val2).name) && !_hudPrefabObjectCache.ContainsKey(((Object)val2).name)) { _hudPrefabObjectCache[((Object)val2).name] = val2; } } } _hudObjectDbItemCountCached = num; _hudZNetScenePrefabCountCached = num2; } private string HumanizeTokenNameForHud(string tokenOrName) { if (string.IsNullOrWhiteSpace(tokenOrName)) { return ""; } string text = tokenOrName.Trim(); if (text.StartsWith("$item_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(6); } else if (text.StartsWith("$", StringComparison.Ordinal)) { text = text.Substring(1); } return HumanizePrefabName(text); } private string CleanPrefabNameForHud(string prefabName) { if (string.IsNullOrWhiteSpace(prefabName)) { return ""; } string text = prefabName.Trim(); int num = text.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase); if (num >= 0) { text = text.Substring(0, num).Trim(); } return text; } private string TryLocalizeTokenForHud(string tokenOrName) { if (string.IsNullOrWhiteSpace(tokenOrName)) { return ""; } try { if (!_hudLocalizationReflectionReady) { _hudLocalizationReflectionReady = true; _hudLocalizationType = AccessTools.TypeByName("Localization"); if (_hudLocalizationType == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type[] types; try { types = assemblies[i].GetTypes(); } catch { continue; } foreach (Type type in types) { if (type != null && type.Name == "Localization") { _hudLocalizationType = type; break; } } if (_hudLocalizationType != null) { break; } } } if (_hudLocalizationType != null) { _hudLocalizationInstanceField = AccessTools.Field(_hudLocalizationType, "instance"); _hudLocalizationLocalizeMethod = AccessTools.Method(_hudLocalizationType, "Localize", new Type[1] { typeof(string) }, (Type[])null); if (_hudLocalizationLocalizeMethod == null) { MethodInfo[] methods = _hudLocalizationType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo == null) && !(methodInfo.Name != "Localize")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length >= 1 && parameters[0].ParameterType == typeof(string)) { _hudLocalizationLocalizeMethod = methodInfo; break; } } } } } } if (_hudLocalizationType == null || _hudLocalizationInstanceField == null || _hudLocalizationLocalizeMethod == null) { return tokenOrName; } object value = _hudLocalizationInstanceField.GetValue(null); if (value == null) { return tokenOrName; } ParameterInfo[] parameters2 = _hudLocalizationLocalizeMethod.GetParameters(); object[] array = new object[parameters2.Length]; array[0] = tokenOrName; for (int l = 1; l < array.Length; l++) { if (parameters2[l].ParameterType == typeof(bool)) { array[l] = true; } else { array[l] = parameters2[l].DefaultValue; } } object obj2 = _hudLocalizationLocalizeMethod.Invoke(value, array); return (obj2 as string) ?? tokenOrName; } catch { return tokenOrName; } } private string TryManualPortugueseNameForHud(string key) { if (string.IsNullOrWhiteSpace(key)) { return ""; } string text = key.Trim(); if (text.StartsWith("$item_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(6); } else if (text.StartsWith("$", StringComparison.Ordinal)) { text = text.Substring(1); } text = text.Replace("_", "").Replace("-", "").Replace(" ", ""); if (ManualPortuguesePrefabNames.TryGetValue(text, out var value)) { return value; } return ""; } private string HumanizePrefabNamePt(string key) { if (string.IsNullOrWhiteSpace(key)) { return "Regra"; } string text = TryManualPortugueseNameForHud(key); if (!string.IsNullOrWhiteSpace(text)) { return text; } string text2 = key.Trim(); int num = text2.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase); if (num >= 0) { text2 = text2.Substring(0, num); } text2 = Regex.Replace(text2, "([a-z])([A-Z])", "$1 $2"); text2 = text2.Replace("_", " ").Replace("-", " ").Trim(); string text3 = text2.ToLowerInvariant(); text3 = text3.Replace("helmet", "elmo"); text3 = text3.Replace("armor", "armadura"); text3 = text3.Replace("chest", "peitoral"); text3 = text3.Replace("legs", "perneiras"); text3 = text3.Replace("greaves", "grevas"); text3 = text3.Replace("knife", "faca"); text3 = text3.Replace("sword", "espada"); text3 = text3.Replace("axe", "machado"); text3 = text3.Replace("mace", "maça"); text3 = text3.Replace("bow", "arco"); text3 = text3.Replace("shield", "escudo"); text3 = text3.Replace("spear", "lança"); text3 = text3.Replace("atgier", "atgeir"); text3 = text3.Replace("crossbow", "besta"); text3 = text3.Replace("bronze", "bronze"); text3 = text3.Replace("iron", "ferro"); text3 = text3.Replace("leather", "couro"); text3 = text3.Replace("rag", "trapos"); text3 = text3.Replace("padded", "acolchoado"); text3 = text3.Replace("root", "raiz"); text3 = text3.Replace("trollleather", "couro de troll"); text3 = text3.Replace("troll leather", "couro de troll"); text3 = text3.Replace("blackmetal", "metal negro"); text3 = text3.Replace("black metal", "metal negro"); text3 = text3.Replace("silver", "prata"); text3 = text3.Replace("copper", "cobre"); text3 = text3.Replace("flint", "sílex"); text3 = text3.Replace("carapace", "carapaça"); text3 = text3.Replace("flametal", "flametal"); text3 = text3.Replace("mage", "mago"); text3 = text3.Replace("fenris", "fenris"); text3 = text3.Replace("dverger", "dvergr"); text3 = text3.Replace("drake", "draco"); while (text3.IndexOf(" ", StringComparison.Ordinal) >= 0) { text3 = text3.Replace(" ", " "); } text3 = text3.Trim(); if (text3.Length == 0) { return key; } return char.ToUpperInvariant(text3[0]) + text3.Substring(1); } private string StripRichText(string value) { if (string.IsNullOrWhiteSpace(value)) { return ""; } try { return Regex.Replace(value, "<.*?>", ""); } catch { return value; } } private string HumanizePrefabName(string key) { if (string.IsNullOrWhiteSpace(key)) { return "Regra"; } string text = key.Trim(); if (text.StartsWith("$", StringComparison.Ordinal)) { text = text.Substring(1); } int num = text.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase); if (num >= 0) { text = text.Substring(0, num); } text = text.Replace("_", " ").Replace("-", " "); while (text.IndexOf(" ", StringComparison.Ordinal) >= 0) { text = text.Replace(" ", " "); } text = text.Trim(); if (text.Length == 0) { return key; } string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text2 = array[i]; if (text2.Length <= 1) { array[i] = text2.ToUpperInvariant(); } else { array[i] = char.ToUpperInvariant(text2[0]) + text2.Substring(1).ToLowerInvariant(); } } return string.Join(" ", array); } private string FormatExplorationMapJackpotRulesForHud(Dictionary rules) { if (rules == null || rules.Count == 0) { return ""; } return string.Join(";", (from p in rules where p.Key > 0 && p.Value > 0 orderby p.Key select "Mapa " + Mathf.Clamp(p.Key, 1, 100) + "%:" + p.Value).ToArray()); } private string FormatDeathPenaltyRulesForHud(Dictionary rules) { if (rules == null || rules.Count == 0) { return ""; } return string.Join(",", (from x in rules orderby x.Key select Mathf.Max(1, x.Key) + ":" + Mathf.Max(0, x.Value)).ToArray()); } private string FormatSkillJackpotRulesForHud(Dictionary> rules) { if (rules == null || rules.Count == 0) { return ""; } List list = new List(); foreach (KeyValuePair> item in rules.OrderBy((KeyValuePair> x) => x.Key)) { if (item.Value == null) { continue; } foreach (KeyValuePair item2 in item.Value.OrderBy((KeyValuePair x) => x.Key)) { list.Add(SafeKey(item.Key) + ":" + Mathf.Max(1, item2.Key) + ":" + item2.Value); } } return string.Join(",", list.ToArray()); } private Texture2D GetRuleCategoryIcon(string categoryKey) { if (string.IsNullOrWhiteSpace(categoryKey)) { return null; } Texture2D value; return _uiRuleCategoryIcons.TryGetValue(categoryKey, out value) ? value : null; } private void DrawTextureOrLabel(Rect rect, Texture2D texture, string fallbackText, GUIStyle fallbackStyle) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)texture != (Object)null) { DrawTextureAspectFit(rect, texture); } else { GUI.Label(rect, fallbackText, fallbackStyle); } } private void DrawTextureAspectFit(Rect rect, Texture2D texture) { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)texture == (Object)null) && !(((Rect)(ref rect)).width <= 0f) && !(((Rect)(ref rect)).height <= 0f) && ((Texture)texture).width > 0 && ((Texture)texture).height > 0) { float num = (float)((Texture)texture).width / (float)((Texture)texture).height; float num2 = ((Rect)(ref rect)).width / ((Rect)(ref rect)).height; float num3; float num4; if (num2 > num) { num3 = ((Rect)(ref rect)).height; num4 = num3 * num; } else { num4 = ((Rect)(ref rect)).width; num3 = num4 / num; } Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + (((Rect)(ref rect)).width - num4) * 0.5f, ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - num3) * 0.5f, num4, num3); GUI.DrawTexture(val, (Texture)(object)texture, (ScaleMode)2, true); } } private void DrawTextureOrLabelCropped(Rect rect, Texture2D texture, string fallbackText, GUIStyle fallbackStyle, float cropTop, float cropBottom) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)texture != (Object)null) { DrawTextureCroppedAspectFit(rect, texture, cropTop, cropBottom); } else { GUI.Label(rect, fallbackText, fallbackStyle); } } private void DrawTextureCroppedAspectFit(Rect rect, Texture2D texture, float cropTop, float cropBottom) { //IL_0070: 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_0132: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)texture == (Object)null || ((Rect)(ref rect)).width <= 0f || ((Rect)(ref rect)).height <= 0f || ((Texture)texture).width <= 0 || ((Texture)texture).height <= 0) { return; } cropTop = Mathf.Clamp01(cropTop); cropBottom = Mathf.Clamp01(cropBottom); if (cropBottom <= cropTop + 0.01f) { DrawTextureAspectFit(rect, texture); return; } float num = (float)((Texture)texture).height * (cropBottom - cropTop); float num2 = (float)((Texture)texture).width / Mathf.Max(1f, num); float num3 = ((Rect)(ref rect)).width / ((Rect)(ref rect)).height; float num4; float num5; if (num3 > num2) { num4 = ((Rect)(ref rect)).height; num5 = num4 * num2; } else { num5 = ((Rect)(ref rect)).width; num4 = num5 / num2; } Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + (((Rect)(ref rect)).width - num5) * 0.5f, ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - num4) * 0.5f, num5, num4); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, 1f - cropBottom, 1f, cropBottom - cropTop); GUI.DrawTextureWithTexCoords(val, (Texture)(object)texture, val2, true); } private float GetTextureHeightForWidth(Texture2D texture, float width, float fallbackHeight, float minHeight, float maxHeight) { if ((Object)(object)texture != (Object)null && ((Texture)texture).width > 0 && ((Texture)texture).height > 0) { float num = width * ((float)((Texture)texture).height / (float)((Texture)texture).width); return Mathf.Clamp(num, minHeight, maxHeight); } return Mathf.Clamp(fallbackHeight, minHeight, maxHeight); } private void DrawCroppedIcon(Rect rect, Texture2D texture) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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) if (!(((Rect)(ref rect)).width <= 0f) && !(((Rect)(ref rect)).height <= 0f)) { if ((Object)(object)texture == (Object)null) { GUI.Label(rect, "RANK", _headerStyle); return; } float num = Mathf.Clamp(_uiIconZoom, 0.75f, 1.2f); float num2 = ((Rect)(ref rect)).width * num; float num3 = ((Rect)(ref rect)).height * num; float num4 = (((Rect)(ref rect)).width - num2) * 0.5f; float num5 = (((Rect)(ref rect)).height - num3) * 0.5f; GUI.BeginGroup(rect); GUI.DrawTexture(new Rect(num4, num5, num2, num3), (Texture)(object)texture, (ScaleMode)2, true); GUI.EndGroup(); } } private void DrawPanel(Rect rect) { //IL_0016: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0198: 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_01d5: 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_0218: 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_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_uiWhiteTexture == (Object)null)) { GUI.DrawTexture(rect, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.02f, 0.015f, 0.01f, 0.08f), 0f, 0f); if ((Object)(object)_uiPanelTexture != (Object)null) { GUI.DrawTexture(rect, (Texture)(object)_uiPanelTexture, (ScaleMode)0, true); } Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 8f, ((Rect)(ref rect)).width - 16f, ((Rect)(ref rect)).height - 16f); if (((Rect)(ref val)).width > 0f && ((Rect)(ref val)).height > 0f) { GUI.DrawTexture(val, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.08f, 0.05f, 0.025f, 0.08f), 0f, 0f); } Color val2 = default(Color); ((Color)(ref val2))..ctor(0.92f, 0.76f, 0.42f, 0.34f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.97f, 0.83f, 0.48f, 0.05f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 2f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 2f, ((Rect)(ref rect)).width, 2f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 2f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 2f, ((Rect)(ref rect)).y, 2f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - 4f, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val3, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).yMax - 3f, ((Rect)(ref rect)).width - 4f, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val3, 0f, 0f); } } private void OnGUI() { //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_0087: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00a3: 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_00bc: 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_00da: Expected O, but got Unknown //IL_00d5: 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_00e5: 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) if (!Application.isBatchMode && !((Object)(object)Player.m_localPlayer == (Object)null)) { EnsureUiTexturesLoaded(); EnsureGuiStyles(); DrawRankingIcon(); if (_hudVisible) { ClampRankingWindowRect(); float num = Mathf.Clamp01((Time.realtimeSinceStartup - _hudOpenTime) * 4f); float num2 = (1f - num) * 26f; Rect windowRect = _windowRect; ((Rect)(ref windowRect)).y = ((Rect)(ref windowRect)).y + num2; Color color = GUI.color; GUI.color = new Color(color.r, color.g, color.b, color.a * num); Rect windowRect2 = GUI.Window(918273, windowRect, new WindowFunction(DrawRankingWindow), "", _windowStyle); GUI.color = color; _windowRect = windowRect2; ref Rect windowRect3 = ref _windowRect; ((Rect)(ref windowRect3)).y = ((Rect)(ref windowRect3)).y - num2; ClampRankingWindowRect(); UpdateRankingInputBlockerRect(); ConsumeRankingMouseEventIfNeeded(); } } } private void EnsureRankingInputBlocker() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_0120: Unknown result type (might be due to invalid IL or missing references) if (!Application.isBatchMode && !((Object)(object)_rankingInputBlockerObject != (Object)null)) { _rankingInputBlockerObject = new GameObject("GlitnirRanking_InputBlocker"); Object.DontDestroyOnLoad((Object)(object)_rankingInputBlockerObject); _rankingInputBlockerCanvas = _rankingInputBlockerObject.AddComponent(); _rankingInputBlockerCanvas.renderMode = (RenderMode)0; _rankingInputBlockerCanvas.overrideSorting = true; _rankingInputBlockerCanvas.sortingOrder = 32760; _rankingInputBlockerObject.AddComponent(); GameObject val = new GameObject("Blocker"); val.transform.SetParent(_rankingInputBlockerObject.transform, false); _rankingInputBlockerRect = val.AddComponent(); _rankingInputBlockerRect.anchorMin = new Vector2(0f, 0f); _rankingInputBlockerRect.anchorMax = new Vector2(0f, 0f); _rankingInputBlockerRect.pivot = new Vector2(0f, 0f); Image val2 = val.AddComponent(); ((Graphic)val2).color = new Color(0f, 0f, 0f, 0f); ((Graphic)val2).raycastTarget = true; _rankingInputBlockerObject.SetActive(false); } } private void UpdateRankingInputBlockerRect() { //IL_00da: 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) if (Application.isBatchMode || !_hudVisible) { SetRankingInputBlockerVisible(visible: false); return; } EnsureRankingInputBlocker(); if (!((Object)(object)_rankingInputBlockerObject == (Object)null) && !((Object)(object)_rankingInputBlockerRect == (Object)null)) { float num = Mathf.Clamp(((Rect)(ref _windowRect)).x, 0f, (float)Screen.width); float num2 = Mathf.Clamp((float)Screen.height - ((Rect)(ref _windowRect)).yMax, 0f, (float)Screen.height); float num3 = Mathf.Clamp(((Rect)(ref _windowRect)).width, 0f, (float)Screen.width - num); float num4 = Mathf.Clamp(((Rect)(ref _windowRect)).height, 0f, (float)Screen.height - num2); _rankingInputBlockerRect.anchoredPosition = new Vector2(num, num2); _rankingInputBlockerRect.sizeDelta = new Vector2(num3, num4); SetRankingInputBlockerVisible(visible: true); } } private void SetRankingInputBlockerVisible(bool visible) { if ((Object)(object)_rankingInputBlockerObject != (Object)null && _rankingInputBlockerObject.activeSelf != visible) { _rankingInputBlockerObject.SetActive(visible); } } private void DestroyRankingInputBlocker() { if (!((Object)(object)_rankingInputBlockerObject == (Object)null)) { try { Object.Destroy((Object)(object)_rankingInputBlockerObject); } catch { } _rankingInputBlockerObject = null; _rankingInputBlockerCanvas = null; _rankingInputBlockerRect = null; } } private void ConsumeRankingMouseEventIfNeeded() { //IL_001d: 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) //IL_0023: 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: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 Event current = Event.current; if (current != null && ShouldRankingBlockGameInput()) { EventType type = current.type; if ((int)type == 0 || (int)type == 1 || (int)type == 3 || (int)type == 6) { current.Use(); } } } public bool IsRankingHudUnderMouse() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0055: Unknown result type (might be due to invalid IL or missing references) if (Application.isBatchMode) { return false; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(Input.mousePosition.x, (float)Screen.height - Input.mousePosition.y); if (_hudVisible && ((Rect)(ref _windowRect)).Contains(val)) { return true; } if (((Rect)(ref _iconRect)).Contains(val)) { return true; } return false; } public bool ShouldRankingBlockGameInput() { //IL_001e: 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_0044: Unknown result type (might be due to invalid IL or missing references) if (Application.isBatchMode || !_hudVisible) { return false; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(Input.mousePosition.x, (float)Screen.height - Input.mousePosition.y); return ((Rect)(ref _windowRect)).Contains(val); } private void ClampRankingWindowRect() { float num = 500f; float num2 = 760f; float num3 = Mathf.Max(num, (float)Screen.width - 24f); float num4 = Mathf.Max(num2, (float)Screen.height - 24f); ((Rect)(ref _windowRect)).width = Mathf.Clamp(((Rect)(ref _windowRect)).width, num, num3); ((Rect)(ref _windowRect)).height = Mathf.Clamp(((Rect)(ref _windowRect)).height, num2, num4); ((Rect)(ref _windowRect)).x = Mathf.Clamp(((Rect)(ref _windowRect)).x, 4f, Mathf.Max(4f, (float)Screen.width - ((Rect)(ref _windowRect)).width - 4f)); ((Rect)(ref _windowRect)).y = Mathf.Clamp(((Rect)(ref _windowRect)).y, 4f, Mathf.Max(4f, (float)Screen.height - ((Rect)(ref _windowRect)).height - 4f)); } private void ToggleRankingHud() { if (_hudVisible) { CloseRankingHudAndCollapseAll(); return; } _hudVisible = true; _clientRefreshTimer = 1f; _hudOpenTime = Time.realtimeSinceStartup; _hudTabSwitchTime = Time.realtimeSinceStartup; RequestSnapshotFromServer(); } private void CloseRankingHudAndCollapseAll() { _hudVisible = false; GUI.FocusControl((string)null); SetRankingInputBlockerVisible(visible: false); CollapseAllHudSections(); } private void CollapseAllHudSections() { _expandedActionPlayers.Clear(); _expandedRuleCategories.Clear(); _expandedRuleSubCategories.Clear(); _expandedGuideSkillRows.Clear(); _expandedPerformanceCategories.Clear(); _ruleCategoriesInitialized = false; _performanceCategoriesInitialized = false; } private bool TryParseKeyCode(string value, out KeyCode keyCode) { keyCode = (KeyCode)0; if (string.IsNullOrWhiteSpace(value)) { return false; } value = value.Trim(); try { if (Enum.TryParse(value, ignoreCase: true, out keyCode)) { return true; } } catch { } return false; } private void DrawRankingIcon() { //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: 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_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_0383: 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_03c7: 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) //IL_00a3: Invalid comparison between Unknown and I4 //IL_0045: 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_0072: 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_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_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Invalid comparison between Unknown and I4 //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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) Event current = Event.current; if (current != null) { if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref _iconRect)).Contains(current.mousePosition)) { _iconDragging = true; _iconDragOffset = new Vector2(current.mousePosition.x - ((Rect)(ref _iconRect)).x, current.mousePosition.y - ((Rect)(ref _iconRect)).y); _iconMouseDownPosition = current.mousePosition; _iconMovedDuringDrag = false; current.Use(); } else if ((int)current.type == 3 && _iconDragging) { Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(current.mousePosition.x - _iconDragOffset.x, current.mousePosition.y - _iconDragOffset.y); float num = Mathf.Max(0f, (float)Screen.width - ((Rect)(ref _iconRect)).width); float num2 = Mathf.Max(0f, (float)Screen.height - ((Rect)(ref _iconRect)).height); ((Rect)(ref _iconRect)).x = Mathf.Clamp(val.x, 0f, num); ((Rect)(ref _iconRect)).y = Mathf.Clamp(val.y, 0f, num2); if (!_iconMovedDuringDrag && Vector2.Distance(current.mousePosition, _iconMouseDownPosition) > 6f) { _iconMovedDuringDrag = true; } current.Use(); } else if ((int)current.type == 1 && current.button == 0 && _iconDragging) { bool flag = !_iconMovedDuringDrag && Vector2.Distance(current.mousePosition, _iconMouseDownPosition) <= 6f; _iconDragging = false; current.Use(); if (flag) { ToggleRankingHud(); } SaveUiSettings(); } } Rect rect = default(Rect); ((Rect)(ref rect))..ctor(((Rect)(ref _iconRect)).x + ((Rect)(ref _iconRect)).width * 0.1f, ((Rect)(ref _iconRect)).y + ((Rect)(ref _iconRect)).height * 0.1f, ((Rect)(ref _iconRect)).width * 0.8f, ((Rect)(ref _iconRect)).height * 0.8f); DrawCroppedIcon(rect, _uiRankingIconTexture); if ((Object)(object)_uiWhiteTexture != (Object)null) { Color val2 = (_hudVisible ? new Color(0.98f, 0.82f, 0.34f, 0.42f) : new Color(0.95f, 0.78f, 0.38f, 0.12f)); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 1f, ((Rect)(ref rect)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 1f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 1f, ((Rect)(ref rect)).y, 1f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); } } private void DrawRankingWindow(int windowId) { //IL_003a: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032b: 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_033a: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_0642: Unknown result type (might be due to invalid IL or missing references) //IL_06bb: Unknown result type (might be due to invalid IL or missing references) //IL_0534: Unknown result type (might be due to invalid IL or missing references) //IL_0537: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_0546: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_05a3: Unknown result type (might be due to invalid IL or missing references) //IL_05bc: Unknown result type (might be due to invalid IL or missing references) //IL_05c8: Unknown result type (might be due to invalid IL or missing references) //IL_05ca: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Unknown result type (might be due to invalid IL or missing references) //IL_0766: Unknown result type (might be due to invalid IL or missing references) //IL_0769: Unknown result type (might be due to invalid IL or missing references) //IL_076e: Unknown result type (might be due to invalid IL or missing references) //IL_0773: Unknown result type (might be due to invalid IL or missing references) //IL_0778: Unknown result type (might be due to invalid IL or missing references) //IL_0796: Unknown result type (might be due to invalid IL or missing references) //IL_07ec: Unknown result type (might be due to invalid IL or missing references) //IL_0853: Unknown result type (might be due to invalid IL or missing references) //IL_08fe: Unknown result type (might be due to invalid IL or missing references) //IL_0901: Unknown result type (might be due to invalid IL or missing references) //IL_0906: Unknown result type (might be due to invalid IL or missing references) //IL_090b: Unknown result type (might be due to invalid IL or missing references) //IL_0910: Unknown result type (might be due to invalid IL or missing references) //IL_092e: Unknown result type (might be due to invalid IL or missing references) //IL_0956: Unknown result type (might be due to invalid IL or missing references) //IL_096d: Unknown result type (might be due to invalid IL or missing references) //IL_0986: Unknown result type (might be due to invalid IL or missing references) //IL_0992: Unknown result type (might be due to invalid IL or missing references) //IL_0994: Unknown result type (might be due to invalid IL or missing references) //IL_09ac: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor(0f, 0f, ((Rect)(ref _windowRect)).width, ((Rect)(ref _windowRect)).height); if ((Object)(object)_uiBackgroundTexture != (Object)null) { GUI.DrawTexture(val, (Texture)(object)_uiBackgroundTexture, (ScaleMode)0, true); } else if ((Object)(object)_uiPanelTexture != (Object)null) { GUI.DrawTexture(val, (Texture)(object)_uiPanelTexture, (ScaleMode)0, true); } if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(val, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.03f), 0f, 0f); } float width = ((Rect)(ref _windowRect)).width; float height = ((Rect)(ref _windowRect)).height; float num = Mathf.Clamp(width * 0.075f, 24f, 38f); float num2 = width - num * 2f; float num3 = Mathf.Clamp(num2 * 0.125f, 58f, 82f); float num4 = Mathf.Clamp(num2 * 0.105f, 44f, 64f); float num5 = (((Object)(object)_uiTitleGuideTexture != (Object)null) ? Mathf.Clamp(num2 * 0.26f, 108f, 156f) : num4); float num6 = (((Object)(object)_uiTitleActionsTexture != (Object)null) ? Mathf.Clamp(num2 * 0.26f, 108f, 156f) : num4); Rect rect = default(Rect); ((Rect)(ref rect))..ctor(num, 16f, num2, num3); DrawTextureOrLabel(rect, _uiTitleRankingTexture, "RANKING DE GLITNIR", _headerStyle); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(num + 6f, ((Rect)(ref rect)).yMax + 8f, num2 - 12f, 34f); DrawHudTabs(rect2); float num7 = 28f; if (_hudTabIndex == 1) { BeginHudTabTransition(out var previousColor, out var previousMatrix); Rect rect3 = default(Rect); ((Rect)(ref rect3))..ctor(num + 4f, ((Rect)(ref rect2)).yMax + 8f, num2 - 8f, num5); DrawTextureOrLabelCropped(rect3, _uiTitleGuideTexture, "GUIA DE HONRA", _sectionTitleStyle, 0.22f, 0.82f); Rect rect4 = default(Rect); ((Rect)(ref rect4))..ctor(num + 6f, ((Rect)(ref rect3)).yMax + 8f, num2 - 12f, height - (((Rect)(ref rect3)).yMax + 8f) - num7 - 18f); DrawPanel(rect4); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref rect4)).x + 14f, ((Rect)(ref rect4)).y + 12f, ((Rect)(ref rect4)).width - 28f, ((Rect)(ref rect4)).height - 24f); float rulesContentHeight = GetRulesContentHeight(((Rect)(ref val2)).width); bool flag = rulesContentHeight > ((Rect)(ref val2)).height + 1f; float num8 = (flag ? 18f : 0f); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(0f, 0f, Mathf.Max(40f, ((Rect)(ref val2)).width - num8), Mathf.Max(((Rect)(ref val2)).height, rulesContentHeight)); _rulesInfoScrollPosition = GUI.BeginScrollView(val2, _rulesInfoScrollPosition, val3, false, flag); DrawRulesContent(new Rect(0f, 0f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height)); GUI.EndScrollView(); Rect rect5 = default(Rect); ((Rect)(ref rect5))..ctor(num, height - 34f, num2, 20f); DrawShadowLabel(rect5, "ESC fecha • Clique nas categorias para expandir as regras", _footerStyle, new Vector2(1f, 1f), new Color(0f, 0f, 0f, 0.92f)); EndHudTabTransition(previousColor, previousMatrix); GUI.DragWindow(new Rect(0f, 0f, width, 110f)); return; } if (_hudTabIndex == 2) { BeginHudTabTransition(out var previousColor2, out var previousMatrix2); Rect rect6 = default(Rect); ((Rect)(ref rect6))..ctor(num + 4f, ((Rect)(ref rect2)).yMax + 8f, num2 - 8f, num6); DrawTextureOrLabelCropped(rect6, _uiTitleActionsTexture, "ORÁCULO DO RANKING", _sectionTitleStyle, 0.22f, 0.82f); Rect rect7 = default(Rect); ((Rect)(ref rect7))..ctor(num + 6f, ((Rect)(ref rect6)).yMax + 8f, num2 - 12f, height - (((Rect)(ref rect6)).yMax + 8f) - num7 - 18f); DrawPanel(rect7); Rect val4 = default(Rect); ((Rect)(ref val4))..ctor(((Rect)(ref rect7)).x + 14f, ((Rect)(ref rect7)).y + 12f, ((Rect)(ref rect7)).width - 28f, ((Rect)(ref rect7)).height - 24f); float actionsContentHeight = GetActionsContentHeight(((Rect)(ref val4)).width); bool flag2 = actionsContentHeight > ((Rect)(ref val4)).height + 1f; float num9 = (flag2 ? 18f : 0f); Rect val5 = default(Rect); ((Rect)(ref val5))..ctor(0f, 0f, Mathf.Max(40f, ((Rect)(ref val4)).width - num9), Mathf.Max(((Rect)(ref val4)).height, actionsContentHeight)); _actionsScrollPosition = GUI.BeginScrollView(val4, _actionsScrollPosition, val5, false, flag2); DrawActionsContent(new Rect(0f, 0f, ((Rect)(ref val5)).width, ((Rect)(ref val5)).height)); GUI.EndScrollView(); Rect rect8 = default(Rect); ((Rect)(ref rect8))..ctor(num, height - 34f, num2, 20f); DrawShadowLabel(rect8, "ESC fecha • Clique em cada jogador para abrir/fechar as ações", _footerStyle, new Vector2(1f, 1f), new Color(0f, 0f, 0f, 0.92f)); EndHudTabTransition(previousColor2, previousMatrix2); GUI.DragWindow(new Rect(0f, 0f, width, 110f)); return; } BeginHudTabTransition(out var previousColor3, out var previousMatrix3); float num10 = (((Object)(object)_uiTitleTopTexture != (Object)null) ? Mathf.Clamp(num2 * 0.18f, 76f, 118f) : num4); Rect rect9 = default(Rect); ((Rect)(ref rect9))..ctor(num, ((Rect)(ref rect2)).yMax + 2f, num2, num10); DrawTextureOrLabel(rect9, _uiTitleTopTexture, "TOP GLITNIR", _sectionTitleStyle); float num11 = num4 + num7 + 54f; float num12 = height - (((Rect)(ref rect9)).yMax + 6f) - num11; float num13 = Mathf.Clamp(num12 * 0.48f, 150f, 230f); Rect rect10 = default(Rect); ((Rect)(ref rect10))..ctor(num + 6f, ((Rect)(ref rect9)).yMax + 4f, num2 - 12f, num13); DrawPanel(rect10); Rect val6 = default(Rect); ((Rect)(ref val6))..ctor(((Rect)(ref rect10)).x + 14f, ((Rect)(ref rect10)).y + 12f, ((Rect)(ref rect10)).width - 28f, ((Rect)(ref rect10)).height - 24f); float topEntriesContentHeight = GetTopEntriesContentHeight(((Rect)(ref val6)).width); bool flag3 = topEntriesContentHeight > ((Rect)(ref val6)).height + 1f; float num14 = (flag3 ? 18f : 0f); Rect val7 = default(Rect); ((Rect)(ref val7))..ctor(0f, 0f, Mathf.Max(40f, ((Rect)(ref val6)).width - num14), Mathf.Max(((Rect)(ref val6)).height, topEntriesContentHeight)); _rankingScrollPosition = GUI.BeginScrollView(val6, _rankingScrollPosition, val7, false, flag3); DrawTopEntriesContent(new Rect(0f, 0f, ((Rect)(ref val7)).width, ((Rect)(ref val7)).height)); GUI.EndScrollView(); float num15 = (((Object)(object)_uiTitlePlayerTexture != (Object)null) ? Mathf.Clamp(num2 * 0.12f, 54f, 78f) : num4); Rect rect11 = default(Rect); ((Rect)(ref rect11))..ctor(num, ((Rect)(ref rect10)).yMax + 8f, num2, num15); DrawTextureOrLabel(rect11, _uiTitlePlayerTexture, "SEU DESEMPENHO", _sectionTitleStyle); float num16 = height - (((Rect)(ref rect11)).yMax + 4f) - num7 - 14f; num16 = Mathf.Max(250f, num16); Rect rect12 = default(Rect); ((Rect)(ref rect12))..ctor(num + 6f, ((Rect)(ref rect11)).yMax + 4f, num2 - 12f, num16); DrawPanel(rect12); Rect val8 = default(Rect); ((Rect)(ref val8))..ctor(((Rect)(ref rect12)).x + 14f, ((Rect)(ref rect12)).y + 12f, ((Rect)(ref rect12)).width - 28f, ((Rect)(ref rect12)).height - 24f); float playerContentHeight = GetPlayerContentHeight(((Rect)(ref val8)).width); bool flag4 = playerContentHeight > ((Rect)(ref val8)).height + 1f; float num17 = (flag4 ? 18f : 0f); Rect val9 = default(Rect); ((Rect)(ref val9))..ctor(0f, 0f, Mathf.Max(40f, ((Rect)(ref val8)).width - num17), Mathf.Max(((Rect)(ref val8)).height, playerContentHeight)); _playerInfoScrollPosition = GUI.BeginScrollView(val8, _playerInfoScrollPosition, val9, false, flag4); DrawPlayerContent(new Rect(0f, 0f, ((Rect)(ref val9)).width, ((Rect)(ref val9)).height)); GUI.EndScrollView(); Rect rect13 = default(Rect); ((Rect)(ref rect13))..ctor(num, height - 34f, num2, 20f); DrawShadowLabel(rect13, "ESC fecha • Clique nos cards do desempenho para expandir", _footerStyle, new Vector2(1f, 1f), new Color(0f, 0f, 0f, 0.92f)); EndHudTabTransition(previousColor3, previousMatrix3); GUI.DragWindow(new Rect(0f, 0f, width, 110f)); } private void BeginHudTabTransition(out Color previousColor, out Matrix4x4 previousMatrix) { //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_000d: 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_0068: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) previousColor = GUI.color; previousMatrix = GUI.matrix; float num = Mathf.Clamp01((Time.realtimeSinceStartup - _hudTabSwitchTime) * 5.5f); float num2 = Mathf.SmoothStep(0f, 1f, num); float num3 = (1f - num2) * 18f; GUI.color = new Color(previousColor.r, previousColor.g, previousColor.b, previousColor.a * num2); GUI.matrix = Matrix4x4.TRS(new Vector3(num3, 0f, 0f), Quaternion.identity, Vector3.one) * previousMatrix; } private void EndHudTabTransition(Color previousColor, Matrix4x4 previousMatrix) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) GUI.matrix = previousMatrix; GUI.color = previousColor; } private void DrawHudTabs(Rect rect) { //IL_0034: 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_0092: Unknown result type (might be due to invalid IL or missing references) float num = 8f; float num2 = (((Rect)(ref rect)).width - num * 2f) / 3f; DrawHudTabButton(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num2, ((Rect)(ref rect)).height), "Ranking", 0); DrawHudTabButton(new Rect(((Rect)(ref rect)).x + num2 + num, ((Rect)(ref rect)).y, num2, ((Rect)(ref rect)).height), "Guia", 1); DrawHudTabButton(new Rect(((Rect)(ref rect)).x + (num2 + num) * 2f, ((Rect)(ref rect)).y, num2, ((Rect)(ref rect)).height), "Ações", 2); } private void DrawHudTabButton(Rect rect, string label, int index) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0028: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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) bool flag = _hudTabIndex == index; Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = (flag ? new Color(0.91f, 0.75f, 0.34f, 0.95f) : new Color(0.34f, 0.26f, 0.13f, 0.9f)); if (GUI.Button(rect, label)) { if (_hudTabIndex != index) { _hudTabIndex = index; _hudTabSwitchTime = Time.realtimeSinceStartup; } GUI.FocusControl((string)null); } GUI.backgroundColor = backgroundColor; if ((Object)(object)_uiWhiteTexture != (Object)null && flag) { GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 2f, ((Rect)(ref rect)).width, 2f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(1f, 0.86f, 0.34f, 0.95f), 0f, 0f); } } private float GetTopEntriesContentHeight(float width) { int num = ((_cachedTopEntries != null) ? _cachedTopEntries.Count : 0); if (num <= 0) { return 120f; } return 12f + (float)num * 50f + (float)(num - 1) * 6f + 14f; } private void DrawTopEntriesContent(Rect rect) { //IL_003c: 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) if (_cachedTopEntries == null || _cachedTopEntries.Count == 0) { DrawShadowLabel(new Rect(12f, 10f, ((Rect)(ref rect)).width - 24f, 72f), "Nenhum herói pontuado ainda. Saia para caçar, evoluir skills e dominar Glitnir.", _emptyStateStyle); return; } float num = 6f; Rect rect2 = default(Rect); for (int i = 0; i < _cachedTopEntries.Count; i++) { SnapshotTopEntryData entry = _cachedTopEntries[i]; ((Rect)(ref rect2))..ctor(4f, num, ((Rect)(ref rect)).width - 8f, 50f); DrawRankRow(rect2, entry); num += ((Rect)(ref rect2)).height + 6f; } } private void DrawRankRow(Rect rect, SnapshotTopEntryData entry) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0181: 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_0199: 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_0120: 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_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: 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) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0221: 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) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0293: 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_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Unknown result type (might be due to invalid IL or missing references) if (entry != null && !((Object)(object)_uiWhiteTexture == (Object)null)) { Color rankAccentColor = GetRankAccentColor(entry.Position); bool flag = entry.Position <= 3; float num = (flag ? (0.55f + (Mathf.Sin(Time.time * 3.2f + (float)entry.Position) + 1f) * 0.225f) : 0f); float num2 = (flag ? (0.13f + num * 0.06f) : 0.06f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height - 4f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.03f, 0.02f, 0.01f, num2), 0f, 0f); if (flag) { GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 4f, ((Rect)(ref rect)).y + 3f, ((Rect)(ref rect)).width - 8f, ((Rect)(ref rect)).height - 6f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(rankAccentColor.r, rankAccentColor.g, rankAccentColor.b, 0.05f + num * 0.1f), 0f, 0f); } GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 4f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(rankAccentColor.r, rankAccentColor.g, rankAccentColor.b, flag ? (0.75f + num * 0.2f) : rankAccentColor.a), 0f, 0f); if (flag) { GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 4f, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width - 8f, 1.5f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(rankAccentColor.r, rankAccentColor.g, rankAccentColor.b, 0.35f + num * 0.35f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 4f, ((Rect)(ref rect)).yMax - 2.5f, ((Rect)(ref rect)).width - 8f, 1.5f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(rankAccentColor.r, rankAccentColor.g, rankAccentColor.b, 0.18f + num * 0.22f), 0f, 0f); } Texture2D rankPodiumIcon = GetRankPodiumIcon(entry.Position); float num3 = ((Rect)(ref rect)).x + 58f; if ((Object)(object)rankPodiumIcon != (Object)null) { float num4 = ((entry.Position == 1) ? 42f : ((entry.Position == 2) ? 40f : 38f)); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 5f, num4, num4); DrawTextureAspectFit(rect2, rankPodiumIcon); num3 = ((Rect)(ref rect)).x + 58f; } else { Rect rect3 = default(Rect); ((Rect)(ref rect3))..ctor(((Rect)(ref rect)).x + 10f, ((Rect)(ref rect)).y + 8f, 48f, 20f); DrawShadowLabel(rect3, "#" + Mathf.Max(1, entry.Position), _rankIndexStyle); } float num5 = 10f; if (entry.Position <= 3) { num5 += 18f; } Rect rect4 = default(Rect); ((Rect)(ref rect4))..ctor(num3, ((Rect)(ref rect)).y + 6f, ((Rect)(ref rect)).width - (num3 - ((Rect)(ref rect)).x) - 74f - num5, 22f); DrawShadowLabel(rect4, string.IsNullOrWhiteSpace(entry.PlayerName) ? "Jogador" : entry.PlayerName.ToUpperInvariant(), _rankNameStyle); Rect rect5 = default(Rect); ((Rect)(ref rect5))..ctor(num3, ((Rect)(ref rect)).y + 26f, 140f, 16f); DrawShadowLabel(rect5, ColorizePoints(FormatPoints(entry.Points)), _rankPointsStyle); } } private Texture2D GetRankPodiumIcon(int position) { return (Texture2D)(position switch { 1 => _uiRank1IconTexture, 2 => _uiRank2IconTexture, 3 => _uiRank3IconTexture, _ => null, }); } private string GetRankBadgeLabel(int position) { return position switch { 1 => "OURO", 2 => "PRATA", 3 => "BRONZE", _ => "", }; } private float GetActionsContentHeight(float width) { int num = ((_cachedTopEntries != null) ? _cachedTopEntries.Count : 0); if (num <= 0) { return 130f; } float num2 = 12f; for (int i = 0; i < num; i++) { SnapshotTopEntryData entry = _cachedTopEntries[i]; num2 += (IsActionPlayerExpanded(entry) ? 650f : 58f); num2 += 8f; } return num2 + 14f; } private void DrawActionsContent(Rect rect) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (_cachedTopEntries == null || _cachedTopEntries.Count == 0) { DrawShadowLabel(new Rect(12f, 10f, ((Rect)(ref rect)).width - 24f, 72f), "Nenhum jogador pontuado ainda. Quando o ranking receber pontos, as ações aparecerão aqui.", _emptyStateStyle); return; } float num = 8f; Rect rect2 = default(Rect); for (int i = 0; i < _cachedTopEntries.Count; i++) { SnapshotTopEntryData entry = _cachedTopEntries[i]; float num2 = (IsActionPlayerExpanded(entry) ? 650f : 58f); ((Rect)(ref rect2))..ctor(4f, num, ((Rect)(ref rect)).width - 8f, num2); DrawActionPlayerRow(rect2, entry); num += ((Rect)(ref rect2)).height + 8f; } } private string BuildActionPlayerKey(SnapshotTopEntryData entry) { if (entry == null) { return ""; } return Mathf.Max(1, entry.Position) + ":" + SafeKey(entry.PlayerName); } private bool IsActionPlayerExpanded(SnapshotTopEntryData entry) { string text = BuildActionPlayerKey(entry); return !string.IsNullOrWhiteSpace(text) && _expandedActionPlayers.Contains(text); } private void ToggleActionPlayerExpanded(SnapshotTopEntryData entry) { string text = BuildActionPlayerKey(entry); if (!string.IsNullOrWhiteSpace(text)) { if (_expandedActionPlayers.Contains(text)) { _expandedActionPlayers.Remove(text); } else { _expandedActionPlayers.Add(text); } } } private string GetNextExplorationGoalText(float currentPercent) { SnapshotPlayerData cachedPlayerData = _cachedPlayerData; if (cachedPlayerData == null || string.IsNullOrWhiteSpace(cachedPlayerData.HudExplorationMapJackpotRules)) { return "Sem marco configurado"; } try { string[] array = cachedPlayerData.HudExplorationMapJackpotRules.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }, 2, StringSplitOptions.None); if (array2.Length == 2) { string s = array2[0].Replace("Mapa", "").Replace("%", "").Trim(); if (int.TryParse(s, out var result) && int.TryParse(array2[1].Trim(), out var result2) && currentPercent < (float)result) { return result + "% (+" + result2 + " pts)"; } } } } catch { } return "Completo"; } private void DrawExplorationActionCard(Rect rect, Color accent, SnapshotTopEntryData entry) { //IL_015f: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_010b: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) float currentPercent = 0f; string text = "Disponível no seu perfil"; if (entry != null && entry.IsLocalPlayer) { currentPercent = GetExplorationMapProgressPercent(); text = GetNextExplorationGoalText(currentPercent); } if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(rect, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.26f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(accent.r, accent.g, accent.b, 0.36f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 26f, ((Rect)(ref rect)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(accent.r, accent.g, accent.b, 0.18f), 0f, 0f); } DrawShadowLabel(new Rect(((Rect)(ref rect)).x + 10f, ((Rect)(ref rect)).y + 5f, ((Rect)(ref rect)).width - 20f, 20f), "EXPLORAÇÃO", _cardLabelStyle); string amount = ((entry != null && entry.IsLocalPlayer) ? (currentPercent.ToString("0.0", CultureInfo.InvariantCulture) + "%") : "—"); DrawActionDetailLine(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + 32f, ((Rect)(ref rect)).width - 24f, 20f), "Mapa revelado", amount, 0); DrawShadowLabel(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + 55f, ((Rect)(ref rect)).width - 24f, 20f), ColorizeMuted("Próximo marco: ") + ColorizeHighlight(text), _bodyRowStyle); } private void DrawActionPlayerRow(Rect rect, SnapshotTopEntryData entry) { //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_0065: 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_006a: 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_0079: 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_00b6: 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_00ff: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0161: 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_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017f: 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_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Unknown result type (might be due to invalid IL or missing references) //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_05b4: Unknown result type (might be due to invalid IL or missing references) //IL_05be: Unknown result type (might be due to invalid IL or missing references) //IL_0617: Unknown result type (might be due to invalid IL or missing references) //IL_0621: Unknown result type (might be due to invalid IL or missing references) //IL_0701: Unknown result type (might be due to invalid IL or missing references) //IL_0713: Unknown result type (might be due to invalid IL or missing references) //IL_0719: Unknown result type (might be due to invalid IL or missing references) //IL_071f: Unknown result type (might be due to invalid IL or missing references) //IL_072a: Unknown result type (might be due to invalid IL or missing references) //IL_076c: Unknown result type (might be due to invalid IL or missing references) //IL_06af: Unknown result type (might be due to invalid IL or missing references) //IL_06d2: Unknown result type (might be due to invalid IL or missing references) if (entry == null || (Object)(object)_uiWhiteTexture == (Object)null) { return; } bool flag = IsActionPlayerExpanded(entry); Color rankAccentColor = GetRankAccentColor(entry.Position); Color val = (flag ? new Color(0.035f, 0.022f, 0.01f, 0.5f) : new Color(0.025f, 0.018f, 0.01f, 0.34f)); GUI.DrawTexture(rect, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 5f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, rankAccentColor, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 5f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - 10f, 1.5f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(rankAccentColor.r, rankAccentColor.g, rankAccentColor.b, flag ? 0.72f : 0.36f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 5f, ((Rect)(ref rect)).yMax - 1.5f, ((Rect)(ref rect)).width - 10f, 1.5f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(rankAccentColor.r, rankAccentColor.g, rankAccentColor.b, flag ? 0.46f : 0.2f), 0f, 0f); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + 8f, ((Rect)(ref rect)).width - 24f, 42f); if (GUI.Button(val2, GUIContent.none, GUIStyle.none)) { ToggleActionPlayerExpanded(entry); } string text = (flag ? "▼" : "▶"); string text2 = (string.IsNullOrWhiteSpace(entry.PlayerName) ? "JOGADOR" : entry.PlayerName.ToUpperInvariant()); DrawShadowLabel(new Rect(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 8f, 26f, 22f), text, _bodyValueStyle); DrawShadowLabel(new Rect(((Rect)(ref val2)).x + 32f, ((Rect)(ref val2)).y + 3f, ((Rect)(ref val2)).width - 184f, 26f), "#" + Mathf.Max(1, entry.Position) + " " + text2, _panelHeadingStyle); DrawShadowLabel(new Rect(((Rect)(ref val2)).xMax - 142f, ((Rect)(ref val2)).y + 5f, 132f, 22f), ColorizePoints(FormatPoints(entry.Points)), _bodyValueStyle); if (!flag) { string text3 = ColorizeDanger(entry.TotalKillsPontuadas + " kills") + " • " + ColorizeDanger(entry.TotalBossesPontuadas + " bosses") + " • " + ColorizeProgress(entry.TotalSkillLevelUpsPontuados + " skills") + " • " + ColorizeProgress(entry.TotalCraftPontuadas + " crafts") + " • " + ColorizeDanger(entry.TotalPointsExchanges + " câmbios"); DrawShadowLabel(new Rect(((Rect)(ref val2)).x + 32f, ((Rect)(ref val2)).y + 27f, ((Rect)(ref val2)).width - 48f, 16f), text3, _mutedBodyStyle); return; } float num = ((Rect)(ref rect)).x + 20f; float num2 = ((Rect)(ref rect)).y + 58f; float num3 = ((Rect)(ref rect)).width - 40f; float num4 = 78f; float num5 = 10f; DrawActionSectionCard(new Rect(num, num2, num3, num4), "COMBATE", rankAccentColor, "Kills", entry.TotalKillsPontuadas.ToString() ?? "", entry.KillPointsTotal, "Bosses", entry.TotalBossesPontuadas.ToString() ?? "", entry.BossPointsTotal); num2 += num4 + num5; DrawActionSectionCard(new Rect(num, num2, num3, num4), "PROGRESSÃO", rankAccentColor, "Skills", entry.TotalSkillLevelUpsPontuados + " marcos", entry.SkillPointsTotal, "Pesca", entry.TotalFishingPontuadas + " peixes", entry.FishingPointsTotal); num2 += num4 + num5; DrawExplorationActionCard(new Rect(num, num2, num3, num4), rankAccentColor, entry); num2 += num4 + num5; DrawActionSectionCard(new Rect(num, num2, num3, num4), "ECONOMIA", rankAccentColor, "Crafts", entry.TotalCraftPontuadas.ToString() ?? "", entry.CraftPointsTotal, "Cultivo", entry.TotalFarmJackpotsPontuados + " jackpots", entry.FarmJackpotPointsTotal); num2 += num4 + num5; DrawActionSectionCard(new Rect(num, num2, num3, num4), "FEITOS", rankAccentColor, "Únicos", entry.TotalUniqueCraftJackpotsPontuados.ToString() ?? "", entry.UniqueCraftJackpotPointsTotal, "Mortes", entry.TotalDeaths.ToString() ?? "", -entry.DeathPenaltyPointsTotal); num2 += num4 + num5; DrawActionSectionCard(new Rect(num, num2, num3, num4), "CÂMBIO", rankAccentColor, "Trocas", entry.TotalPointsExchanges + " realizadas", -entry.PointsExchangePenaltyTotal, "Moedas", entry.PointsExchangeCoinsTotal + " Coins", 0); string text4 = (string.IsNullOrWhiteSpace(entry.LastReason) ? "Sem último registro" : entry.LastReason); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(num, ((Rect)(ref rect)).yMax - 32f, num3, 22f); if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(val3, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.24f), 0f, 0f); } GUI.DrawTexture(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, 3f, ((Rect)(ref val3)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(rankAccentColor.r, rankAccentColor.g, rankAccentColor.b, 0.7f), 0f, 0f); DrawShadowLabel(new Rect(((Rect)(ref val3)).x + 10f, ((Rect)(ref val3)).y + 3f, ((Rect)(ref val3)).width - 20f, 18f), ColorizeMuted("Último registro: ") + ColorizeHighlight(text4), _configStyle); } private void DrawActionSectionCard(Rect rect, string title, Color accent, string labelA, string amountA, int pointsA, string labelB, string amountB, int pointsB) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00e2: 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) if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(rect, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.26f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(accent.r, accent.g, accent.b, 0.36f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 26f, ((Rect)(ref rect)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(accent.r, accent.g, accent.b, 0.18f), 0f, 0f); } DrawShadowLabel(new Rect(((Rect)(ref rect)).x + 10f, ((Rect)(ref rect)).y + 5f, ((Rect)(ref rect)).width - 20f, 20f), title, _cardLabelStyle); DrawActionDetailLine(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + 32f, ((Rect)(ref rect)).width - 24f, 20f), labelA, amountA, pointsA); DrawActionDetailLine(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + 55f, ((Rect)(ref rect)).width - 24f, 20f), labelB, amountB, pointsB); } private void DrawActionDetailLine(Rect rect, string label, string amount, int points) { //IL_0007: 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_0014: 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_0025: Expected O, but got Unknown //IL_002b: 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_0038: 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_0049: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) GUIStyle style = new GUIStyle(_bodyRowStyle) { clipping = (TextClipping)1, wordWrap = false, alignment = (TextAnchor)3 }; GUIStyle style2 = new GUIStyle(_bodyValueStyle) { clipping = (TextClipping)1, wordWrap = false, alignment = (TextAnchor)5 }; float num = Mathf.Clamp(((Rect)(ref rect)).width * 0.42f, 145f, 190f); float num2 = Mathf.Max(90f, ((Rect)(ref rect)).width - num - 12f); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num2, ((Rect)(ref rect)).height); Rect rect3 = default(Rect); ((Rect)(ref rect3))..ctor(((Rect)(ref rect)).xMax - num, ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height); string amount2 = (string.IsNullOrWhiteSpace(amount) ? "0" : amount.Trim()); string text = "" + label + " " + ColorizeActionAmount(label, amount2); DrawShadowLabel(rect2, text, style); DrawShadowLabel(rect3, FormatSignedPointsColored(points), style2); } private void DrawActionMetricBox(Rect rect, string label, string amount, int points) { //IL_0050: 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_005d: 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_006e: Expected O, but got Unknown //IL_0074: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0098: 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) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(rect, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.2f), 0f, 0f); } GUIStyle style = new GUIStyle(_mutedBodyStyle) { clipping = (TextClipping)1, wordWrap = false, alignment = (TextAnchor)3 }; GUIStyle style2 = new GUIStyle(_bodyRowStyle) { clipping = (TextClipping)1, wordWrap = false, alignment = (TextAnchor)3 }; GUIStyle style3 = new GUIStyle(_bodyValueStyle) { clipping = (TextClipping)1, wordWrap = false, alignment = (TextAnchor)5 }; float num = ((Rect)(ref rect)).x + 7f; float num2 = ((Rect)(ref rect)).y + 2f; float num3 = ((Rect)(ref rect)).width - 14f; float num4 = ((Rect)(ref rect)).height - 4f; float num5 = num3 * 0.34f; float num6 = num3 * 0.25f; float num7 = num3 - num5 - num6 - 10f; Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(num, num2, num5, num4); Rect rect3 = default(Rect); ((Rect)(ref rect3))..ctor(((Rect)(ref rect2)).xMax + 4f, num2, num6, num4); Rect rect4 = default(Rect); ((Rect)(ref rect4))..ctor(((Rect)(ref rect3)).xMax + 6f, num2, num7, num4); DrawShadowLabel(rect2, label, style); DrawShadowLabel(rect3, ColorizeActionAmount(label, amount), style2); DrawShadowLabel(rect4, FormatSignedPointsColored(points), style3); } private string FormatPoints(int points) { return points.ToString("N0", CultureInfo.InvariantCulture).Replace(",", ".") + " pts"; } private string FormatSignedPoints(int points) { if (points > 0) { return "+" + FormatPoints(points); } if (points < 0) { return "-" + FormatPoints(Mathf.Abs(points)); } return "0 pts"; } private string ColorizeHud(string text, string color) { return "" + text + ""; } private string ColorizePoints(string text) { return ColorizeHud(text, "#00FF7F"); } private string ColorizeDanger(string text) { return ColorizeHud(text, "#FF5555"); } private string ColorizeProgress(string text) { return ColorizeHud(text, "#4FC3F7"); } private string ColorizeHighlight(string text) { return ColorizeHud(text, "#FFD700"); } private string ColorizeMuted(string text) { return ColorizeHud(text, "#D7DCE5"); } private string FormatSignedPointsColored(int points) { if (points > 0) { return ColorizePoints("+" + FormatPoints(points)); } if (points < 0) { return ColorizeDanger("-" + FormatPoints(Mathf.Abs(points))); } return ColorizeMuted("0 pts"); } private string ColorizeActionAmount(string label, string amount) { string text = (label ?? "").ToLowerInvariant(); if (text.Contains("morte") || text.Contains("câmbio") || text.Contains("cambio") || text.Contains("kill") || text.Contains("boss") || text.Contains("combate")) { return ColorizeDanger(amount); } if (text.Contains("skill") || text.Contains("pesca") || text.Contains("craft") || text.Contains("cultivo") || text.Contains("únic") || text.Contains("unico")) { return ColorizeProgress(amount); } return ColorizeHighlight(amount); } private string ColorizePerformanceValue(string label, string value) { string text = (label ?? "").ToLowerInvariant(); if (text.Contains("pontos")) { if (int.TryParse(value, out var result)) { return FormatSignedPointsColored(result); } return ColorizePoints(value); } if (text.Contains("kill") || text.Contains("boss") || text.Contains("morte") || text.Contains("câmbio") || text.Contains("cambio") || text.Contains("penalidade")) { return ColorizeDanger(value); } if (text.Contains("skill") || text.Contains("craft") || text.Contains("pesca") || text.Contains("cultivo") || text.Contains("níve") || text.Contains("nive")) { return ColorizeProgress(value); } if (text.Contains("posição") || text.Contains("origem") || text.Contains("item") || text.Contains("recompensa")) { return ColorizeHighlight(value); } return ColorizeMuted(value); } private float GetPlayerContentHeight(float width) { if (_cachedPlayerData == null || !_cachedPlayerData.HasData) { return 230f; } float num = 12f; num += 80f; num += EstimatePerformanceBlockHeight("Resumo", 108f); num += EstimatePerformanceBlockHeight("Origem", 304f); num += EstimatePerformanceBlockHeight("Último registro", 58f); num += EstimatePerformanceBlockHeight("Recompensa", 250f); num += EstimatePerformanceBlockHeight("Configuração", 44f); return Mathf.Max(230f, num + 18f); } private float EstimatePerformanceBlockHeight(string categoryKey, float expandedContentHeight) { if (!IsPerformanceCategoryExpanded(categoryKey)) { return 42f; } return 72f + expandedContentHeight + 14f; } private void DrawPlayerContent(Rect rect) { //IL_0097: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_014f: 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_0042: 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) float num = 8f; float num2 = ((Rect)(ref rect)).width - 16f; float num3 = 12f; if (_cachedPlayerData == null || !_cachedPlayerData.HasData) { DrawPerformanceEmptyState(new Rect(num, num3, num2, 150f)); num3 += 166f; DrawPerformanceBlock(new Rect(num, num3, num2, 10f), "Configuração", "Configuração", "Resumo rápido das regras ativas no servidor.", 44f, delegate(Rect contentRect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DrawConfigSection(contentRect, _cachedPlayerData); }); return; } DrawPlayerSummaryBlock(new Rect(num, num3, num2, 58f)); num3 += 80f; num3 = DrawPerformanceBlock(new Rect(num, num3, num2, 10f), "Resumo da jornada", "Resumo", "Sua atividade principal registrada no ranking.", 108f, delegate(Rect contentRect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DrawSimpleInfoRows(contentRect, new string[4] { "Kills pontuadas|" + _cachedPlayerData.TotalKillsPontuadas, "Bosses pontuados|" + _cachedPlayerData.TotalBossesPontuadas, "Níveis de skill|" + _cachedPlayerData.TotalSkillLevelUpsPontuados, "Câmbios realizados|" + _cachedPlayerData.TotalPointsExchanges }); }); num3 = DrawPerformanceBlock(new Rect(num, num3, num2, 10f), "Origem dos pontos", "Origem", "Veja quais caminhos estão sustentando sua posição.", 304f, delegate(Rect contentRect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DrawSimpleInfoRows(contentRect, new string[11] { "Pontos por kills|" + _cachedPlayerData.KillPointsTotal, "Pontos por bosses|" + _cachedPlayerData.BossPointsTotal, "Pontos por skills|" + _cachedPlayerData.SkillPointsTotal, "Pontos por pesca|" + _cachedPlayerData.FishingPointsTotal, "Pontos por craft|" + _cachedPlayerData.CraftPointsTotal, "Pontos por cultivo|" + _cachedPlayerData.FarmJackpotPointsTotal, "Pontos por itens únicos|" + _cachedPlayerData.UniqueCraftJackpotPointsTotal, "Pontos por exploração|" + _cachedPlayerData.ExplorationMapJackpotPointsTotal, "Penalidade por mortes|-" + _cachedPlayerData.DeathPenaltyPointsTotal, "Penalidade por câmbio|-" + _cachedPlayerData.PointsExchangePenaltyTotal, "Coins recebidas no câmbio|" + _cachedPlayerData.PointsExchangeCoinsTotal }); }); num3 = DrawPerformanceBlock(new Rect(num, num3, num2, 10f), "Último registro", "Último registro", "Última ação registrada pelo servidor para sua jornada.", 58f, delegate(Rect contentRect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DrawSimpleInfoRows(contentRect, new string[2] { "Origem|" + (string.IsNullOrWhiteSpace(_cachedPlayerData.LastReason) ? "sem registro" : _cachedPlayerData.LastReason), "Atualização|" + FormatHudLastUpdate(_cachedPlayerData.LastUpdateUtc) }); }); num3 = DrawPerformanceBlock(new Rect(num, num3, num2, 10f), "Recompensa do ranking", "Recompensa", "Prêmios disponíveis para os melhores colocados da temporada e câmbio de pontos por moedas.", 300f, delegate(Rect contentRect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DrawRewardClaimSection(contentRect); }); num3 = DrawPerformanceBlock(new Rect(num, num3, num2, 10f), "Configuração atual", "Configuração", "Estado das regras principais que afetam sua pontuação.", 44f, delegate(Rect contentRect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DrawConfigSection(contentRect, _cachedPlayerData); }); } private void DrawPerformanceEmptyState(Rect rect) { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height - 4f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.03f, 0.02f, 0.01f, 0.06f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 4f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.91f, 0.75f, 0.34f, 0.82f), 0f, 0f); } DrawShadowLabel(new Rect(((Rect)(ref rect)).x + 14f, ((Rect)(ref rect)).y + 12f, ((Rect)(ref rect)).width - 28f, 24f), "Sua jornada ainda não começou", _panelHeadingStyle); DrawBodyParagraph(new Rect(((Rect)(ref rect)).x + 14f, ((Rect)(ref rect)).y + 42f, ((Rect)(ref rect)).width - 28f, 72f), "Ganhe pontos derrotando criaturas, produzindo itens, pescando, completando jackpots e evoluindo seu personagem. Quando o servidor registrar seus primeiros pontos, seu desempenho será exibido em cards expansíveis."); } private float DrawPerformanceBlock(Rect startRect, string title, string categoryKey, string description, float expandedContentHeight, Action drawContent) { //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0136: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0215: 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_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) float x = ((Rect)(ref startRect)).x; float y = ((Rect)(ref startRect)).y; float width = ((Rect)(ref startRect)).width; bool flag = IsPerformanceCategoryExpanded(categoryKey); Rect val = default(Rect); ((Rect)(ref val))..ctor(x, y, width, 34f); if ((Object)(object)_uiWhiteTexture != (Object)null) { Color val2 = (flag ? new Color(0.17f, 0.11f, 0.035f, 0.55f) : new Color(0.045f, 0.032f, 0.018f, 0.42f)); GUI.DrawTexture(val, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).yMax - 1f, ((Rect)(ref val)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.95f, 0.76f, 0.33f, flag ? 0.55f : 0.24f), 0f, 0f); } Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = new Color(0.27f, 0.2f, 0.09f, flag ? 0.86f : 0.62f); if (GUI.Button(val, GUIContent.none)) { TogglePerformanceCategory(categoryKey); GUI.FocusControl((string)null); } GUI.backgroundColor = backgroundColor; string text = (flag ? "▼" : "▶"); DrawShadowLabel(new Rect(x + 10f, y + 7f, 20f, 22f), text, _panelHeadingStyle); Texture2D ruleCategoryIcon = GetRuleCategoryIcon(categoryKey); float num = x + 36f; if ((Object)(object)ruleCategoryIcon != (Object)null) { Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(x + 31f, y + 5f, 24f, 24f); GUI.DrawTexture(val3, (Texture)(object)ruleCategoryIcon, (ScaleMode)2, true); num = ((Rect)(ref val3)).xMax + 8f; } DrawShadowLabel(new Rect(num, y + 7f, width - (num - x) - 12f, 22f), title, _panelHeadingStyle); y += 40f; if (!flag) { return y + 2f; } DrawBodyParagraph(new Rect(x + 8f, y, width - 16f, 24f), description); y += 30f; Rect obj = default(Rect); ((Rect)(ref obj))..ctor(x + 8f, y, width - 16f, expandedContentHeight); drawContent?.Invoke(obj); return y + (expandedContentHeight + 14f); } private void EnsurePerformanceCategoriesInitialized() { if (!_performanceCategoriesInitialized) { _expandedPerformanceCategories.Clear(); _performanceCategoriesInitialized = true; } } private bool IsPerformanceCategoryExpanded(string categoryKey) { if (string.IsNullOrWhiteSpace(categoryKey)) { return false; } EnsurePerformanceCategoriesInitialized(); return _expandedPerformanceCategories.Contains(categoryKey); } private void TogglePerformanceCategory(string categoryKey) { if (!string.IsNullOrWhiteSpace(categoryKey)) { EnsurePerformanceCategoriesInitialized(); if (_expandedPerformanceCategories.Contains(categoryKey)) { _expandedPerformanceCategories.Remove(categoryKey); } else { _expandedPerformanceCategories.Add(categoryKey); } } } private float GetRulesContentHeight(float width) { SnapshotPlayerData snapshotPlayerData = _cachedPlayerData ?? new SnapshotPlayerData(); float num = 14f; num += 54f; num += 34f; num += EstimateRulesBlockHeight(width, "Combate", snapshotPlayerData.HudKillRules); num += EstimateRulesBlockHeight(width, "Bosses", snapshotPlayerData.HudBossRules); num += EstimateRulesBlockHeight(width, "Skills", snapshotPlayerData.HudSkillJackpotRules); num += EstimateRulesBlockHeight(width, "Quests", snapshotPlayerData.HudMarketplaceQuestRules); num += EstimateRulesBlockHeight(width, "Pesca", snapshotPlayerData.HudFishingRules); num += EstimateRulesBlockHeight(width, "Exploração", snapshotPlayerData.HudExplorationMapJackpotRules); num += EstimateRulesBlockHeight(width, "Produção", snapshotPlayerData.HudCraftRules); num += EstimateRulesBlockHeight(width, "Cultivo", snapshotPlayerData.HudFarmJackpotRules); num += EstimateRulesBlockHeight(width, "Conquistas", snapshotPlayerData.HudUniqueCraftJackpotRules); num += EstimateRulesBlockHeight(width, "Penalidades", GetDeathPenaltyHudRules(snapshotPlayerData)); return Mathf.Max(260f, num + 18f); } private float EstimateRulesBlockHeight(float width, string title, string rules) { if (!IsRuleCategoryExpanded(title)) { return 42f; } if (string.Equals(title, "Skills", StringComparison.OrdinalIgnoreCase)) { return EstimateSkillGuideBlockHeight(rules); } if (ShouldGroupRulesByItemCategory(title)) { return EstimateCategorizedGuideBlockHeight(title, rules); } int num = SplitRulesForHud(rules).Count(); num = Mathf.Max(1, num); float num2 = ((string.Equals(title, "Exploração", StringComparison.OrdinalIgnoreCase) || string.Equals(title, "Exploracao", StringComparison.OrdinalIgnoreCase) || string.Equals(title, "Exploration", StringComparison.OrdinalIgnoreCase)) ? 58f : 0f); return 72f + num2 + (float)num * 26f + 14f; } private void DrawRulesContent(Rect rect) { //IL_0034: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0159: 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_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) SnapshotPlayerData snapshotPlayerData = _cachedPlayerData ?? new SnapshotPlayerData(); float num = 8f; float num2 = ((Rect)(ref rect)).width - 16f; float num3 = 12f; DrawBodyParagraph(new Rect(num, num3, num2, 42f), "Clique em uma categoria para abrir ou fechar. Use este guia como mapa rápido de pontos: ações comuns aparecem com +pts, jackpots mostram meta e recompensa, e penalidades aparecem como perda."); num3 += 54f; num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Combate", "Combate", snapshotPlayerData.EnableKillPoints, snapshotPlayerData.HudKillRules, "Mate criaturas configuradas pelo servidor.", "Nome:pontos", jackpotFormat: false); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Bosses", "Bosses", snapshotPlayerData.EnableBossPoints, snapshotPlayerData.HudBossRules, "Derrote bosses válidos e receba pontos pelo crédito registrado.", "Nome:pontos", jackpotFormat: false); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Skills", "Skills", snapshotPlayerData.EnableSkillPoints, snapshotPlayerData.HudSkillJackpotRules, "Evolua uma habilidade até um marco configurado para receber pontos. Cada habilidade pode ser aberta separadamente para ver seus marcos.", "Clique na habilidade para ver níveis e recompensas", jackpotFormat: false); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Quests", "Quests", snapshotPlayerData.EnableMarketplaceQuestPoints, snapshotPlayerData.HudMarketplaceQuestRules, "Complete quests configuradas do Marketplace para receber pontos únicos.", "Quest:pontos", jackpotFormat: false); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Pesca", "Pesca", enabled: true, snapshotPlayerData.HudFishingRules, "Pesque os peixes configurados para receber pontos.", "Nome:pontos", jackpotFormat: false); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Exploração", "Exploração", snapshotPlayerData.RankingEnabled, snapshotPlayerData.HudExplorationMapJackpotRules, "Revele o mapa para ativar jackpots de exploração.", "Mapa %:pontos", jackpotFormat: false); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Produção", "Produção", enabled: true, snapshotPlayerData.HudCraftRules, "Crie armas, armaduras, comidas ou outros itens configurados.", "Nome:pontos", jackpotFormat: false); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Cultivo", "Cultivo", enabled: true, snapshotPlayerData.HudFarmJackpotRules, "Complete grandes metas de colheita para ativar jackpots.", "Nome:quantidade:pontos", jackpotFormat: true); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Conquistas", "Conquistas", enabled: true, snapshotPlayerData.HudUniqueCraftJackpotRules, "Crie itens especiais uma única vez para ganhar bônus.", "Nome:quantidade:pontos", jackpotFormat: true); string deathPenaltyHudRules = GetDeathPenaltyHudRules(snapshotPlayerData); string description = (snapshotPlayerData.DeathPenaltyUseMultiplier ? "Modo multiplicador ativo: cada morte reduz pontos pelo valor fixo configurado." : "Mortes podem reduzir pontos conforme a configuração por marcos."); string formatHint = (snapshotPlayerData.DeathPenaltyUseMultiplier ? "mortes x pontos por morte" : "mortes:pontos perdidos"); num3 = DrawRulesBlock(new Rect(num, num3, num2, 10f), "Penalidades", "Penalidades", snapshotPlayerData.EnableDeathPenalty, deathPenaltyHudRules, description, formatHint, !snapshotPlayerData.DeathPenaltyUseMultiplier); } private string GetDeathPenaltyHudRules(SnapshotPlayerData data) { if (data == null) { return string.Empty; } if (!data.DeathPenaltyUseMultiplier) { return data.HudDeathPenaltyRules ?? string.Empty; } int num = Mathf.Max(0, data.DeathPenaltyPerDeath); return "1 morte:-" + num + ";15 mortes:-" + num * 15; } private float GetExplorationMapProgressPercent() { SnapshotPlayerData cachedPlayerData = _cachedPlayerData; if (cachedPlayerData == null) { return 0f; } if (cachedPlayerData.FloatProgressCounters != null) { if (cachedPlayerData.FloatProgressCounters.TryGetValue("ExplorationMap:Percent", out var value)) { return Mathf.Clamp(value, 0f, 100f); } if (cachedPlayerData.FloatProgressCounters.TryGetValue("Exploration:Map", out value)) { return Mathf.Clamp(value, 0f, 100f); } if (cachedPlayerData.FloatProgressCounters.TryGetValue("Exploracao:Mapa", out value)) { return Mathf.Clamp(value, 0f, 100f); } } if (cachedPlayerData.ProgressCounters == null) { return 0f; } if (cachedPlayerData.ProgressCounters.TryGetValue("ExplorationMap:Percent", out var value2)) { return Mathf.Clamp(value2, 0, 100); } if (cachedPlayerData.ProgressCounters.TryGetValue("Exploration:Map", out value2)) { return Mathf.Clamp(value2, 0, 100); } if (cachedPlayerData.ProgressCounters.TryGetValue("Exploracao:Mapa", out value2)) { return Mathf.Clamp(value2, 0, 100); } return 0f; } private void DrawExplorationMapProgressBar(Rect rect) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) float explorationMapProgressPercent = GetExplorationMapProgressPercent(); float num = Mathf.Clamp01(explorationMapProgressPercent / 100f); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 18f); DrawShadowLabel(rect2, "Mapa revelado: " + explorationMapProgressPercent.ToString("0.0", CultureInfo.InvariantCulture) + "%", GetHudTintedStyle(_bodyValueStyle, new Color(0.58f, 0.9f, 1f, 1f), (TextAnchor)3)); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 24f, ((Rect)(ref rect)).width, 14f); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 2f, ((Rect)(ref val)).y + 2f, Mathf.Max(0f, (((Rect)(ref val)).width - 4f) * num), ((Rect)(ref val)).height - 4f); if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(val, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.48f), 0f, 6f); GUI.DrawTexture(val2, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.22f, 0.75f, 1f, 0.86f), 0f, 5f); GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.95f, 0.76f, 0.33f, 0.42f), 0f, 0f); } DrawShadowLabel(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y - 1f, ((Rect)(ref val)).width, ((Rect)(ref val)).height + 2f), explorationMapProgressPercent.ToString("0.0", CultureInfo.InvariantCulture) + "%", GetHudTintedStyle(_mutedBodyStyle, new Color(0.95f, 0.95f, 0.88f, 1f), (TextAnchor)4)); } private float DrawRulesBlock(Rect startRect, string title, string categoryKey, bool enabled, string rules, string description, string formatHint, bool jackpotFormat) { //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0136: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0215: 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_0275: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) float x = ((Rect)(ref startRect)).x; float y = ((Rect)(ref startRect)).y; float width = ((Rect)(ref startRect)).width; bool flag = IsRuleCategoryExpanded(categoryKey); Rect val = default(Rect); ((Rect)(ref val))..ctor(x, y, width, 34f); if ((Object)(object)_uiWhiteTexture != (Object)null) { Color val2 = (flag ? new Color(0.17f, 0.11f, 0.035f, 0.55f) : new Color(0.045f, 0.032f, 0.018f, 0.42f)); GUI.DrawTexture(val, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).yMax - 1f, ((Rect)(ref val)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.95f, 0.76f, 0.33f, flag ? 0.55f : 0.24f), 0f, 0f); } Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = new Color(0.27f, 0.2f, 0.09f, flag ? 0.86f : 0.62f); if (GUI.Button(val, GUIContent.none)) { ToggleRuleCategory(categoryKey); GUI.FocusControl((string)null); } GUI.backgroundColor = backgroundColor; string text = (flag ? "▼" : "▶"); DrawShadowLabel(new Rect(x + 10f, y + 7f, 20f, 22f), text, _panelHeadingStyle); Texture2D ruleCategoryIcon = GetRuleCategoryIcon(categoryKey); float num = x + 36f; if ((Object)(object)ruleCategoryIcon != (Object)null) { Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(x + 31f, y + 5f, 24f, 24f); GUI.DrawTexture(val3, (Texture)(object)ruleCategoryIcon, (ScaleMode)2, true); num = ((Rect)(ref val3)).xMax + 8f; } DrawShadowLabel(new Rect(num, y + 7f, width - (num - x) - 12f, 22f), title, _panelHeadingStyle); y += 40f; if (!flag) { return y + 2f; } float num2 = (string.Equals(categoryKey, "Skills", StringComparison.OrdinalIgnoreCase) ? 52f : 28f); DrawBodyParagraph(new Rect(x + 8f, y, width - 16f, num2), description + " • " + formatHint); y += num2 + 8f; if (string.Equals(categoryKey, "Exploração", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Exploracao", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Exploration", StringComparison.OrdinalIgnoreCase)) { DrawExplorationMapProgressBar(new Rect(x + 8f, y, width - 16f, 46f)); y += 56f; } if (string.Equals(categoryKey, "Skills", StringComparison.OrdinalIgnoreCase)) { return DrawSkillGuideRows(x, y, width, rules); } if (ShouldGroupRulesByItemCategory(categoryKey)) { return DrawCategorizedGuideRows(x, y, width, categoryKey, rules, jackpotFormat); } List list = SplitRulesForHud(rules).ToList(); if (list.Count == 0) { list.Add("Nenhuma regra encontrada."); } for (int i = 0; i < list.Count; i++) { if (IsHudCategoryHeader(list[i])) { DrawGuideCategoryHeader(new Rect(x + 8f, y + 4f, width - 16f, 24f), GetHudCategoryHeaderTitle(list[i])); y += 30f; } else { DrawGuideRuleRow(new Rect(x + 8f, y, width - 16f, 24f), list[i], categoryKey, jackpotFormat, title.IndexOf("Penalidades", StringComparison.OrdinalIgnoreCase) >= 0); y += 26f; } } return y + 14f; } private int GetRuleProgressCount(string categoryKey, string prefab) { SnapshotPlayerData cachedPlayerData = _cachedPlayerData; if (cachedPlayerData == null || cachedPlayerData.ProgressCounters == null || string.IsNullOrWhiteSpace(prefab)) { return 0; } string text = SafeKey(prefab); string[] array = ((!string.Equals(categoryKey, "Combate", StringComparison.OrdinalIgnoreCase) && !string.Equals(categoryKey, "Combat", StringComparison.OrdinalIgnoreCase)) ? ((!string.Equals(categoryKey, "Produção", StringComparison.OrdinalIgnoreCase) && !string.Equals(categoryKey, "Producao", StringComparison.OrdinalIgnoreCase) && !string.Equals(categoryKey, "Production", StringComparison.OrdinalIgnoreCase)) ? ((!string.Equals(categoryKey, "Conquistas", StringComparison.OrdinalIgnoreCase) && !string.Equals(categoryKey, "Achievements", StringComparison.OrdinalIgnoreCase)) ? ((!string.Equals(categoryKey, "Bosses", StringComparison.OrdinalIgnoreCase) && !string.Equals(categoryKey, "Chefes", StringComparison.OrdinalIgnoreCase)) ? ((!string.Equals(categoryKey, "Pesca", StringComparison.OrdinalIgnoreCase) && !string.Equals(categoryKey, "Fishing", StringComparison.OrdinalIgnoreCase)) ? (string.Equals(categoryKey, "Cultivo", StringComparison.OrdinalIgnoreCase) ? new string[1] { "Farm:" + text } : ((!string.Equals(categoryKey, "Exploração", StringComparison.OrdinalIgnoreCase) && !string.Equals(categoryKey, "Exploracao", StringComparison.OrdinalIgnoreCase) && !string.Equals(categoryKey, "Exploration", StringComparison.OrdinalIgnoreCase)) ? new string[1] { SafeKey(categoryKey) + ":" + text } : new string[3] { "ExplorationMap:Percent", "Exploration:Map", "Exploracao:Mapa" })) : new string[2] { "Fishing:" + text, "Pesca:" + text }) : new string[1] { "Bosses:" + text }) : new string[1] { "UniqueCraft:" + text }) : new string[2] { "Craft:" + text, "Production:" + text }) : new string[2] { "Kill:" + text, "Combat:" + text }); for (int i = 0; i < array.Length; i++) { if (cachedPlayerData.ProgressCounters.TryGetValue(array[i], out var value)) { return Mathf.Clamp(value, 0, int.MaxValue); } } string value2 = ":" + text; int num = 0; foreach (KeyValuePair progressCounter in cachedPlayerData.ProgressCounters) { if (!string.IsNullOrWhiteSpace(progressCounter.Key) && progressCounter.Key.EndsWith(value2, StringComparison.OrdinalIgnoreCase)) { num = Mathf.Clamp(num + Mathf.Max(0, progressCounter.Value), 0, int.MaxValue); } } return num; } private float EstimateCategorizedGuideBlockHeight(string categoryKey, string rules) { List list = BuildRuleGuideGroups(categoryKey, rules, applySearchFilter: false); if (list.Count == 0) { return 118f; } float num = 76f; for (int i = 0; i < list.Count; i++) { RuleGuideGroup ruleGuideGroup = list[i]; num += 32f; if (IsRuleSubCategoryExpanded(categoryKey, ruleGuideGroup.Name)) { num += (float)Mathf.Max(1, ruleGuideGroup.Rows.Count) * 26f + 6f; } } return num + 14f; } private float DrawCategorizedGuideRows(float x, float y, float width, string categoryKey, string rules, bool jackpotFormat) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) List list = BuildRuleGuideGroups(categoryKey, rules, applySearchFilter: false); if (list.Count == 0) { DrawGuideRuleRow(new Rect(x + 8f, y, width - 16f, 24f), "Nenhuma regra configurada.", categoryKey, jackpotFormat, penaltyFormat: false); return y + 40f; } Rect val = default(Rect); for (int i = 0; i < list.Count; i++) { RuleGuideGroup ruleGuideGroup = list[i]; bool flag = IsRuleSubCategoryExpanded(categoryKey, ruleGuideGroup.Name); ((Rect)(ref val))..ctor(x + 8f, y, width - 16f, 28f); if ((Object)(object)_uiWhiteTexture != (Object)null) { Color val2 = (flag ? new Color(0.16f, 0.1f, 0.035f, 0.62f) : new Color(0.05f, 0.035f, 0.015f, 0.48f)); GUI.DrawTexture(val, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 8f); GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).yMax - 1f, ((Rect)(ref val)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.95f, 0.76f, 0.33f, flag ? 0.42f : 0.18f), 0f, 0f); } if (GUI.Button(val, GUIContent.none, GUIStyle.none)) { ToggleRuleSubCategory(categoryKey, ruleGuideGroup.Name); GUI.FocusControl((string)null); } string text = (flag ? "▼" : "▶"); int ruleGroupProgressCount = GetRuleGroupProgressCount(categoryKey, ruleGuideGroup); string text2 = ((ruleGuideGroup.Rows.Count == 1) ? "1 item" : (ruleGuideGroup.Rows.Count + " itens")) + ((ruleGroupProgressCount > 0) ? (" • " + ruleGroupProgressCount + "x") : ""); DrawShadowLabel(new Rect(((Rect)(ref val)).x + 10f, ((Rect)(ref val)).y + 4f, 22f, 20f), text, _panelHeadingStyle); DrawShadowLabel(new Rect(((Rect)(ref val)).x + 34f, ((Rect)(ref val)).y + 5f, ((Rect)(ref val)).width - 160f, 18f), ruleGuideGroup.Name.ToUpperInvariant(), GetHudTintedStyle(_configStyle, new Color(1f, 0.78f, 0.28f, 1f), (TextAnchor)3)); DrawShadowLabel(new Rect(((Rect)(ref val)).xMax - 118f, ((Rect)(ref val)).y + 5f, 110f, 18f), text2, GetRuleProgressStyle(categoryKey, penaltyFormat: false)); y += 32f; if (flag) { for (int j = 0; j < ruleGuideGroup.Rows.Count; j++) { DrawGuideRuleRow(new Rect(x + 22f, y, width - 30f, 24f), ruleGuideGroup.Rows[j], categoryKey, jackpotFormat, penaltyFormat: false); y += 26f; } y += 6f; } } return y + 14f; } private bool ShouldGroupRulesByItemCategory(string categoryKey) { return string.Equals(categoryKey, "Produção", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Producao", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Production", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Conquistas", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Achievements", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Combate", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Combat", StringComparison.OrdinalIgnoreCase); } private bool IsRuleSubCategoryExpanded(string categoryKey, string subCategory) { if (string.IsNullOrWhiteSpace(categoryKey) || string.IsNullOrWhiteSpace(subCategory)) { return false; } return _expandedRuleSubCategories.Contains(BuildRuleSubCategoryKey(categoryKey, subCategory)); } private void ToggleRuleSubCategory(string categoryKey, string subCategory) { if (!string.IsNullOrWhiteSpace(categoryKey) && !string.IsNullOrWhiteSpace(subCategory)) { string item = BuildRuleSubCategoryKey(categoryKey, subCategory); if (_expandedRuleSubCategories.Contains(item)) { _expandedRuleSubCategories.Remove(item); } else { _expandedRuleSubCategories.Add(item); } } } private string BuildRuleSubCategoryKey(string categoryKey, string subCategory) { return (categoryKey ?? "").Trim() + "::" + (subCategory ?? "").Trim(); } private int GetRuleGroupProgressCount(string categoryKey, RuleGuideGroup group) { if (group == null || group.Rows == null) { return 0; } int num = 0; for (int i = 0; i < group.Rows.Count; i++) { string prefab = ExtractRulePrefabKey(group.Rows[i]); num = Mathf.Clamp(num + GetRuleProgressCount(categoryKey, prefab), 0, int.MaxValue); } return num; } private List BuildRuleGuideGroups(string categoryKey, string rules, bool applySearchFilter) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); List list = SplitRulesForHud(rules); for (int i = 0; i < list.Count; i++) { string text = list[i] ?? ""; if (!IsHudCategoryHeader(text)) { string prefab = ExtractRulePrefabKey(text); string ruleGuideGroupName = GetRuleGuideGroupName(categoryKey, prefab); if (!dictionary.TryGetValue(ruleGuideGroupName, out var value)) { value = (dictionary[ruleGuideGroupName] = new RuleGuideGroup(ruleGuideGroupName)); } value.Rows.Add(text); } } string[] order = GetRuleGuideGroupOrder(categoryKey); List list2 = (from g in dictionary.Values orderby (Array.IndexOf(order, g.Name) < 0) ? 999 : Array.IndexOf(order, g.Name), g.Name select g).ToList(); for (int j = 0; j < list2.Count; j++) { list2[j].Rows.Sort((string a, string b) => string.Compare(FriendlyRuleNameForHud(ExtractRulePrefabKey(a)), FriendlyRuleNameForHud(ExtractRulePrefabKey(b)), StringComparison.OrdinalIgnoreCase)); } return list2; } private string ExtractRulePrefabKey(string rawRule) { if (string.IsNullOrWhiteSpace(rawRule)) { return ""; } string[] array = rawRule.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { return rawRule.Trim(); } return (array[0] ?? "").Trim(); } private string GetRuleGuideGroupName(string categoryKey, string prefab) { if (string.Equals(categoryKey, "Combate", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Combat", StringComparison.OrdinalIgnoreCase)) { return GetCreatureBiomeCategoryName(prefab); } return GetRuleItemCategoryName(prefab); } private string[] GetRuleGuideGroupOrder(string categoryKey) { if (string.Equals(categoryKey, "Combate", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Combat", StringComparison.OrdinalIgnoreCase)) { return new string[10] { "Prados", "Floresta Negra", "Pântano", "Montanha", "Planícies", "Mistlands", "Ashlands", "Oceano", "Criaturas Especiais", "Outros" }; } return new string[9] { "Armaduras", "Armas", "Escudos", "Munições", "Comidas", "Comidas e Consumíveis", "Ferramentas", "Materiais", "Outros" }; } private string GetCreatureBiomeCategoryName(string prefab) { string text = (prefab ?? "").Trim().ToLowerInvariant(); if (string.IsNullOrWhiteSpace(text)) { return "Outros"; } text = text.Replace(" ", "").Replace("-", "").Replace("_", ""); if (text.Contains("boar") || text.Contains("deer") || text.Contains("neck") || text.Contains("greyling")) { return "Prados"; } if (text.Contains("greydwarf") || text.Contains("troll") || text.Contains("skeleton") || text.Contains("ghost") || text.Contains("rancidremains")) { return "Floresta Negra"; } if (text.Contains("draugr") || text.Contains("blob") || text.Contains("oozer") || text.Contains("leech") || text.Contains("wraith") || text.Contains("surtling") || text.Contains("abomination")) { return "Pântano"; } if (text.Contains("wolf") || text.Contains("fenring") || text.Contains("hatchling") || text.Contains("stonegolem") || text.Contains("cultist") || text.Contains("ulv") || text.Contains("bat")) { return "Montanha"; } if (text.Contains("goblin") || text.Contains("fuling") || text.Contains("lox") || text.Contains("deathsquito") || text.Contains("tarblob") || text.Contains("growth")) { return "Planícies"; } if (text.Contains("seeker") || text.Contains("gjall") || text.Contains("tick") || text.Contains("dverger") || text.Contains("hare")) { return "Mistlands"; } if (text.Contains("charred") || text.Contains("morgen") || text.Contains("valkyrie") || text.Contains("volture") || text.Contains("asksvin") || text.Contains("bonemaw") || text.Contains("fader")) { return "Ashlands"; } if (text.Contains("serpent") || text.Contains("leviathan")) { return "Oceano"; } if (text.Contains("eikthyr") || text.Contains("gdking") || text.Contains("elder") || text.Contains("bonemass") || text.Contains("dragon") || text.Contains("moder") || text.Contains("goblinking") || text.Contains("yagluth") || text.Contains("queen")) { return "Criaturas Especiais"; } return "Outros"; } private string GetRuleItemCategoryName(string prefab) { string text = (prefab ?? "").Trim().ToLowerInvariant(); if (string.IsNullOrWhiteSpace(text)) { return "Outros"; } if (text.Contains("helmet") || text.Contains("chest") || text.Contains("legs") || text.Contains("armor") || text.Contains("cape") || text.Contains("root") || text.Contains("fenris")) { return "Armaduras"; } if (text.Contains("shield") || text.Contains("buckler")) { return "Escudos"; } if (text.Contains("arrow") || text.Contains("bolt")) { return "Munições"; } if (text.Contains("bow") || text.Contains("crossbow") || text.Contains("sword") || text.Contains("knife") || text.Contains("axe") || text.Contains("mace") || text.Contains("club") || text.Contains("spear") || text.Contains("atgeir") || text.Contains("staff") || text.Contains("bomb")) { return "Armas"; } if (text.Contains("pickaxe") || text.Contains("hammer") || text.Contains("hoe") || text.Contains("cultivator") || text.Contains("fishingrod") || text.Contains("torch") || text.Contains("tankard")) { return "Ferramentas"; } if (text.Contains("mead") || text.Contains("stew") || text.Contains("soup") || text.Contains("jerky") || text.Contains("honey") || text.Contains("chicken") || text.Contains("meat") || text.Contains("fish") || text.Contains("pie") || text.Contains("pudding") || text.Contains("porridge") || text.Contains("mushroom") || text.Contains("carrot") || text.Contains("turnip") || text.Contains("onion") || text.Contains("salad") || text.Contains("omelet") || text.Contains("seekeraspic") || text.Contains("bloodpudding") || text.Contains("sausage") || text.Contains("deerstew") || text.Contains("queensjam") || text.Contains("bukeperries")) { return "Comidas e Consumíveis"; } if (text.Contains("wood") || text.Contains("stone") || text.Contains("ore") || text.Contains("scrap") || text.Contains("bar") || text.Contains("iron") || text.Contains("copper") || text.Contains("tin") || text.Contains("bronze") || text.Contains("silver") || text.Contains("blackmetal") || text.Contains("flametal") || text.Contains("chitin") || text.Contains("thread") || text.Contains("linen") || text.Contains("leather") || text.Contains("hide") || text.Contains("pelt") || text.Contains("trophy") || text.Contains("resin") || text.Contains("coal") || text.Contains("crystal") || text.Contains("yagluth") || text.Contains("eitr") || text.Contains("sap")) { return "Materiais"; } return "Outros"; } private float EstimateSkillGuideBlockHeight(string rules) { if (!IsRuleCategoryExpanded("Skills")) { return 42f; } List list = BuildSkillGuideGroups(rules); if (list.Count == 0) { return 122f; } float num = 102f; for (int i = 0; i < list.Count; i++) { SkillGuideGroup skillGuideGroup = list[i]; num += 58f; if (IsGuideSkillRowExpanded(skillGuideGroup.Name)) { num += (float)Mathf.Max(1, skillGuideGroup.Milestones.Count) * 28f + 10f; } } return num + 14f; } private float DrawSkillGuideRows(float x, float y, float width, string rules) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: 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_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Unknown result type (might be due to invalid IL or missing references) //IL_0400: Unknown result type (might be due to invalid IL or missing references) List list = BuildSkillGuideGroups(rules); if (list.Count == 0) { DrawGuideRuleRow(new Rect(x + 8f, y, width - 16f, 24f), "Nenhuma regra configurada.", "Skills", jackpotFormat: false, penaltyFormat: false); return y + 40f; } Rect val = default(Rect); Rect val3 = default(Rect); for (int i = 0; i < list.Count; i++) { SkillGuideGroup skillGuideGroup = list[i]; bool flag = IsGuideSkillRowExpanded(skillGuideGroup.Name); ((Rect)(ref val))..ctor(x + 8f, y, width - 16f, 54f); if ((Object)(object)_uiWhiteTexture != (Object)null) { Color val2 = (flag ? new Color(0.13f, 0.09f, 0.035f, 0.58f) : new Color(0f, 0f, 0f, 0.24f)); GUI.DrawTexture(val, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, 4f, ((Rect)(ref val)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, GetSkillGuideAccentColor(skillGuideGroup.Name), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref val)).xMax - 116f, ((Rect)(ref val)).y + 15f, 84f, 24f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.05f, 0.035f, 0.015f, 0.62f), 0f, 12f); } if (GUI.Button(val, GUIContent.none, GUIStyle.none)) { ToggleGuideSkillRow(skillGuideGroup.Name); GUI.FocusControl((string)null); } string skillGuideDisplayName = GetSkillGuideDisplayName(skillGuideGroup.Name); string skillGuideDescription = GetSkillGuideDescription(skillGuideGroup.Name); string text = (flag ? "▼" : "▶"); string text2 = ((skillGuideGroup.Milestones.Count == 1) ? "1 marco" : (skillGuideGroup.Milestones.Count + " marcos")); float num = ((Rect)(ref val)).x + 14f; float num2 = 126f; float num3 = ((Rect)(ref val)).width - num2 - 24f; DrawShadowLabel(new Rect(num, ((Rect)(ref val)).y + 7f, num3, 20f), skillGuideDisplayName, _bodyRowStyle); DrawShadowLabel(new Rect(num, ((Rect)(ref val)).y + 30f, num3, 18f), skillGuideDescription, _configStyle); DrawShadowLabel(new Rect(((Rect)(ref val)).xMax - 112f, ((Rect)(ref val)).y + 18f, 78f, 18f), text2, _bodyValueStyle); DrawShadowLabel(new Rect(((Rect)(ref val)).xMax - 28f, ((Rect)(ref val)).y + 17f, 20f, 20f), text, _panelHeadingStyle); y += 58f; if (!flag) { continue; } for (int j = 0; j < skillGuideGroup.Milestones.Count; j++) { SkillGuideMilestone skillGuideMilestone = skillGuideGroup.Milestones[j]; ((Rect)(ref val3))..ctor(x + 24f, y, width - 40f, 26f); if ((Object)(object)_uiWhiteTexture != (Object)null) { Color val4 = ((j % 2 == 0) ? new Color(0f, 0f, 0f, 0.16f) : new Color(0.08f, 0.055f, 0.025f, 0.18f)); GUI.DrawTexture(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y + 1f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height - 2f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, val4, 0f, 0f); } DrawShadowLabel(new Rect(((Rect)(ref val3)).x + 10f, ((Rect)(ref val3)).y + 3f, ((Rect)(ref val3)).width - 128f, 18f), "Alcance o nível " + skillGuideMilestone.Level, _bodyRowStyle); DrawShadowLabel(new Rect(((Rect)(ref val3)).xMax - 112f, ((Rect)(ref val3)).y + 3f, 104f, 18f), "+" + skillGuideMilestone.Points + " pontos", _bodyValueStyle); y += 28f; } y += 10f; } return y + 14f; } private string GetSkillGuideDisplayName(string skillName) { string text = (skillName ?? "").Trim(); return text.ToLowerInvariant() switch { "axes" => "Machados", "blocking" => "Bloqueio", "bloodmagic" => "Magia de Sangue", "bows" => "Arcos", "clubs" => "Porretes", "crossbows" => "Bestas", "elementalmagic" => "Magia Elemental", "farming" => "Cultivo", "jump" => "Salto", "knives" => "Facas", "pickaxes" => "Picaretas", "polearms" => "Armas de Haste", "run" => "Corrida", "spears" => "Lanças", "swords" => "Espadas", "swim" => "Natação", "unarmed" => "Combate Desarmado", "woodcutting" => "Lenhador", "fishing" => "Pesca", "sneak" => "Furtividade", "ride" => "Montaria", _ => FriendlyRuleNameForHud(text), }; } private string GetSkillGuideDescription(string skillName) { string text = (skillName ?? "").Trim(); return text.ToLowerInvariant() switch { "axes" => "Evolua usando machados.", "blocking" => "Ganhe resistência defendendo ataques.", "bloodmagic" => "Aprimore poderes de sangue.", "bows" => "Treine ataques à distância.", "clubs" => "Esmague inimigos com armas contundentes.", "crossbows" => "Use bestas com precisão.", "elementalmagic" => "Domine fogo, gelo e raios.", "farming" => "Plante, colha e prospere.", "jump" => "Explore o mundo superando obstáculos.", "knives" => "Ataque rápido e de perto.", "pickaxes" => "Extraia minérios e recursos.", "polearms" => "Controle distância com armas longas.", "run" => "Corra, viaje e sobreviva.", "spears" => "Lance ou ataque mantendo distância.", "swords" => "Equilibre ataque e defesa.", "swim" => "Atravesse águas com segurança.", "unarmed" => "Lute sem armas.", "woodcutting" => "Derrube árvores e colete madeira.", "fishing" => "Pesque para receber honra.", "sneak" => "Mova-se sem ser percebido.", "ride" => "Evolua cavalgando.", _ => "Abra para ver níveis e recompensas.", }; } private Color GetSkillGuideAccentColor(string skillName) { //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_0082: Unknown result type (might be due to invalid IL or missing references) int num = Math.Abs((skillName ?? "skill").ToLowerInvariant().GetHashCode()); float num2 = 0.32f + (float)(num & 0xFF) / 255f * 0.34f; float num3 = 0.24f + (float)((num >> 8) & 0xFF) / 255f * 0.28f; float num4 = 0.12f + (float)((num >> 16) & 0xFF) / 255f * 0.24f; return new Color(num2, num3, num4, 0.78f); } private bool IsGuideSkillRowExpanded(string skillName) { if (string.IsNullOrWhiteSpace(skillName)) { return false; } return _expandedGuideSkillRows.Contains(skillName); } private void ToggleGuideSkillRow(string skillName) { if (!string.IsNullOrWhiteSpace(skillName)) { if (_expandedGuideSkillRows.Contains(skillName)) { _expandedGuideSkillRows.Remove(skillName); } else { _expandedGuideSkillRows.Add(skillName); } } } private List BuildSkillGuideGroups(string rules) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); List list = SplitRulesForHud(rules); for (int i = 0; i < list.Count; i++) { string text = list[i] ?? ""; string[] array = text.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length >= 3) { string text2 = (array[0] ?? "").Trim(); string level = (array[1] ?? "").Trim(); string points = (array[2] ?? "").Trim(); if (string.IsNullOrWhiteSpace(text2)) { text2 = "Habilidade"; } if (!dictionary.TryGetValue(text2, out var value)) { value = (dictionary[text2] = new SkillGuideGroup(text2)); } value.Milestones.Add(new SkillGuideMilestone(level, points)); } } List list2 = dictionary.Values.OrderBy((SkillGuideGroup x) => GetSkillGuideDisplayName(x.Name)).ToList(); for (int j = 0; j < list2.Count; j++) { list2[j].Milestones = (from x in list2[j].Milestones orderby ParseIntSafe(x.Level), x.Level select x).ToList(); } return list2; } private int ParseIntSafe(string value) { if (int.TryParse(value, out var result)) { return result; } return int.MaxValue; } private void EnsureRuleCategoriesInitialized() { if (!_ruleCategoriesInitialized) { _expandedRuleCategories.Clear(); _ruleCategoriesInitialized = true; } } private bool IsRuleCategoryExpanded(string categoryKey) { if (string.IsNullOrWhiteSpace(categoryKey)) { return false; } EnsureRuleCategoriesInitialized(); return _expandedRuleCategories.Contains(categoryKey); } private void ToggleRuleCategory(string categoryKey) { if (!string.IsNullOrWhiteSpace(categoryKey)) { EnsureRuleCategoriesInitialized(); if (_expandedRuleCategories.Contains(categoryKey)) { _expandedRuleCategories.Remove(categoryKey); } else { _expandedRuleCategories.Add(categoryKey); } } } private void DrawGuideCategoryHeader(Rect rect, string title) { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(title)) { title = "Outros"; } if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 10f, ((Rect)(ref rect)).width, 1f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.95f, 0.76f, 0.33f, 0.36f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, Mathf.Min(210f, ((Rect)(ref rect)).width), ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.12f, 0.075f, 0.025f, 0.72f), 0f, 8f); } DrawShadowLabel(new Rect(((Rect)(ref rect)).x + 10f, ((Rect)(ref rect)).y + 3f, ((Rect)(ref rect)).width - 20f, 18f), title.ToUpperInvariant(), _configStyle); } private void DrawGuideRuleRow(Rect rect, string rawRule, string categoryKey, bool jackpotFormat, bool penaltyFormat) { //IL_004c: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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) FormatGuideRule(rawRule, categoryKey, jackpotFormat, penaltyFormat, out var left, out var right); if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height - 2f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.12f), 0f, 0f); } int ruleProgressCount = GetRuleProgressCount(categoryKey, ExtractRulePrefabKey(rawRule)); string text = ((string.Equals(categoryKey, "Exploração", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Exploracao", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Exploration", StringComparison.OrdinalIgnoreCase)) ? (GetExplorationMapProgressPercent().ToString("0.0", CultureInfo.InvariantCulture) + "%") : ((ruleProgressCount > 0) ? (ruleProgressCount + "x") : "0x")); GUIStyle ruleNameStyle = GetRuleNameStyle(categoryKey, penaltyFormat); GUIStyle ruleProgressStyle = GetRuleProgressStyle(categoryKey, penaltyFormat); GUIStyle ruleValueStyle = GetRuleValueStyle(categoryKey, penaltyFormat); DrawShadowLabel(new Rect(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 3f, ((Rect)(ref rect)).width - 190f, 18f), left, ruleNameStyle); DrawShadowLabel(new Rect(((Rect)(ref rect)).xMax - 176f, ((Rect)(ref rect)).y + 3f, 48f, 18f), text, ruleProgressStyle); DrawShadowLabel(new Rect(((Rect)(ref rect)).xMax - 126f, ((Rect)(ref rect)).y + 3f, 118f, 18f), right, ruleValueStyle); } private GUIStyle GetRuleNameStyle(string categoryKey, bool penaltyFormat) { //IL_0214: Unknown result type (might be due to invalid IL or missing references) Color color = default(Color); ((Color)(ref color))..ctor(0.92f, 0.9f, 0.82f, 1f); if (penaltyFormat || string.Equals(categoryKey, "Mortes", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Deaths", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(1f, 0.42f, 0.36f, 1f); } else if (string.Equals(categoryKey, "Combate", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Combat", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Bosses", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(1f, 0.7f, 0.58f, 1f); } else if (string.Equals(categoryKey, "Produção", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Producao", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Production", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(0.78f, 0.9f, 1f, 1f); } else if (string.Equals(categoryKey, "Conquistas", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Achievements", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(1f, 0.86f, 0.38f, 1f); } else if (string.Equals(categoryKey, "Skills", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(0.82f, 0.68f, 1f, 1f); } else if (string.Equals(categoryKey, "Cultivo", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Farming", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(0.64f, 1f, 0.58f, 1f); } else if (string.Equals(categoryKey, "Exploração", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Exploracao", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Exploration", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(0.58f, 0.9f, 1f, 1f); } return GetHudTintedStyle(_bodyRowStyle, color, (TextAnchor)3); } private GUIStyle GetRuleValueStyle(string categoryKey, bool penaltyFormat) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_004b: Unknown result type (might be due to invalid IL or missing references) Color color = (penaltyFormat ? new Color(1f, 0.28f, 0.22f, 1f) : new Color(0.25f, 1f, 0.45f, 1f)); return GetHudTintedStyle(penaltyFormat ? _configStyle : _bodyValueStyle, color, (TextAnchor)5); } private GUIStyle GetRuleProgressStyle(string categoryKey, bool penaltyFormat) { //IL_01be: Unknown result type (might be due to invalid IL or missing references) Color color = default(Color); ((Color)(ref color))..ctor(0.45f, 0.78f, 1f, 1f); if (penaltyFormat || string.Equals(categoryKey, "Mortes", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Deaths", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(1f, 0.28f, 0.22f, 1f); } else if (string.Equals(categoryKey, "Combate", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Combat", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Bosses", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(1f, 0.28f, 0.22f, 1f); } else if (string.Equals(categoryKey, "Produção", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Producao", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Production", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(0.45f, 0.78f, 1f, 1f); } else if (string.Equals(categoryKey, "Conquistas", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Achievements", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(1f, 0.82f, 0.28f, 1f); } else if (string.Equals(categoryKey, "Skills", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(0.82f, 0.68f, 1f, 1f); } else if (string.Equals(categoryKey, "Cultivo", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Farming", StringComparison.OrdinalIgnoreCase)) { ((Color)(ref color))..ctor(0.42f, 1f, 0.48f, 1f); } return GetHudTintedStyle(_configStyle, color, (TextAnchor)5); } private GUIStyle GetHudTintedStyle(GUIStyle baseStyle, Color color, TextAnchor alignment) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0017: 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) GUIStyle val = new GUIStyle(baseStyle ?? GUI.skin.label); val.alignment = alignment; val.normal.textColor = color; return val; } private void FormatGuideRule(string rawRule, string categoryKey, bool jackpotFormat, bool penaltyFormat, out string left, out string right) { left = (string.IsNullOrWhiteSpace(rawRule) ? "Regra" : rawRule.Trim()); right = ""; if (IsHudCategoryHeader(left)) { left = GetHudCategoryHeaderTitle(left); return; } string[] array = left.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length <= 1) { return; } if (penaltyFormat && array.Length >= 2) { left = array[0].Trim() + " morte(s)"; right = "-" + array[1].Trim() + " pts"; return; } if (string.Equals(categoryKey, "Skills", StringComparison.OrdinalIgnoreCase) && array.Length >= 3) { left = array[0].Trim() + " • ao alcançar nível " + array[1].Trim(); right = "+" + array[2].Trim() + " pts"; return; } bool flag = string.Equals(categoryKey, "Combate", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Combat", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Bosses", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Produção", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Conquistas", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Producao", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Production", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Achievements", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Cultivo", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Pesca", StringComparison.OrdinalIgnoreCase) || string.Equals(categoryKey, "Fishing", StringComparison.OrdinalIgnoreCase); string text = array[0].Trim(); if (flag) { text = FriendlyRuleNameForHud(text); } if (jackpotFormat && array.Length >= 3) { left = text + " • " + array[1].Trim() + "x"; right = "+" + array[2].Trim() + " pts"; } else { left = text; right = "+" + array[1].Trim() + " pts"; } } private List SplitRulesForHud(string rules) { List list = new List(); if (string.IsNullOrWhiteSpace(rules)) { return list; } string[] array = rules.Split(new char[2] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = (array[i] ?? "").Trim(); if (!string.IsNullOrWhiteSpace(text)) { list.Add(text); } } return list; } private void DrawPlayerSummaryBlock(Rect rect) { //IL_003a: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height - 4f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.03f, 0.02f, 0.01f, 0.05f), 0f, 0f); } string text = (string.IsNullOrWhiteSpace(_cachedPlayerData.PlayerName) ? GetLocalPlayerName() : _cachedPlayerData.PlayerName); DrawShadowLabel(new Rect(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - 120f, 26f), text.ToUpperInvariant(), _panelHeadingStyle); DrawShadowLabel(new Rect(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y + 30f, ((Rect)(ref rect)).width - 140f, 22f), ColorizeHighlight("Posição #" + Mathf.Max(1, _cachedPlayerData.Position)) + " • " + ColorizePoints(FormatPoints(_cachedPlayerData.Points)), _bodyValueStyle); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).xMax - 102f, ((Rect)(ref rect)).y + 15f, 96f, 20f); DrawPill(rect2, GetRankTitle(_cachedPlayerData.Position), new Color(0.91f, 0.75f, 0.34f, 0.88f), new Color(0.18f, 0.11f, 0.03f, 0.88f)); } private void DrawSectionHeader(Rect rect, string title) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DrawShadowLabel(rect, title, _panelHeadingStyle); } private void DrawBodyParagraph(Rect rect, string text) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) DrawShadowLabel(rect, text, _mutedBodyStyle); } private void DrawSimpleInfoRows(Rect rect, string[] rows) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (rows != null && rows.Length != 0) { float num = Mathf.Max(24f, ((Rect)(ref rect)).height / (float)Mathf.Max(1, rows.Length)); Rect rect2 = default(Rect); for (int i = 0; i < rows.Length; i++) { string text = rows[i] ?? ""; int num2 = text.IndexOf('|'); string label = ((num2 >= 0) ? text.Substring(0, num2) : text); string value = ((num2 >= 0) ? text.Substring(num2 + 1) : ""); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + num * (float)i, ((Rect)(ref rect)).width, num); DrawInfoRow(rect2, label, value); } } } private void DrawRewardClaimSection(Rect rect) { //IL_003f: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_uiWhiteTexture != (Object)null) { GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height - 4f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.03f, 0.02f, 0.01f, 0.06f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 4f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.91f, 0.75f, 0.34f, 0.88f), 0f, 0f); } SnapshotPlayerData snapshotPlayerData = _cachedPlayerData ?? new SnapshotPlayerData(); string text = ((snapshotPlayerData.RewardRank >= 1 && snapshotPlayerData.RewardRank <= 3) ? ("Top " + snapshotPlayerData.RewardRank + " • " + (string.IsNullOrWhiteSpace(snapshotPlayerData.RewardLabel) ? "Recompensa" : snapshotPlayerData.RewardLabel)) : "Recompensa bloqueada"); float num = ((Rect)(ref rect)).x + 12f; float num2 = 144f; float num3 = ((Rect)(ref rect)).xMax - num2 - 12f; float num4 = Mathf.Max(120f, num3 - num - 12f); DrawShadowLabel(new Rect(num, ((Rect)(ref rect)).y + 8f, ((Rect)(ref rect)).width - 24f, 20f), text, _bodyValueStyle); string text2 = ((string.IsNullOrWhiteSpace(snapshotPlayerData.RewardPrefabName) || snapshotPlayerData.RewardAmount <= 0) ? "Item ainda não configurado." : ("Item: " + snapshotPlayerData.RewardPrefabName + " x" + snapshotPlayerData.RewardAmount)); string text3 = ((snapshotPlayerData.RewardRank >= 1 && snapshotPlayerData.RewardRank <= 3) ? ("Exigência: " + snapshotPlayerData.RewardMinPoints + " pontos") : "Somente Top 1, 2 e 3 têm resgate."); DrawShadowLabel(new Rect(num, ((Rect)(ref rect)).y + 34f, num4, 18f), text2, _mutedBodyStyle); DrawShadowLabel(new Rect(num, ((Rect)(ref rect)).y + 54f, num4, 18f), text3, _mutedBodyStyle); string text4 = (string.IsNullOrWhiteSpace(snapshotPlayerData.RewardBlockReason) ? "Recompensa indisponível." : snapshotPlayerData.RewardBlockReason); DrawShadowLabel(new Rect(num, ((Rect)(ref rect)).y + 76f, num4, 34f), text4, _configStyle); Rect val = default(Rect); ((Rect)(ref val))..ctor(num3, ((Rect)(ref rect)).y + 56f, num2, 30f); if (snapshotPlayerData.RewardCanClaim && !_rewardClaimRequestPending) { Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = new Color(0.22f, 0.72f, 0.28f, 1f); if (GUI.Button(val, "Resgatar")) { RequestRewardClaimFromServer(); } GUI.backgroundColor = backgroundColor; } else { GUI.enabled = false; GUI.Button(val, _rewardClaimRequestPending ? "Processando..." : "Resgatar"); GUI.enabled = true; } DrawPointsExchangeSection(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 122f, ((Rect)(ref rect)).width, 158f), snapshotPlayerData); } private string SanitizeNumericInput(string value, int maxDigits = 8) { if (string.IsNullOrEmpty(value)) { return ""; } StringBuilder stringBuilder = new StringBuilder(Mathf.Max(0, value.Length)); for (int i = 0; i < value.Length; i++) { if (stringBuilder.Length >= maxDigits) { break; } char c = value[i]; if (c >= '0' && c <= '9') { stringBuilder.Append(c); } } string text = stringBuilder.ToString().TrimStart(new char[1] { '0' }); return string.IsNullOrEmpty(text) ? "" : text; } private void DrawPointsExchangeSection(Rect rect, SnapshotPlayerData data) { //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: 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_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03da: Unknown result type (might be due to invalid IL or missing references) bool flag = _rules != null && _rules.PointsExchangeEnabled; int num = ((data != null) ? Mathf.Max(0, data.Points) : 0); int num2 = ((_rules == null) ? 1 : Mathf.Max(1, _rules.PointsExchangeCoinsPerPoint)); int num3 = ((_rules != null) ? Mathf.Max(0, _rules.PointsExchangeMaxPointsPerRequest) : 0); string text = ((_rules != null && !string.IsNullOrWhiteSpace(_rules.PointsExchangePrefab)) ? _rules.PointsExchangePrefab : "Coins"); int num4 = ((num3 > 0) ? Mathf.Min(num, num3) : num); if (string.IsNullOrWhiteSpace(_pointsExchangeAmountInput) && num4 > 0) { _pointsExchangeAmountInput = num4.ToString(); } int result = 0; int.TryParse((_pointsExchangeAmountInput ?? "").Trim(), out result); result = Mathf.Clamp(result, 0, Mathf.Max(0, num4)); int num5 = Mathf.Max(0, result * num2); float num6 = ((Rect)(ref rect)).x + 12f; float num7 = 144f; float num8 = ((Rect)(ref rect)).xMax - num7 - 12f; float num9 = 8f; float num10 = 86f; float num11 = 86f; DrawShadowLabel(new Rect(num6, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - 24f, 20f), "Câmbio de pontos", _bodyValueStyle); string text2 = (flag ? ("Disponível: " + num + " pontos") : "Câmbio de pontos desativado."); DrawShadowLabel(new Rect(num6, ((Rect)(ref rect)).y + 24f, ((Rect)(ref rect)).width - 24f, 18f), text2, _mutedBodyStyle); if (flag) { DrawShadowLabel(new Rect(num6, ((Rect)(ref rect)).y + 44f, ((Rect)(ref rect)).width - 24f, 18f), "Máximo por troca: " + num4 + " pontos", _mutedBodyStyle); DrawShadowLabel(new Rect(num6, ((Rect)(ref rect)).y + 64f, ((Rect)(ref rect)).width - 24f, 18f), "Recebe: " + num5 + " " + text, _mutedBodyStyle); } Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(num6, ((Rect)(ref rect)).y + 92f, 52f, 18f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect2)).xMax + 6f, ((Rect)(ref rect)).y + 86f, num10, 30f); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).xMax + num9, ((Rect)(ref rect)).y + 86f, num11, 30f); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(num8, ((Rect)(ref rect)).y + 124f, num7, 30f); DrawShadowLabel(rect2, "Pontos:", _mutedBodyStyle); bool flag3 = (GUI.enabled = flag && !_pointsExchangeRequestPending && num > 0 && num4 > 0); _pointsExchangeAmountInput = SanitizeNumericInput(GUI.TextField(val, _pointsExchangeAmountInput ?? "", 8)); if (GUI.Button(val2, "Máximo")) { _pointsExchangeAmountInput = num4.ToString(); } GUI.enabled = true; if (flag3 && result > 0 && result <= num4 && num5 > 0) { Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = new Color(0.78f, 0.55f, 0.18f, 1f); if (GUI.Button(val3, "Trocar")) { RequestPointsExchangeFromServer(result); } GUI.backgroundColor = backgroundColor; } else { GUI.enabled = false; GUI.Button(val3, _pointsExchangeRequestPending ? "Processando..." : "Trocar"); GUI.enabled = true; } } private void DrawConfigSection(Rect rect, SnapshotPlayerData data) { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) string text = "Ranking " + ((data != null && data.RankingEnabled) ? "ON" : "OFF") + " • Kills " + ((data != null && data.EnableKillPoints) ? "ON" : "OFF") + " • Bosses " + ((data != null && data.EnableBossPoints) ? "ON" : "OFF"); string text2 = "Skills " + ((data != null && data.EnableSkillPoints) ? "ON" : "OFF") + " • Top exibido " + ((data != null) ? data.TopCount.ToString() : _rules.TopCount.ToString()); DrawShadowLabel(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 20f), text, _configStyle); DrawShadowLabel(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 20f, ((Rect)(ref rect)).width, 20f), text2, _configStyle); } private void DrawInfoRow(Rect rect, string label, string value) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(((Rect)(ref rect)).width * 0.28f, 74f, 130f); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - num - 12f, Mathf.Max(24f, ((Rect)(ref rect)).height - 4f)); Rect rect3 = default(Rect); ((Rect)(ref rect3))..ctor(((Rect)(ref rect)).xMax - num - 4f, ((Rect)(ref rect)).y + 2f, num, Mathf.Max(24f, ((Rect)(ref rect)).height - 4f)); DrawShadowLabel(rect2, label, _bodyRowStyle); DrawShadowLabel(rect3, ColorizePerformanceValue(label, value), _bodyValueStyle); } private string GetRankTitle(int position) { if (position <= 1) { return "LENDÁRIO"; } if (position <= 3) { return "GLORIOSO"; } if (position <= 10) { return "ASCENDENTE"; } return "GUERREIRO"; } private void DrawShadowLabel(Rect rect, string text, GUIStyle style) { //IL_0002: 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_0028: Unknown result type (might be due to invalid IL or missing references) DrawShadowLabel(rect, text, style, new Vector2(1f, 1f), new Color(0f, 0f, 0f, 0.92f)); } private void DrawShadowLabel(Rect rect, string text, GUIStyle style, Vector2 shadowOffset, Color shadowColor) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0018: 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_0038: 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_0065: Unknown result type (might be due to invalid IL or missing references) if (style != null) { GUIStyle val = new GUIStyle(style); val.normal.textColor = shadowColor; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref rect)).x + shadowOffset.x, ((Rect)(ref rect)).y + shadowOffset.y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height); GUI.Label(val2, text ?? "", val); GUI.Label(rect, text ?? "", style); } } private void DrawPill(Rect rect, string text, Color borderColor, Color fillColor) { //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_0050: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_0137: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_uiWhiteTexture == (Object)null)) { GUI.DrawTexture(rect, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, fillColor, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 1.5f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, borderColor, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 1.5f, ((Rect)(ref rect)).width, 1.5f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, borderColor, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 1.5f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, borderColor, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 1.5f, ((Rect)(ref rect)).y, 1.5f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, borderColor, 0f, 0f); DrawShadowLabel(rect, text, _youTagStyle); } } private void DrawInnerCard(Rect rect, Color borderColor, float fillAlpha) { //IL_0016: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_011b: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_016a: 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_01ad: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_uiWhiteTexture == (Object)null)) { GUI.DrawTexture(rect, (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.02f, 0.015f, 0.01f, 0.68f + fillAlpha), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 6f, ((Rect)(ref rect)).y + 6f, ((Rect)(ref rect)).width - 12f, ((Rect)(ref rect)).height - 12f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, new Color(0.07f, 0.045f, 0.02f, 0.52f), 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 1.5f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, borderColor, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 1.5f, ((Rect)(ref rect)).width, 1.5f), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, borderColor, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 1.5f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, borderColor, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 1.5f, ((Rect)(ref rect)).y, 1.5f, ((Rect)(ref rect)).height), (Texture)(object)_uiWhiteTexture, (ScaleMode)0, true, 0f, borderColor, 0f, 0f); } } private Color GetRankAccentColor(int position) { //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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_008b: 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_0088: Unknown result type (might be due to invalid IL or missing references) return (Color)(position switch { 1 => new Color(0.95f, 0.77f, 0.26f, 0.95f), 2 => new Color(0.82f, 0.82f, 0.78f, 0.9f), 3 => new Color(0.8f, 0.58f, 0.31f, 0.9f), _ => new Color(0.79f, 0.63f, 0.32f, 0.72f), }); } private Font TryCreateFont(string preferredNames, int size) { if (string.IsNullOrWhiteSpace(preferredNames)) { return null; } try { string[] array = (from x in preferredNames.Split(new char[3] { '|', ',', ';' }, StringSplitOptions.RemoveEmptyEntries) select x.Trim() into x where !string.IsNullOrWhiteSpace(x) select x).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); if (array.Length == 0) { return null; } return Font.CreateDynamicFontFromOSFont(array, Mathf.Max(10, size)); } catch { return null; } } private void ApplyFont(GUIStyle style, Font font) { if (style != null && (Object)(object)font != (Object)null) { style.font = font; } } private void EnsureGuiStyles() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Expected O, but got Unknown //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Expected O, but got Unknown //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Expected O, but got Unknown //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Expected O, but got Unknown //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Expected O, but got Unknown //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Expected O, but got Unknown //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Expected O, but got Unknown //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_05c6: Unknown result type (might be due to invalid IL or missing references) //IL_05d0: Expected O, but got Unknown //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_064d: Unknown result type (might be due to invalid IL or missing references) //IL_0657: Expected O, but got Unknown //IL_069e: Unknown result type (might be due to invalid IL or missing references) //IL_06c7: Unknown result type (might be due to invalid IL or missing references) //IL_06d1: Expected O, but got Unknown //IL_0725: Unknown result type (might be due to invalid IL or missing references) //IL_0771: Unknown result type (might be due to invalid IL or missing references) //IL_077b: Expected O, but got Unknown //IL_07b5: Unknown result type (might be due to invalid IL or missing references) //IL_07eb: Unknown result type (might be due to invalid IL or missing references) //IL_07f5: Expected O, but got Unknown //IL_083c: Unknown result type (might be due to invalid IL or missing references) //IL_087b: Unknown result type (might be due to invalid IL or missing references) //IL_0885: Expected O, but got Unknown //IL_08cc: Unknown result type (might be due to invalid IL or missing references) //IL_08f5: Unknown result type (might be due to invalid IL or missing references) //IL_08ff: Expected O, but got Unknown //IL_0939: Unknown result type (might be due to invalid IL or missing references) //IL_097c: Unknown result type (might be due to invalid IL or missing references) //IL_0986: Expected O, but got Unknown //IL_09cd: Unknown result type (might be due to invalid IL or missing references) //IL_09f6: Unknown result type (might be due to invalid IL or missing references) //IL_0a00: Expected O, but got Unknown //IL_0a47: Unknown result type (might be due to invalid IL or missing references) //IL_0a70: Unknown result type (might be due to invalid IL or missing references) //IL_0a7a: Expected O, but got Unknown //IL_0ae0: Unknown result type (might be due to invalid IL or missing references) //IL_0aea: Expected O, but got Unknown //IL_0af5: Unknown result type (might be due to invalid IL or missing references) //IL_0aff: Expected O, but got Unknown //IL_0b0a: Unknown result type (might be due to invalid IL or missing references) //IL_0b14: Expected O, but got Unknown if (!_stylesReady) { if ((Object)(object)_uiTransparentTexture == (Object)null) { _uiTransparentTexture = CreateSolidTexture(new Color(0f, 0f, 0f, 0f)); } _uiTitleFont = (_uiUseSystemFonts ? TryCreateFont(_uiTitleFontNames, 26) : null); _uiBodyFont = (_uiUseSystemFonts ? TryCreateFont(_uiBodyFontNames, 15) : null); _uiAccentFont = (_uiUseSystemFonts ? TryCreateFont(_uiAccentFontNames, 16) : null); _windowStyle = new GUIStyle(GUI.skin.window); _windowStyle.normal.background = _uiTransparentTexture; _windowStyle.active.background = _uiTransparentTexture; _windowStyle.hover.background = _uiTransparentTexture; _windowStyle.focused.background = _uiTransparentTexture; _windowStyle.border = new RectOffset(0, 0, 0, 0); _windowStyle.padding = new RectOffset(0, 0, 0, 0); _headerStyle = new GUIStyle(GUI.skin.label); _headerStyle.fontSize = 26; _headerStyle.fontStyle = (FontStyle)1; _headerStyle.alignment = (TextAnchor)4; _headerStyle.wordWrap = true; _headerStyle.richText = true; _headerStyle.normal.textColor = new Color(0.98f, 0.92f, 0.78f, 1f); ApplyFont(_headerStyle, _uiTitleFont); _sectionTitleStyle = new GUIStyle(_headerStyle); _sectionTitleStyle.fontSize = 21; ApplyFont(_sectionTitleStyle, _uiTitleFont); _rankingTextStyle = new GUIStyle(GUI.skin.label); _rankingTextStyle.fontSize = 15; _rankingTextStyle.wordWrap = true; _rankingTextStyle.richText = true; _rankingTextStyle.alignment = (TextAnchor)0; _rankingTextStyle.normal.textColor = new Color(0.97f, 0.92f, 0.82f, 1f); _rankingTextStyle.padding = new RectOffset(2, 2, 0, 0); ApplyFont(_rankingTextStyle, _uiBodyFont); _playerTextStyle = new GUIStyle(_rankingTextStyle); _playerTextStyle.fontSize = 14; ApplyFont(_playerTextStyle, _uiBodyFont); _panelHeadingStyle = new GUIStyle(GUI.skin.label); _panelHeadingStyle.fontSize = 15; _panelHeadingStyle.fontStyle = (FontStyle)1; _panelHeadingStyle.alignment = (TextAnchor)3; _panelHeadingStyle.normal.textColor = new Color(0.96f, 0.82f, 0.47f, 1f); _panelHeadingStyle.richText = true; ApplyFont(_panelHeadingStyle, ((Object)(object)_uiAccentFont != (Object)null) ? _uiAccentFont : _uiTitleFont); _cardLabelStyle = new GUIStyle(GUI.skin.label); _cardLabelStyle.fontSize = 11; _cardLabelStyle.alignment = (TextAnchor)0; _cardLabelStyle.fontStyle = (FontStyle)1; _cardLabelStyle.normal.textColor = new Color(0.86f, 0.73f, 0.48f, 0.95f); ApplyFont(_cardLabelStyle, ((Object)(object)_uiAccentFont != (Object)null) ? _uiAccentFont : _uiTitleFont); _cardValueStyle = new GUIStyle(GUI.skin.label); _cardValueStyle.fontSize = 24; _cardValueStyle.alignment = (TextAnchor)0; _cardValueStyle.fontStyle = (FontStyle)1; _cardValueStyle.normal.textColor = new Color(0.98f, 0.93f, 0.84f, 1f); ApplyFont(_cardValueStyle, _uiTitleFont); _bodyRowStyle = new GUIStyle(GUI.skin.label); _bodyRowStyle.fontSize = 13; _bodyRowStyle.alignment = (TextAnchor)3; _bodyRowStyle.normal.textColor = new Color(0.96f, 0.9f, 0.78f, 1f); _bodyRowStyle.clipping = (TextClipping)0; _bodyRowStyle.wordWrap = false; _bodyRowStyle.richText = true; ApplyFont(_bodyRowStyle, _uiBodyFont); _bodyValueStyle = new GUIStyle(_bodyRowStyle); _bodyValueStyle.fontSize = 13; _bodyValueStyle.fontStyle = (FontStyle)1; _bodyValueStyle.alignment = (TextAnchor)5; _bodyValueStyle.normal.textColor = new Color(0.98f, 0.92f, 0.8f, 1f); _bodyValueStyle.clipping = (TextClipping)0; _bodyValueStyle.wordWrap = false; _bodyValueStyle.richText = true; ApplyFont(_bodyValueStyle, ((Object)(object)_uiAccentFont != (Object)null) ? _uiAccentFont : _uiBodyFont); _mutedBodyStyle = new GUIStyle(_bodyRowStyle); _mutedBodyStyle.fontSize = 13; _mutedBodyStyle.wordWrap = true; _mutedBodyStyle.normal.textColor = new Color(0.86f, 0.79f, 0.67f, 0.95f); _mutedBodyStyle.clipping = (TextClipping)0; _mutedBodyStyle.richText = true; ApplyFont(_mutedBodyStyle, _uiBodyFont); _rankIndexStyle = new GUIStyle(GUI.skin.label); _rankIndexStyle.fontSize = 18; _rankIndexStyle.fontStyle = (FontStyle)1; _rankIndexStyle.alignment = (TextAnchor)3; _rankIndexStyle.normal.textColor = new Color(0.97f, 0.82f, 0.33f, 1f); ApplyFont(_rankIndexStyle, _uiTitleFont); _rankNameStyle = new GUIStyle(GUI.skin.label); _rankNameStyle.fontSize = 16; _rankNameStyle.fontStyle = (FontStyle)1; _rankNameStyle.alignment = (TextAnchor)3; _rankNameStyle.clipping = (TextClipping)1; _rankNameStyle.normal.textColor = new Color(0.95f, 0.89f, 0.77f, 1f); _rankNameStyle.richText = true; ApplyFont(_rankNameStyle, ((Object)(object)_uiAccentFont != (Object)null) ? _uiAccentFont : _uiTitleFont); _rankPointsStyle = new GUIStyle(GUI.skin.label); _rankPointsStyle.fontSize = 12; _rankPointsStyle.alignment = (TextAnchor)3; _rankPointsStyle.normal.textColor = new Color(0.88f, 0.78f, 0.6f, 0.95f); _rankPointsStyle.richText = true; ApplyFont(_rankPointsStyle, _uiBodyFont); _youTagStyle = new GUIStyle(GUI.skin.label); _youTagStyle.fontSize = 10; _youTagStyle.alignment = (TextAnchor)4; _youTagStyle.fontStyle = (FontStyle)1; _youTagStyle.normal.textColor = new Color(0.86f, 0.97f, 0.82f, 1f); ApplyFont(_youTagStyle, ((Object)(object)_uiAccentFont != (Object)null) ? _uiAccentFont : _uiBodyFont); _emptyStateStyle = new GUIStyle(GUI.skin.label); _emptyStateStyle.fontSize = 16; _emptyStateStyle.wordWrap = true; _emptyStateStyle.alignment = (TextAnchor)0; _emptyStateStyle.normal.textColor = new Color(0.95f, 0.89f, 0.78f, 0.95f); ApplyFont(_emptyStateStyle, _uiBodyFont); _configStyle = new GUIStyle(GUI.skin.label); _configStyle.fontSize = 12; _configStyle.alignment = (TextAnchor)0; _configStyle.normal.textColor = new Color(0.88f, 0.82f, 0.73f, 0.94f); _configStyle.clipping = (TextClipping)0; _configStyle.richText = true; ApplyFont(_configStyle, _uiBodyFont); _footerStyle = new GUIStyle(GUI.skin.label); _footerStyle.fontSize = 13; _footerStyle.alignment = (TextAnchor)4; _footerStyle.richText = true; _footerStyle.normal.textColor = new Color(0.95f, 0.89f, 0.76f, 0.95f); ApplyFont(_footerStyle, _uiBodyFont); _statusStyle = new GUIStyle(GUI.skin.label); _statusStyle.fontSize = 13; _statusStyle.fontStyle = (FontStyle)1; _statusStyle.alignment = (TextAnchor)4; _statusStyle.normal.textColor = new Color(0.95f, 0.89f, 0.76f, 1f); ApplyFont(_statusStyle, _uiBodyFont); _iconButtonStyle = new GUIStyle(GUI.skin.button); _iconButtonStyle.normal.background = _uiTransparentTexture; _iconButtonStyle.active.background = _uiTransparentTexture; _iconButtonStyle.hover.background = _uiTransparentTexture; _iconButtonStyle.focused.background = _uiTransparentTexture; _iconButtonStyle.border = new RectOffset(0, 0, 0, 0); _iconButtonStyle.padding = new RectOffset(0, 0, 0, 0); _iconButtonStyle.margin = new RectOffset(0, 0, 0, 0); _stylesReady = true; } } private int GetRankingPosition(RankingEntry target) { if (target == null || _database == null || _database.Entries == null) { return int.MaxValue; } List list = (from x in _database.Entries where x != null && !string.IsNullOrWhiteSpace(x.PlayerName) && !ShouldIgnorePlayerForRanking(x.PlayerName) orderby x.Points descending, x.BossPointsTotal descending, x.KillPointsTotal descending, x.SkillPointsTotal descending, x.PlayerName select x).ToList(); for (int i = 0; i < list.Count; i++) { RankingEntry rankingEntry = list[i]; if (rankingEntry == target) { return i + 1; } if (rankingEntry != null && string.Equals(rankingEntry.PlayerName, target.PlayerName, StringComparison.OrdinalIgnoreCase)) { return i + 1; } } return int.MaxValue; } private RankingEntry FindRankingEntryByName(string playerName) { if (string.IsNullOrWhiteSpace(playerName) || _database == null || _database.Entries == null) { return null; } return _database.Entries.FirstOrDefault((RankingEntry x) => x != null && !string.IsNullOrWhiteSpace(x.PlayerName) && string.Equals(x.PlayerName, playerName, StringComparison.OrdinalIgnoreCase)); } private string GetHudTopAccent(int position) { return position switch { 1 => "#FFD700", 2 => "#D7DCE5", 3 => "#D79A63", _ => "#E8C988", }; } private string BuildHudTopLine(int position, RankingEntry entry, string localPlayerName) { string hudTopAccent = GetHudTopAccent(position); string text = ((entry != null) ? entry.PlayerName : "Jogador"); int num = entry?.Points ?? 0; return "#" + position + " " + text + "\n" + num + " pts"; } private void SetStatus(string text, float seconds = 2.5f) { _statusText = (string.IsNullOrWhiteSpace(text) ? "" : text); _statusUntil = Time.unscaledTime + Mathf.Max(0.1f, seconds); } private void RequestRewardClaimFromServer() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown try { if (_cachedPlayerData == null || _rewardClaimRequestPending) { return; } if (!_cachedPlayerData.RewardCanClaim) { SetStatus(string.IsNullOrWhiteSpace(_cachedPlayerData.RewardBlockReason) ? "Recompensa indisponível." : _cachedPlayerData.RewardBlockReason, 3f); } else if (_rpcsRegistered && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null)) { long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0) { ZPackage val = new ZPackage(); val.Write(_cachedPlayerData.RewardClaimCycleId ?? ""); val.Write(Mathf.Clamp(_cachedPlayerData.RewardRank, 0, int.MaxValue)); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.requestrewardclaim", new object[1] { val }); _rewardClaimRequestPending = true; _rewardClaimPendingCycleId = _cachedPlayerData.RewardClaimCycleId ?? ""; _rewardClaimPendingRank = Mathf.Clamp(_cachedPlayerData.RewardRank, 0, int.MaxValue); SetStatus("Solicitando resgate da recompensa...", 2f); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao solicitar resgate da recompensa: " + ex)); } } private void RequestPointsExchangeFromServer(int requestedPoints) { //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown try { if (_pointsExchangeRequestPending) { return; } if (_cachedPlayerData == null || _cachedPlayerData.Points <= 0) { SetStatus("Você não possui pontos para trocar.", 3f); return; } if (_rules == null || !_rules.PointsExchangeEnabled) { SetStatus("Câmbio de pontos desativado.", 3f); return; } int num = Mathf.Max(0, _cachedPlayerData.Points); int num2 = Mathf.Max(0, _rules.PointsExchangeMaxPointsPerRequest); int num3 = ((num2 > 0) ? Mathf.Min(num, num2) : num); if (requestedPoints <= 0) { SetStatus("Informe uma quantidade válida para trocar.", 3f); } else if (requestedPoints > num3) { SetStatus("Quantidade acima do limite disponível para câmbio.", 3f); } else if (_rpcsRegistered && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null)) { long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0) { ZPackage val = new ZPackage(); val.Write(SafeLimit(_rules.RewardClaimCycleId, 64)); val.Write(Mathf.Clamp(requestedPoints, 1, int.MaxValue)); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.requestpointsexchange", new object[1] { val }); _pointsExchangeRequestPending = true; SetStatus("Solicitando câmbio de " + requestedPoints + " pontos por moedas...", 2f); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao solicitar câmbio de pontos: " + ex)); } } private void RPC_RequestRewardClaim(long sender, ZPackage pkg) { //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Expected O, but got Unknown try { if (!IsServerInstance() || pkg == null) { return; } string text = SafeLimit(pkg.ReadString(), 64); int num = Mathf.Clamp(pkg.ReadInt(), 0, int.MaxValue); string text2 = ResolvePlayerNameFromSender(sender); if (string.IsNullOrWhiteSpace(text2)) { SendRewardClaimFeedback(sender, success: false, "Não foi possível identificar o jogador."); return; } if (_rules == null || !_rules.RewardClaimsEnabled) { SendRewardClaimFeedback(sender, success: false, "Sistema de recompensas desativado."); return; } if (!string.Equals(SafeLimit(_rules.RewardClaimCycleId, 64), text, StringComparison.OrdinalIgnoreCase)) { SendRewardClaimFeedback(sender, success: false, "Ciclo de recompensa inválido. Abra o ranking novamente."); return; } List list = (from x in _database.Entries where x != null && !string.IsNullOrWhiteSpace(x.PlayerName) && !ShouldIgnorePlayerForRanking(x.PlayerName) orderby x.Points descending, x.BossPointsTotal descending, x.KillPointsTotal descending, x.SkillPointsTotal descending, x.PlayerName select x).ToList(); RankingEntry rankingEntry = null; int num2 = -1; for (int i = 0; i < list.Count; i++) { if (list[i] != null && string.Equals(list[i].PlayerName, text2, StringComparison.OrdinalIgnoreCase)) { rankingEntry = list[i]; num2 = i + 1; break; } } if (rankingEntry == null || num2 <= 0) { SendRewardClaimFeedback(sender, success: false, "Você não está no ranking."); return; } if (num2 != num) { SendRewardClaimFeedback(sender, success: false, "Sua posição mudou. Abra o ranking novamente."); return; } RankRewardInfo rankRewardInfo = GetRankRewardInfo(num2); if (rankRewardInfo == null) { SendRewardClaimFeedback(sender, success: false, "Somente Top 1, 2 e 3 podem resgatar."); return; } if (rankingEntry.Points < rankRewardInfo.MinPoints) { SendRewardClaimFeedback(sender, success: false, "Você precisa de " + rankRewardInfo.MinPoints + " pontos para resgatar."); return; } if (string.IsNullOrWhiteSpace(rankRewardInfo.PrefabName) || rankRewardInfo.Amount <= 0) { SendRewardClaimFeedback(sender, success: false, "Recompensa não configurada."); return; } if (HasClaimedReward(text, text2, num2)) { SendRewardClaimFeedback(sender, success: false, "Essa recompensa já foi resgatada."); return; } if (HasPendingRewardClaim(text, text2, num2)) { SendRewardClaimFeedback(sender, success: false, "Essa recompensa já está em processamento."); return; } string item = BuildPendingRewardKey(sender, text, num2); if (_pendingRewardClaims.Contains(item)) { SendRewardClaimFeedback(sender, success: false, "Já existe um resgate em andamento."); return; } ReserveRewardClaim(text, text2, num2); SaveDatabase(); _pendingRewardClaims.Add(item); ZPackage val = new ZPackage(); val.Write(text); val.Write(num2); val.Write(SafeLimit(text2, 32)); val.Write(rankRewardInfo.PrefabName ?? ""); val.Write(Mathf.Max(1, rankRewardInfo.Amount)); val.Write(rankRewardInfo.Label ?? ""); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "glitnir.ranking.grantrewarditem", new object[1] { val }); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_RequestRewardClaim: " + ex)); SendRewardClaimFeedback(sender, success: false, "Erro interno ao validar recompensa."); } } private void RPC_GrantRewardItem(long sender, ZPackage pkg) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown try { if (pkg != null) { string text = SafeLimit(pkg.ReadString(), 64); int num = Mathf.Clamp(pkg.ReadInt(), 0, int.MaxValue); string text2 = SanitizePlayerName(pkg.ReadString()); string prefabName = SafeLimit(pkg.ReadString(), 96); int amount = Mathf.Clamp(pkg.ReadInt(), 0, int.MaxValue); string text3 = SafeLimit(pkg.ReadString(), 96); string message; bool flag = TryAddRewardItemToLocalInventory(prefabName, amount, out message); ZPackage val = new ZPackage(); val.Write(text); val.Write(num); val.Write(text2); val.Write(flag); val.Write(string.IsNullOrWhiteSpace(message) ? text3 : message); ZRoutedRpc.instance.InvokeRoutedRPC(GetServerPeerUid(), "glitnir.ranking.finalizerewardclaim", new object[1] { val }); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_GrantRewardItem: " + ex)); } } private void RPC_FinalizeRewardClaim(long sender, ZPackage pkg) { try { if (IsServerInstance() && pkg != null) { string cycleId = SafeLimit(pkg.ReadString(), 64); int rank = Mathf.Clamp(pkg.ReadInt(), 0, int.MaxValue); string text = SanitizePlayerName(pkg.ReadString()); bool flag = pkg.ReadBool(); string text2 = SafeLimit(pkg.ReadString(), 128); string item = BuildPendingRewardKey(sender, cycleId, rank); if (_pendingRewardClaims.Contains(item)) { _pendingRewardClaims.Remove(item); } string text3 = ResolvePlayerNameFromSender(sender); if (!string.IsNullOrWhiteSpace(text3)) { text = text3; } if (string.IsNullOrWhiteSpace(text)) { ClearPendingRewardClaim(cycleId, text, rank); SaveDatabase(); SendRewardClaimFeedback(sender, success: false, "Não foi possível confirmar o jogador."); } else if (!flag) { ClearPendingRewardClaim(cycleId, text, rank); SaveDatabase(); SendRewardClaimFeedback(sender, success: false, string.IsNullOrWhiteSpace(text2) ? "Falha ao adicionar item no inventário." : text2); } else if (HasClaimedReward(cycleId, text, rank)) { SendRewardClaimFeedback(sender, success: false, "Essa recompensa já foi resgatada."); } else { MarkRewardClaimed(cycleId, text, rank); SaveDatabase(); SendRewardClaimFeedback(sender, success: true, string.IsNullOrWhiteSpace(text2) ? "Recompensa adicionada ao inventário." : text2); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_FinalizeRewardClaim: " + ex)); SendRewardClaimFeedback(sender, success: false, "Erro ao finalizar o resgate."); } } private void RPC_RequestPointsExchange(long sender, ZPackage pkg) { //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Expected O, but got Unknown try { if (!IsServerInstance() || pkg == null) { return; } string text = SafeLimit(pkg.ReadString(), 64); int num = Mathf.Clamp(pkg.ReadInt(), 0, int.MaxValue); string playerName = ResolvePlayerNameFromSender(sender); if (string.IsNullOrWhiteSpace(playerName)) { SendPointsExchangeFeedback(sender, success: false, "Não foi possível identificar o jogador."); return; } if (_rules == null || !_rules.PointsExchangeEnabled) { SendPointsExchangeFeedback(sender, success: false, "Câmbio de pontos desativado."); return; } if (!string.Equals(SafeLimit(_rules.RewardClaimCycleId, 64), text, StringComparison.OrdinalIgnoreCase)) { SendPointsExchangeFeedback(sender, success: false, "Ciclo inválido. Abra o ranking novamente."); return; } if (string.IsNullOrWhiteSpace(_rules.PointsExchangePrefab)) { SendPointsExchangeFeedback(sender, success: false, "Prefab do câmbio não configurado."); return; } RankingEntry rankingEntry = _database.Entries.FirstOrDefault((RankingEntry x) => x != null && string.Equals(x.PlayerName, playerName, StringComparison.OrdinalIgnoreCase)); if (rankingEntry == null) { SendPointsExchangeFeedback(sender, success: false, "Você não está no ranking."); return; } int num2 = Mathf.Max(0, rankingEntry.Points); if (num2 <= 0) { SendPointsExchangeFeedback(sender, success: false, "Você não possui pontos para trocar."); return; } string item = BuildPendingPointsExchangeKey(sender, text); if (_pendingPointsExchanges.Contains(item)) { SendPointsExchangeFeedback(sender, success: false, "Já existe um câmbio em andamento."); return; } int num3 = Mathf.Max(0, _rules.PointsExchangeMaxPointsPerRequest); int num4 = ((num3 > 0) ? Mathf.Min(num2, num3) : num2); if (num <= 0) { SendPointsExchangeFeedback(sender, success: false, "Informe uma quantidade válida para trocar."); return; } if (num > num2) { SendPointsExchangeFeedback(sender, success: false, "Você possui apenas " + num2 + " pontos."); return; } if (num > num4) { SendPointsExchangeFeedback(sender, success: false, "O limite por câmbio é " + num4 + " pontos."); return; } int num5 = num; int num6 = Mathf.Max(1, _rules.PointsExchangeCoinsPerPoint); int num7 = Mathf.Max(1, num5 * num6); _pendingPointsExchanges.Add(item); ZPackage val = new ZPackage(); val.Write(text); val.Write(SafeLimit(playerName, 32)); val.Write(num5); val.Write(_rules.PointsExchangePrefab ?? "Coins"); val.Write(num7); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "glitnir.ranking.grantexchangecoins", new object[1] { val }); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_RequestPointsExchange: " + ex)); SendPointsExchangeFeedback(sender, success: false, "Erro ao processar o câmbio."); } } private void RPC_GrantExchangeCoins(long sender, ZPackage pkg) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown try { if (pkg != null) { string text = SafeLimit(pkg.ReadString(), 64); string text2 = SanitizePlayerName(pkg.ReadString()); int num = Mathf.Clamp(pkg.ReadInt(), 0, int.MaxValue); string text3 = SafeLimit(pkg.ReadString(), 96); int amount = Mathf.Clamp(pkg.ReadInt(), 0, int.MaxValue); string message; bool flag = TryAddExchangeItemToLocalInventoryOrDropOverflow(text3, amount, out message); ZPackage val = new ZPackage(); val.Write(text); val.Write(text2); val.Write(num); val.Write(flag); val.Write(flag ? ("Câmbio concluído: -" + num + " pontos, +" + amount + " " + text3 + ". " + message) : message); ZRoutedRpc.instance.InvokeRoutedRPC(GetServerPeerUid(), "glitnir.ranking.finalizepointsexchange", new object[1] { val }); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_GrantExchangeCoins: " + ex)); } } private void RPC_FinalizePointsExchange(long sender, ZPackage pkg) { try { if (IsServerInstance() && pkg != null) { string cycleId = SafeLimit(pkg.ReadString(), 64); string playerName = SanitizePlayerName(pkg.ReadString()); int num = Mathf.Clamp(pkg.ReadInt(), 0, int.MaxValue); bool flag = pkg.ReadBool(); string text = SafeLimit(pkg.ReadString(), 128); string item = BuildPendingPointsExchangeKey(sender, cycleId); if (_pendingPointsExchanges.Contains(item)) { _pendingPointsExchanges.Remove(item); } string text2 = ResolvePlayerNameFromSender(sender); if (!string.IsNullOrWhiteSpace(text2)) { playerName = text2; } RankingEntry rankingEntry = _database.Entries.FirstOrDefault((RankingEntry x) => x != null && string.Equals(x.PlayerName, playerName, StringComparison.OrdinalIgnoreCase)); if (rankingEntry == null) { SendPointsExchangeFeedback(sender, success: false, "Jogador não encontrado no ranking."); return; } if (!flag) { SendPointsExchangeFeedback(sender, success: false, string.IsNullOrWhiteSpace(text) ? "Falha ao adicionar moedas no inventário." : text); return; } if (num <= 0 || rankingEntry.Points < num) { SendPointsExchangeFeedback(sender, success: false, "Pontos insuficientes para finalizar o câmbio."); return; } int num2 = Mathf.Max(1, num * Mathf.Max(1, (_rules == null) ? 1 : _rules.PointsExchangeCoinsPerPoint)); rankingEntry.Points = Mathf.Max(0, rankingEntry.Points - num); rankingEntry.TotalPointsExchanges = Mathf.Clamp(rankingEntry.TotalPointsExchanges + 1, 0, int.MaxValue); rankingEntry.PointsExchangePenaltyTotal = Mathf.Clamp(rankingEntry.PointsExchangePenaltyTotal + num, 0, int.MaxValue); rankingEntry.PointsExchangeCoinsTotal = Mathf.Clamp(rankingEntry.PointsExchangeCoinsTotal + num2, 0, int.MaxValue); rankingEntry.LastReason = "Câmbio de pontos: -" + num + " pts, +" + num2 + " moedas"; rankingEntry.LastUpdateUtc = DateTime.UtcNow.ToString("o"); SaveDatabase(); SendPointsExchangeFeedback(sender, success: true, string.IsNullOrWhiteSpace(text) ? "Câmbio concluído." : text); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_FinalizePointsExchange: " + ex)); SendPointsExchangeFeedback(sender, success: false, "Erro ao finalizar o câmbio."); } } private void RPC_PointsExchangeFeedback(long sender, ZPackage pkg) { try { if (pkg != null) { bool flag = pkg.ReadBool(); string text = SafeLimit(pkg.ReadString(), 128); _pointsExchangeRequestPending = false; SetStatus((!string.IsNullOrWhiteSpace(text)) ? text : (flag ? "Câmbio concluído." : "Câmbio não concluído."), flag ? 4f : 3.5f); if (flag) { SpawnGlitnirRewardClaimEffect(); } RequestSnapshotFromServer(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_PointsExchangeFeedback: " + ex)); } } private void SendPointsExchangeFeedback(long sender, bool success, string message) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(success); val.Write(SafeLimit(message, 128)); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "glitnir.ranking.pointsexchangefeedback", new object[1] { val }); } } private string BuildPendingPointsExchangeKey(long sender, string cycleId) { return sender + "|" + SafeLimit(cycleId, 64); } private void RPC_RewardClaimFeedback(long sender, ZPackage pkg) { try { if (pkg != null) { bool flag = pkg.ReadBool(); string text = SafeLimit(pkg.ReadString(), 128); _rewardClaimRequestPending = false; _rewardClaimPendingCycleId = ""; _rewardClaimPendingRank = 0; SetStatus((!string.IsNullOrWhiteSpace(text)) ? text : (flag ? "Recompensa resgatada." : "Resgate não concluído."), flag ? 4f : 3.5f); if (flag) { SpawnGlitnirRewardClaimEffect(); } RequestSnapshotFromServer(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_RewardClaimFeedback: " + ex)); } } private void SendRewardClaimFeedback(long sender, bool success, string message) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(success); val.Write(SafeLimit(message, 128)); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "glitnir.ranking.rewardclaimfeedback", new object[1] { val }); } } private void SpawnGlitnirRewardClaimEffect() { //IL_00b9: 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_00dc: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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) //IL_0135: 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_013f: Unknown result type (might be due to invalid IL or missing references) try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return; } string[] array = new string[4] { "vfx_Potion_stamina_medium", "vfx_Potion_health_medium", "vfx_Potion_eitr_minor", "vfx_coin_pile_destroyed" }; GameObject val = null; string[] array2 = array; foreach (string text in array2) { val = ZNetScene.instance.GetPrefab(text); if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GlitnirRanking] Nenhum prefab de efeito encontrado para o claim."); return; } Vector3 position = ((Component)localPlayer).transform.position; for (int j = 0; j < 10; j++) { float num = (float)j * (float)Math.PI * 2f / 10f; Vector3 val2 = position + new Vector3(Mathf.Cos(num) * 2.1f, 0.9f, Mathf.Sin(num) * 2.1f); Object.Instantiate(val, val2, Quaternion.identity); } Object.Instantiate(val, position + Vector3.up * 1.6f, Quaternion.identity); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[GlitnirRanking] Falha ao criar efeito visual do claim: " + ex.Message)); } } private void CheckInitialServerSnapshotRequest() { try { if (!_rpcsRegistered || ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null) { return; } long serverPeerUid = GetServerPeerUid(); if (serverPeerUid == 0) { _lastKnownServerPeerUid = 0L; _requestedInitialServerSnapshot = false; return; } if (serverPeerUid != _lastKnownServerPeerUid) { _lastKnownServerPeerUid = serverPeerUid; _requestedInitialServerSnapshot = false; _cachedTopText = "Sincronizando ranking..."; _cachedPlayerText = "Aguardando dados do servidor..."; } if (!_requestedInitialServerSnapshot && (Object)(object)Player.m_localPlayer != (Object)null) { _requestedInitialServerSnapshot = true; _clientRefreshTimer = 0f; RequestSnapshotFromServer(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao solicitar snapshot inicial: " + ex.Message)); } } private Dictionary GetRankingSnapshot() { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (_database == null || _database.Entries == null) { return dictionary; } List list = (from x in _database.Entries where x != null && !string.IsNullOrWhiteSpace(x.PlayerName) && !ShouldIgnorePlayerForRanking(x.PlayerName) orderby x.Points descending, x.BossPointsTotal descending, x.KillPointsTotal descending, x.SkillPointsTotal descending, x.PlayerName select x).ToList(); for (int i = 0; i < list.Count; i++) { RankingEntry rankingEntry = list[i]; if (rankingEntry != null && !string.IsNullOrWhiteSpace(rankingEntry.PlayerName)) { dictionary[rankingEntry.PlayerName] = i + 1; } } return dictionary; } private void RequestSnapshotFromServer() { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown try { if (IsServerInstance()) { long serverPeerUid = GetServerPeerUid(); if (serverPeerUid == 0) { string localPlayerName = GetLocalPlayerName(); BuildSnapshotTexts(localPlayerName, out var topText, out var playerText); BuildSnapshotData(localPlayerName, out var topEntries, out var playerData); _cachedTopText = topText; _cachedPlayerText = playerText; CacheSnapshotData(topEntries, playerData); SetStatus("Snapshot local atualizado.", 2f); return; } } if (_rpcsRegistered && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null)) { long serverPeerUid2 = GetServerPeerUid(); if (serverPeerUid2 != 0) { ZPackage val = new ZPackage(); val.Write(GetLocalPlayerName()); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid2, "glitnir.ranking.requestsnapshot", new object[1] { val }); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao solicitar snapshot do ranking: " + ex)); } } private void RPC_RequestSnapshot(long sender, ZPackage pkg) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown try { if (IsServerInstance()) { string text = ""; if (pkg != null) { text = SanitizePlayerName(pkg.ReadString()); } DebugLog(DebugCategory.Snapshot, "Snapshot solicitado por sender=" + sender + " player=" + text + " entries=" + _database.Entries.Count); BuildSnapshotTexts(text, out var topText, out var playerText); BuildSnapshotData(text, out var topEntries, out var playerData); ZPackage val = new ZPackage(); val.Write(topText); val.Write(playerText); WriteSnapshotPayload(val, topEntries, playerData); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "glitnir.ranking.receivesnapshot", new object[1] { val }); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_RequestSnapshot: " + ex)); } } private void RPC_ReceiveSnapshot(long sender, ZPackage pkg) { try { if (pkg != null) { _cachedTopText = pkg.ReadString(); _cachedPlayerText = pkg.ReadString(); ReadSnapshotPayload(pkg); SetStatus("Ranking sincronizado.", 1f); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReceiveSnapshot: " + ex)); } } private void CacheSnapshotData(List topEntries, SnapshotPlayerData playerData) { _cachedTopEntries.Clear(); if (topEntries != null) { _cachedTopEntries.AddRange(topEntries); } _cachedPlayerData = playerData ?? new SnapshotPlayerData(); } private void BuildSnapshotData(string playerName, out List topEntries, out SnapshotPlayerData playerData) { topEntries = new List(); playerData = new SnapshotPlayerData { RankingEnabled = _rules.RankingEnabled, EnableKillPoints = _rules.EnableKillPoints, EnableBossPoints = _rules.EnableBossPoints, EnableSkillPoints = _rules.EnableSkillPoints, EnableMarketplaceQuestPoints = _rules.EnableMarketplaceQuestPoints, EnableDeathPenalty = _rules.EnableDeathPenalty, DeathPenaltyUseMultiplier = _rules.DeathPenaltyUseMultiplier, DeathPenaltyPerDeath = Mathf.Max(0, _rules.DeathPenaltyPerDeath), TopCount = _rules.TopCount, HudKillRules = FormatCategorizedIntRulesForHud(_rules.KillPoints, _rules.CombatHudCategories, combatMode: true), HudBossRules = FormatIntRulesForHud(_rules.BossPoints), HudSkillJackpotRules = FormatSkillJackpotRulesForHud(_rules.SkillMilestoneJackpotPoints), HudMarketplaceQuestRules = FormatIntRulesForHud(_rules.MarketplaceQuestPoints), HudFishingRules = FormatIntRulesForHud(_rules.FishingPoints), HudCraftRules = FormatCategorizedIntRulesForHud(_rules.CraftPoints, _rules.ProductionHudCategories), HudFarmJackpotRules = FormatCategorizedJackpotRulesForHud(_rules.FarmJackpots, _rules.ProductionHudCategories), HudUniqueCraftJackpotRules = FormatCategorizedJackpotRulesForHud(_rules.UniqueCraftJackpots, _rules.ProductionHudCategories), HudDeathPenaltyRules = FormatDeathPenaltyRulesForHud(_rules.DeathPenaltyRules), HudExplorationMapJackpotRules = FormatExplorationMapJackpotRulesForHud(_rules.ExplorationMapJackpots) }; if (!_rules.RankingEnabled) { FillRewardSnapshotData(playerData); return; } List list = (from x in _database.Entries where x != null && !string.IsNullOrWhiteSpace(x.PlayerName) && !ShouldIgnorePlayerForRanking(x.PlayerName) orderby x.Points descending, x.BossPointsTotal descending, x.KillPointsTotal descending, x.SkillPointsTotal descending, x.PlayerName select x).ToList(); playerName = SanitizePlayerName(playerName); int num = Mathf.Min(Mathf.Clamp(_rules.TopCount, 1, 50), list.Count); for (int i = 0; i < num; i++) { RankingEntry rankingEntry = list[i]; topEntries.Add(new SnapshotTopEntryData { Position = i + 1, PlayerName = ((rankingEntry != null) ? rankingEntry.PlayerName : "Jogador"), Points = (rankingEntry?.Points ?? 0), IsLocalPlayer = (rankingEntry != null && string.Equals(rankingEntry.PlayerName, playerName, StringComparison.OrdinalIgnoreCase)), TotalKillsPontuadas = (rankingEntry?.TotalKillsPontuadas ?? 0), TotalBossesPontuadas = (rankingEntry?.TotalBossesPontuadas ?? 0), TotalSkillLevelUpsPontuados = (rankingEntry?.TotalSkillLevelUpsPontuados ?? 0), TotalFishingPontuadas = (rankingEntry?.TotalFishingPontuadas ?? 0), TotalCraftPontuadas = (rankingEntry?.TotalCraftPontuadas ?? 0), TotalFarmJackpotsPontuados = (rankingEntry?.TotalFarmJackpotsPontuados ?? 0), TotalUniqueCraftJackpotsPontuados = (rankingEntry?.TotalUniqueCraftJackpotsPontuados ?? 0), TotalDeaths = (rankingEntry?.TotalDeaths ?? 0), KillPointsTotal = (rankingEntry?.KillPointsTotal ?? 0), BossPointsTotal = (rankingEntry?.BossPointsTotal ?? 0), SkillPointsTotal = (rankingEntry?.SkillPointsTotal ?? 0), FishingPointsTotal = (rankingEntry?.FishingPointsTotal ?? 0), CraftPointsTotal = (rankingEntry?.CraftPointsTotal ?? 0), FarmJackpotPointsTotal = (rankingEntry?.FarmJackpotPointsTotal ?? 0), UniqueCraftJackpotPointsTotal = (rankingEntry?.UniqueCraftJackpotPointsTotal ?? 0), DeathPenaltyPointsTotal = (rankingEntry?.DeathPenaltyPointsTotal ?? 0), TotalPointsExchanges = (rankingEntry?.TotalPointsExchanges ?? 0), PointsExchangePenaltyTotal = (rankingEntry?.PointsExchangePenaltyTotal ?? 0), PointsExchangeCoinsTotal = (rankingEntry?.PointsExchangeCoinsTotal ?? 0), ExplorationMapJackpotPointsTotal = (rankingEntry?.ExplorationMapJackpotPointsTotal ?? 0), LastReason = ((rankingEntry != null) ? (rankingEntry.LastReason ?? "") : ""), LastUpdateUtc = ((rankingEntry != null) ? (rankingEntry.LastUpdateUtc ?? "") : "") }); } for (int j = 0; j < list.Count; j++) { RankingEntry rankingEntry2 = list[j]; if (rankingEntry2 != null && string.Equals(rankingEntry2.PlayerName, playerName, StringComparison.OrdinalIgnoreCase)) { playerData.HasData = true; playerData.Position = j + 1; playerData.PlayerName = rankingEntry2.PlayerName; playerData.Points = rankingEntry2.Points; playerData.TotalKillsPontuadas = rankingEntry2.TotalKillsPontuadas; playerData.TotalBossesPontuadas = rankingEntry2.TotalBossesPontuadas; playerData.TotalSkillLevelUpsPontuados = rankingEntry2.TotalSkillLevelUpsPontuados; playerData.KillPointsTotal = rankingEntry2.KillPointsTotal; playerData.BossPointsTotal = rankingEntry2.BossPointsTotal; playerData.SkillPointsTotal = rankingEntry2.SkillPointsTotal; playerData.TotalFishingPontuadas = rankingEntry2.TotalFishingPontuadas; playerData.TotalCraftPontuadas = rankingEntry2.TotalCraftPontuadas; playerData.TotalFarmJackpotsPontuados = rankingEntry2.TotalFarmJackpotsPontuados; playerData.TotalUniqueCraftJackpotsPontuados = rankingEntry2.TotalUniqueCraftJackpotsPontuados; playerData.TotalDeaths = rankingEntry2.TotalDeaths; playerData.FishingPointsTotal = rankingEntry2.FishingPointsTotal; playerData.CraftPointsTotal = rankingEntry2.CraftPointsTotal; playerData.FarmJackpotPointsTotal = rankingEntry2.FarmJackpotPointsTotal; playerData.UniqueCraftJackpotPointsTotal = rankingEntry2.UniqueCraftJackpotPointsTotal; playerData.DeathPenaltyPointsTotal = rankingEntry2.DeathPenaltyPointsTotal; playerData.TotalPointsExchanges = rankingEntry2.TotalPointsExchanges; playerData.PointsExchangePenaltyTotal = rankingEntry2.PointsExchangePenaltyTotal; playerData.PointsExchangeCoinsTotal = rankingEntry2.PointsExchangeCoinsTotal; playerData.ExplorationMapJackpotPointsTotal = rankingEntry2.ExplorationMapJackpotPointsTotal; playerData.LastReason = rankingEntry2.LastReason ?? ""; playerData.LastUpdateUtc = rankingEntry2.LastUpdateUtc ?? ""; playerData.ProgressCounters = ((rankingEntry2.ProgressCounters != null) ? new Dictionary(rankingEntry2.ProgressCounters, StringComparer.OrdinalIgnoreCase) : new Dictionary(StringComparer.OrdinalIgnoreCase)); playerData.FloatProgressCounters = ((rankingEntry2.FloatProgressCounters != null) ? new Dictionary(rankingEntry2.FloatProgressCounters, StringComparer.OrdinalIgnoreCase) : new Dictionary(StringComparer.OrdinalIgnoreCase)); FillRewardSnapshotData(playerData); return; } } FillRewardSnapshotData(playerData); } private void WriteSnapshotPayload(ZPackage response, List topEntries, SnapshotPlayerData playerData) { if (response != null) { int num = topEntries?.Count ?? 0; response.Write(num); for (int i = 0; i < num; i++) { SnapshotTopEntryData snapshotTopEntryData = topEntries[i] ?? new SnapshotTopEntryData(); response.Write(snapshotTopEntryData.Position); response.Write(snapshotTopEntryData.PlayerName ?? ""); response.Write(snapshotTopEntryData.Points); response.Write(snapshotTopEntryData.IsLocalPlayer); response.Write(snapshotTopEntryData.TotalKillsPontuadas); response.Write(snapshotTopEntryData.TotalBossesPontuadas); response.Write(snapshotTopEntryData.TotalSkillLevelUpsPontuados); response.Write(snapshotTopEntryData.TotalFishingPontuadas); response.Write(snapshotTopEntryData.TotalCraftPontuadas); response.Write(snapshotTopEntryData.TotalFarmJackpotsPontuados); response.Write(snapshotTopEntryData.TotalUniqueCraftJackpotsPontuados); response.Write(snapshotTopEntryData.TotalDeaths); response.Write(snapshotTopEntryData.KillPointsTotal); response.Write(snapshotTopEntryData.BossPointsTotal); response.Write(snapshotTopEntryData.SkillPointsTotal); response.Write(snapshotTopEntryData.FishingPointsTotal); response.Write(snapshotTopEntryData.CraftPointsTotal); response.Write(snapshotTopEntryData.FarmJackpotPointsTotal); response.Write(snapshotTopEntryData.UniqueCraftJackpotPointsTotal); response.Write(snapshotTopEntryData.DeathPenaltyPointsTotal); response.Write(snapshotTopEntryData.TotalPointsExchanges); response.Write(snapshotTopEntryData.PointsExchangePenaltyTotal); response.Write(snapshotTopEntryData.PointsExchangeCoinsTotal); response.Write(snapshotTopEntryData.ExplorationMapJackpotPointsTotal); response.Write(snapshotTopEntryData.LastReason ?? ""); response.Write(snapshotTopEntryData.LastUpdateUtc ?? ""); } SnapshotPlayerData snapshotPlayerData = playerData ?? new SnapshotPlayerData(); response.Write(snapshotPlayerData.HasData); response.Write(snapshotPlayerData.Position); response.Write(snapshotPlayerData.PlayerName ?? ""); response.Write(snapshotPlayerData.Points); response.Write(snapshotPlayerData.TotalKillsPontuadas); response.Write(snapshotPlayerData.TotalBossesPontuadas); response.Write(snapshotPlayerData.TotalSkillLevelUpsPontuados); response.Write(snapshotPlayerData.KillPointsTotal); response.Write(snapshotPlayerData.BossPointsTotal); response.Write(snapshotPlayerData.SkillPointsTotal); response.Write(snapshotPlayerData.TotalFishingPontuadas); response.Write(snapshotPlayerData.TotalCraftPontuadas); response.Write(snapshotPlayerData.TotalFarmJackpotsPontuados); response.Write(snapshotPlayerData.TotalUniqueCraftJackpotsPontuados); response.Write(snapshotPlayerData.TotalDeaths); response.Write(snapshotPlayerData.FishingPointsTotal); response.Write(snapshotPlayerData.CraftPointsTotal); response.Write(snapshotPlayerData.FarmJackpotPointsTotal); response.Write(snapshotPlayerData.UniqueCraftJackpotPointsTotal); response.Write(snapshotPlayerData.DeathPenaltyPointsTotal); response.Write(snapshotPlayerData.TotalPointsExchanges); response.Write(snapshotPlayerData.PointsExchangePenaltyTotal); response.Write(snapshotPlayerData.PointsExchangeCoinsTotal); response.Write(snapshotPlayerData.ExplorationMapJackpotPointsTotal); response.Write(snapshotPlayerData.LastReason ?? ""); response.Write(snapshotPlayerData.LastUpdateUtc ?? ""); response.Write(snapshotPlayerData.RankingEnabled); response.Write(snapshotPlayerData.EnableKillPoints); response.Write(snapshotPlayerData.EnableBossPoints); response.Write(snapshotPlayerData.EnableSkillPoints); response.Write(snapshotPlayerData.EnableMarketplaceQuestPoints); response.Write(snapshotPlayerData.TopCount); response.Write(snapshotPlayerData.RewardClaimsEnabled); response.Write(snapshotPlayerData.RewardCanClaim); response.Write(snapshotPlayerData.RewardAlreadyClaimed); response.Write(snapshotPlayerData.RewardRank); response.Write(snapshotPlayerData.RewardMinPoints); response.Write(snapshotPlayerData.RewardLabel ?? ""); response.Write(snapshotPlayerData.RewardPrefabName ?? ""); response.Write(snapshotPlayerData.RewardAmount); response.Write(snapshotPlayerData.RewardBlockReason ?? ""); response.Write(snapshotPlayerData.RewardClaimCycleId ?? ""); response.Write(snapshotPlayerData.HudKillRules ?? ""); response.Write(snapshotPlayerData.HudBossRules ?? ""); response.Write(snapshotPlayerData.HudSkillJackpotRules ?? ""); response.Write(snapshotPlayerData.HudMarketplaceQuestRules ?? ""); response.Write(snapshotPlayerData.HudFishingRules ?? ""); response.Write(snapshotPlayerData.HudCraftRules ?? ""); response.Write(snapshotPlayerData.HudFarmJackpotRules ?? ""); response.Write(snapshotPlayerData.HudUniqueCraftJackpotRules ?? ""); response.Write(snapshotPlayerData.HudDeathPenaltyRules ?? ""); response.Write(snapshotPlayerData.HudExplorationMapJackpotRules ?? ""); response.Write(snapshotPlayerData.EnableDeathPenalty); response.Write(snapshotPlayerData.DeathPenaltyUseMultiplier); response.Write(Mathf.Max(0, snapshotPlayerData.DeathPenaltyPerDeath)); response.Write(SerializeStringIntDictionary(snapshotPlayerData.ProgressCounters)); response.Write(SerializeStringFloatDictionary(snapshotPlayerData.FloatProgressCounters)); } } private void ReadSnapshotPayload(ZPackage pkg) { _cachedTopEntries.Clear(); _cachedPlayerData = new SnapshotPlayerData(); if (pkg == null) { return; } int num = 0; try { num = Mathf.Clamp(pkg.ReadInt(), 0, 100); } catch { num = 0; } for (int i = 0; i < num; i++) { SnapshotTopEntryData snapshotTopEntryData = new SnapshotTopEntryData(); try { snapshotTopEntryData.Position = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.PlayerName = pkg.ReadString(); } catch { snapshotTopEntryData.PlayerName = ""; } try { snapshotTopEntryData.Points = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.IsLocalPlayer = pkg.ReadBool(); } catch { } try { snapshotTopEntryData.TotalKillsPontuadas = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.TotalBossesPontuadas = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.TotalSkillLevelUpsPontuados = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.TotalFishingPontuadas = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.TotalCraftPontuadas = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.TotalFarmJackpotsPontuados = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.TotalUniqueCraftJackpotsPontuados = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.TotalDeaths = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.KillPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.BossPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.SkillPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.FishingPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.CraftPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.FarmJackpotPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.UniqueCraftJackpotPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.DeathPenaltyPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.TotalPointsExchanges = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.PointsExchangePenaltyTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.PointsExchangeCoinsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.ExplorationMapJackpotPointsTotal = pkg.ReadInt(); } catch { } try { snapshotTopEntryData.LastReason = pkg.ReadString(); } catch { } try { snapshotTopEntryData.LastUpdateUtc = pkg.ReadString(); } catch { } _cachedTopEntries.Add(snapshotTopEntryData); } SnapshotPlayerData snapshotPlayerData = new SnapshotPlayerData(); try { snapshotPlayerData.HasData = pkg.ReadBool(); } catch { } try { snapshotPlayerData.Position = pkg.ReadInt(); } catch { } try { snapshotPlayerData.PlayerName = pkg.ReadString(); } catch { } try { snapshotPlayerData.Points = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalKillsPontuadas = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalBossesPontuadas = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalSkillLevelUpsPontuados = pkg.ReadInt(); } catch { } try { snapshotPlayerData.KillPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.BossPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.SkillPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalFishingPontuadas = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalCraftPontuadas = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalFarmJackpotsPontuados = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalUniqueCraftJackpotsPontuados = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalDeaths = pkg.ReadInt(); } catch { } try { snapshotPlayerData.FishingPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.CraftPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.FarmJackpotPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.UniqueCraftJackpotPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.DeathPenaltyPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.TotalPointsExchanges = pkg.ReadInt(); } catch { } try { snapshotPlayerData.PointsExchangePenaltyTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.PointsExchangeCoinsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.ExplorationMapJackpotPointsTotal = pkg.ReadInt(); } catch { } try { snapshotPlayerData.LastReason = pkg.ReadString(); } catch { } try { snapshotPlayerData.LastUpdateUtc = pkg.ReadString(); } catch { } try { snapshotPlayerData.RankingEnabled = pkg.ReadBool(); } catch { snapshotPlayerData.RankingEnabled = _rules.RankingEnabled; } try { snapshotPlayerData.EnableKillPoints = pkg.ReadBool(); } catch { snapshotPlayerData.EnableKillPoints = _rules.EnableKillPoints; } try { snapshotPlayerData.EnableBossPoints = pkg.ReadBool(); } catch { snapshotPlayerData.EnableBossPoints = _rules.EnableBossPoints; } try { snapshotPlayerData.EnableSkillPoints = pkg.ReadBool(); } catch { snapshotPlayerData.EnableSkillPoints = _rules.EnableSkillPoints; } try { snapshotPlayerData.EnableMarketplaceQuestPoints = pkg.ReadBool(); } catch { snapshotPlayerData.EnableMarketplaceQuestPoints = _rules.EnableMarketplaceQuestPoints; } try { snapshotPlayerData.TopCount = pkg.ReadInt(); } catch { snapshotPlayerData.TopCount = _rules.TopCount; } try { snapshotPlayerData.RewardClaimsEnabled = pkg.ReadBool(); } catch { snapshotPlayerData.RewardClaimsEnabled = _rules.RewardClaimsEnabled; } try { snapshotPlayerData.RewardCanClaim = pkg.ReadBool(); } catch { } try { snapshotPlayerData.RewardAlreadyClaimed = pkg.ReadBool(); } catch { } try { snapshotPlayerData.RewardRank = pkg.ReadInt(); } catch { } try { snapshotPlayerData.RewardMinPoints = pkg.ReadInt(); } catch { } try { snapshotPlayerData.RewardLabel = pkg.ReadString(); } catch { } try { snapshotPlayerData.RewardPrefabName = pkg.ReadString(); } catch { } try { snapshotPlayerData.RewardAmount = pkg.ReadInt(); } catch { } try { snapshotPlayerData.RewardBlockReason = pkg.ReadString(); } catch { } try { snapshotPlayerData.RewardClaimCycleId = pkg.ReadString(); } catch { } try { snapshotPlayerData.HudKillRules = pkg.ReadString(); } catch { snapshotPlayerData.HudKillRules = FormatCategorizedIntRulesForHud(_rules.KillPoints, _rules.CombatHudCategories, combatMode: true); } try { snapshotPlayerData.HudBossRules = pkg.ReadString(); } catch { snapshotPlayerData.HudBossRules = FormatIntRulesForHud(_rules.BossPoints); } try { snapshotPlayerData.HudSkillJackpotRules = pkg.ReadString(); } catch { snapshotPlayerData.HudSkillJackpotRules = FormatSkillJackpotRulesForHud(_rules.SkillMilestoneJackpotPoints); } try { snapshotPlayerData.HudMarketplaceQuestRules = pkg.ReadString(); } catch { snapshotPlayerData.HudMarketplaceQuestRules = FormatIntRulesForHud(_rules.MarketplaceQuestPoints); } try { snapshotPlayerData.HudFishingRules = pkg.ReadString(); } catch { snapshotPlayerData.HudFishingRules = FormatIntRulesForHud(_rules.FishingPoints); } try { snapshotPlayerData.HudCraftRules = pkg.ReadString(); } catch { snapshotPlayerData.HudCraftRules = FormatCategorizedIntRulesForHud(_rules.CraftPoints, _rules.ProductionHudCategories); } try { snapshotPlayerData.HudFarmJackpotRules = pkg.ReadString(); } catch { snapshotPlayerData.HudFarmJackpotRules = FormatCategorizedJackpotRulesForHud(_rules.FarmJackpots, _rules.ProductionHudCategories); } try { snapshotPlayerData.HudUniqueCraftJackpotRules = pkg.ReadString(); } catch { snapshotPlayerData.HudUniqueCraftJackpotRules = FormatCategorizedJackpotRulesForHud(_rules.UniqueCraftJackpots, _rules.ProductionHudCategories); } try { snapshotPlayerData.HudDeathPenaltyRules = pkg.ReadString(); } catch { snapshotPlayerData.HudDeathPenaltyRules = FormatDeathPenaltyRulesForHud(_rules.DeathPenaltyRules); } try { snapshotPlayerData.HudExplorationMapJackpotRules = pkg.ReadString(); } catch { snapshotPlayerData.HudExplorationMapJackpotRules = FormatExplorationMapJackpotRulesForHud(_rules.ExplorationMapJackpots); } try { snapshotPlayerData.EnableDeathPenalty = pkg.ReadBool(); } catch { snapshotPlayerData.EnableDeathPenalty = _rules.EnableDeathPenalty; } try { snapshotPlayerData.DeathPenaltyUseMultiplier = pkg.ReadBool(); } catch { snapshotPlayerData.DeathPenaltyUseMultiplier = _rules.DeathPenaltyUseMultiplier; } try { snapshotPlayerData.DeathPenaltyPerDeath = Mathf.Max(0, pkg.ReadInt()); } catch { snapshotPlayerData.DeathPenaltyPerDeath = Mathf.Max(0, _rules.DeathPenaltyPerDeath); } try { snapshotPlayerData.ProgressCounters = DeserializeStringIntDictionary(pkg.ReadString()); } catch { snapshotPlayerData.ProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); } try { snapshotPlayerData.FloatProgressCounters = DeserializeStringFloatDictionary(pkg.ReadString()); } catch { snapshotPlayerData.FloatProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); } _cachedPlayerData = snapshotPlayerData; } private void BuildSnapshotTexts(string playerName, out string topText, out string playerText) { if (!_rules.RankingEnabled) { topText = "Ranking desativado."; playerText = "Status: desativado"; return; } List list = (from x in _database.Entries where x != null && !string.IsNullOrWhiteSpace(x.PlayerName) && !ShouldIgnorePlayerForRanking(x.PlayerName) orderby x.Points descending, x.BossPointsTotal descending, x.KillPointsTotal descending, x.SkillPointsTotal descending, x.PlayerName select x).ToList(); int num = Mathf.Clamp(_rules.TopCount, 1, 50); playerName = SanitizePlayerName(playerName); int num2 = -1; RankingEntry rankingEntry = null; for (int i = 0; i < list.Count; i++) { if (string.Equals(list[i].PlayerName, playerName, StringComparison.OrdinalIgnoreCase)) { num2 = i + 1; rankingEntry = list[i]; break; } } StringBuilder stringBuilder = new StringBuilder(1400); if (list.Count == 0) { stringBuilder.Append("Nenhum jogador pontuado ainda.\n"); stringBuilder.Append("Saia para caçar, evoluir skills e dominar Glitnir."); } else { int num3 = Mathf.Min(num, list.Count); for (int j = 0; j < num3; j++) { RankingEntry entry = list[j]; string text = BuildHudTopLine(j + 1, entry, playerName); if (stringBuilder.Length + text.Length + 8 > 3000) { break; } if (j > 0) { stringBuilder.Append("\n\n────────────────────────\n\n"); } stringBuilder.Append(text); } } topText = stringBuilder.ToString().TrimEnd(Array.Empty()); StringBuilder stringBuilder2 = new StringBuilder(1800); if (rankingEntry != null) { stringBuilder2.Append("POSIÇÃO #" + num2 + "\n"); stringBuilder2.Append("Pontuação total\n"); stringBuilder2.Append("" + rankingEntry.Points + " pts\n\n"); stringBuilder2.Append("Resumo da jornada\n"); stringBuilder2.Append("• Kills pontuadas: " + rankingEntry.TotalKillsPontuadas + "\n"); stringBuilder2.Append("• Bosses pontuados: " + rankingEntry.TotalBossesPontuadas + "\n"); stringBuilder2.Append("• Níveis de skills pontuados: " + rankingEntry.TotalSkillLevelUpsPontuados + "\n\n"); stringBuilder2.Append("Origem dos pontos\n"); stringBuilder2.Append("• Kills: " + rankingEntry.KillPointsTotal + "\n"); stringBuilder2.Append("• Bosses: " + rankingEntry.BossPointsTotal + "\n"); stringBuilder2.Append("• Skills: " + rankingEntry.SkillPointsTotal + "\n\n"); stringBuilder2.Append("Último registro\n"); stringBuilder2.Append("• Origem: " + (string.IsNullOrWhiteSpace(rankingEntry.LastReason) ? "sem registro" : rankingEntry.LastReason) + "\n"); stringBuilder2.Append("• Atualização: " + FormatHudLastUpdate(rankingEntry.LastUpdateUtc) + ""); } else { stringBuilder2.Append("Você ainda não tem pontos.\n"); stringBuilder2.Append("Participe de combates, derrote bosses e evolua skills para subir no ranking."); } stringBuilder2.Append("\n\n────────────────────────\n\n"); stringBuilder2.Append("Configuração atual\n"); stringBuilder2.Append("• Ranking: " + (_rules.RankingEnabled ? "ON" : "OFF") + "\n"); stringBuilder2.Append("• Kills: " + (_rules.EnableKillPoints ? "ON" : "OFF") + "\n"); stringBuilder2.Append("• Bosses: " + (_rules.EnableBossPoints ? "ON" : "OFF") + "\n"); stringBuilder2.Append("• Skills: " + (_rules.EnableSkillPoints ? "ON" : "OFF") + "\n"); stringBuilder2.Append("• Top exibido: " + _rules.TopCount + ""); playerText = stringBuilder2.ToString().TrimEnd(Array.Empty()); } public void NotifyLocalCraftedRecipe(Recipe recipe) { try { if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null)) { string prefabName = GetPrefabName(((Component)recipe.m_item).gameObject); int amount = Mathf.Max(1, recipe.m_amount); NotifyLocalCraftedItem(prefabName, amount); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao reportar craft local: " + ex)); } } public void NotifyLocalCraftedItem(string prefabName, int amount) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown try { if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } prefabName = SafeKey(prefabName); amount = Mathf.Clamp(amount, 1, 100); if (!string.IsNullOrWhiteSpace(prefabName)) { long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0L && _rpcsRegistered && ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(prefabName); val.Write(amount); val.Write(SafeLimit(Player.m_localPlayer.GetPlayerName(), 32)); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.reportcrafteditem", new object[1] { val }); DebugLog(DebugCategory.Points, "Cliente reportando craft: player=" + GetLocalPlayerName() + " item=" + prefabName + " amount=" + amount); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao enviar craft local: " + ex)); } } private void RPC_ReportCraftedItem(long sender, ZPackage pkg) { try { if (IsServerInstance() && pkg != null) { string prefabName = SafeKey(pkg.ReadString()); int amount = Mathf.Clamp(pkg.ReadInt(), 1, 100); string text = SanitizePlayerName(pkg.ReadString()); string text2 = ResolvePlayerNameFromSender(sender); if (string.IsNullOrWhiteSpace(text2)) { text2 = text; } if (ShouldIgnoreSenderForRanking(sender, text2)) { DebugLog(DebugCategory.Points, "Craft ignorado para admin: " + text2); } else { ProcessCraftReport(text2, prefabName, amount, "rpc-craft"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportCraftedItem: " + ex)); } } private void ProcessCraftReport(string playerName, string prefabName, int amount, string source) { try { if (!IsServerInstance() || _rules == null || !_rules.RankingEnabled) { return; } playerName = SanitizePlayerName(playerName); prefabName = SafeKey(prefabName); amount = Mathf.Clamp(amount, 1, 100); if (string.IsNullOrWhiteSpace(playerName) || string.IsNullOrWhiteSpace(prefabName)) { return; } if (ShouldIgnorePlayerForRanking(playerName)) { DebugLog(DebugCategory.Points, "Ação de ranking ignorada para admin: " + playerName); return; } RankingEntry orCreateEntry = GetOrCreateEntry(playerName); if (orCreateEntry != null) { int value = 0; if (_rules.CraftPoints != null && _rules.CraftPoints.TryGetValue(prefabName, out value) && value > 0) { int num = Mathf.Clamp(value * amount, 0, int.MaxValue); ApplyPointsToEntry(orCreateEntry, num, "Craft: " + prefabName + " x" + amount); orCreateEntry.TotalCraftPontuadas = Mathf.Clamp(orCreateEntry.TotalCraftPontuadas + amount, 0, int.MaxValue); orCreateEntry.CraftPointsTotal = Mathf.Clamp(orCreateEntry.CraftPointsTotal + num, -2147483647, int.MaxValue); IncrementProgressCounter(orCreateEntry, "Craft", prefabName, amount); SaveDatabase(); } JackpotRule value2 = null; bool flag = _rules.UniqueCraftJackpots != null && _rules.UniqueCraftJackpots.TryGetValue(prefabName, out value2) && value2 != null && value2.Points > 0; if (flag) { AddProgressAndCheckJackpot(orCreateEntry, "UniqueCraft", prefabName, amount, value2, "Jackpot craft único: " + prefabName, unique: true); } if (value <= 0 && !flag) { DebugLog(DebugCategory.Points, "Craft sem regra configurada: prefab=" + prefabName + " amount=" + amount + " player=" + playerName); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar craft: " + ex)); } } public void NotifyLocalFarmHarvest(string prefabName, int amount) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown try { if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } prefabName = SafeKey(prefabName); amount = Mathf.Clamp(amount, 1, 100); if (!string.IsNullOrWhiteSpace(prefabName)) { long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0L && _rpcsRegistered && ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(prefabName); val.Write(amount); val.Write(SafeLimit(Player.m_localPlayer.GetPlayerName(), 32)); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.reportfarmharvest", new object[1] { val }); DebugLog(DebugCategory.Points, "Cliente reportando colheita: player=" + GetLocalPlayerName() + " item=" + prefabName + " amount=" + amount); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao enviar colheita local: " + ex)); } } private void RPC_ReportFarmHarvest(long sender, ZPackage pkg) { try { if (IsServerInstance() && pkg != null) { string prefabName = SafeKey(pkg.ReadString()); int amount = Mathf.Clamp(pkg.ReadInt(), 1, 100); string text = SanitizePlayerName(pkg.ReadString()); string text2 = ResolvePlayerNameFromSender(sender); if (string.IsNullOrWhiteSpace(text2)) { text2 = text; } if (ShouldIgnoreSenderForRanking(sender, text2)) { DebugLog(DebugCategory.Points, "Cultivo ignorado para admin: " + text2); } else { ProcessFarmHarvestReport(text2, prefabName, amount, "rpc-farm"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportFarmHarvest: " + ex)); } } private void ProcessFarmHarvestReport(string playerName, string prefabName, int amount, string source) { try { if (!IsServerInstance() || _rules == null || !_rules.RankingEnabled) { return; } playerName = SanitizePlayerName(playerName); prefabName = SafeKey(prefabName); amount = Mathf.Clamp(amount, 1, 100); if (string.IsNullOrWhiteSpace(playerName) || string.IsNullOrWhiteSpace(prefabName)) { return; } JackpotRule value; if (ShouldIgnorePlayerForRanking(playerName)) { DebugLog(DebugCategory.Points, "Cultivo ignorado para admin: " + playerName); } else if (_rules.FarmJackpots == null || !_rules.FarmJackpots.TryGetValue(prefabName, out value) || value == null || value.Points <= 0) { DebugLog(DebugCategory.Points, "Colheita sem jackpot configurado: prefab=" + prefabName + " amount=" + amount + " player=" + playerName); } else { RankingEntry orCreateEntry = GetOrCreateEntry(playerName); if (orCreateEntry != null) { AddProgressAndCheckJackpot(orCreateEntry, "Farm", prefabName, amount, value, "Jackpot colheita: " + prefabName, unique: false); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar colheita: " + ex)); } } public void NotifyLocalFishCaught(object fishInstance, Player player) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown try { if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return; } Component val = (Component)((fishInstance is Component) ? fishInstance : null); if ((Object)(object)val == (Object)null) { return; } string prefabName = GetPrefabName(val.gameObject); if (!IsFishPrefab(prefabName)) { return; } string zdoKey = GetZdoKey(val.gameObject); if (string.IsNullOrWhiteSpace(zdoKey)) { DebugLog(DebugCategory.Points, "Pesca ignorada: peixe sem ZDO real. prefab=" + prefabName); return; } long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0L && _rpcsRegistered && ZRoutedRpc.instance != null) { ZPackage val2 = new ZPackage(); val2.Write(SafeKey(zdoKey)); val2.Write(SafeKey(prefabName)); val2.Write(SafeLimit(Player.m_localPlayer.GetPlayerName(), 32)); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.reportfishcaught", new object[1] { val2 }); DebugLog(DebugCategory.Points, "Cliente reportando pesca: player=" + GetLocalPlayerName() + " fish=" + prefabName + " zdo=" + zdoKey); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao reportar pesca local: " + ex)); } } public void NotifyLocalFishItemAdded(string fishPrefab, int amount) { try { fishPrefab = SafeKey(fishPrefab); if (IsFishPrefab(fishPrefab)) { DebugLog(DebugCategory.Points, "Peixe em inventário ignorado para evitar exploit: fish=" + fishPrefab + " amount=" + amount); } } catch { } } private bool IsValidFishCatchCreditKey(string zdoKey) { zdoKey = SafeKey(zdoKey); if (string.IsNullOrWhiteSpace(zdoKey)) { return false; } if (zdoKey.StartsWith("inventory-fish:", StringComparison.OrdinalIgnoreCase)) { return false; } if (zdoKey.StartsWith("Fish", StringComparison.OrdinalIgnoreCase) && zdoKey.Split(new char[1] { ':' }).Length >= 3) { return false; } return true; } private void RPC_ReportFishCaught(long sender, ZPackage pkg) { try { if (IsServerInstance() && pkg != null) { string text = SafeKey(pkg.ReadString()); string text2 = SafeKey(pkg.ReadString()); string text3 = SanitizePlayerName(pkg.ReadString()); string text4 = ResolvePlayerNameFromSender(sender); if (string.IsNullOrWhiteSpace(text4)) { text4 = text3; } if (ShouldIgnoreSenderForRanking(sender, text4)) { DebugLog(DebugCategory.Points, "Pesca ignorada para admin: " + text4); } else if (!IsValidFishCatchCreditKey(text)) { DebugLog(DebugCategory.Points, "Pesca rejeitada por chave inválida/forjada: player=" + text4 + " fish=" + text2 + " zdo=" + text); } else { ProcessFishingCatchReport(text4, text2, text, "rpc-fishing"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportFishCaught: " + ex)); } } private void ProcessFishingCatchReport(string playerName, string fishPrefab, string zdoKey, string source) { try { if (!IsServerInstance() || _rules == null || !_rules.RankingEnabled || !_rules.EnableFishingPoints) { return; } playerName = SanitizePlayerName(playerName); fishPrefab = NormalizeFishPrefabName(fishPrefab); zdoKey = SafeKey(zdoKey); if (string.IsNullOrWhiteSpace(playerName) || !IsFishPrefab(fishPrefab)) { return; } if (ShouldIgnorePlayerForRanking(playerName)) { DebugLog(DebugCategory.Points, "Pesca ignorada para admin: " + playerName); } else { if (_rules.FishingPoints == null || !_rules.FishingPoints.TryGetValue(fishPrefab, out var value)) { return; } value = Mathf.Max(0, value); if (value <= 0) { return; } if (HasFishingCatchCredit(zdoKey)) { DebugLog(DebugCategory.Points, "Pesca já creditada: zdo=" + zdoKey + " fish=" + fishPrefab + " source=" + source); return; } RankingEntry orCreateEntry = GetOrCreateEntry(playerName); if (orCreateEntry != null) { ApplyPointsToEntry(orCreateEntry, value, "Pesca: " + fishPrefab); orCreateEntry.TotalFishingPontuadas++; orCreateEntry.FishingPointsTotal = Mathf.Clamp(orCreateEntry.FishingPointsTotal + value, 0, int.MaxValue); IncrementProgressCounter(orCreateEntry, "Fishing", fishPrefab, 1); MarkFishingCatchCredit(playerName, fishPrefab, zdoKey); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar pontuação de pesca: " + ex)); } } private bool HasFishingCatchCredit(string zdoKey) { if (string.IsNullOrWhiteSpace(zdoKey) || _database == null || _database.FishingCatchCredits == null) { return false; } return _database.FishingCatchCredits.Any((FishingCatchCreditRecord x) => x != null && string.Equals(SafeKey(x.ZdoKey), SafeKey(zdoKey), StringComparison.OrdinalIgnoreCase)); } private void MarkFishingCatchCredit(string playerName, string fishPrefab, string zdoKey) { if (_database == null) { _database = new RankingDatabase(); } if (_database.FishingCatchCredits == null) { _database.FishingCatchCredits = new List(); } if (!HasFishingCatchCredit(zdoKey)) { _database.FishingCatchCredits.Add(new FishingCatchCreditRecord { PlayerName = SanitizePlayerName(playerName), FishPrefab = SafeKey(fishPrefab), ZdoKey = SafeKey(zdoKey), GrantedAtUtc = DateTime.UtcNow.ToString("O") }); if (IsServerInstance()) { SaveDatabase(); } } } private string GetAttackerKeyFromHit(HitData hit) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (hit == null) { return ""; } try { ZDOID attacker = hit.m_attacker; if (!((ZDOID)(ref attacker)).IsNone()) { return ((ZDOID)(ref attacker)).UserID + ":" + ((ZDOID)(ref attacker)).ID; } } catch { } try { Character attacker2 = hit.GetAttacker(); if ((Object)(object)attacker2 != (Object)null) { return GetZdoKey(attacker2); } } catch { } return ""; } private void CleanupOldLocalRecentHits() { List list = new List(); foreach (KeyValuePair localRecentHit in _localRecentHits) { if (Time.time - localRecentHit.Value > 15f) { list.Add(localRecentHit.Key); } } foreach (string item in list) { _localRecentHits.Remove(item); } } private bool HasRecentLocalHit(string zdoKey) { if (string.IsNullOrWhiteSpace(zdoKey)) { return false; } if (!_localRecentHits.TryGetValue(zdoKey, out var value)) { return false; } if (Time.time - value > 15f) { _localRecentHits.Remove(zdoKey); return false; } return true; } private void SendKillReportToServer(string zdoKey, string prefabName, string attackerKey, string sourceTag, bool victimTamed) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown try { if (string.IsNullOrWhiteSpace(zdoKey) || string.IsNullOrWhiteSpace(prefabName)) { return; } if (string.IsNullOrWhiteSpace(attackerKey)) { attackerKey = GetLocalPlayerKey(); } if (!string.IsNullOrWhiteSpace(attackerKey)) { long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0L && _rpcsRegistered && ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(zdoKey); val.Write(prefabName); val.Write(attackerKey); val.Write(victimTamed); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.reportkill", new object[1] { val }); DebugLog(DebugCategory.Kill, "Cliente reportando KILL(" + sourceTag + "): player=" + GetLocalPlayerName() + " attackerKey=" + attackerKey + " zdo=" + zdoKey + " prefab=" + prefabName + " tamed=" + victimTamed); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao enviar KILL local do ranking: " + ex)); } } public void NotifyLocalDamage(Character victim, HitData hit, bool postDamage) { //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown try { if ((Object)(object)victim == (Object)null || hit == null || victim is Player || (_rules.IgnoreTamedKills && IsTamedCharacter(victim)) || (Object)(object)Player.m_localPlayer == (Object)null || !IsLocalPlayerAttackAuthor(hit)) { return; } string zdoKey = GetZdoKey(victim); if (string.IsNullOrWhiteSpace(zdoKey)) { return; } string prefabName = GetPrefabName(((Component)victim).gameObject); if (string.IsNullOrWhiteSpace(prefabName)) { return; } string text = GetAttackerKeyFromHit(hit); if (string.IsNullOrWhiteSpace(text)) { text = GetLocalPlayerKey(); } if (string.IsNullOrWhiteSpace(text)) { return; } long serverPeerUid = GetServerPeerUid(); if (serverPeerUid == 0L || !_rpcsRegistered || ZRoutedRpc.instance == null) { return; } _localRecentHits[zdoKey] = Time.time; ZPackage val = new ZPackage(); val.Write(zdoKey); val.Write(prefabName); val.Write(text); val.Write(IsTamedCharacter(victim)); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "glitnir.ranking.reporthit", new object[1] { val }); DebugLog(DebugCategory.Hit, "Cliente reportando HIT: player=" + GetLocalPlayerName() + " attackerKey=" + text + " zdo=" + zdoKey + " prefab=" + prefabName); if (postDamage) { bool flag = false; float num = 1f; try { num = victim.GetHealth(); } catch { } try { flag = victim.IsDead(); } catch { } if ((flag || !(num > 0f)) && HasRecentLocalHit(zdoKey)) { SendKillReportToServer(zdoKey, prefabName, text, "Damage", IsTamedCharacter(victim)); _localRecentHits.Remove(zdoKey); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao reportar dano local do ranking: " + ex)); } } public void NotifyLocalCharacterDeath(Character victim) { try { if ((Object)(object)victim == (Object)null || victim is Player || (_rules.IgnoreTamedKills && IsTamedCharacter(victim)) || (Object)(object)Player.m_localPlayer == (Object)null) { return; } string zdoKey = GetZdoKey(victim); if (string.IsNullOrWhiteSpace(zdoKey) || !HasRecentLocalHit(zdoKey)) { return; } string prefabName = GetPrefabName(((Component)victim).gameObject); if (!string.IsNullOrWhiteSpace(prefabName)) { string localPlayerKey = GetLocalPlayerKey(); if (!string.IsNullOrWhiteSpace(localPlayerKey)) { SendKillReportToServer(zdoKey, prefabName, localPlayerKey, "OnDeath", IsTamedCharacter(victim)); _localRecentHits.Remove(zdoKey); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao reportar morte local do ranking: " + ex)); } } private bool DoesSenderMatchAttackerKey(long sender, string attackerKey) { if (sender == 0L || string.IsNullOrWhiteSpace(attackerKey)) { return false; } int num = attackerKey.IndexOf(':'); string s = ((num >= 0) ? attackerKey.Substring(0, num) : attackerKey); if (!long.TryParse(s, out var result)) { return false; } return result == sender; } private void SchedulePendingKillCheck(string zdoKey, string prefabName) { if (!IsServerInstance()) { return; } zdoKey = SafeKey(zdoKey); prefabName = SafeKey(prefabName); if (string.IsNullOrWhiteSpace(zdoKey)) { return; } if (!_pendingKillChecks.TryGetValue(zdoKey, out var value) || value == null) { value = new PendingKillCheck(); value.PrefabName = prefabName; value.FirstSeenTime = Time.time; value.LastHitTime = Time.time; _pendingKillChecks[zdoKey] = value; } else { value.LastHitTime = Time.time; if (!string.IsNullOrWhiteSpace(prefabName)) { value.PrefabName = prefabName; } } } private bool TryFindCharacterByZdoKey(string zdoKey, out Character found) { found = null; if (string.IsNullOrWhiteSpace(zdoKey)) { return false; } try { Character[] array = Object.FindObjectsByType((FindObjectsSortMode)0); if (array == null || array.Length == 0) { return false; } foreach (Character val in array) { if (!((Object)(object)val == (Object)null) && !(val is Player)) { string zdoKey2 = GetZdoKey(val); if (string.Equals(zdoKey2, zdoKey, StringComparison.Ordinal)) { found = val; return true; } } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao localizar Character por zdoKey=" + zdoKey + ": " + ex.Message)); } return false; } private void ProcessPendingKillChecks() { if (!IsServerInstance() || _pendingKillChecks.Count == 0 || Time.time < _serverPendingKillCheckAt) { return; } _serverPendingKillCheckAt = Time.time + 0.25f; List list = new List(); KeyValuePair[] array = _pendingKillChecks.ToArray(); KeyValuePair[] array2 = array; for (int i = 0; i < array2.Length; i++) { KeyValuePair keyValuePair = array2[i]; string key = keyValuePair.Key; PendingKillCheck value = keyValuePair.Value; if (!_pendingKillChecks.ContainsKey(key)) { continue; } if (value == null) { list.Add(key); } else if (_processedKills.ContainsKey(key)) { list.Add(key); } else if (Time.time - value.FirstSeenTime > 12f) { DebugLog(DebugCategory.PendingKill, "Pending kill expirado: zdo=" + key + " prefab=" + value.PrefabName); RemoveDamageCredit(key); list.Add(key); } else { if (Time.time - value.LastHitTime < 0.25f) { continue; } List creditedPlayerNames = GetCreditedPlayerNames(key); Character found; if (creditedPlayerNames.Count == 0) { list.Add(key); } else if (TryFindCharacterByZdoKey(key, out found)) { if (_rules.IgnoreTamedKills && IsTamedCharacter(found)) { MarkTamedKillIgnored(key, "pending-check"); list.Add(key); continue; } bool flag = false; float num = 1f; try { num = found.GetHealth(); } catch { } try { flag = found.IsDead(); } catch { } if (flag || !(num > 0f)) { string text = ((!string.IsNullOrWhiteSpace(value.PrefabName)) ? value.PrefabName : GetPrefabName(((Component)found).gameObject)); DebugLog(DebugCategory.PendingKill, "Pending kill confirmado por estado morto: zdo=" + key + " prefab=" + text + " credited=" + string.Join(",", creditedPlayerNames.ToArray())); ProcessKillReportMulti(creditedPlayerNames, key, text, "pending-dead"); list.Add(key); } } else { DebugLog(DebugCategory.PendingKill, "Pending kill confirmado por alvo ausente: zdo=" + key + " prefab=" + value.PrefabName + " credited=" + string.Join(",", creditedPlayerNames.ToArray())); ProcessKillReportMulti(creditedPlayerNames, key, value.PrefabName, "pending-missing"); list.Add(key); } } } foreach (string item in list.Distinct(StringComparer.Ordinal)) { _pendingKillChecks.Remove(item); } } private void RPC_ReportHit(long sender, ZPackage pkg) { try { if (!IsServerInstance() || pkg == null) { return; } string text = SafeKey(pkg.ReadString()); string text2 = SafeKey(pkg.ReadString()); string text3 = SafeKey(pkg.ReadString()); bool flag = false; try { flag = pkg.ReadBool(); } catch { } string text4 = ResolvePlayerNameFromSender(sender); DebugLog(DebugCategory.Hit, "Servidor recebeu HIT: sender=" + sender + " reporter=" + text4 + " attackerKey=" + text3 + " zdo=" + text + " prefab=" + text2); if (!string.IsNullOrWhiteSpace(text) && !string.IsNullOrWhiteSpace(text2) && !string.IsNullOrWhiteSpace(text4)) { if (ShouldIgnoreSenderForRanking(sender, text4)) { DebugLog(DebugCategory.Hit, "HIT ignorado para admin: sender=" + sender + " reporter=" + text4); } else if (!DoesSenderMatchAttackerKey(sender, text3)) { DebugLog(DebugCategory.Hit, "HIT rejeitado por mismatch: sender=" + sender + " reporter=" + text4 + " attackerKey=" + text3); } else if (_rules.IgnoreTamedKills && flag) { MarkTamedKillIgnored(text, "rpc-hit-client-flag"); } else if (!ShouldIgnoreTamedKill(text, "rpc-hit")) { RecordDamageCredit(text, text4); SchedulePendingKillCheck(text, text2); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportHit: " + ex)); } } private void RPC_ReportKill(long sender, ZPackage pkg) { try { if (!IsServerInstance() || pkg == null) { return; } string text = SafeKey(pkg.ReadString()); string text2 = SafeKey(pkg.ReadString()); string text3 = SafeKey(pkg.ReadString()); bool flag = false; try { flag = pkg.ReadBool(); } catch { } string text4 = ResolvePlayerNameFromSender(sender); DebugLog(DebugCategory.Kill, "Servidor recebeu KILL: sender=" + sender + " reporter=" + text4 + " attackerKey=" + text3 + " zdo=" + text + " prefab=" + text2); if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(text2) || string.IsNullOrWhiteSpace(text4)) { return; } if (ShouldIgnoreSenderForRanking(sender, text4)) { DebugLog(DebugCategory.Kill, "KILL ignorado para admin: sender=" + sender + " reporter=" + text4); } else if (!DoesSenderMatchAttackerKey(sender, text3)) { DebugLog(DebugCategory.Kill, "KILL rejeitado por mismatch: sender=" + sender + " reporter=" + text4 + " attackerKey=" + text3); } else if (_rules.IgnoreTamedKills && flag) { MarkTamedKillIgnored(text, "rpc-kill-client-flag"); } else if (!ShouldIgnoreTamedKill(text, "rpc-kill")) { List creditedPlayerNames = GetCreditedPlayerNames(text); if (creditedPlayerNames.Count == 0) { creditedPlayerNames.Add(text4); } ProcessKillReportMulti(creditedPlayerNames, text, text2, "rpc-kill"); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro no RPC_ReportKill: " + ex)); } } private string ResolvePlayerNameFromSender(long sender) { //IL_0072: 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_007b: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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) try { if ((Object)(object)ZNet.instance != (Object)null) { ZNetPeer peer = ZNet.instance.GetPeer(sender); if (peer != null && !string.IsNullOrWhiteSpace(peer.m_playerName)) { return SanitizePlayerName(peer.m_playerName); } List playerList = ZNet.instance.GetPlayerList(); if (playerList != null) { foreach (PlayerInfo item in playerList) { try { ZDOID characterID = item.m_characterID; long num = Convert.ToInt64(((ZDOID)(ref characterID)).UserID); if (num == sender && !string.IsNullOrWhiteSpace(item.m_name)) { return SanitizePlayerName(item.m_name); } } catch { } } } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Ranking] Falha ao resolver player por sender=" + sender + ": " + ex.Message)); } return ""; } private bool ShouldIgnoreSenderForRanking(long sender, string playerName) { try { if (_cfgIgnoreAdminsInRanking == null || !_cfgIgnoreAdminsInRanking.Value) { return false; } if (ShouldIgnorePlayerForRanking(playerName)) { return true; } if (sender != 0L && IsSenderDetectedInAdminList(sender)) { return true; } } catch { } return false; } private bool ShouldIgnorePlayerForRanking(string playerName) { if (_cfgIgnoreAdminsInRanking == null || !_cfgIgnoreAdminsInRanking.Value) { return false; } string text = SanitizePlayerName(playerName); if (string.IsNullOrWhiteSpace(text)) { return false; } if (IsNameOrIdInIgnoredAdminConfig(text)) { return true; } HashSet allKnownAdminIdentifiers = GetAllKnownAdminIdentifiers(); if (allKnownAdminIdentifiers.Contains(text)) { return true; } return false; } private bool IsNameOrIdInIgnoredAdminConfig(string value) { try { if (_cfgIgnoredAdminNames == null || string.IsNullOrWhiteSpace(_cfgIgnoredAdminNames.Value)) { return false; } string b = SanitizePlayerName(value); string[] array = _cfgIgnoredAdminNames.Value.Split(new char[5] { ',', ';', '\n', '\r', '|' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = SanitizePlayerName(array[i]); if (!string.IsNullOrWhiteSpace(text) && string.Equals(text, b, StringComparison.OrdinalIgnoreCase)) { return true; } } } catch { } return false; } private bool IsSenderDetectedInAdminList(long sender) { try { HashSet allKnownAdminIdentifiers = GetAllKnownAdminIdentifiers(); if (allKnownAdminIdentifiers == null || allKnownAdminIdentifiers.Count == 0) { return false; } string item = sender.ToString(); if (allKnownAdminIdentifiers.Contains(item)) { return true; } if ((Object)(object)ZNet.instance != (Object)null) { ZNetPeer peer = ZNet.instance.GetPeer(sender); HashSet possiblePeerIdentifiers = GetPossiblePeerIdentifiers(peer); foreach (string item2 in possiblePeerIdentifiers) { if (!string.IsNullOrWhiteSpace(item2) && allKnownAdminIdentifiers.Contains(item2.Trim())) { return true; } } } } catch { } return false; } private HashSet GetAllKnownAdminIdentifiers() { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); try { if ((Object)(object)ZNet.instance != (Object)null) { HashSet adminIdentifiersFromZNet = GetAdminIdentifiersFromZNet(ZNet.instance); foreach (string item in adminIdentifiersFromZNet) { if (!string.IsNullOrWhiteSpace(item)) { hashSet.Add(item.Trim()); } } } } catch { } try { foreach (string item2 in ReadAdminIdentifiersFromKnownFiles()) { if (!string.IsNullOrWhiteSpace(item2)) { hashSet.Add(item2.Trim()); } } } catch { } return hashSet; } private HashSet ReadAdminIdentifiersFromKnownFiles() { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); string[] array = new string[6] { Path.Combine(Paths.ConfigPath, "adminlist.txt"), Path.Combine(Paths.ConfigPath, "adminlist"), Path.Combine(Application.persistentDataPath, "adminlist.txt"), Path.Combine(Application.persistentDataPath, "adminlist"), Path.Combine(Directory.GetCurrentDirectory(), "adminlist.txt"), Path.Combine(Directory.GetCurrentDirectory(), "adminlist") }; foreach (string text in array) { try { if (string.IsNullOrWhiteSpace(text) || !File.Exists(text)) { continue; } string[] array2 = File.ReadAllLines(text, Encoding.UTF8); foreach (string text2 in array2) { string text3 = ((text2 != null) ? text2.Trim() : ""); if (!string.IsNullOrWhiteSpace(text3) && !text3.StartsWith("#") && !text3.StartsWith("//")) { int num = text3.IndexOf('#'); if (num >= 0) { text3 = text3.Substring(0, num).Trim(); } if (!string.IsNullOrWhiteSpace(text3)) { hashSet.Add(text3); } } } } catch { } } return hashSet; } private HashSet GetAdminIdentifiersFromZNet(object znet) { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); try { if (znet == null) { return hashSet; } Type type = znet.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo[] fields = type.GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { if (!(fieldInfo == null) && !string.IsNullOrWhiteSpace(fieldInfo.Name) && fieldInfo.Name.IndexOf("admin", StringComparison.OrdinalIgnoreCase) >= 0) { object value = fieldInfo.GetValue(znet); AddStringsFromObject(value, hashSet); } } PropertyInfo[] properties = type.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo == null) && !string.IsNullOrWhiteSpace(propertyInfo.Name) && propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.Name.IndexOf("admin", StringComparison.OrdinalIgnoreCase) >= 0) { try { object value2 = propertyInfo.GetValue(znet, null); AddStringsFromObject(value2, hashSet); } catch { } } } } catch { } return hashSet; } private void AddStringsFromObject(object value, HashSet output) { if (value == null || output == null) { return; } try { string text = value as string; if (!string.IsNullOrWhiteSpace(text)) { output.Add(text.Trim()); } else { if (!(value is IEnumerable enumerable)) { return; } { foreach (object item in enumerable) { if (item == null) { continue; } string text2 = item as string; if (!string.IsNullOrWhiteSpace(text2)) { output.Add(text2.Trim()); continue; } string text3 = item.ToString(); if (!string.IsNullOrWhiteSpace(text3)) { output.Add(text3.Trim()); } } return; } } } catch { } } private HashSet GetPossiblePeerIdentifiers(object peer) { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); try { if (peer == null) { return hashSet; } Type type = peer.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; string[] array = new string[16] { "m_uid", "uid", "UID", "m_userId", "userId", "UserId", "m_userID", "UserID", "m_steamID", "steamID", "SteamID", "m_hostName", "hostName", "HostName", "m_socketHost", "socketHost" }; for (int i = 0; i < array.Length; i++) { string stringMemberByNames = GetStringMemberByNames(peer, array[i]); if (!string.IsNullOrWhiteSpace(stringMemberByNames)) { hashSet.Add(stringMemberByNames.Trim()); } } FieldInfo[] fields = type.GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo == null || string.IsNullOrWhiteSpace(fieldInfo.Name)) { continue; } string name = fieldInfo.Name; if (name.IndexOf("uid", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("id", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("host", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("steam", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("playfab", StringComparison.OrdinalIgnoreCase) >= 0) { object value = fieldInfo.GetValue(peer); if (value != null && !string.IsNullOrWhiteSpace(value.ToString())) { hashSet.Add(value.ToString().Trim()); } } } } catch { } return hashSet; } private string GetStringMemberByNames(object obj, params string[] names) { if (obj == null || names == null) { return null; } try { Type type = obj.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; for (int i = 0; i < names.Length; i++) { FieldInfo field = type.GetField(names[i], bindingAttr); if (field != null) { object value = field.GetValue(obj); if (value != null) { return value.ToString(); } } PropertyInfo property = type.GetProperty(names[i], bindingAttr); if (property != null && property.GetIndexParameters().Length == 0) { object value2 = property.GetValue(obj, null); if (value2 != null) { return value2.ToString(); } } } } catch { } return null; } private bool IsTamedCharacter(Character character) { try { if ((Object)(object)character == (Object)null) { return false; } try { if (character.IsTamed()) { return true; } } catch { } try { ZNetView component = ((Component)character).GetComponent(); if ((Object)(object)component != (Object)null && component.GetZDO() != null && component.GetZDO().GetBool("tamed", false)) { return true; } } catch { } try { Tameable component2 = ((Component)character).GetComponent(); if ((Object)(object)component2 != (Object)null) { ZNetView component3 = ((Component)component2).GetComponent(); if ((Object)(object)component3 != (Object)null && component3.GetZDO() != null && component3.GetZDO().GetBool("tamed", false)) { return true; } } } catch { } return false; } catch { return false; } } private void MarkTamedKillIgnored(string zdoKey, string source) { zdoKey = SafeKey(zdoKey); if (!string.IsNullOrWhiteSpace(zdoKey)) { _ignoredTamedKills[zdoKey] = Time.time; _processedKills[zdoKey] = Time.time; RemoveDamageCredit(zdoKey); DebugLog(DebugCategory.Kill, "Kill ignorado por criatura domada: source=" + source + " zdo=" + zdoKey); } } private bool ShouldIgnoreTamedKill(string zdoKey, string source) { if (_rules == null || !_rules.IgnoreTamedKills) { return false; } zdoKey = SafeKey(zdoKey); if (string.IsNullOrWhiteSpace(zdoKey)) { return false; } if (_ignoredTamedKills.ContainsKey(zdoKey)) { return true; } if (TryFindCharacterByZdoKey(zdoKey, out var found) && IsTamedCharacter(found)) { MarkTamedKillIgnored(zdoKey, source); return true; } return false; } private bool TryNormalizeBossPrefabName(string rawName, out string prefabName) { prefabName = ""; string text = SafeKey(rawName); if (string.IsNullOrWhiteSpace(text)) { return false; } if (BossPortugueseToPrefab.TryGetValue(text, out prefabName)) { return true; } if (BossDisplayNamesPtBr.ContainsKey(text)) { prefabName = text; return true; } return false; } private string NormalizeBossPrefabName(string rawName) { string prefabName; return TryNormalizeBossPrefabName(rawName, out prefabName) ? prefabName : SafeKey(rawName); } private bool TryNormalizeFishPrefabName(string rawName, out string prefabName) { prefabName = ""; string text = SafeKey(rawName); if (string.IsNullOrWhiteSpace(text)) { return false; } if (FishPortugueseToPrefab.TryGetValue(text, out prefabName)) { return true; } if (FishDisplayNamesPtBr.ContainsKey(text)) { prefabName = text; return true; } if (text.StartsWith("Fish", StringComparison.OrdinalIgnoreCase)) { prefabName = text; return true; } return false; } private string NormalizeFishPrefabName(string rawName) { string prefabName; return TryNormalizeFishPrefabName(rawName, out prefabName) ? prefabName : SafeKey(rawName); } private bool IsFishPrefab(string prefabName) { string prefabName2; return TryNormalizeFishPrefabName(prefabName, out prefabName2); } public void NotifyServerCharacterDeath(Character victim) { try { if (!IsServerInstance() || (Object)(object)victim == (Object)null || victim is Player) { return; } string zdoKey = GetZdoKey(victim); string prefabName = GetPrefabName(((Component)victim).gameObject); List creditedPlayerNames = GetCreditedPlayerNames(zdoKey); DebugLog(DebugCategory.Kill, "OnDeath servidor: zdo=" + zdoKey + " prefab=" + prefabName + " credited=" + string.Join(",", creditedPlayerNames.ToArray())); if (!string.IsNullOrWhiteSpace(zdoKey) && !string.IsNullOrWhiteSpace(prefabName) && creditedPlayerNames.Count != 0) { if (IsFishPrefab(prefabName)) { DebugLog(DebugCategory.Kill, "Kill de peixe ignorado: source=ondeath zdo=" + zdoKey + " prefab=" + prefabName); } else if (_rules.IgnoreTamedKills && IsTamedCharacter(victim)) { MarkTamedKillIgnored(zdoKey, "ondeath"); } else { ProcessKillReportMulti(creditedPlayerNames, zdoKey, prefabName, "ondeath"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar OnDeath do ranking: " + ex)); } } private bool IsConfiguredCombatPointPrefab(string prefabName) { prefabName = SafeKey(prefabName); if (string.IsNullOrWhiteSpace(prefabName) || _rules == null) { return false; } string key = NormalizeBossPrefabName(prefabName); if (_rules.EnableBossPoints && _rules.BossPoints != null && _rules.BossPoints.ContainsKey(key)) { return true; } if (_rules.EnableKillPoints && _rules.KillPoints != null && _rules.KillPoints.ContainsKey(prefabName)) { return true; } return false; } private void ProcessKillReportMulti(List playerNames, string zdoKey, string prefabName, string source) { try { if (!IsServerInstance() || !_rules.RankingEnabled) { return; } zdoKey = SafeKey(zdoKey); prefabName = SafeKey(prefabName); if (string.IsNullOrWhiteSpace(zdoKey) || string.IsNullOrWhiteSpace(prefabName) || playerNames == null || playerNames.Count == 0) { return; } if (IsFishPrefab(prefabName)) { DebugLog(DebugCategory.Kill, "Kill de peixe ignorado: source=" + source + " zdo=" + zdoKey + " prefab=" + prefabName); RemoveDamageCredit(zdoKey); return; } if (!IsConfiguredCombatPointPrefab(prefabName)) { DebugLog(DebugCategory.Kill, "Kill ignorado porque o prefab nao esta configurado em KillPoints/BossPoints: source=" + source + " zdo=" + zdoKey + " prefab=" + prefabName); RemoveDamageCredit(zdoKey); return; } CleanupOldProcessedKills(); if (ShouldIgnoreTamedKill(zdoKey, source)) { return; } if (_processedKills.ContainsKey(zdoKey)) { DebugLog(DebugCategory.Kill, "Kill duplicado ignorado: source=" + source + " zdo=" + zdoKey + " prefab=" + prefabName); return; } _processedKills[zdoKey] = Time.time; foreach (string item in playerNames.Distinct(StringComparer.OrdinalIgnoreCase)) { string text = SanitizePlayerName(item); if (string.IsNullOrWhiteSpace(text)) { continue; } RankingEntry orCreateEntry = GetOrCreateEntry(text); string text2 = NormalizeBossPrefabName(prefabName); if (_rules.EnableBossPoints && _rules.BossPoints.TryGetValue(text2, out var value)) { bool flag = orCreateEntry.BossCredits != null && orCreateEntry.BossCredits.Contains(text2); orCreateEntry.TotalBossesPontuadas++; IncrementProgressCounter(orCreateEntry, "Bosses", text2, 1); if (!_rules.AllowRepeatedBossPoints && flag) { DebugLog(DebugCategory.Kill, "Boss repetido sem pontos, progresso contado: player=" + text + " boss=" + prefabName); SaveDatabase(); continue; } orCreateEntry.BossPointsTotal = Mathf.Clamp(orCreateEntry.BossPointsTotal + value, -2147483647, int.MaxValue); if (orCreateEntry.BossCredits == null) { orCreateEntry.BossCredits = new HashSet(StringComparer.OrdinalIgnoreCase); } orCreateEntry.BossCredits.Add(text2); string reason = "Boss: " + prefabName; ApplyPointsToEntry(orCreateEntry, value, reason); } else if (_rules.EnableKillPoints && _rules.KillPoints.TryGetValue(prefabName, out value)) { orCreateEntry.TotalKillsPontuadas++; orCreateEntry.KillPointsTotal = Mathf.Clamp(orCreateEntry.KillPointsTotal + value, -2147483647, int.MaxValue); IncrementProgressCounter(orCreateEntry, "Kill", prefabName, 1); IncrementProgressCounterAlias(orCreateEntry, "Combat", prefabName, 1); IncrementProgressCounterAlias(orCreateEntry, "Combate", prefabName, 1); string reason = "Kill: " + prefabName; ApplyPointsToEntry(orCreateEntry, value, reason); } else { DebugLog(DebugCategory.Kill, "Kill sem regra de pontos: player=" + text + " prefab=" + prefabName); } } RemoveDamageCredit(zdoKey); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao processar kill múltiplo reportado: " + ex)); } } private void RecordDamageCredit(string zdoKey, string playerName) { if (!IsServerInstance()) { return; } zdoKey = SafeKey(zdoKey); playerName = SanitizePlayerName(playerName); if (string.IsNullOrWhiteSpace(zdoKey) || string.IsNullOrWhiteSpace(playerName)) { return; } if (ShouldIgnorePlayerForRanking(playerName)) { DebugLog(DebugCategory.Hit, "Crédito de dano ignorado para admin: " + playerName); return; } if (!_damageCredits.TryGetValue(zdoKey, out var value) || value == null) { value = new Dictionary(StringComparer.OrdinalIgnoreCase); _damageCredits[zdoKey] = value; } value[playerName] = Time.time; } private List GetCreditedPlayerNames(string zdoKey) { List list = new List(); if (string.IsNullOrWhiteSpace(zdoKey)) { return list; } if (!_damageCredits.TryGetValue(zdoKey, out var value) || value == null) { return list; } foreach (KeyValuePair item in value) { if (Time.time - item.Value <= 180f) { string text = SanitizePlayerName(item.Key); if (!ShouldIgnorePlayerForRanking(text)) { list.Add(text); } } } return list.Where((string x) => !string.IsNullOrWhiteSpace(x)).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); } private void CleanupOldDamageCredits() { List list = new List(); foreach (KeyValuePair> damageCredit in _damageCredits) { Dictionary value = damageCredit.Value; if (value == null) { list.Add(damageCredit.Key); continue; } List list2 = new List(); foreach (KeyValuePair item in value) { if (Time.time - item.Value > 180f) { list2.Add(item.Key); } } foreach (string item2 in list2) { value.Remove(item2); } if (value.Count == 0) { list.Add(damageCredit.Key); } } foreach (string item3 in list) { _damageCredits.Remove(item3); } } private void CleanupOldProcessedKills() { List list = new List(); foreach (KeyValuePair processedKill in _processedKills) { if (Time.time - processedKill.Value > 180f) { list.Add(processedKill.Key); } } foreach (string item in list) { _processedKills.Remove(item); } list.Clear(); foreach (KeyValuePair ignoredTamedKill in _ignoredTamedKills) { if (Time.time - ignoredTamedKill.Value > 180f) { list.Add(ignoredTamedKill.Key); } } foreach (string item2 in list) { _ignoredTamedKills.Remove(item2); } } private void RemoveDamageCredit(string zdoKey) { if (!string.IsNullOrWhiteSpace(zdoKey)) { _damageCredits.Remove(zdoKey); _pendingKillChecks.Remove(zdoKey); } } } [HarmonyPatch] internal static class RankingPatches { [HarmonyPostfix] [HarmonyPatch(typeof(Character), "ApplyDamage")] private static void Character_ApplyDamage_Postfix(Character __instance, HitData hit) { if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null)) { GlitnirRankingPlugin.Instance.NotifyLocalDamage(__instance, hit, postDamage: false); } } [HarmonyPatch(typeof(Character), "Damage")] [HarmonyPostfix] private static void Character_Damage_Postfix(Character __instance, HitData hit) { if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null)) { GlitnirRankingPlugin.Instance.NotifyLocalDamage(__instance, hit, postDamage: true); } } [HarmonyPatch(typeof(Character), "OnDeath")] [HarmonyPostfix] private static void Character_OnDeath_Postfix(Character __instance) { if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null)) { GlitnirRankingPlugin.Instance.NotifyLocalCharacterDeath(__instance); GlitnirRankingPlugin.Instance.NotifyServerCharacterDeath(__instance); } } [HarmonyPrefix] [HarmonyPatch(typeof(Skills), "RaiseSkill")] private static void Skills_RaiseSkill_Prefix(Skills __instance, SkillType skillType, ref float __state) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null)) { __state = GlitnirRankingPlugin.Instance.CaptureLocalSkillLevelBeforeRaise(__instance, skillType); } } [HarmonyPostfix] [HarmonyPatch(typeof(Skills), "RaiseSkill")] private static void Skills_RaiseSkill_Postfix(Skills __instance, SkillType skillType, float __state) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null)) { GlitnirRankingPlugin.Instance.NotifyLocalSkillGain(__instance, skillType, __state); } } } [HarmonyPatch] internal static class CraftRankingPatches { [CompilerGenerated] private sealed class d__0 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private Type 5__1; private MethodInfo[] <>s__2; private int <>s__3; private MethodInfo 5__4; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; <>s__2 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00ac; } <>1__state = -1; 5__1 = AccessTools.TypeByName("InventoryGui"); if (5__1 == null) { return false; } <>s__2 = 5__1.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); <>s__3 = 0; goto IL_00c2; IL_00ac: 5__4 = null; <>s__3++; goto IL_00c2; IL_00c2: if (<>s__3 < <>s__2.Length) { 5__4 = <>s__2[<>s__3]; if (string.Equals(5__4.Name, "DoCrafting", StringComparison.OrdinalIgnoreCase)) { <>2__current = 5__4; <>1__state = 1; return true; } goto IL_00ac; } <>s__2 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [HarmonyTargetMethods] [IteratorStateMachine(typeof(d__0))] private static IEnumerable TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(-2); } [HarmonyPostfix] private static void Postfix(object __instance, object[] __args) { try { if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null)) { Recipe val = ExtractRecipe(__args); if ((Object)(object)val == (Object)null && __instance != null) { val = ExtractRecipeFromInventoryGui(__instance); } if (!((Object)(object)val == (Object)null)) { GlitnirRankingPlugin.Instance.NotifyLocalCraftedRecipe(val); } } } catch (Exception ex) { GlitnirRankingPlugin.Log.LogError((object)("Erro no patch de craft: " + ex)); } } private static Recipe ExtractRecipe(object[] args) { if (args == null) { return null; } foreach (object obj in args) { Recipe val = (Recipe)((obj is Recipe) ? obj : null); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Recipe ExtractRecipeFromInventoryGui(object inventoryGui) { try { FieldInfo field = inventoryGui.GetType().GetField("m_craftRecipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object? value = field.GetValue(inventoryGui); return (Recipe)((value is Recipe) ? value : null); } } catch { } return null; } } [HarmonyPatch] internal static class MarketplaceQuestRankingPatches { [HarmonyTargetMethod] private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("Marketplace.Modules.Quests.Quests_DataTypes+Quest"); if (type == null) { return null; } return AccessTools.Method(type, "RemoveQuestComplete", new Type[1] { typeof(int) }, (Type[])null); } [HarmonyPostfix] private static void Postfix(int UID) { if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null)) { GlitnirRankingPlugin.Instance.ReportLocalMarketplaceQuestCompletion(UID); } } } [Serializable] [HarmonyPatch(typeof(Player), "OnDeath")] public static class GlitnirRankingPlayerDeathPatch { private static float _lastLocalDeathReportAt; private static void Postfix(Player __instance) { try { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !(Time.realtimeSinceStartup - _lastLocalDeathReportAt < 2f)) { _lastLocalDeathReportAt = Time.realtimeSinceStartup; GlitnirRankingPlugin.Instance?.ReportLocalPlayerDeathToServer(); } } catch (Exception ex) { ManualLogSource log = GlitnirRankingPlugin.Log; if (log != null) { log.LogWarning((object)("[Ranking] Falha ao reportar morte do jogador: " + ex.Message)); } } } } public class MarketplaceQuestPointRule { public string QuestKey = ""; public int Points = 0; } [Serializable] public class MarketplaceQuestCreditRecord { public string PlayerName = ""; public string QuestKey = ""; public string GrantedAtUtc = ""; } [Serializable] public class RewardClaimRecord { public string CycleId = ""; public string PlayerName = ""; public int Rank = 0; public string ClaimedAtUtc = ""; public string Status = "claimed"; } public class RankingEntryDocument { [BsonId] public string PlayerName { get; set; } public int Points { get; set; } public string LastReason { get; set; } public string LastUpdateUtc { get; set; } public int TotalKillsPontuadas { get; set; } public int TotalBossesPontuadas { get; set; } public int KillPointsTotal { get; set; } public int BossPointsTotal { get; set; } public int TotalSkillLevelUpsPontuados { get; set; } public int SkillPointsTotal { get; set; } public int TotalFishingPontuadas { get; set; } public int FishingPointsTotal { get; set; } public int TotalCraftPontuadas { get; set; } public int CraftPointsTotal { get; set; } public int TotalFarmJackpotsPontuados { get; set; } public int FarmJackpotPointsTotal { get; set; } public int TotalUniqueCraftJackpotsPontuados { get; set; } public int UniqueCraftJackpotPointsTotal { get; set; } public int TotalDeaths { get; set; } public int DeathPenaltyPointsTotal { get; set; } public int TotalPointsExchanges { get; set; } public int PointsExchangePenaltyTotal { get; set; } public int PointsExchangeCoinsTotal { get; set; } public int ExplorationMapJackpotPointsTotal { get; set; } public string ProgressCounters { get; set; } public string FloatProgressCounters { get; set; } public string GenericJackpotCredits { get; set; } public string BossCredits { get; set; } public string SkillLevel100JackpotCredits { get; set; } } public class RewardClaimDocument { [BsonId] public string Key { get; set; } public string CycleId { get; set; } public string PlayerName { get; set; } public int Rank { get; set; } public string ClaimedAtUtc { get; set; } public string Status { get; set; } } public class MarketplaceQuestCreditDocument { [BsonId] public string Key { get; set; } public string PlayerName { get; set; } public string QuestKey { get; set; } public string GrantedAtUtc { get; set; } } public class FishingCatchCreditDocument { public string PlayerName { get; set; } public string FishPrefab { get; set; } [BsonId] public string ZdoKey { get; set; } public string GrantedAtUtc { get; set; } } [Serializable] public class RankingDatabase { public List Entries = new List(); public List Claims = new List(); public List MarketplaceQuestCredits = new List(); public List FishingCatchCredits = new List(); } [Serializable] public class RankingEntry { public string PlayerName = ""; public int Points = 0; public string LastReason = ""; public string LastUpdateUtc = ""; public int TotalKillsPontuadas = 0; public int TotalBossesPontuadas = 0; public int KillPointsTotal = 0; public int BossPointsTotal = 0; public int TotalSkillLevelUpsPontuados = 0; public int SkillPointsTotal = 0; public int TotalFishingPontuadas = 0; public int FishingPointsTotal = 0; public int TotalCraftPontuadas = 0; public int CraftPointsTotal = 0; public int TotalFarmJackpotsPontuados = 0; public int FarmJackpotPointsTotal = 0; public int TotalUniqueCraftJackpotsPontuados = 0; public int UniqueCraftJackpotPointsTotal = 0; public int TotalDeaths = 0; public int DeathPenaltyPointsTotal = 0; public int TotalPointsExchanges = 0; public int PointsExchangePenaltyTotal = 0; public int PointsExchangeCoinsTotal = 0; public int ExplorationMapJackpotPointsTotal = 0; public Dictionary ProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary FloatProgressCounters = new Dictionary(StringComparer.OrdinalIgnoreCase); public HashSet GenericJackpotCredits = new HashSet(StringComparer.OrdinalIgnoreCase); public HashSet BossCredits = new HashSet(StringComparer.OrdinalIgnoreCase); public HashSet SkillLevel100JackpotCredits = new HashSet(StringComparer.OrdinalIgnoreCase); } [Serializable] public class FishingCatchCreditRecord { public string PlayerName = ""; public string FishPrefab = ""; public string ZdoKey = ""; public string GrantedAtUtc = ""; } [Serializable] public class JackpotRule { public int RequiredAmount = 1; public int Points = 0; } [Serializable] public class RankingRules { public bool RankingEnabled = true; public bool EnableKillPoints = true; public bool EnableBossPoints = true; public int DefaultKillPoints = 1; public int TopCount = 10; public bool AllowRepeatedBossPoints = false; public bool DebugLogging = false; public bool LogHitReports = false; public bool LogKillReports = false; public bool LogSkillReports = false; public bool LogPendingKillReports = false; public bool LogSnapshotRequests = false; public bool LogPointsChanges = false; public bool EnableSkillPoints = true; public bool IgnoreTamedKills = true; public bool EnableMarketplaceQuestPoints = true; public bool EnableFishingPoints = true; public bool EnableDeathPenalty = true; public bool DeathPenaltyUseMultiplier = false; public int DeathPenaltyPerDeath = 100; public bool EnableExplorationJackpots = true; public bool RewardClaimsEnabled = true; public string RewardClaimCycleId = "temporada_001"; public int RewardTop1MinPoints = 300; public string RewardTop1Label = "Recompensa do 1 lugar"; public string RewardTop1Prefab = "Coins"; public int RewardTop1Amount = 500; public int RewardTop2MinPoints = 200; public string RewardTop2Label = "Recompensa do 2 lugar"; public string RewardTop2Prefab = "AmberPearl"; public int RewardTop2Amount = 10; public int RewardTop3MinPoints = 100; public string RewardTop3Label = "Recompensa do 3 lugar"; public string RewardTop3Prefab = "Ruby"; public int RewardTop3Amount = 5; public bool PointsExchangeEnabled = true; public string PointsExchangePrefab = "Coins"; public int PointsExchangeCoinsPerPoint = 1; public int PointsExchangeMinPoints = 1; public int PointsExchangeMaxPointsPerRequest = 0; public Dictionary KillPoints = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary CombatHudCategories = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary ProductionHudCategories = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary BossPoints = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary> SkillMilestoneJackpotPoints = new Dictionary>(StringComparer.OrdinalIgnoreCase); public Dictionary MarketplaceQuestPoints = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary FishingPoints = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary CraftPoints = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary FarmJackpots = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary UniqueCraftJackpots = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary DeathPenaltyRules = new Dictionary(); public Dictionary ExplorationMapJackpots = new Dictionary(); } [HarmonyPatch] internal static class FarmHarvestRankingPatches { [CompilerGenerated] private sealed class d__0 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private Type 5__1; private MethodInfo[] <>s__2; private int <>s__3; private MethodInfo 5__4; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; <>s__2 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00ac; } <>1__state = -1; 5__1 = AccessTools.TypeByName("Pickable"); if (5__1 == null) { return false; } <>s__2 = 5__1.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); <>s__3 = 0; goto IL_00c2; IL_00ac: 5__4 = null; <>s__3++; goto IL_00c2; IL_00c2: if (<>s__3 < <>s__2.Length) { 5__4 = <>s__2[<>s__3]; if (string.Equals(5__4.Name, "Interact", StringComparison.OrdinalIgnoreCase)) { <>2__current = 5__4; <>1__state = 1; return true; } goto IL_00ac; } <>s__2 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [IteratorStateMachine(typeof(d__0))] [HarmonyTargetMethods] private static IEnumerable TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(-2); } [HarmonyPostfix] private static void Postfix(object __instance, object[] __args, object __result) { try { if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && __instance != null && (!(__result is bool) || (bool)__result)) { Player val = ExtractPlayer(__args); if ((!((Object)(object)val != (Object)null) || !((Object)(object)val != (Object)(object)Player.m_localPlayer)) && TryExtractPickableDrop(__instance, out var prefabName, out var amount)) { GlitnirRankingPlugin.Instance.NotifyLocalFarmHarvest(prefabName, amount); } } } catch (Exception ex) { GlitnirRankingPlugin.Log.LogError((object)("Erro no patch de colheita: " + ex)); } } private static Player ExtractPlayer(object[] args) { if (args == null) { return null; } for (int i = 0; i < args.Length; i++) { object obj = args[i]; Player val = (Player)((obj is Player) ? obj : null); if ((Object)(object)val != (Object)null) { return val; } object obj2 = args[i]; Humanoid val2 = (Humanoid)((obj2 is Humanoid) ? obj2 : null); if (val2 is Player) { return (Player)(object)((val2 is Player) ? val2 : null); } } return null; } private static bool TryExtractPickableDrop(object pickable, out string prefabName, out int amount) { prefabName = ""; amount = 1; try { Type type = pickable.GetType(); FieldInfo field = type.GetField("m_itemPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); GameObject val = (GameObject)((field != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null) { return false; } prefabName = ((Object)val).name.Replace("(Clone)", "").Trim(); FieldInfo field2 = type.GetField("m_amount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null && field2.GetValue(pickable) is int) { amount = Mathf.Max(1, (int)field2.GetValue(pickable)); } return !string.IsNullOrWhiteSpace(prefabName); } catch { return false; } } } [HarmonyPatch] internal static class FishingRankingPatches { [CompilerGenerated] private sealed class d__1 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private Type 5__1; private MethodInfo 5__2; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; 5__2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = AccessTools.TypeByName("FishingFloat"); if (5__1 == null) { return false; } 5__2 = AccessTools.Method(5__1, "SetCatch", (Type[])null, (Type[])null); if (5__2 != null) { <>2__current = 5__2; <>1__state = 1; return true; } break; case 1: <>1__state = -1; break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__1(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [HarmonyPrepare] private static bool Prepare() { try { Type type = AccessTools.TypeByName("FishingFloat"); if (type == null) { GlitnirRankingPlugin.Log.LogWarning((object)"[Ranking] Patch de pesca não aplicado: classe FishingFloat não encontrada."); return false; } MethodInfo methodInfo = AccessTools.Method(type, "SetCatch", (Type[])null, (Type[])null); if (methodInfo == null) { GlitnirRankingPlugin.Log.LogWarning((object)"[Ranking] Patch de pesca não aplicado: FishingFloat.SetCatch não encontrado."); return false; } return true; } catch { return false; } } [HarmonyTargetMethods] [IteratorStateMachine(typeof(d__1))] private static IEnumerable TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(-2); } [HarmonyPostfix] private static void Postfix(MethodBase __originalMethod, object __instance, object[] __args) { try { if (!((Object)(object)GlitnirRankingPlugin.Instance == (Object)null)) { string text = ((__originalMethod != null) ? (__originalMethod.Name ?? "") : ""); GameObject val = TryExtractFishGameObject(__instance, __args); if (!((Object)(object)val == (Object)null)) { GlitnirRankingPlugin.Instance.NotifyLocalFishCaught(val.transform, Player.m_localPlayer); } } } catch (Exception ex) { GlitnirRankingPlugin.Log.LogError((object)("Erro no patch FishingFloat de pesca: " + ex)); } } private static GameObject TryExtractFishGameObject(object instance, object[] args) { try { GameObject val = FindGameObjectRecursive(args, 0); if ((Object)(object)val != (Object)null) { return val; } Component val2 = (Component)((instance is Component) ? instance : null); if ((Object)(object)val2 == (Object)null) { return null; } GameObject val3 = FindGameObjectInFields(val2, 0); if ((Object)(object)val3 != (Object)null) { return val3; } Transform transform = val2.transform; if ((Object)(object)transform != (Object)null) { for (int i = 0; i < transform.childCount; i++) { Transform child = transform.GetChild(i); if (!((Object)(object)child == (Object)null) && IsFishObject(((Component)child).gameObject)) { return ((Component)child).gameObject; } } } } catch { } return null; } private static GameObject FindGameObjectRecursive(object value, int depth) { if (value == null || depth > 2) { return null; } if (value is object[] array) { for (int i = 0; i < array.Length; i++) { GameObject val = FindGameObjectRecursive(array[i], depth + 1); if ((Object)(object)val != (Object)null) { return val; } } return null; } GameObject val2 = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val2 != (Object)null && IsFishObject(val2)) { return val2; } Component val3 = (Component)((value is Component) ? value : null); if ((Object)(object)val3 != (Object)null && (Object)(object)val3.gameObject != (Object)null && IsFishObject(val3.gameObject)) { return val3.gameObject; } return null; } private static GameObject FindGameObjectInFields(Component component, int depth) { if ((Object)(object)component == (Object)null || depth > 2) { return null; } Type type = ((object)component).GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo == null) { continue; } string text = fieldInfo.Name ?? ""; if (text.IndexOf("fish", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("catch", StringComparison.OrdinalIgnoreCase) >= 0) { object value = null; try { value = fieldInfo.GetValue(component); } catch { } GameObject val = FindGameObjectRecursive(value, depth + 1); if ((Object)(object)val != (Object)null) { return val; } } } return null; } private static bool IsFishObject(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } string text = ((Object)go).name ?? ""; if (text.StartsWith("Fish", StringComparison.OrdinalIgnoreCase)) { return true; } try { ZNetView component = go.GetComponent(); if ((Object)(object)component != (Object)null && component.GetZDO() != null) { string text2 = (((Object)(object)GlitnirRankingPlugin.Instance != (Object)null) ? GlitnirRankingPlugin.Instance.GetPrefabName(go) : ""); return !string.IsNullOrWhiteSpace(text2) && text2.StartsWith("Fish", StringComparison.OrdinalIgnoreCase); } } catch { } return false; } } } namespace Glitnir.Ranking.Patches { [HarmonyPatch(typeof(InventoryGui), "Update")] public static class Glitnir_AAA_CraftMaterialFix_Update { private static void Postfix() { Glitnir_AAA_CraftMaterialFix_Core.ClampInventoryGui(force: false); } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] public static class Glitnir_AAA_CraftMaterialFix_DoCrafting { private static void Prefix() { Glitnir_AAA_CraftMaterialFix_Core.ClampInventoryGui(force: true); } } [HarmonyPatch] public static class Glitnir_AAA_CraftMaterialFix_RefreshHooks { [CompilerGenerated] private sealed class d__0 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private string[] 5__1; private string[] <>s__2; private int <>s__3; private string 5__4; private MethodInfo 5__5; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; <>s__2 = null; 5__4 = null; 5__5 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00ca; } <>1__state = -1; 5__1 = new string[5] { "UpdateRecipe", "SetRecipe", "SelectRecipe", "UpdateCraftingPanel", "UpdateRecipeList" }; <>s__2 = 5__1; <>s__3 = 0; goto IL_00e7; IL_00ca: 5__5 = null; 5__4 = null; <>s__3++; goto IL_00e7; IL_00e7: if (<>s__3 < <>s__2.Length) { 5__4 = <>s__2[<>s__3]; 5__5 = AccessTools.Method(typeof(InventoryGui), 5__4, (Type[])null, (Type[])null); if (5__5 != null) { <>2__current = 5__5; <>1__state = 1; return true; } goto IL_00ca; } <>s__2 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [IteratorStateMachine(typeof(d__0))] private static IEnumerable TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(-2); } private static void Postfix() { Glitnir_AAA_CraftMaterialFix_Core.MarkDirty(); Glitnir_AAA_CraftMaterialFix_Core.ClampInventoryGui(force: true); } } public static class Glitnir_AAA_CraftMaterialFix_Core { private const int ABSOLUTE_MAX_CRAFT_AMOUNT = 9999; private static float _nextSoftCheck; private static int _lastRecipeHash; private static int _lastStationHash; private static bool _dirty = true; public static void MarkDirty() { _dirty = true; _nextSoftCheck = 0f; } public static void ClampInventoryGui(bool force) { try { if ((Object)(object)InventoryGui.instance == (Object)null || !InventoryGui.IsVisible()) { return; } object obj = GetSelectedRecipe(InventoryGui.instance); object currentCraftingStation = GetCurrentCraftingStation(InventoryGui.instance); int num = obj?.GetHashCode() ?? 0; int num2 = currentCraftingStation?.GetHashCode() ?? 0; if (num != _lastRecipeHash || num2 != _lastStationHash) { _lastRecipeHash = num; _lastStationHash = num2; _dirty = true; force = true; } if (force || _dirty || !(Time.time < _nextSoftCheck)) { _nextSoftCheck = Time.time + 0.05f; _dirty = false; if (obj == null) { obj = GetRecipeFromVisibleCraftButtonOrPanel(((Component)InventoryGui.instance).gameObject); } int maxCraftAmount = Mathf.Clamp(GetMaxCraftAmountSafe(obj), 1, 9999); GameObject gameObject = ((Component)InventoryGui.instance).gameObject; RaiseKnownMaxCraftAmountFields(InventoryGui.instance, maxCraftAmount); UpdateVisibleMaxCraftLabels(gameObject, maxCraftAmount); ClampCraftAmountInputs(gameObject, maxCraftAmount); ClampKnownCraftAmountFields(InventoryGui.instance, maxCraftAmount); } } catch { } } private static void ClampCraftAmountInputs(GameObject root, int maxCraftAmount) { int num = Mathf.Max(1, maxCraftAmount); Component[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && IsInputField(val) && LooksLikeCraftAmountInput(val)) { string text = GetText(val); if (!int.TryParse(text, out var result)) { result = 1; } int num2 = Mathf.Clamp(result, 1, num); if (text != num2.ToString()) { SetText(val, num2.ToString()); InvokeNoArg(val, "ForceLabelUpdate"); InvokeNoArg(val, "UpdateLabel"); } } } } private static void RaiseKnownMaxCraftAmountFields(object inventoryGui, int maxCraftAmount) { int num = Mathf.Clamp(maxCraftAmount, 1, 9999); string[] array = new string[6] { "m_maxCraftAmount", "m_maxCraftingAmount", "m_multiCraftMaxAmount", "m_maxMultiCraftAmount", "m_craftMaxAmount", "m_maxAmount" }; string[] array2 = array; foreach (string name in array2) { object fieldOrProperty = GetFieldOrProperty(inventoryGui, name); if (fieldOrProperty == null) { continue; } try { if (fieldOrProperty is int) { SetFieldOrProperty(inventoryGui, name, num); } else if (fieldOrProperty is float) { SetFieldOrProperty(inventoryGui, name, (float)num); } else if (fieldOrProperty is double) { SetFieldOrProperty(inventoryGui, name, (double)num); } } catch { } } } private static void UpdateVisibleMaxCraftLabels(GameObject root, int maxCraftAmount) { string value = "Max: " + Mathf.Clamp(maxCraftAmount, 1, 9999); Component[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } string text = GetText(val); if (!string.IsNullOrEmpty(text)) { string text2 = text.Trim(); if (text2.StartsWith("Max:", StringComparison.OrdinalIgnoreCase)) { SetText(val, value); InvokeNoArg(val, "ForceLabelUpdate"); InvokeNoArg(val, "UpdateLabel"); } } } } private static void ClampKnownCraftAmountFields(object inventoryGui, int maxCraftAmount) { int num = Mathf.Max(1, maxCraftAmount); string[] array = new string[5] { "m_craftAmount", "m_multiCraftAmount", "m_multiCraftingAmount", "m_selectedAmount", "m_amount" }; string[] array2 = array; foreach (string name in array2) { object fieldOrProperty = GetFieldOrProperty(inventoryGui, name); if (fieldOrProperty != null && int.TryParse(fieldOrProperty.ToString(), out var result)) { int num2 = Mathf.Clamp(result, 1, num); if (num2 != result) { SetFieldOrProperty(inventoryGui, name, num2); } } } } private static bool LooksLikeCraftAmountInput(Component component) { string text = GetText(component); if (!int.TryParse(text, out var _)) { return false; } Transform parent = component.transform.parent; if ((Object)(object)parent == (Object)null) { return false; } bool flag = false; bool flag2 = false; Button[] componentsInChildren = ((Component)parent).GetComponentsInChildren