Decompiled source of Progress Editor v1.0.0
BepInEx/plugins/ProgressEditor/ProgressEditor.dll
Decompiled 21 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Logging; using CG.Client.PlayerData; using CG.Client.UserData; using CG.Cloud; using CG.Game; using CG.Network; using CG.Profile; using Client.Player.Interactions; using ExitGames.Client.Photon; using Gameplay.Perks; using HarmonyLib; using Newtonsoft.Json; using Photon.Pun; using Photon.Realtime; using ResourceAssets; using UI.Core; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UIElements; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace VoidCrewProgressEditor; internal static class ProfileUIRefresh { private const BindingFlags Members = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly HashSet<string> reportedErrors = new HashSet<string>(); internal static void RefreshCosmetics(ManualLogSource log) { ForSceneObjects("AchievementsUIController", log, delegate(object controller) { if (Field(controller, "tabHeader") != null) { Invoke(controller, "UpdateAllEntries", null); Invoke(controller, "UpdateUnclaimed", null); Invoke(controller, "SortEntries", null); } }); ForSceneObjects("UI.PersonalLoadout.PersonalLoadoutTerminal", log, delegate(object terminal) { if (Field(terminal, "root") != null && Field(terminal, "selectionPanel") != null) { MethodInfo method = terminal.GetType().GetMethod("UpdateUnseen", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method != null) { method.Invoke(terminal, null); } object obj = Field(terminal, "shownCategory"); if (obj != null) { Invoke(terminal, "SelectedCategory", new object[2] { obj, Field(terminal, "selectedMultiSlotIndex") }); } } }); } internal static void RefreshShips(ManualLogSource log) { ForSceneObjects("UI.ShipLoadoutTerminal.ShipLoadoutTerminal", log, delegate(object terminal) { object obj = Field(terminal, "loadoutList"); if (Field(terminal, "root") != null && obj != null) { if ((bool)Field(obj, "IgnoreRankRequirements")) { Invoke(obj, "RefreshLoadouts", null); } else { ShipLoadoutDataContainer instance = ResourceAssetContainer<ShipLoadoutDataContainer, ShipLoadoutData, ShipLoadoutDataDef>.Instance; if (!((Object)(object)instance == (Object)null)) { List<ShipLoadoutDataDef> list = new List<ShipLoadoutDataDef>(); list.AddRange(instance.GetUnlockedShipDefinitionsFromHighestRankPlayer()); list.AddRange(instance.GetLockedShipDefinitionsFromHighestRankPlayer()); if (list.Count != 0) { object value = obj.GetType().GetProperty("ShipListed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(obj, null); Invoke(obj, "SetLoadouts", new object[2] { list, value }); } } } } }); } internal static void NotifyPlayerProperties(ManualLogSource log) { Attempt("player rank properties", log, delegate { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown PlayerProfile instance = PlayerProfile.Instance; if (instance != null && PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) { Hashtable val = new Hashtable(); ((Dictionary<object, object>)(object)val).Add((object)"RP_PR", (object)instance.Profile.Rank); ((Dictionary<object, object>)(object)val).Add((object)"RP_FR", (object)instance.Profile.FavorRank); PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } }); } internal static void Refresh(ManualLogSource log) { if (PlayerProfile.Instance == null) { return; } Attempt("rank event", log, delegate { if ((Object)(object)ClientGame.Current != (Object)null) { ClientGame.Current.ModelEventBus.OnRankChanged.Publish(); } }); RefreshShips(log); RefreshBars("TitleMenu", "_expBar", null, log); RefreshBars("EscapeMenu", "expBar", null, log); RefreshBars("UI.PersonalLoadout.PersonalLoadoutTerminal", "expBar", "rankingOverview", log); ForSceneObjects("RankingPanel", log, delegate(object panel) { object obj = Field(panel, "root"); VisualElement val = (VisualElement)((obj is VisualElement) ? obj : null); if (val != null && Field(panel, "leftPanel") != null && Field(panel, "rightPanel") != null) { List<VisualElement> list = Field(panel, "rankEntries") as List<VisualElement>; int rank = PlayerProfile.Instance.Profile.Rank; if (list != null) { for (int i = 0; i < list.Count; i++) { list[i].RemoveFromClassList("rank__past"); list[i].RemoveFromClassList("rank__current"); list[i].RemoveFromClassList("rank__future"); list[i].AddToClassList((i < rank) ? "rank__past" : ((i == rank) ? "rank__current" : "rank__future")); } } object[] args = new object[1]; Invoke(panel, "Enter", args); } }); RefreshBars("RankingPanel", "expBar", "root", log); ForSceneObjects("UI.Token.TokenTerminal", log, delegate(object terminal) { if (Field(terminal, "mainLabel") != null) { Invoke(terminal, "UpdateLeftSide", null); Invoke(terminal, "UpdateTrees", null); } }); } private static void RefreshBars(string type, string barField, string rootField, ManualLogSource log) { ForSceneObjects(type, log, delegate(object owner) { object obj = Field(owner, barField); if (obj != null && (rootField == null || Field(owner, rootField) != null) && (rootField != null || Field(obj, "rankDisplay") != null)) { Invoke(owner, "UpdateXpBar", null); Invoke(obj, "SkipToEndSequence", null); } }); } private static object Field(object owner, string name) { FieldInfo field = owner.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { throw new MissingFieldException(owner.GetType().FullName, name); } return field.GetValue(owner); } private static void Invoke(object owner, string name, object[] args) { MethodInfo method = owner.GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { throw new MissingMethodException(owner.GetType().FullName, name); } method.Invoke(owner, args); } private static void ForSceneObjects(string typeName, ManualLogSource log, Action<object> action) { //IL_00a5: 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) Type type = typeof(PlayerProfile).Assembly.GetType(typeName); if (type == null) { Attempt(typeName, log, delegate { throw new TypeLoadException(typeName); }); return; } Object[] array = Resources.FindObjectsOfTypeAll(type); foreach (Object item in array) { Object obj = item; Component val = (Component)(object)((obj is Component) ? obj : null); if ((Object)(object)val == (Object)null) { continue; } Scene scene = val.gameObject.scene; if (((Scene)(ref scene)).IsValid()) { Attempt(typeName, log, delegate { action(item); }); } } } private static void Attempt(string label, ManualLogSource log, Action action) { try { action(); } catch (Exception ex) { Exception ex2 = ((ex is TargetInvocationException && ex.InnerException != null) ? ex.InnerException : ex); string item = label + ": " + ex2.Message; if (reportedErrors.Add(item)) { log.LogWarning((object)("Profile UI refresh skipped " + label + ": " + ex2)); } } } } [BepInProcess("Void Crew.exe")] [BepInPlugin("local.VoidCrewProgressEditor", "Progress Editor", "1.0.0")] public sealed class ProgressEditor : BaseUnityPlugin { internal string xp = ""; internal string rank = ""; internal string favor = ""; internal string status = ""; private ProgressUndoHistory progressHistory; private string lastError; private float refreshAt = -1f; private long favorSliderMaximum = 100L; private Channel rankChangedChannel; private bool rankReloadPending; private PlayerProfileData lastLoadedProfile; private long lastLoadedXp; private int lastLoadedRank; private int lastLoadedFavor; private PluginUnlockLedger pluginUnlocks; internal bool HasProgressUndo { get { try { return progressHistory != null && progressHistory.Peek(PlayerProfile.GetPlayerUniqueID()) != null; } catch { return false; } } } internal long FavorSliderMaximum { get { if (int.TryParse(favor, out var result)) { favorSliderMaximum = Math.Max(favorSliderMaximum, result); } return favorSliderMaximum; } } private void Awake() { ((MonoBehaviour)this).useGUILayout = false; try { pluginUnlocks = new PluginUnlockLedger(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); } try { progressHistory = new ProgressUndoHistory(Path.Combine(Paths.ConfigPath, "ProgressEditor-rank-history.json")); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)ex2); } SteamAwardGuard.Install(((BaseUnityPlugin)this).Logger); try { PauseProgressScreen.Install(this); } catch (Exception ex3) { ((BaseUnityPlugin)this).Logger.LogError((object)("Pause menu integration failed: " + ex3)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Progress Editor initialized. Use Edit Progress in the main or pause menu."); } private void ReportError(Exception ex) { status = "Editor error: " + ex.Message + " (see BepInEx log)."; string text = ex.ToString(); if (lastError != text) { ((BaseUnityPlugin)this).Logger.LogError((object)text); lastError = text; } } internal void NativeLog(string text) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); } internal void NativeError(Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); } internal void OpenNativeEditor() { try { Reload(); } catch (Exception ex) { ReportError(ex); } } private void Update() { BindRankChangedEvent(); if (refreshAt >= 0f && Time.unscaledTime >= refreshAt) { refreshAt = -1f; ProfileUIRefresh.Refresh(((BaseUnityPlugin)this).Logger); } if (rankReloadPending) { rankReloadPending = false; ProfileUIRefresh.RefreshShips(((BaseUnityPlugin)this).Logger); try { if (TryProfile(out var _, out var data) && (!object.ReferenceEquals(data, lastLoadedProfile) || data.Xp != lastLoadedXp || data.Rank != lastLoadedRank || data.FavorRank != lastLoadedFavor)) { Reload(); } } catch (Exception ex) { ReportError(ex); } } PauseProgressScreen.UpdateOpenScreens(); } private void BindRankChangedEvent() { ClientGame current = ClientGame.Current; Channel objA = (((Object)(object)current != (Object)null && (Object)(object)current.ModelEventBus != (Object)null) ? current.ModelEventBus.OnRankChanged : null); if (!object.ReferenceEquals(objA, rankChangedChannel)) { UnbindRankChangedEvent(); rankChangedChannel = objA; if (rankChangedChannel != null) { rankChangedChannel.Subscribe((Action)OnProfileRankChanged, (AutoUnsubscribeCollection)null); rankReloadPending = true; } } } private void OnProfileRankChanged() { rankReloadPending = true; } private void UnbindRankChangedEvent() { if (rankChangedChannel != null) { rankChangedChannel.Unsubscribe((Action)OnProfileRankChanged); } rankChangedChannel = null; } private void OnDisable() { UnbindRankChangedEvent(); } private void OnDestroy() { UnbindRankChangedEvent(); } private bool TryProfile(out CloudPlayerProfileDataSync cloud, out PlayerProfileData data) { cloud = null; data = null; PlayerProfile instance = PlayerProfile.Instance; if (instance == null) { return false; } IPlayerProfileData profile = instance.Profile; cloud = (CloudPlayerProfileDataSync)(object)((profile is CloudPlayerProfileDataSync) ? profile : null); object source = GetSource(cloud); PhotonPlayerDataSync wrapper = (PhotonPlayerDataSync)((source is PhotonPlayerDataSync) ? source : null); object source2 = GetSource(wrapper); data = (PlayerProfileData)((source2 is PlayerProfileData) ? source2 : null); return data != null; } private static object GetSource(object wrapper) { if (wrapper == null) { return null; } Type type = wrapper.GetType(); while (type != null) { PropertyInfo property = type.GetProperty("source", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(wrapper, null); } type = type.BaseType; } return null; } private void Reload() { if (!TryProfile(out var _, out var data)) { status = "Profile unavailable. Load your profile first."; return; } xp = data.Xp.ToString(CultureInfo.InvariantCulture); rank = data.Rank.ToString(CultureInfo.InvariantCulture); favor = data.FavorRank.ToString(CultureInfo.InvariantCulture); favorSliderMaximum = Math.Max(100, data.FavorRank); lastLoadedProfile = data; lastLoadedXp = data.Xp; lastLoadedRank = data.Rank; lastLoadedFavor = data.FavorRank; status = "Values loaded from your profile."; } internal bool IsCosmeticCategoryEnabled(string category) { try { return pluginUnlocks != null && pluginUnlocks.IsEnabled(category); } catch { return false; } } internal void SetCosmeticCategory(string category, bool enabled) { try { if (category != "Lootbox" && category != "Seasonal" && category != "Achievement") { throw new ArgumentException("Unknown cosmetic category."); } if (pluginUnlocks == null) { throw new InvalidOperationException("Plugin unlock ledger is unavailable."); } pluginUnlocks.SetEnabled(category, enabled); RefreshProfileDisplays(); ProfileUIRefresh.RefreshCosmetics(((BaseUnityPlugin)this).Logger); status = (enabled ? (category + " cosmetics enabled.") : (category + " plugin unlocks removed; previous ownership and achievement state restored.")); ((BaseUnityPlugin)this).Logger.LogInfo((object)status); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); status = "Cosmetic change failed: " + ex.Message; } } internal static bool TryGetMaximumXp(string rankText, out long maximum) { maximum = 0L; if (!int.TryParse(rankText, NumberStyles.None, CultureInfo.InvariantCulture, out var result) || result > 30) { return false; } PlayerRanksTable instance = PlayerRanksTable.Instance; if ((Object)(object)instance == (Object)null) { return false; } if (result == 30) { maximum = instance.FavorXpPerRank; } else { if (instance.titles == null || instance.titles.Length <= result + 1 || instance.titles[result + 1] == null) { return false; } maximum = instance.titles[result + 1].rankExp; } return maximum > 0; } internal void Apply() { if (!long.TryParse(xp, NumberStyles.None, CultureInfo.InvariantCulture, out var result) || !int.TryParse(rank, NumberStyles.None, CultureInfo.InvariantCulture, out var result2) || !int.TryParse(favor, NumberStyles.None, CultureInfo.InvariantCulture, out var result3)) { status = "Use non-negative whole numbers within the field's integer range."; return; } if (result2 > 30) { status = "Rank must be between 0 and 30; nothing changed."; return; } string text = ProgressValidation.ValidateFavor(result2, result3); if (text != null) { status = text; return; } PlayerRanksTable instance = PlayerRanksTable.Instance; if ((Object)(object)instance == (Object)null || (result2 < 30 && (instance.titles == null || instance.titles.Length <= result2 + 1 || instance.titles[result2 + 1] == null))) { status = "The game's XP thresholds are not loaded; nothing changed."; return; } long maximumXp = ((result2 == 30) ? instance.FavorXpPerRank : instance.titles[result2 + 1].rankExp); string text2 = ProgressValidation.Validate(result, result2, maximumXp); if (text2 != null) { status = text2; return; } if (!TryProfile(out var cloud, out var data)) { status = "Profile unavailable; nothing changed."; return; } if (data.Xp == result && data.Rank == result2 && data.FavorRank == result3) { status = "No values changed."; return; } try { GeneSnapshot geneSnapshot = GeneSnapshot.Capture(); GenePlan genePlan = ((result2 < data.Rank) ? new GenePlan(geneSnapshot) : null); if (progressHistory == null) { throw new InvalidOperationException("Rank undo history is unavailable; edit cancelled."); } int num = Math.Max(0, data.Rank - result2); progressHistory.Push(PlayerProfile.GetPlayerUniqueID(), new ProgressUndoEntry { savedUtc = DateTime.UtcNow.ToString("o"), xp = data.Xp, rank = data.Rank, favor = data.FavorRank, loadouts = geneSnapshot.SaveLevels() }); SetValues(cloud, data, result, result2, result3, publish: false); string text3 = ""; if (num > 0) { List<int> removed; List<Dictionary<PerkBuff, int>> target = genePlan.Reduce(geneSnapshot, num, out removed); geneSnapshot.Commit(target); for (int i = 0; i < removed.Count; i++) { string text4 = "Loadout " + (i + 1) + ": removed " + removed[i] + "/" + num + " gene points. "; text3 += text4; ((BaseUnityPlugin)this).Logger.LogInfo((object)text4); } } RefreshProfileDisplays(); Reload(); status = "Applied. " + text3; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); status = "Edit failed or sync incomplete. Reload to inspect; undo is available if values changed."; } } internal void Undo() { if (!TryProfile(out var cloud, out var data)) { status = "Profile unavailable; undo was not applied."; return; } try { if (progressHistory == null) { throw new InvalidOperationException("Rank undo history is unavailable."); } string playerUniqueID = PlayerProfile.GetPlayerUniqueID(); ProgressUndoEntry progressUndoEntry = progressHistory.Peek(playerUniqueID); if (progressUndoEntry == null) { status = "No saved rank edits to undo."; return; } GeneSnapshot geneSnapshot = GeneSnapshot.Capture(); List<Dictionary<PerkBuff, int>> target = geneSnapshot.ResolveLevels(progressUndoEntry.loadouts); SetValues(cloud, data, progressUndoEntry.xp, progressUndoEntry.rank, progressUndoEntry.favor, publish: false); geneSnapshot.Commit(target); progressHistory.Pop(playerUniqueID, progressUndoEntry); RefreshProfileDisplays(); Reload(); status = "Restored rank, XP, favor rank, and saved gene loadouts from history."; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); status = "Undo failed or sync incomplete; the history entry was retained if restoration did not finish."; } } private static void SetValues(CloudPlayerProfileDataSync cloud, PlayerProfileData data, long newXp, int newRank, int newFavor, bool publish) { data.Xp = newXp; data.Rank = newRank; data.FavorRank = newFavor; cloud.AddXp(0L); if (publish) { PublishRankChanged(); } } private void RefreshProfileDisplays() { ProfileUIRefresh.NotifyPlayerProperties(((BaseUnityPlugin)this).Logger); ProfileUIRefresh.Refresh(((BaseUnityPlugin)this).Logger); refreshAt = Time.unscaledTime + 0.25f; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Refreshed profile displays; one follow-up refresh scheduled."); } private static void PublishRankChanged() { if (GameSessionManager.ActiveSession != null && (Object)(object)ClientGame.Current != (Object)null) { ClientGame.Current.ModelEventBus.OnRankChanged.Publish(); } } } internal sealed class CosmeticPlan { internal readonly Dictionary<GUIDUnion, IResourceAssetContainer> Items = new Dictionary<GUIDUnion, IResourceAssetContainer>(); internal readonly HashSet<GUIDUnion> Achievements = new HashSet<GUIDUnion>(); private static bool IsCosmetic(IUnlockableDataContainer owner) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected I4, but got Unknown EUnlockCategory category = owner.Category; switch (category - 9) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 12: return true; default: return false; } } internal CosmeticPlan(string category) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0147: 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_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_0428: 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_02d9: Invalid comparison between Unknown and I4 //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: 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_03b6: Invalid comparison between Unknown and I4 //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Invalid comparison between Unknown and I4 //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Invalid comparison between Unknown and I4 //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) GUIDUnion val = GUIDUnion.Empty(); if (category == "Hunter") { HashSet<GUIDUnion> hashSet = new HashSet<GUIDUnion>(); List<AchievementDef> list = new List<AchievementDef>(((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).AssetDescriptions); if (((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).RuntimeDescriptions != null) { list.AddRange(((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).RuntimeDescriptions); } foreach (AchievementDef item in list) { IResourceAssetContextInfo contextInfo = item.ContextInfo; ContextInfo val2 = (ContextInfo)(object)((contextInfo is ContextInfo) ? contextInfo : null); string text = (((Object)(object)val2 == (Object)null || val2.HeaderDefaultableLocalizedString == null) ? "" : val2.HeaderDefaultableLocalizedString.FallBackString); string text2 = Regex.Replace((text + " " + (((Object)(object)val2 == (Object)null) ? "" : val2.HeaderText) + " " + ((ResourceAssetDef<Achievement>)(object)item).Path + " " + ((ResourceAssetDef<Achievement>)(object)item).Asset.AchievementID).ToLowerInvariant(), "[^a-z0-9]", ""); if (text2.Contains("hunterofhollow") || text2.Contains("hunterofthehollow")) { hashSet.Add(((ResourceAssetDef<Achievement>)(object)item).AssetGuid); } } if (hashSet.Count != 1) { throw new InvalidOperationException("Hunter of Hollow could not be identified uniquely; nothing unlocked."); } foreach (GUIDUnion item2 in hashSet) { val = item2; } Achievements.Add(val); } ResourceAssetContainerRegister instance = ResourceAssetContainerRegister.Instance; UnlockContainer instance2 = ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>.Instance; RewardPoolContainer instance3 = ResourceAssetContainer<RewardPoolContainer, RewardPool, RewardPoolDef>.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)instance3 == (Object)null) { throw new InvalidOperationException("Cosmetic definitions are not loaded."); } HashSet<GUIDUnion> hashSet2 = new HashSet<GUIDUnion>(); HashSet<GUIDUnion> hashSet3 = new HashSet<GUIDUnion>(); HashSet<GUIDUnion> hashSet4 = new HashSet<GUIDUnion>(); List<RewardPoolDef> list2 = new List<RewardPoolDef>(((ResourceAssetContainer<RewardPoolContainer, RewardPool, RewardPoolDef>)(object)instance3).AssetDescriptions); if (((ResourceAssetContainer<RewardPoolContainer, RewardPool, RewardPoolDef>)(object)instance3).RuntimeDescriptions != null) { list2.AddRange(((ResourceAssetContainer<RewardPoolContainer, RewardPool, RewardPoolDef>)(object)instance3).RuntimeDescriptions); } if (category == "Lootbox" || category == "Seasonal") { foreach (RewardPoolDef item3 in list2) { RewardPool asset = ((ResourceAssetDef<RewardPool>)(object)item3).Asset; if ((Object)(object)asset == (Object)null || asset.Rewards == null) { throw new InvalidOperationException("A reward pool could not be read."); } foreach (UnlockItemRef reward in asset.Rewards) { hashSet4.Add(((ResourceAssetRef)reward).AssetGuid); if ((int)item3.category == 0) { hashSet2.Add(((ResourceAssetRef)reward).AssetGuid); } if ((int)item3.category == 1 || (int)item3.category == 2) { hashSet3.Add(((ResourceAssetRef)reward).AssetGuid); } } } } List<UnlockItemDef> list3 = new List<UnlockItemDef>(((ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>)(object)instance2).AssetDescriptions); if (((ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>)(object)instance2).RuntimeDescriptions != null) { list3.AddRange(((ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>)(object)instance2).RuntimeDescriptions); } foreach (UnlockItemDef item4 in list3) { IUnlockableDataContainer val3 = instance.FindOwner(((ResourceAssetDef<Object>)(object)item4).AssetGuid); if (val3 == null || !IsCosmetic(val3)) { continue; } UnlockOptions unlockOptions = item4.UnlockOptions; bool num; if (!(category == "Seasonal")) { if (!(category == "Lootbox")) { if ((int)unlockOptions.UnlockCriteria != 6) { continue; } if (!(category != "Hunter")) { if (!((ResourceAssetRef)(object)unlockOptions.RequiredAchievement != (ResourceAssetRef)null)) { continue; } num = ((ResourceAssetRef)unlockOptions.RequiredAchievement).AssetGuid == val; goto IL_0432; } } else if (!hashSet2.Contains(((ResourceAssetDef<Object>)(object)item4).AssetGuid)) { if ((int)unlockOptions.UnlockCriteria != 4) { continue; } num = !hashSet4.Contains(((ResourceAssetDef<Object>)(object)item4).AssetGuid); goto IL_0432; } goto IL_0438; } num = hashSet3.Contains(((ResourceAssetDef<Object>)(object)item4).AssetGuid); goto IL_0432; IL_0438: Items[((ResourceAssetDef<Object>)(object)item4).AssetGuid] = (IResourceAssetContainer)(object)val3; if (category == "Achievement" || category == "Hunter") { AchievementRef requiredAchievement = unlockOptions.RequiredAchievement; if ((ResourceAssetRef)(object)requiredAchievement == (ResourceAssetRef)null || (Object)(object)((ResourceAssetRef<AchievementContainer, Achievement, AchievementDef>)(object)requiredAchievement).Asset == (Object)null) { throw new InvalidOperationException("A cosmetic achievement definition could not be read."); } Achievements.Add(((ResourceAssetRef)requiredAchievement).AssetGuid); } continue; IL_0432: if (!num) { continue; } goto IL_0438; } } } [Serializable] public sealed class PluginItemRecord { public string id; public bool unseen; public List<string> categories = new List<string>(); } [Serializable] public sealed class PluginAchievementRecord { public string id; public string steamId; public string metricId; public List<string> categories = new List<string>(); public bool completed; public bool claimed; public bool metricExisted; public int metricProgress; public int liveProgress; } [Serializable] public sealed class PluginUnlockData { public string account; public int categorySchema; public List<string> enabledCategories = new List<string>(); public List<PluginItemRecord> items = new List<PluginItemRecord>(); public List<PluginAchievementRecord> achievements = new List<PluginAchievementRecord>(); } internal sealed class PluginUnlockLedger { private readonly string path = Path.Combine(Paths.ConfigPath, "ProgressEditor-plugin-unlocks.json"); internal PluginUnlockData Data = new PluginUnlockData(); internal bool HasChanges { get { if (Data.items.Count <= 0) { return Data.achievements.Count > 0; } return true; } } internal PluginUnlockLedger() { if (File.Exists(path)) { Data = JsonUtility.FromJson<PluginUnlockData>(File.ReadAllText(path)); if (Data == null || Data.items == null || Data.achievements == null) { throw new InvalidOperationException("Plugin unlock ledger is invalid; unlock actions disabled."); } } SteamAwardGuard.Ledger = this; } internal void CheckAccount() { string playerUniqueID = PlayerProfile.GetPlayerUniqueID(); if (string.IsNullOrEmpty(playerUniqueID)) { throw new InvalidOperationException("Player account is not ready."); } if (HasChanges && Data.account != playerUniqueID) { throw new InvalidOperationException("The unlock ledger belongs to another account."); } if (!HasChanges && !string.IsNullOrEmpty(Data.account) && Data.account != playerUniqueID) { Data.enabledCategories = new List<string>(); Data.categorySchema = 1; } Data.account = playerUniqueID; } internal void Save() { string sourceFileName = path + ".tmp"; File.WriteAllText(sourceFileName, JsonUtility.ToJson((object)Data, true)); if (File.Exists(path)) { File.Replace(sourceFileName, path, path + ".bak"); } else { File.Move(sourceFileName, path); } } internal void PrepareCategories() { //IL_012b: 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) CheckAccount(); if (Data.enabledCategories == null) { Data.enabledCategories = new List<string>(); } foreach (PluginItemRecord item in Data.items) { if (item.categories == null) { item.categories = new List<string>(); } } foreach (PluginAchievementRecord achievement in Data.achievements) { if (achievement.categories == null) { achievement.categories = new List<string>(); } } if (Data.categorySchema >= 1) { return; } string[] array = new string[3] { "Lootbox", "Seasonal", "Achievement" }; foreach (string text in array) { CosmeticPlan cosmeticPlan = new CosmeticPlan(text); bool flag = false; foreach (PluginItemRecord item2 in Data.items) { if (cosmeticPlan.Items.ContainsKey(new GUIDUnion(item2.id))) { if (!item2.categories.Contains(text)) { item2.categories.Add(text); } flag = true; } } foreach (PluginAchievementRecord achievement2 in Data.achievements) { if (cosmeticPlan.Achievements.Contains(new GUIDUnion(achievement2.id))) { if (!achievement2.categories.Contains(text)) { achievement2.categories.Add(text); } flag = true; } } if (flag && !Data.enabledCategories.Contains(text)) { Data.enabledCategories.Add(text); } } Data.categorySchema = 1; Save(); } internal bool IsEnabled(string category) { PrepareCategories(); return Data.enabledCategories.Contains(category); } internal void SetEnabled(string category, bool enabled) { PrepareCategories(); if (enabled) { Apply(new CosmeticPlan(category), category); return; } List<PluginItemRecord> items = Data.items.FindAll((PluginItemRecord r) => r.categories.Contains(category) && r.categories.Count == 1); List<PluginAchievementRecord> achievements = Data.achievements.FindAll((PluginAchievementRecord r) => r.categories.Contains(category) && r.categories.Count == 1); UndoRecords(items, achievements); foreach (PluginItemRecord item in Data.items) { item.categories.Remove(category); } foreach (PluginAchievementRecord achievement in Data.achievements) { achievement.categories.Remove(category); } Data.enabledCategories.Remove(category); Save(); } internal void Apply(CosmeticPlan plan, string category) { //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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0157: 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_0187: 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_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Invalid comparison between Unknown and I4 //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0283: 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_044a: Unknown result type (might be due to invalid IL or missing references) //IL_044f: Unknown result type (might be due to invalid IL or missing references) //IL_0480: 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_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_051b: 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_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0555: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Unknown result type (might be due to invalid IL or missing references) //IL_05bd: Unknown result type (might be due to invalid IL or missing references) CheckAccount(); PlayerProfile instance = PlayerProfile.Instance; if (plan.Achievements.Count > 0 && !SteamAwardGuard.Ready) { throw new InvalidOperationException("Steam-award guard is unavailable; achievement unlock cancelled."); } foreach (GUIDUnion id in plan.Achievements) { List<PluginAchievementRecord> achievements = Data.achievements; Predicate<PluginAchievementRecord> match = delegate(PluginAchievementRecord r) { //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) string id2 = r.id; GUIDUnion val2 = id; return id2 == ((GUIDUnion)(ref val2)).AsHex(); }; if (achievements.Exists(match)) { PluginAchievementRecord pluginAchievementRecord = Data.achievements.Find(delegate(PluginAchievementRecord r) { //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) string id2 = r.id; GUIDUnion val2 = id; return id2 == ((GUIDUnion)(ref val2)).AsHex(); }); if (!pluginAchievementRecord.categories.Contains(category)) { pluginAchievementRecord.categories.Add(category); } } else { if (instance.Achievements.IsCompleted(id) && instance.Achievements.IsClaimed(id)) { continue; } Achievement asset = ((ResourceAssetDef<Achievement>)(object)((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).GetAssetDefById(id, true)).Asset; PluginAchievementRecord pluginAchievementRecord2 = new PluginAchievementRecord(); GUIDUnion val = id; pluginAchievementRecord2.id = ((GUIDUnion)(ref val)).AsHex(); pluginAchievementRecord2.steamId = asset.AchievementID; pluginAchievementRecord2.completed = instance.Achievements.IsCompleted(id); pluginAchievementRecord2.claimed = instance.Achievements.IsClaimed(id); PluginAchievementRecord record = pluginAchievementRecord2; if ((int)asset.Source == 0 && asset.LocalMetric != null) { record.liveProgress = asset.LocalMetric.Progress; foreach (PluginAchievementRecord achievement in Data.achievements) { Achievement asset2 = ((ResourceAssetDef<Achievement>)(object)((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).GetAssetDefById(new GUIDUnion(achievement.id), true)).Asset; if ((int)asset2.Source == 0 && asset2.LocalMetric == asset.LocalMetric) { record.liveProgress = achievement.liveProgress; break; } } } if ((int)asset.Source == 1 && (ResourceAssetRef)(object)asset.ExternalMetric != (ResourceAssetRef)null) { GUIDUnion assetGuid = ((ResourceAssetRef)asset.ExternalMetric).AssetGuid; record.metricId = ((GUIDUnion)(ref assetGuid)).AsHex(); record.metricExisted = instance.Metrics.TrackedMetricProgress.TryGetValue(assetGuid, out record.metricProgress); if ((Object)(object)((ResourceAssetRef<TrackedMetricContainer, TrackedMetric, TrackedMetricDef>)(object)asset.ExternalMetric).Asset != (Object)null && ((ResourceAssetRef<TrackedMetricContainer, TrackedMetric, TrackedMetricDef>)(object)asset.ExternalMetric).Asset.Metric != null) { record.liveProgress = ((ResourceAssetRef<TrackedMetricContainer, TrackedMetric, TrackedMetricDef>)(object)asset.ExternalMetric).Asset.Metric.Progress; } PluginAchievementRecord pluginAchievementRecord3 = Data.achievements.Find((PluginAchievementRecord r) => r.metricId == record.metricId); if (pluginAchievementRecord3 != null) { record.metricProgress = pluginAchievementRecord3.metricProgress; record.metricExisted = pluginAchievementRecord3.metricExisted; record.liveProgress = pluginAchievementRecord3.liveProgress; } } record.categories.Add(category); Data.achievements.Add(record); } } foreach (KeyValuePair<GUIDUnion, IResourceAssetContainer> item in plan.Items) { List<PluginItemRecord> items = Data.items; Predicate<PluginItemRecord> match2 = delegate(PluginItemRecord r) { //IL_000f: 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) string id2 = r.id; KeyValuePair<GUIDUnion, IResourceAssetContainer> keyValuePair6 = item; GUIDUnion key2 = keyValuePair6.Key; return id2 == ((GUIDUnion)(ref key2)).AsHex(); }; PluginItemRecord pluginItemRecord = items.Find(match2); if (pluginItemRecord != null) { if (!pluginItemRecord.categories.Contains(category)) { pluginItemRecord.categories.Add(category); } continue; } ICategorisedCollection unlockedItems = instance.UnlockedItems; KeyValuePair<GUIDUnion, IResourceAssetContainer> keyValuePair = item; IReadOnlyList<GUIDUnion> itemsInCategory = unlockedItems.GetItemsInCategory(keyValuePair.Value, true); KeyValuePair<GUIDUnion, IResourceAssetContainer> keyValuePair2 = item; if (!itemsInCategory.Contains(keyValuePair2.Key)) { PluginItemRecord pluginItemRecord2 = new PluginItemRecord(); KeyValuePair<GUIDUnion, IResourceAssetContainer> keyValuePair3 = item; GUIDUnion key = keyValuePair3.Key; pluginItemRecord2.id = ((GUIDUnion)(ref key)).AsHex(); ICategorisedCollection unseen = instance.Unseen; KeyValuePair<GUIDUnion, IResourceAssetContainer> keyValuePair4 = item; IResourceAssetContainer value = keyValuePair4.Value; KeyValuePair<GUIDUnion, IResourceAssetContainer> keyValuePair5 = item; pluginItemRecord2.unseen = unseen.HasItem(value, keyValuePair5.Key); pluginItemRecord = pluginItemRecord2; pluginItemRecord.categories.Add(category); Data.items.Add(pluginItemRecord); } } if (!Data.enabledCategories.Contains(category)) { Data.enabledCategories.Add(category); } Save(); foreach (GUIDUnion achievement2 in plan.Achievements) { if (!instance.Achievements.CompletedAchievements.Contains(achievement2)) { instance.Achievements.CompletedAchievements.Add(achievement2); } if (!instance.Achievements.ClaimedAchievements.Contains(achievement2)) { instance.Achievements.ClaimedAchievements.Add(achievement2); } } foreach (KeyValuePair<GUIDUnion, IResourceAssetContainer> item2 in plan.Items) { if (!instance.UnlockedItems.GetItemsInCategory(item2.Value, true).Contains(item2.Key)) { instance.UnlockedItems.AddItem(item2.Value, item2.Key, true); } } if (plan.Achievements.Count > 0) { CloudProfileWriter.WritePlayerAchievementsProgress(instance.Achievements); CloudProfileWriter.WritePlayerClaimedAchievements(instance.Achievements); } } internal void Undo() { PrepareCategories(); UndoRecords(new List<PluginItemRecord>(Data.items), new List<PluginAchievementRecord>(Data.achievements)); Data.enabledCategories.Clear(); Save(); } private void UndoRecords(List<PluginItemRecord> items, List<PluginAchievementRecord> achievements) { //IL_002f: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: 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_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) CheckAccount(); PlayerProfile instance = PlayerProfile.Instance; Dictionary<string, IResourceAssetContainer> dictionary = new Dictionary<string, IResourceAssetContainer>(); foreach (PluginItemRecord item in items) { IResourceAssetContainer val = (IResourceAssetContainer)(object)ResourceAssetContainerRegister.Instance.FindOwner(new GUIDUnion(item.id)); if (val == null) { throw new InvalidOperationException("A recorded unlock cannot be resolved; undo cancelled."); } dictionary.Add(item.id, val); } foreach (PluginAchievementRecord achievement in achievements) { if ((Object)(object)((ResourceAssetDef<Achievement>)(object)((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).GetAssetDefById(new GUIDUnion(achievement.id), true)).Asset == (Object)null) { throw new InvalidOperationException("A recorded achievement cannot be resolved; undo cancelled."); } } GUIDUnion val2 = default(GUIDUnion); GUIDUnion key = default(GUIDUnion); foreach (PluginAchievementRecord achievement2 in achievements) { ((GUIDUnion)(ref val2))..ctor(achievement2.id); Achievement asset = ((ResourceAssetDef<Achievement>)(object)((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).GetAssetDefById(val2, true)).Asset; SetMembership(instance.Achievements.CompletedAchievements, val2, achievement2.completed); SetMembership(instance.Achievements.ClaimedAchievements, val2, achievement2.claimed); if (MetricStillUsed(achievement2, achievements)) { continue; } if ((int)asset.Source == 0 && asset.LocalMetric != null) { SetMetricWithoutEvents(asset.LocalMetric, achievement2.liveProgress); } if (!string.IsNullOrEmpty(achievement2.metricId)) { ((GUIDUnion)(ref key))..ctor(achievement2.metricId); if (achievement2.metricExisted) { instance.Metrics.TrackedMetricProgress[key] = achievement2.metricProgress; } else { instance.Metrics.TrackedMetricProgress.Remove(key); } if ((Object)(object)((ResourceAssetRef<TrackedMetricContainer, TrackedMetric, TrackedMetricDef>)(object)asset.ExternalMetric).Asset != (Object)null && ((ResourceAssetRef<TrackedMetricContainer, TrackedMetric, TrackedMetricDef>)(object)asset.ExternalMetric).Asset.Metric != null) { SetMetricWithoutEvents(((ResourceAssetRef<TrackedMetricContainer, TrackedMetric, TrackedMetricDef>)(object)asset.ExternalMetric).Asset.Metric, achievement2.liveProgress); } } } GUIDUnion val3 = default(GUIDUnion); foreach (PluginItemRecord item2 in items) { ((GUIDUnion)(ref val3))..ctor(item2.id); instance.UnlockedItems.RemoveItem(dictionary[item2.id], val3); if (item2.unseen) { instance.Unseen.AddItem(dictionary[item2.id], val3, true); } else { instance.Unseen.RemoveItem(dictionary[item2.id], val3); } } CloudProfileWriter.WritePlayerAchievementsProgress(instance.Achievements); CloudProfileWriter.WritePlayerClaimedAchievements(instance.Achievements); instance.Metrics.Save(); foreach (PluginItemRecord item3 in items) { Data.items.Remove(item3); } foreach (PluginAchievementRecord achievement3 in achievements) { Data.achievements.Remove(achievement3); } } private bool MetricStillUsed(PluginAchievementRecord record, List<PluginAchievementRecord> removing) { //IL_000b: 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_0080: 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) Achievement asset = ((ResourceAssetDef<Achievement>)(object)((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).GetAssetDefById(new GUIDUnion(record.id), true)).Asset; foreach (PluginAchievementRecord achievement in Data.achievements) { if (removing.Contains(achievement)) { continue; } if (!string.IsNullOrEmpty(record.metricId) && record.metricId == achievement.metricId) { return true; } if ((int)asset.Source == 0 && asset.LocalMetric != null) { Achievement asset2 = ((ResourceAssetDef<Achievement>)(object)((ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>)(object)ResourceAssetContainer<AchievementContainer, Achievement, AchievementDef>.Instance).GetAssetDefById(new GUIDUnion(achievement.id), true)).Asset; if ((int)asset2.Source == 0 && asset2.LocalMetric == asset.LocalMetric) { return true; } } } return false; } private static void SetMembership(List<GUIDUnion> list, GUIDUnion id, bool present) { //IL_0007: 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) //IL_0012: 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) if (present) { if (!list.Contains(id)) { list.Add(id); } } else { list.RemoveAll((GUIDUnion existing) => existing == id); } } private static void SetMetricWithoutEvents(PlayerMetric metric, int progress) { typeof(PlayerMetric).GetField("progress", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(metric, progress); } } internal static class SteamAwardGuard { internal static PluginUnlockLedger Ledger; internal static bool Ready; private static ManualLogSource logger; internal static void Install(ManualLogSource log) { //IL_0093: 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_00bd: Expected O, but got Unknown logger = log; try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("Steamworks.SteamUserStats"); if (type != null) { break; } } if (type == null) { throw new TypeLoadException("SteamUserStats not loaded"); } MethodInfo method = type.GetMethod("SetAchievement", new Type[1] { typeof(string) }); if (method == null) { throw new MissingMethodException("SteamUserStats.SetAchievement"); } new Harmony("local.VoidCrewProgressEditor.SteamAwardGuard").Patch((MethodBase)method, new HarmonyMethod(typeof(SteamAwardGuard).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Ready = true; log.LogInfo((object)"Steam-award guard installed for plugin-tracked achievements."); } catch (Exception ex) { Ready = false; log.LogError((object)("Steam-award guard failed; achievement unlocks disabled: " + ex)); } } private static bool Prefix(string __0, ref bool __result) { if (Ledger == null || !Ledger.Data.achievements.Exists((PluginAchievementRecord r) => r.steamId == __0)) { return true; } __result = false; if (logger != null) { logger.LogInfo((object)("Blocked Steam achievement award for plugin-tracked achievement: " + __0)); } return false; } } internal sealed class GeneSnapshot { internal IPlayerPerkData Owner; internal List<PerkLoadout> Loadouts; internal List<Dictionary<PerkBuff, int>> Levels; internal static GeneSnapshot Capture() { IPlayerPerkData perks = PlayerProfile.Instance.Perks; if (perks == null || perks.Loadouts == null) { throw new InvalidOperationException("Gene loadouts are not available."); } GeneSnapshot geneSnapshot = new GeneSnapshot(); geneSnapshot.Owner = perks; geneSnapshot.Loadouts = perks.Loadouts; geneSnapshot.Levels = new List<Dictionary<PerkBuff, int>>(); GeneSnapshot geneSnapshot2 = geneSnapshot; foreach (PerkLoadout loadout in geneSnapshot2.Loadouts) { if (loadout == null || loadout.Perks == null) { throw new InvalidOperationException("A gene loadout could not be read."); } geneSnapshot2.Levels.Add(new Dictionary<PerkBuff, int>(loadout.Perks)); } return geneSnapshot2; } internal List<SavedGeneLoadout> SaveLevels() { //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) List<SavedGeneLoadout> list = new List<SavedGeneLoadout>(); foreach (Dictionary<PerkBuff, int> level in Levels) { SavedGeneLoadout savedGeneLoadout = new SavedGeneLoadout(); foreach (KeyValuePair<PerkBuff, int> item in level) { List<SavedGenePoint> points = savedGeneLoadout.points; SavedGenePoint savedGenePoint = new SavedGenePoint(); GUIDUnion containerGuid = ((SelfReferencingScriptableObject)item.Key).ContainerGuid; savedGenePoint.id = ((GUIDUnion)(ref containerGuid)).AsHex(); savedGenePoint.level = item.Value; points.Add(savedGenePoint); } list.Add(savedGeneLoadout); } return list; } internal List<Dictionary<PerkBuff, int>> ResolveLevels(List<SavedGeneLoadout> saved) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) CheckOwner(); if (saved == null || saved.Count != Loadouts.Count) { throw new InvalidOperationException("Saved gene loadout count differs; undo cancelled."); } ResourceAssetContainerRegister instance = ResourceAssetContainerRegister.Instance; ResourceAssetContainer<PerkBuffContainer, PerkBuff, PerkBuffDef> val = (((Object)(object)instance == (Object)null) ? null : instance.GetContainer<PerkBuffContainer, PerkBuff, PerkBuffDef>()); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("Gene definitions are not loaded."); } List<Dictionary<PerkBuff, int>> list = new List<Dictionary<PerkBuff, int>>(); foreach (SavedGeneLoadout item in saved) { Dictionary<PerkBuff, int> dictionary = new Dictionary<PerkBuff, int>(); foreach (SavedGenePoint point in item.points) { PerkBuff val2 = ((ResourceAssetDef<PerkBuff>)(object)val.GetAssetDefById(new GUIDUnion(point.id), true))?.Asset; if ((Object)(object)val2 == (Object)null || point.level < 0 || point.level > val2.Levels.Count || dictionary.ContainsKey(val2)) { throw new InvalidOperationException("A saved gene allocation cannot be restored; undo cancelled."); } dictionary.Add(val2, point.level); } list.Add(dictionary); } return list; } internal void CheckOwner() { if (!object.ReferenceEquals(PlayerProfile.Instance.Perks, Owner) || !object.ReferenceEquals(Owner.Loadouts, Loadouts) || Loadouts.Count != Levels.Count) { throw new InvalidOperationException("Gene loadouts changed since the edit; restoration was not applied."); } } internal void Commit(List<Dictionary<PerkBuff, int>> target) { CheckOwner(); int activeLoudoutIndex = Owner.ActiveLoudoutIndex; if (activeLoudoutIndex < 0 || activeLoudoutIndex >= Loadouts.Count) { throw new InvalidOperationException("Active gene loadout index is invalid."); } List<int> list = new List<int>(); PerkBuff val = null; for (int i = 0; i < target.Count; i++) { Dictionary<PerkBuff, int> perks = Loadouts[i].Perks; bool flag = perks.Count != target[i].Count; foreach (KeyValuePair<PerkBuff, int> item in perks) { if (!target[i].TryGetValue(item.Key, out var value) || value != item.Value) { flag = true; if (i == activeLoudoutIndex) { val = item.Key; } } } if (!flag) { foreach (KeyValuePair<PerkBuff, int> item2 in target[i]) { if (!perks.ContainsKey(item2.Key)) { flag = true; break; } } } if (!flag) { continue; } if (i == activeLoudoutIndex && (Object)(object)val == (Object)null) { using Dictionary<PerkBuff, int>.Enumerator enumerator3 = target[i].GetEnumerator(); if (enumerator3.MoveNext()) { val = enumerator3.Current.Key; } } list.Add(i); } foreach (int item3 in list) { Loadouts[item3].Perks.Clear(); foreach (KeyValuePair<PerkBuff, int> item4 in target[item3]) { Loadouts[item3].Perks.Add(item4.Key, item4.Value); } } foreach (int item5 in list) { CloudProfileWriter.WritePerkLoadout(item5, Loadouts[item5].Perks); } if ((Object)(object)val != (Object)null) { Loadouts[activeLoudoutIndex].Perks.TryGetValue(val, out var value2); Owner.SetPerkBuffLevel(val, value2); } if (list.Count > 0) { TokenTerminalEvents.Instance.OnPerkLoadoutChanged?.Invoke(); } } } internal sealed class GenePlan { private readonly List<PerkBuff> buffs = new List<PerkBuff>(); private readonly Dictionary<PerkBuff, GeneNode> definitions = new Dictionary<PerkBuff, GeneNode>(); internal GenePlan(GeneSnapshot snapshot) { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected I4, but got Unknown ResourceAssetContainerRegister instance = ResourceAssetContainerRegister.Instance; if ((Object)(object)instance == (Object)null) { throw new InvalidOperationException("Gene-tree registry is not loaded."); } ResourceAssetContainer<PerkTreeContainer, PerkTree, PerkTreeDef> container = instance.GetContainer<PerkTreeContainer, PerkTree, PerkTreeDef>(); if ((Object)(object)container == (Object)null) { throw new InvalidOperationException("Gene-tree definitions are not loaded."); } List<PerkTreeDef> list = new List<PerkTreeDef>(container.AssetDescriptions); if (container.RuntimeDescriptions != null) { list.AddRange(container.RuntimeDescriptions); } list.Sort((PerkTreeDef a, PerkTreeDef b) => ((int)a.perkTree).CompareTo((int)b.perkTree)); foreach (PerkTreeDef item in list) { PerkTree asset = ((ResourceAssetDef<PerkTree>)(object)item).Asset; if ((Object)(object)asset == (Object)null || asset.Perks == null) { continue; } foreach (PerkBuffRef perk in asset.Perks) { PerkBuff asset2 = ((ResourceAssetRef<PerkBuffContainer, PerkBuff, PerkBuffDef>)(object)perk).Asset; if (!((Object)(object)asset2 == (Object)null) && !definitions.ContainsKey(asset2)) { definitions.Add(asset2, new GeneNode { Id = buffs.Count, Tree = (int)item.perkTree, Row = asset2.Row, Column = asset2.Column }); buffs.Add(asset2); } } } foreach (Dictionary<PerkBuff, int> level in snapshot.Levels) { foreach (KeyValuePair<PerkBuff, int> item2 in level) { if ((Object)(object)item2.Key == (Object)null || item2.Value < 0 || !definitions.ContainsKey(item2.Key)) { throw new InvalidOperationException("An allocated gene node cannot be mapped to a tree. Edit cancelled."); } } } } internal List<Dictionary<PerkBuff, int>> Reduce(GeneSnapshot snapshot, int decrease, out List<int> removed) { List<Dictionary<PerkBuff, int>> list = new List<Dictionary<PerkBuff, int>>(); removed = new List<int>(); foreach (Dictionary<PerkBuff, int> level in snapshot.Levels) { List<GeneNode> list2 = new List<GeneNode>(); foreach (KeyValuePair<PerkBuff, int> item in level) { GeneNode geneNode = definitions[item.Key].Copy(); geneNode.Points = item.Value; list2.Add(geneNode); } removed.Add(GeneReduction.Remove(list2, decrease)); Dictionary<PerkBuff, int> dictionary = new Dictionary<PerkBuff, int>(); foreach (GeneNode item2 in list2) { if (item2.Points > 0) { dictionary.Add(buffs[item2.Id], item2.Points); } } list.Add(dictionary); } return list; } } public sealed class GeneNode { public int Id; public int Tree; public int Row; public int Column; public int Points; public GeneNode Copy() { return (GeneNode)MemberwiseClone(); } } public static class GeneReduction { public static int Remove(List<GeneNode> nodes, int count) { if (count < 0) { throw new ArgumentOutOfRangeException("count"); } int i; for (i = 0; i < count; i++) { SortedDictionary<int, long> sortedDictionary = new SortedDictionary<int, long>(); foreach (GeneNode node in nodes) { if (node.Points < 0) { throw new InvalidOperationException("Negative gene allocation."); } if (!sortedDictionary.ContainsKey(node.Tree)) { sortedDictionary.Add(node.Tree, 0L); } sortedDictionary[node.Tree] += node.Points; } int num = -1; long num2 = 0L; foreach (KeyValuePair<int, long> item in sortedDictionary) { if (item.Value > num2) { num = item.Key; num2 = item.Value; } } if (num2 == 0) { break; } GeneNode geneNode = null; foreach (GeneNode node2 in nodes) { if (node2.Tree == num && node2.Points != 0 && (geneNode == null || node2.Row > geneNode.Row || (node2.Row == geneNode.Row && node2.Column < geneNode.Column) || (node2.Row == geneNode.Row && node2.Column == geneNode.Column && node2.Id < geneNode.Id))) { geneNode = node2; } } geneNode.Points--; } return i; } } [Serializable] internal sealed class SavedGenePoint { public string id; public int level; } [Serializable] internal sealed class SavedGeneLoadout { public List<SavedGenePoint> points = new List<SavedGenePoint>(); } [Serializable] internal sealed class ProgressUndoEntry { public string savedUtc; public long xp; public int rank; public int favor; public List<SavedGeneLoadout> loadouts = new List<SavedGeneLoadout>(); } [Serializable] internal sealed class ProgressUndoAccount { public string account; public List<ProgressUndoEntry> entries = new List<ProgressUndoEntry>(); } [Serializable] internal sealed class ProgressUndoData { public int schema = 1; public List<ProgressUndoAccount> accounts = new List<ProgressUndoAccount>(); } internal sealed class ProgressUndoHistory { private readonly string path; private readonly ProgressUndoData data; internal ProgressUndoHistory(string filename) { path = filename; data = (File.Exists(path) ? JsonConvert.DeserializeObject<ProgressUndoData>(File.ReadAllText(path)) : new ProgressUndoData()); if (data == null || data.schema != 1 || data.accounts == null) { throw new InvalidOperationException("Rank undo history is invalid; edits disabled to preserve it."); } HashSet<string> hashSet = new HashSet<string>(); foreach (ProgressUndoAccount account in data.accounts) { if (account == null || string.IsNullOrEmpty(account.account) || !hashSet.Add(account.account) || account.entries == null || account.entries.Count > 10) { throw new InvalidOperationException("Rank undo history contains an invalid account."); } foreach (ProgressUndoEntry entry in account.entries) { if (entry == null || entry.rank < 0 || entry.rank > 30 || entry.xp < 0 || entry.favor < 0 || (entry.rank < 30 && entry.favor > 0) || entry.loadouts == null) { throw new InvalidOperationException("Rank undo history contains an invalid snapshot."); } foreach (SavedGeneLoadout loadout in entry.loadouts) { if (loadout == null || loadout.points == null) { throw new InvalidOperationException("Invalid gene snapshot."); } HashSet<string> hashSet2 = new HashSet<string>(); foreach (SavedGenePoint point in loadout.points) { if (point == null || string.IsNullOrEmpty(point.id) || point.level < 0 || !hashSet2.Add(point.id)) { throw new InvalidOperationException("Invalid gene snapshot."); } } } } } } private ProgressUndoAccount Find(string id) { if (string.IsNullOrEmpty(id)) { throw new InvalidOperationException("Player account is not ready."); } return data.accounts.Find((ProgressUndoAccount a) => a.account == id); } internal ProgressUndoEntry Peek(string account) { ProgressUndoAccount progressUndoAccount = Find(account); if (progressUndoAccount != null && progressUndoAccount.entries.Count != 0) { return progressUndoAccount.entries[progressUndoAccount.entries.Count - 1]; } return null; } internal void Push(string account, ProgressUndoEntry entry) { ProgressUndoAccount progressUndoAccount = Find(account); bool flag = progressUndoAccount == null; if (flag) { ProgressUndoAccount progressUndoAccount2 = new ProgressUndoAccount(); progressUndoAccount2.account = account; progressUndoAccount = progressUndoAccount2; data.accounts.Add(progressUndoAccount); } List<ProgressUndoEntry> entries = new List<ProgressUndoEntry>(progressUndoAccount.entries); progressUndoAccount.entries.Add(entry); if (progressUndoAccount.entries.Count > 10) { progressUndoAccount.entries.RemoveAt(0); } try { Save(); } catch { progressUndoAccount.entries = entries; if (flag) { data.accounts.Remove(progressUndoAccount); } throw; } } internal void Pop(string account, ProgressUndoEntry expected) { ProgressUndoAccount progressUndoAccount = Find(account); if (progressUndoAccount == null || progressUndoAccount.entries.Count == 0 || !object.ReferenceEquals(Peek(account), expected)) { throw new InvalidOperationException("Rank undo history changed; entry was not removed."); } progressUndoAccount.entries.RemoveAt(progressUndoAccount.entries.Count - 1); try { Save(); } catch { progressUndoAccount.entries.Add(expected); throw; } } private void Save() { Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path))); string sourceFileName = path + ".tmp"; File.WriteAllText(sourceFileName, JsonConvert.SerializeObject((object)data, (Formatting)1)); if (File.Exists(path)) { File.Replace(sourceFileName, path, path + ".bak"); } else { File.Move(sourceFileName, path); } } } public static class ProgressValidation { public static string ValidateFavor(int rank, int favorRank) { if (favorRank < 0) { return "Favor rank must be non-negative; nothing changed."; } if (rank != 30 && favorRank > 0) { return "Favor rank must be 0 unless rank is 30; nothing changed."; } return null; } public static string Validate(long xp, int rank, long maximumXp) { if (rank < 0 || rank > 30) { return "Rank must be between 0 and 30; nothing changed."; } if (xp < 0) { return "XP must be non-negative; nothing changed."; } if (maximumXp <= 0) { return "The game's XP threshold is unavailable; nothing changed."; } if (xp >= maximumXp) { return "XP must be less than " + maximumXp + " for rank " + rank + "; nothing changed."; } return null; } } internal sealed class MainMenuRankPreview { private sealed class NativeSize { internal float Width; internal float Height; internal Scale Scale; } private static VisualTreeAsset titleAsset; private static float mainBarOffsetX = 72f; private static float mainBarWidth = 633f; private static float mainBarHeight = 131f; private static float mainBackgroundWidth = 563f; private static readonly Dictionary<string, NativeSize> nativeSizes = new Dictionary<string, NativeSize>(); private readonly VisualElement host; private readonly ProgressEditor plugin; private VisualElement bar; private VisualElement card; private long lastXp = -1L; private int lastRank = -1; private int lastFavor = -1; private bool failed; private string lastName; internal static void Capture(UIDocument document) { //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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: 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) if ((Object)(object)document == (Object)null || (Object)(object)document.visualTreeAsset == (Object)null) { return; } titleAsset = document.visualTreeAsset; VisualElement val = ((document.rootVisualElement == null) ? null : UQueryExtensions.Q<VisualElement>(document.rootVisualElement, "mainmenu", (string)null)); VisualElement val2 = ((val == null) ? null : UQueryExtensions.Q<VisualElement>(val, "background", (string)null)); VisualElement val3 = ((document.rootVisualElement == null) ? null : UQueryExtensions.Q<VisualElement>(document.rootVisualElement, "ExpProgressBar", (string)null)); if (val2 == null || val3 == null) { return; } Rect worldBound = val3.worldBound; if (!(((Rect)(ref worldBound)).width > 0f)) { return; } Rect worldBound2 = val2.worldBound; if (!(((Rect)(ref worldBound2)).height > 0f)) { return; } Rect worldBound3 = val3.worldBound; mainBarOffsetX = VisualElementExtensions.WorldToLocal(val2, ((Rect)(ref worldBound3)).position).x; mainBarWidth = val3.resolvedStyle.width; mainBarHeight = val3.resolvedStyle.height; mainBackgroundWidth = val2.resolvedStyle.width; string[] array = new string[7] { "MainBarContainer", "MainBar", "ProgressBar", "RankDisplayVE", "LowerText", "LowerRank", "LowerEXP" }; foreach (string text in array) { VisualElement val4 = UQueryExtensions.Q<VisualElement>(val3, text, (string)null); if (val4 != null && !(val4.resolvedStyle.width <= 0f) && !(val4.resolvedStyle.height <= 0f)) { nativeSizes[text] = new NativeSize { Width = val4.resolvedStyle.width, Height = val4.resolvedStyle.height, Scale = val4.resolvedStyle.scale }; } } } internal MainMenuRankPreview(VisualElement container, ProgressEditor owner) { host = container; plugin = owner; } internal void Update() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_0106: 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_0136: 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_0167: 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_0197: 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_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: 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_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: 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_0339: 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_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0388: 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_03b8: Unknown result type (might be due to invalid IL or missing references) //IL_05fc: Unknown result type (might be due to invalid IL or missing references) //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_065a: Unknown result type (might be due to invalid IL or missing references) //IL_0660: 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_0427: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_0455: 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) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_075b: Unknown result type (might be due to invalid IL or missing references) //IL_0760: Unknown result type (might be due to invalid IL or missing references) //IL_07d0: Unknown result type (might be due to invalid IL or missing references) if (failed) { return; } try { if (bar == null) { if ((Object)(object)titleAsset == (Object)null) { TitleMenu[] array = Resources.FindObjectsOfTypeAll<TitleMenu>(); foreach (TitleMenu val in array) { Capture(val.UIDoc); } } if ((Object)(object)titleAsset == (Object)null) { return; } TemplateContainer val2 = titleAsset.CloneTree(); bar = UQueryExtensions.Q<VisualElement>((VisualElement)(object)val2, "ExpProgressBar", (string)null); if (bar == null) { throw new InvalidOperationException("Main menu rank display asset is missing."); } CopySheets((VisualElement)(object)val2, host); TitleMenu[] array2 = Resources.FindObjectsOfTypeAll<TitleMenu>(); foreach (TitleMenu val3 in array2) { Capture(val3.UIDoc); } VisualElement val4 = new VisualElement(); val4.name = "ProgressEditorProfileCard"; card = val4; host.style.width = StyleLength.op_Implicit(mainBarWidth + 24f); host.style.maxWidth = StyleLength.op_Implicit((StyleKeyword)3); host.style.flexShrink = StyleFloat.op_Implicit(0f); card.style.width = StyleLength.op_Implicit(mainBarWidth); card.style.maxWidth = StyleLength.op_Implicit((StyleKeyword)3); card.style.height = StyleLength.op_Implicit(350f); card.style.position = StyleEnum<Position>.op_Implicit((Position)0); card.style.overflow = StyleEnum<Overflow>.op_Implicit((Overflow)0); RankCardDiamond rankCardDiamond = new RankCardDiamond(); ((VisualElement)rankCardDiamond).name = "ProgressEditorRankDiamond"; RankCardDiamond rankCardDiamond2 = rankCardDiamond; ((VisualElement)rankCardDiamond2).style.position = StyleEnum<Position>.op_Implicit((Position)1); ((VisualElement)rankCardDiamond2).style.left = StyleLength.op_Implicit(0f - mainBarOffsetX); ((VisualElement)rankCardDiamond2).style.top = StyleLength.op_Implicit(0f); ((VisualElement)rankCardDiamond2).style.width = StyleLength.op_Implicit(mainBackgroundWidth); float artworkHeight = mainBackgroundWidth * rankCardDiamond2.AspectRatio; ((VisualElement)rankCardDiamond2).style.height = StyleLength.op_Implicit(artworkHeight); card.style.height = StyleLength.op_Implicit(artworkHeight); card.Add((VisualElement)(object)rankCardDiamond2); bar.RemoveFromHierarchy(); bar.style.position = StyleEnum<Position>.op_Implicit((Position)1); bar.style.left = StyleLength.op_Implicit(0f); bar.style.top = StyleLength.op_Implicit((artworkHeight - mainBarHeight) / 2f); IStyle style = bar.style; StyleLength right = (bar.style.bottom = StyleLength.op_Implicit((StyleKeyword)2)); style.right = right; IStyle style2 = bar.style; IStyle style3 = bar.style; IStyle style4 = bar.style; StyleLength val6 = (bar.style.marginRight = StyleLength.op_Implicit(0f)); StyleLength val8 = (style4.marginLeft = val6); StyleLength marginTop = (style3.marginBottom = val8); style2.marginTop = marginTop; bar.style.height = StyleLength.op_Implicit(mainBarHeight); bar.style.width = StyleLength.op_Implicit(mainBarWidth); bar.style.maxWidth = StyleLength.op_Implicit((StyleKeyword)3); bar.style.flexShrink = StyleFloat.op_Implicit(0f); foreach (KeyValuePair<string, NativeSize> nativeSize in nativeSizes) { VisualElement val11 = UQueryExtensions.Q<VisualElement>(bar, nativeSize.Key, (string)null); if (val11 != null) { val11.style.width = StyleLength.op_Implicit(nativeSize.Value.Width); val11.style.height = StyleLength.op_Implicit(nativeSize.Value.Height); val11.style.flexShrink = StyleFloat.op_Implicit(0f); val11.style.scale = StyleScale.op_Implicit(nativeSize.Value.Scale); } } bar.style.minWidth = StyleLength.op_Implicit(0f); bar.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)0); bar.RemoveFromClassList("hidden-element"); card.Add(bar); host.Add(card); RankDisplayVE centerBadge = UQueryExtensions.Q<RankDisplayVE>(bar, (string)null, (string)null); EventCallback<GeometryChangedEvent> val12 = delegate { //IL_000e: 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_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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00a9: 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) if (centerBadge != null) { Rect worldBound = ((VisualElement)centerBadge).worldBound; if (!(((Rect)(ref worldBound)).height <= 0f)) { Rect worldBound2 = bar.worldBound; if (!(((Rect)(ref worldBound2)).height <= 0f)) { VisualElement obj = bar; Rect worldBound3 = ((VisualElement)centerBadge).worldBound; float y = VisualElementExtensions.WorldToLocal(obj, ((Rect)(ref worldBound3)).center).y; float num4 = artworkHeight / 2f - y; if (!float.IsNaN(num4) && !float.IsInfinity(num4)) { StyleLength top = bar.style.top; Length value = ((StyleLength)(ref top)).value; if (Mathf.Abs(((Length)(ref value)).value - num4) > 0.1f) { bar.style.top = StyleLength.op_Implicit(num4); } } } } } }; ((CallbackEventHandler)bar).RegisterCallback<GeometryChangedEvent>(val12, (TrickleDown)0); if (centerBadge != null) { ((CallbackEventHandler)centerBadge).RegisterCallback<GeometryChangedEvent>(val12, (TrickleDown)0); } SetText("PlayerName", ""); } PlayerProfile instance = PlayerProfile.Instance; if (instance == null || instance.Profile == null) { return; } int rank = instance.Profile.Rank; int favorRank = instance.Profile.FavorRank; long xp = instance.Profile.Xp; string text = PlayerProfile.SanitizedUserAccountNickname() ?? ""; if (rank == lastRank && favorRank == lastFavor && xp == lastXp && text == lastName) { return; } SetText("PlayerName", text); List<XpSliderData> sequence = XPSliderFactory.GetSequence(rank, favorRank, xp, new List<XPSource>()); if (sequence == null || sequence.Count == 0) { return; } XpSliderData val13 = sequence[sequence.Count - 1]; bar.EnableInClassList("style__metem-rank", !val13.IsInFavorLevels); bar.EnableInClassList("style__favor-level", val13.IsInFavorLevels); RankDisplayVE val14 = UQueryExtensions.Q<RankDisplayVE>(bar, (string)null, (string)null); if (val14 != null) { val14.Show(val13.Rank, val13.IsInFavorLevels, false, default(Times)); } SetText("RankNumber", val13.Rank.ToString()); SetText("Title", ". " + val13.title); SetText("CurrentXp", val13.TargetXP.ToString()); SetText("MaxXp", val13.MaxXP.ToString()); float num = ((val13.MaxXP > 0) ? ((float)Math.Max(0.0, Math.Min(100.0, (double)val13.TargetXP * 100.0 / (double)val13.MaxXP))) : 0f); string[] array3 = new string[2] { "FrontProgress", "BackProgress" }; foreach (string text2 in array3) { VisualElement val15 = UQueryExtensions.Q<VisualElement>(bar, text2, (string)null); if (val15 != null) { val15.style.width = StyleLength.op_Implicit(Length.Percent(num)); } } string[] array4 = new string[4] { "SourceContainer", "RankUpContainer", "RankRewards", "TotalXP" }; foreach (string text3 in array4) { VisualElement val16 = UQueryExtensions.Q<VisualElement>(bar, text3, (string)null); if (val16 != null) { val16.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)1); } } lastRank = rank; lastFavor = favorRank; lastXp = xp; lastName = text; } catch (Exception ex) { failed = true; plugin.NativeError(ex); } } private void SetText(string name, string value) { Label val = UQueryExtensions.Q<Label>(bar, name, (string)null); if (val != null) { ((TextElement)val).text = value; } } private static void CopySheets(VisualElement source, VisualElement destination) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) int num = 0; while (true) { int num2 = num; VisualElementStyleSheetSet styleSheets = source.styleSheets; if (num2 >= ((VisualElementStyleSheetSet)(ref styleSheets)).count) { break; } VisualElementStyleSheetSet styleSheets2 = destination.styleSheets; VisualElementStyleSheetSet styleSheets3 = source.styleSheets; if (!((VisualElementStyleSheetSet)(ref styleSheets2)).Contains(((VisualElementStyleSheetSet)(ref styleSheets3))[num])) { VisualElementStyleSheetSet styleSheets4 = destination.styleSheets; VisualElementStyleSheetSet styleSheets5 = source.styleSheets; ((VisualElementStyleSheetSet)(ref styleSheets4)).Add(((VisualElementStyleSheetSet)(ref styleSheets5))[num]); } num++; } foreach (VisualElement item in source.Children()) { CopySheets(item, destination); } } } internal sealed class PauseProgressScreen { private static ProgressEditor plugin; private static readonly Dictionary<object, PauseProgressScreen> screens = new Dictionary<object, PauseProgressScreen>(); private readonly VisualElement overlay; private readonly Button entry; private readonly Button progressUndo; private readonly List<Action> synchronize = new List<Action>(); private readonly List<Slider> sliders = new List<Slider>(); private VisualElement contentHost; private VisualElement tabHost; private VisualTreeAsset settingsAsset; private float tabFontSize = 28f; private float tabInset = 48f; private VisualElement settingsTabLead; private VisualElement settingsTabTail; private float rowHeight = 64f; private float rowTop; private float rowBottom = 14f; private float rowPaddingTop; private float rowPaddingBottom; private readonly List<string> tabTextClasses = new List<string>(); private bool open; private readonly object pauseMenu; private readonly VisualElement screenRoot; private readonly bool titleMenu; internal static bool IsOpen { get { foreach (PauseProgressScreen value in screens.Values) { if (value.open) { return true; } } return false; } } internal static void Install(ProgressEditor owner) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Expected O, but got Unknown plugin = owner; Type type = typeof(PlayerProfile).Assembly.GetType("EscapeMenu"); Harmony val = new Harmony("local.VoidCrewProgressEditor.PauseMenu"); string[] array = new string[2] { "OnInitialize", "OnEnter" }; foreach (string name in array) { val.Patch((MethodBase)type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (HarmonyMethod)null, new HarmonyMethod(typeof(PauseProgressScreen).GetMethod("Ensure", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } val.Patch((MethodBase)type.GetMethod("OnExit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(PauseProgressScreen).GetMethod("BeforeExit", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Type type2 = typeof(PlayerProfile).Assembly.GetType("MainMenu"); val.Patch((MethodBase)type2.GetMethod("StartAsTitleMenu", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (HarmonyMethod)null, new HarmonyMethod(typeof(PauseProgressScreen).GetMethod("EnsureTitle", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); string[] array2 = new string[2] { "Shutdown", "Dispose" }; foreach (string name2 in array2) { val.Patch((MethodBase)type2.GetMethod(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(PauseProgressScreen).GetMethod("RemoveTitle", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static object Field(object owner, string name) { FieldInfo field = owner.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null)) { return field.GetValue(owner); } return null; } private static void EnsureTitle(object __instance) { try { object obj = Field(__instance, "_mainmenuRoot"); VisualElement val = (VisualElement)((obj is VisualElement) ? obj : null); object obj2 = Field(__instance, "_settingsButton"); Button val2 = (Button)((obj2 is Button) ? obj2 : null); if (val == null || val2 == null || ((VisualElement)val2).parent == null) { return; } VisualElement root = val; UIDocument[] array = Resources.FindObjectsOfTypeAll<UIDocument>(); foreach (UIDocument val3 in array) { if (val3.rootVisualElement != null && val3.rootVisualElement.Contains(val)) { root = val3.rootVisualElement; MainMenuRankPreview.Capture(val3); break; } } EnsureScreen(__instance, root, val2, title: true); } catch (Exception ex) { plugin.NativeError(ex); } } private static void RemoveTitle(object __instance) { if (screens.TryGetValue(__instance, out var value)) { value.open = false; ((VisualElement)value.entry).RemoveFromHierarchy(); value.overlay.RemoveFromHierarchy(); screens.Remove(__instance); } } private static void EnsureScreen(object owner, VisualElement root, Button settings, bool title) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (screens.TryGetValue(owner, out var value)) { if (root.Contains((VisualElement)(object)value.entry) && root.Contains(value.overlay)) { return; } RemoveTitle(owner); } List<VisualElement> stale = new List<VisualElement>(); UQueryExtensions.Query<VisualElement>(root, (string)null, (string)null).ForEach((Action<VisualElement>)delegate(VisualElement element) { if (element.name == "ProgressEditorMenuEntry" || element.name == "ProgressEditorScreen") { stale.Add(element); } }); foreach (VisualElement item in stale) { item.RemoveFromHierarchy(); } PauseProgressScreen value2 = new PauseProgressScreen(root, settings, owner, title); screens.Add(owner, value2); plugin.NativeLog(title ? "Added Edit Progress above Settings in the main menu." : "Added Edit Progress after Settings in the pause menu."); } private static void Ensure(object __instance) { try { object obj = Field(__instance, "UIDoc"); UIDocument val = (UIDocument)((obj is UIDocument) ? obj : null); if ((Object)(object)val == (Object)null || val.rootVisualElement == null) { return; } object obj2 = Field(__instance, "_mainMenu"); if (obj2 != null) { object obj3 = Field(obj2, "_settingsButton"); Button val2 = (Button)((obj3 is Button) ? obj3 : null); if (val2 != null && ((VisualElement)val2).parent != null) { EnsureScreen(__instance, val.rootVisualElement, val2, title: false); } } } catch (Exception ex) { plugin.NativeError(ex); } } private static bool BeforeExit(object __instance, ref bool __result) { if (!screens.TryGetValue(__instance, out var value) || !value.open) { return true; } value.Close(); __result = false; return false; } private PauseProgressScreen(VisualElement root, Button settings, object menu, bool title) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Expected O, but got Unknown //IL_0256: 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_0296: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0342: 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_0371: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Expected O, but got Unknown //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_03b9: 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_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Expected O, but got Unknown //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Expected O, but got Unknown //IL_053c: 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_054d: Expected O, but got Unknown //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_057c: Unknown result type (might be due to invalid IL or missing references) //IL_0581: Unknown result type (might be due to invalid IL or missing references) //IL_0596: Unknown result type (might be due to invalid IL or missing references) //IL_05ab: Unknown result type (might be due to invalid IL or missing references) //IL_05b5: Unknown result type (might be due to invalid IL or missing references) //IL_05bc: Expected O, but got Unknown //IL_05d6: Unknown result type (might be due to invalid IL or missing references) //IL_05eb: Unknown result type (might be due to invalid IL or missing references) //IL_05f0: Unknown result type (might be due to invalid IL or missing references) //IL_0605: Unknown result type (might be due to invalid IL or missing references) //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Unknown result type (might be due to invalid IL or missing references) //IL_0640: Unknown result type (might be due to invalid IL or missing references) //IL_0687: Unknown result type (might be due to invalid IL or missing references) //IL_068e: Expected O, but got Unknown //IL_06a6: Unknown result type (might be due to invalid IL or missing references) //IL_06b8: Unknown result type (might be due to invalid IL or missing references) //IL_06ca: Unknown result type (might be due to invalid IL or missing references) //IL_06e0: Unknown result type (might be due to invalid IL or missing references) //IL_06e5: Unknown result type (might be due to invalid IL or missing references) //IL_06fd: Unknown result type (might be due to invalid IL or missing references) //IL_0715: Unknown result type (might be due to invalid IL or missing references) //IL_075f: Unknown result type (might be due to invalid IL or missing references) //IL_0775: Unknown result type (might be due to invalid IL or missing references) //IL_078b: Unknown result type (might be due to invalid IL or missing references) //IL_0795: Unknown result type (might be due to invalid IL or missing references) //IL_079c: Expected O, but got Unknown //IL_07c0: Unknown result type (might be due to invalid IL or missing references) //IL_07d6: 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_07fe: Unknown result type (might be due to invalid IL or missing references) //IL_0729: Unknown result type (might be due to invalid IL or missing references) //IL_0730: Expected O, but got Unknown //IL_0851: Unknown result type (might be due to invalid IL or missing references) //IL_0867: Unknown result type (might be due to invalid IL or missing references) //IL_0886: Unknown result type (might be due to invalid IL or missing references) //IL_088d: Expected O, but got Unknown //IL_08a2: Unknown result type (might be due to invalid IL or missing references) //IL_08a9: Expected O, but got Unknown //IL_081b: Unknown result type (might be due to invalid IL or missing references) //IL_0822: Expected O, but got Unknown //IL_094a: Unknown result type (might be due to invalid IL or missing references) //IL_094f: Unknown result type (might be due to invalid IL or missing references) //IL_0950: Unknown result type (might be due to invalid IL or missing references) //IL_0957: Unknown result type (might be due to invalid IL or missing references) //IL_096c: Unknown result type (might be due to invalid IL or missing references) //IL_0973: Expected O, but got Unknown //IL_099b: Unknown result type (might be due to invalid IL or missing references) //IL_09b1: Unknown result type (might be due to invalid IL or missing references) //IL_0c15: Unknown result type (might be due to invalid IL or missing references) //IL_0c2b: Unknown result type (might be due to invalid IL or missing references) //IL_0c41: Unknown result type (might be due to invalid IL or missing references) //IL_0c8a: Unknown result type (might be du