using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using CatAPI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace CustomAchievements
{
public sealed class AchIcon
{
internal readonly string Ref;
internal readonly byte[] Png;
private AchIcon(string reference, byte[] png)
{
Ref = reference;
Png = png;
}
public static AchIcon Item(int itemId)
{
return new AchIcon("item:" + itemId, null);
}
public static AchIcon VanillaAchievement(int achievementId)
{
return new AchIcon("ach:" + achievementId, null);
}
public static AchIcon Resource(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentException("Resource path is required", "path");
}
return new AchIcon("res:" + path, null);
}
public static AchIcon FromPng(byte[] png)
{
if (png == null || png.Length < 8 || png[0] != 137 || png[1] != 80 || png[2] != 78 || png[3] != 71)
{
throw new ArgumentException("Not a PNG image", "png");
}
using SHA1 sHA = SHA1.Create();
StringBuilder stringBuilder = new StringBuilder();
byte[] array = sHA.ComputeHash(png);
foreach (byte b in array)
{
stringBuilder.Append(b.ToString("x2"));
}
return new AchIcon("png:" + stringBuilder, (byte[])png.Clone());
}
public static AchIcon FromEmbeddedPng(Assembly assembly, string resourceName)
{
using Stream stream = assembly.GetManifestResourceStream(resourceName);
if (stream == null)
{
throw new ArgumentException("Embedded resource not found: " + resourceName, "resourceName");
}
using MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
return FromPng(memoryStream.ToArray());
}
}
public static class AchievementRegistry
{
public static AchievementMod RegisterMod(string githubUrl, AchText name)
{
if (!GitHubId.TryNormalize(githubUrl, out var id))
{
throw new ArgumentException("Expected a GitHub repository URL like https://github.com/owner/repo, got: " + githubUrl, "githubUrl");
}
if (name == null)
{
throw new ArgumentNullException("name");
}
return new AchievementMod(Store.GetOrAddMod(id, name));
}
}
public sealed class AchievementMod
{
private readonly ModRecord record;
public string Id => record.Id;
internal AchievementMod(ModRecord record)
{
this.record = record;
}
public Achievement Register(string key, AchText name, AchText description, long target = 1L, AchIcon icon = null, bool allowSandbox = false)
{
if (!GitHubId.IsKey(key))
{
throw new ArgumentException("Achievement key must use letters, digits, '-', '_' or '.', got: " + key, "key");
}
if (name == null)
{
throw new ArgumentNullException("name");
}
if (target < 1)
{
throw new ArgumentOutOfRangeException("target", "target must be at least 1");
}
return new Achievement(Store.GetOrAddAchievement(record, key.ToLowerInvariant(), name, description ?? AchText.Empty(), target, icon, allowSandbox));
}
}
public sealed class Achievement
{
private readonly AchRecord rec;
public string Id => rec.FullId;
public long Target => rec.Target;
public long Progress
{
get
{
lock (Store.Sync)
{
return rec.Progress;
}
}
}
public bool Unlocked
{
get
{
lock (Store.Sync)
{
return rec.Unlocked;
}
}
}
public bool CanProgress
{
get
{
lock (Store.Sync)
{
return Store.CanProgress(rec);
}
}
}
internal Achievement(AchRecord rec)
{
this.rec = rec;
}
public void Unlock()
{
Store.Unlock(rec);
}
public void SetProgress(long value)
{
Store.SetProgress(rec, value);
}
public void AddProgress(long delta)
{
Store.AddProgress(rec, delta);
}
}
public sealed class AchText
{
private readonly string en;
private readonly Dictionary<int, string> text = new Dictionary<int, string>();
public string English => en;
private AchText(string en)
{
this.en = en ?? "";
}
public static AchText En(string en)
{
if (string.IsNullOrEmpty(en))
{
throw new ArgumentException("English text is required / 必须提供英文", "en");
}
return new AchText(en);
}
internal static AchText Empty()
{
return new AchText("");
}
public static implicit operator AchText(string en)
{
return En(en);
}
public AchText ZhCN(string value)
{
return Set(2052, value);
}
public AchText FrFR(string value)
{
return Set(1036, value);
}
public AchText DeDE(string value)
{
return Set(1031, value);
}
public AchText EsES(string value)
{
return Set(3082, value);
}
public AchText JaJP(string value)
{
return Set(1041, value);
}
public AchText KoKR(string value)
{
return Set(1042, value);
}
public AchText Set(int lcid, string value)
{
if (!string.IsNullOrEmpty(value))
{
text[lcid] = value;
}
return this;
}
public override string ToString()
{
int lcid = Lang.Lcid;
if (text.TryGetValue(lcid, out var value))
{
return value;
}
int num = lcid & 0x3FF;
foreach (KeyValuePair<int, string> item in text)
{
if ((item.Key & 0x3FF) == num)
{
return item.Value;
}
}
return en;
}
internal void Write(BinaryWriter w)
{
w.Write(en);
w.Write(text.Count);
foreach (KeyValuePair<int, string> item in text)
{
w.Write(item.Key);
w.Write(item.Value);
}
}
internal static AchText Read(BinaryReader r)
{
AchText achText = new AchText(r.ReadString());
int num = r.ReadInt32();
for (int i = 0; i < num; i++)
{
int lcid = r.ReadInt32();
achText.Set(lcid, r.ReadString());
}
return achText;
}
}
internal static class GitHubId
{
internal static bool TryNormalize(string url, out string id)
{
id = null;
if (string.IsNullOrWhiteSpace(url))
{
return false;
}
string text = url.Trim();
int num = text.IndexOfAny(new char[2] { '?', '#' });
if (num >= 0)
{
text = text.Substring(0, num);
}
int num2 = text.IndexOf("://", StringComparison.Ordinal);
if (num2 >= 0)
{
text = text.Substring(num2 + 3);
}
if (text.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
{
text = text.Substring(4);
}
string[] array = text.Split(new char[1] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if (array.Length < 3 || !array[0].Equals("github.com", StringComparison.OrdinalIgnoreCase))
{
return false;
}
string text2 = array[1];
string text3 = array[2];
if (text3.EndsWith(".git", StringComparison.OrdinalIgnoreCase))
{
text3 = text3.Substring(0, text3.Length - 4);
}
if (!IsName(text2) || !IsName(text3))
{
return false;
}
id = ("github.com/" + text2 + "/" + text3).ToLowerInvariant();
return true;
}
internal static bool IsKey(string key)
{
return IsName(key);
}
private static bool IsName(string s)
{
if (string.IsNullOrEmpty(s) || s.Length > 100)
{
return false;
}
foreach (char c in s)
{
if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '-' && c != '_' && c != '.')
{
return false;
}
}
return true;
}
}
internal static class IconCache
{
private const string DefaultIconResource = "CustomAchievements.res.default_icon.png";
private static readonly Dictionary<string, Sprite> pngSprites = new Dictionary<string, Sprite>();
private static Sprite fallback;
internal static Sprite Get(string reference, byte[] png)
{
Sprite val = null;
try
{
val = Resolve(reference, png);
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)("Icon " + reference + " failed: " + ex.Message));
}
}
if (!((Object)(object)val != (Object)null))
{
return Fallback();
}
return val;
}
private static Sprite Resolve(string reference, byte[] png)
{
if (string.IsNullOrEmpty(reference))
{
return null;
}
int num = reference.IndexOf(':');
if (num < 0)
{
return null;
}
string text = reference.Substring(0, num);
string text2 = reference.Substring(num + 1);
switch (text)
{
case "item":
{
if (!int.TryParse(text2, out var result2))
{
return null;
}
ItemProto obj2 = ((ProtoSet<ItemProto>)(object)LDB.items).Select(result2);
if (obj2 == null)
{
return null;
}
return obj2.iconSprite;
}
case "ach":
{
if (!int.TryParse(text2, out var result))
{
return null;
}
AchievementProto obj = ((ProtoSet<AchievementProto>)(object)LDB.achievements).Select(result);
if (obj == null)
{
return null;
}
return obj.iconSprite;
}
case "res":
return Resources.Load<Sprite>(text2);
case "png":
return PngSprite(text2, png);
default:
return null;
}
}
private static Sprite PngSprite(string hash, byte[] png)
{
if (pngSprites.TryGetValue(hash, out var value))
{
return value;
}
byte[] array = png ?? Store.ReadIcon(hash);
Sprite val = ((array == null) ? null : ToSprite(array));
pngSprites[hash] = val;
return val;
}
private static Sprite Fallback()
{
if ((Object)(object)fallback == (Object)null)
{
using Stream stream = typeof(IconCache).Assembly.GetManifestResourceStream("CustomAchievements.res.default_icon.png");
using MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
fallback = ToSprite(memoryStream.ToArray());
}
return fallback;
}
private static Sprite ToSprite(byte[] png)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Expected O, but got Unknown
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
try
{
if (!ImageConversion.LoadImage(val, png))
{
return null;
}
Texture2D val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, true)
{
wrapMode = (TextureWrapMode)1,
filterMode = (FilterMode)2,
anisoLevel = 4
};
val2.SetPixels32(BleedTransparent(val.GetPixels32()));
val2.Apply(true, true);
return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f));
}
finally
{
Object.Destroy((Object)(object)val);
}
}
private static Color32[] BleedTransparent(Color32[] pixels)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: 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_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
long num = 0L;
long num2 = 0L;
long num3 = 0L;
long num4 = 0L;
foreach (Color32 val in pixels)
{
num += val.r * val.a;
num2 += val.g * val.a;
num3 += val.b * val.a;
num4 += val.a;
}
if (num4 == 0L)
{
return pixels;
}
Color32 val2 = default(Color32);
((Color32)(ref val2))..ctor((byte)(num / num4), (byte)(num2 / num4), (byte)(num3 / num4), (byte)0);
for (int j = 0; j < pixels.Length; j++)
{
if (pixels[j].a == 0)
{
pixels[j] = val2;
}
}
return pixels;
}
}
internal static class PanelView
{
private struct Row
{
public string FullId;
public string Name;
public string Description;
public string Source;
public long Target;
public long Progress;
public bool Unlocked;
public long UnlockedUtcTicks;
public string IconRef;
public byte[] IconPng;
}
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction <>9__31_0;
public static Comparison<Row> <>9__36_0;
public static Comparison<Row> <>9__36_1;
internal void <CreateToggle>b__31_0()
{
SetMode(!showMods);
}
internal int <Rebuild>b__36_0(Row a, Row b)
{
return a.UnlockedUtcTicks.CompareTo(b.UnlockedUtcTicks);
}
internal int <Rebuild>b__36_1(Row a, Row b)
{
return ((double)b.Progress / (double)b.Target).CompareTo((double)a.Progress / (double)a.Target);
}
}
private const int Columns = 4;
private const int EntryWidth = 270;
private const int EntryHeight = 310;
private const int EntryLeft = 8;
private const int EntryTop = 41;
private const int ContainerBottom = 8;
private const int ContainerGap = 16;
private const float RebuildInterval = 0.5f;
private static UIAchievementPanel panel;
private static RectTransform unlockedBox;
private static RectTransform progressBox;
private static RectTransform lockedBox;
private static Text toggleText;
private static readonly List<UIAchievementEntry> entries = new List<UIAchievementEntry>();
private static readonly Dictionary<string, UIAchievementEntry> entriesById = new Dictionary<string, UIAchievementEntry>();
private static bool showMods;
private static string pendingReveal;
private static int builtVersion = -1;
private static int builtLcid = -1;
private static int toggleLcid = -1;
private static float lastRebuildTime = -100f;
private static float contentHeight;
private static int total;
private static int unlockedCount;
internal static void LateUpdate()
{
UIAchievementPanel val = FindPanel();
if ((Object)(object)val == (Object)null)
{
return;
}
if ((Object)(object)val != (Object)(object)panel || (Object)(object)unlockedBox == (Object)null || (Object)(object)toggleText == (Object)null)
{
Attach(val);
}
if (!((Component)panel).gameObject.activeInHierarchy)
{
return;
}
if (Lang.Lcid != toggleLcid)
{
UpdateToggleText();
}
if (pendingReveal != null)
{
RevealNow();
}
else if (showMods && panel.highlightingEntries.Count > 0)
{
SetMode(mods: false);
}
if (showMods)
{
if ((Store.Version != builtVersion || Lang.Lcid != builtLcid) && Time.unscaledTime - lastRebuildTime >= 0.5f)
{
Rebuild();
}
Enforce();
}
}
internal static void Reveal(string fullId)
{
UIGame uiGame = UIRoot.instance.uiGame;
if (!((ManualBehaviour)uiGame.statWindow).active)
{
uiGame.ShutAllFunctionWindow();
uiGame.ShutPlayerInventory();
uiGame.OpenProductionWindow();
}
uiGame.statWindow.OnTabButtonClick(5);
pendingReveal = fullId;
}
private static void RevealNow()
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
string text = pendingReveal;
pendingReveal = null;
if (!showMods)
{
SetMode(mods: true);
}
else if (Store.Version != builtVersion)
{
Rebuild();
}
if (text != null && entriesById.TryGetValue(text, out var value) && (Object)(object)value != (Object)null)
{
float num = 0f - (((RectTransform)((Transform)value.selfRect).parent).anchoredPosition.y + value.selfRect.anchoredPosition.y) - 30f;
panel.scrollViewConent.anchoredPosition = new Vector2(panel.scrollViewConent.anchoredPosition.x, Mathf.Max(0f, num));
}
}
private static UIAchievementPanel FindPanel()
{
UIRoot instance = UIRoot.instance;
if ((Object)(object)instance == (Object)null || (Object)(object)instance.uiGame == (Object)null || (Object)(object)instance.uiGame.statWindow == (Object)null)
{
return null;
}
return instance.uiGame.statWindow.achievementPanelUI;
}
private static void Attach(UIAchievementPanel target)
{
panel = target;
entries.Clear();
entriesById.Clear();
showMods = false;
builtVersion = -1;
unlockedBox = CloneContainer(panel.unlockedContainerRect);
progressBox = CloneContainer(panel.inProgressContainerRect);
lockedBox = CloneContainer(panel.lockedContainerRect);
CreateToggle();
UpdateToggleText();
}
private static RectTransform CloneContainer(RectTransform source)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
GameObject val = Object.Instantiate<GameObject>(((Component)source).gameObject, ((Transform)source).parent, false);
((Object)val).name = ((Object)source).name + "_Mod";
UIAchievementEntry[] componentsInChildren = val.GetComponentsInChildren<UIAchievementEntry>(true);
foreach (UIAchievementEntry obj in componentsInChildren)
{
((Component)obj).gameObject.SetActive(false);
Object.Destroy((Object)(object)((Component)obj).gameObject);
}
val.SetActive(false);
return (RectTransform)val.transform;
}
private static void CreateToggle()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Expected O, but got Unknown
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: 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_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Expected O, but got Unknown
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
RectTransform val = (RectTransform)((Component)panel).transform;
GameObject val2 = Object.Instantiate<GameObject>(((Component)panel.enableAchBtn).gameObject, (Transform)(object)val, false);
((Object)val2).name = "ModAchievementToggle";
Localizer[] componentsInChildren = val2.GetComponentsInChildren<Localizer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren[i]);
}
Button component = val2.GetComponent<Button>();
component.onClick = new ButtonClickedEvent();
ButtonClickedEvent onClick = component.onClick;
object obj = <>c.<>9__31_0;
if (obj == null)
{
UnityAction val3 = delegate
{
SetMode(!showMods);
};
<>c.<>9__31_0 = val3;
obj = (object)val3;
}
((UnityEvent)onClick).AddListener((UnityAction)obj);
toggleText = val2.GetComponentInChildren<Text>(true);
RectTransform val4 = (RectTransform)val2.transform;
val4.anchorMin = new Vector2(0.5f, 0.5f);
val4.anchorMax = new Vector2(0.5f, 0.5f);
val4.pivot = new Vector2(0.5f, 0.5f);
val4.sizeDelta = new Vector2(160f, 32f);
RectTransform rectTransform = ((Graphic)panel.overallProgressImg).rectTransform;
Rect rect = rectTransform.rect;
Vector3 val5 = ((Transform)val).InverseTransformPoint(((Transform)rectTransform).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)));
rect = rectTransform.rect;
float x = ((Transform)val).InverseTransformPoint(((Transform)rectTransform).TransformPoint(new Vector3(((Rect)(ref rect)).xMin, 0f, 0f))).x;
float num = ProgressLabelLeft(val, val5.y, x) ?? (x - 110f);
((Transform)val4).localPosition = new Vector3(num - 16f - val4.sizeDelta.x / 2f, val5.y, 0f);
val2.SetActive(true);
}
private static float? ProgressLabelLeft(RectTransform panelRect, float rowY, float barLeft)
{
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: 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_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: 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_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Expected I4, but got Unknown
//IL_0216: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_0237: Unknown result type (might be due to invalid IL or missing references)
//IL_0243: Unknown result type (might be due to invalid IL or missing references)
float? result = null;
float num = float.MinValue;
Text[] componentsInChildren = ((Component)panelRect).GetComponentsInChildren<Text>(true);
foreach (Text val in componentsInChildren)
{
if ((Object)(object)val == (Object)(object)toggleText || (Object)(object)val == (Object)(object)panel.topTipText || (Object)(object)val == (Object)(object)panel.overallProgressText || (Object)(object)val == (Object)(object)panel.detailText || string.IsNullOrEmpty(val.text) || (Object)(object)((Component)val).GetComponentInParent<UIAchievementEntry>() != (Object)null || ((Component)val).transform.IsChildOf(panel.enableDetectionTip.transform))
{
continue;
}
RectTransform rectTransform = ((Graphic)val).rectTransform;
Rect rect = rectTransform.rect;
float xMin = ((Rect)(ref rect)).xMin;
rect = rectTransform.rect;
Vector3 val2 = ((Transform)panelRect).InverseTransformPoint(((Transform)rectTransform).TransformPoint(new Vector3(xMin, ((Rect)(ref rect)).yMin, 0f)));
rect = rectTransform.rect;
float xMax = ((Rect)(ref rect)).xMax;
rect = rectTransform.rect;
Vector3 val3 = ((Transform)panelRect).InverseTransformPoint(((Transform)rectTransform).TransformPoint(new Vector3(xMax, ((Rect)(ref rect)).yMax, 0f)));
if (!(rowY < val2.y - 4f) && !(rowY > val3.y + 4f) && !((val2.x + val3.x) / 2f >= barLeft) && !(val3.x <= num))
{
float num2 = val3.x - val2.x;
rect = rectTransform.rect;
float num3 = num2 / Mathf.Max(((Rect)(ref rect)).width, 1f);
float num4 = Mathf.Min(val.preferredWidth * num3, val3.x - val2.x);
TextAnchor alignment = val.alignment;
switch (alignment - 1)
{
case 1:
case 4:
case 7:
result = val3.x - num4;
break;
case 0:
case 3:
case 6:
result = (val2.x + val3.x - num4) / 2f;
break;
default:
result = val2.x;
break;
}
num = val3.x;
}
}
return result;
}
private static void UpdateToggleText()
{
toggleLcid = Lang.Lcid;
if ((Object)(object)toggleText != (Object)null)
{
toggleText.text = Line.op_Implicit(showMods ? Lang.En("Official Achievements").ZhCN("官方成就") : Lang.En("Mod Achievements").ZhCN("MOD成就"));
}
}
private static void SetMode(bool mods)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
showMods = mods;
Vector2 anchoredPosition = panel.scrollViewConent.anchoredPosition;
panel.scrollViewConent.anchoredPosition = new Vector2(anchoredPosition.x, 0f);
if (mods)
{
Rebuild();
Enforce();
}
else
{
((Component)unlockedBox).gameObject.SetActive(false);
((Component)progressBox).gameObject.SetActive(false);
((Component)lockedBox).gameObject.SetActive(false);
panel.SetLayout();
panel.SetOverallProgress();
AccessTools.Method(typeof(UIAchievementPanel), "_OnOpen", (Type[])null, (Type[])null).Invoke(panel, null);
}
UpdateToggleText();
}
private static void Enforce()
{
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
((Component)panel.unlockedContainerRect).gameObject.SetActive(false);
((Component)panel.inProgressContainerRect).gameObject.SetActive(false);
((Component)panel.lockedContainerRect).gameObject.SetActive(false);
((Component)panel.topTipText).gameObject.SetActive(false);
panel.enableDetectionTip.SetActive(false);
panel.scrollViewConent.sizeDelta = new Vector2(0f, contentHeight);
float num = ((total == 0) ? 0f : ((float)unlockedCount / (float)total));
panel.overallProgressImg.fillAmount = num;
RectTransform progressPointRect = panel.progressPointRect;
Rect rect = ((Graphic)panel.overallProgressImg).rectTransform.rect;
progressPointRect.anchoredPosition = new Vector2(((Rect)(ref rect)).width * num, 0f);
panel.overallProgressText.text = unlockedCount + " / " + total;
}
private static void Rebuild()
{
lastRebuildTime = Time.unscaledTime;
builtVersion = Store.Version;
builtLcid = Lang.Lcid;
foreach (UIAchievementEntry entry in entries)
{
if ((Object)(object)entry != (Object)null)
{
((ManualBehaviour)entry)._Destroy();
}
}
entries.Clear();
entriesById.Clear();
List<Row> list = new List<Row>();
List<Row> list2 = new List<Row>();
List<Row> list3 = new List<Row>();
foreach (ModRecord item2 in Store.SnapshotMods())
{
lock (Store.Sync)
{
string text = Line.op_Implicit(Lang.En("From: ").ZhCN("源自:")) + item2.Name;
if (!item2.Installed)
{
text += Line.op_Implicit(Lang.En(" (not installed)").ZhCN("(未安装)"));
}
foreach (AchRecord achievement in item2.Achievements)
{
Row item = new Row
{
FullId = achievement.FullId,
Name = achievement.Name.ToString(),
Description = achievement.Description.ToString(),
Source = text,
Target = achievement.Target,
Progress = achievement.Progress,
Unlocked = achievement.Unlocked,
UnlockedUtcTicks = achievement.UnlockedUtcTicks,
IconRef = achievement.IconRef,
IconPng = achievement.IconPng
};
if (item.Unlocked)
{
list.Add(item);
}
else if (item.Target > 1 && item.Progress > 0)
{
list2.Add(item);
}
else
{
list3.Add(item);
}
}
}
}
list.Sort((Row a, Row b) => a.UnlockedUtcTicks.CompareTo(b.UnlockedUtcTicks));
list2.Sort((Row a, Row b) => ((double)b.Progress / (double)b.Target).CompareTo((double)a.Progress / (double)a.Target));
total = list.Count + list2.Count + list3.Count;
unlockedCount = list.Count;
Fill(unlockedBox, list);
Fill(progressBox, list2);
Fill(lockedBox, list3);
Layout(list.Count, list2.Count, list3.Count);
}
private static void Fill(RectTransform box, List<Row> rows)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < rows.Count; i++)
{
UIAchievementEntry val = Object.Instantiate<UIAchievementEntry>(panel.entryPrefab, (Transform)(object)box);
((ManualBehaviour)val)._Create();
((ManualBehaviour)val)._Init((object)null);
((ManualBehaviour)val)._Open();
val.selfRect.anchoredPosition = new Vector2((float)(i % 4 * 270 + 8), (float)(-(i / 4 * 310 + 41)));
Show(val, rows[i]);
entries.Add(val);
entriesById[rows[i].FullId] = val;
}
}
private static void Show(UIAchievementEntry card, Row row)
{
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_0268: Unknown result type (might be due to invalid IL or missing references)
//IL_0282: Unknown result type (might be due to invalid IL or missing references)
//IL_029c: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0201: 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_0326: 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_0348: Unknown result type (might be due to invalid IL or missing references)
//IL_035e: Unknown result type (might be due to invalid IL or missing references)
//IL_0364: Unknown result type (might be due to invalid IL or missing references)
card.icon.sprite = IconCache.Get(row.IconRef, row.IconPng);
card.titleText.text = row.Name;
card.descText.supportRichText = true;
card.descText.text = row.Description + "\n<color=#ffffff80>" + row.Source + "</color>";
((Component)card.propertyTipRect).gameObject.SetActive(false);
float num;
if (row.Unlocked)
{
card.iconRect.anchoredPosition = new Vector2(0f, -35f);
card.titleRect.anchoredPosition = new Vector2(0f, -130f);
card.descRect.anchoredPosition = new Vector2(0f, -165f);
((Component)card.progressRect).gameObject.SetActive(false);
((Component)card.lockedRect).gameObject.SetActive(false);
((Component)card.unlockedBelt).gameObject.SetActive(true);
((Component)card.unlockedBeltText).gameObject.SetActive(true);
num = 1f;
}
else if (row.Target > 1 && row.Progress > 0)
{
card.iconRect.anchoredPosition = new Vector2(0f, -28f);
card.titleRect.anchoredPosition = new Vector2(0f, -108f);
card.descRect.anchoredPosition = new Vector2(0f, -130f);
((Component)card.progressRect).gameObject.SetActive(true);
((Component)card.lockedRect).gameObject.SetActive(false);
((Component)card.unlockedBelt).gameObject.SetActive(false);
((Component)card.unlockedBeltText).gameObject.SetActive(false);
card.progress = (double)row.Progress / (double)row.Target;
card.progressBar.fillAmount = (float)card.progress;
RectTransform progressPointRect = card.progressPointRect;
Rect rect = ((Graphic)card.progressBar).rectTransform.rect;
progressPointRect.anchoredPosition = new Vector2(((Rect)(ref rect)).width * (float)card.progress, 0f);
card.progressText.text = row.Progress + " / " + row.Target;
num = -1f;
}
else
{
card.iconRect.anchoredPosition = new Vector2(0f, -35f);
card.titleRect.anchoredPosition = new Vector2(0f, -116f);
card.descRect.anchoredPosition = new Vector2(0f, -140f);
((Component)card.progressRect).gameObject.SetActive(false);
((Component)card.lockedRect).gameObject.SetActive(true);
((Component)card.unlockedBelt).gameObject.SetActive(false);
((Component)card.unlockedBeltText).gameObject.SetActive(false);
num = -1f;
}
float a = ((num > 0f) ? 1f : (3f / 85f));
float a2 = ((num > 0f) ? 1f : 0.2509804f);
((Graphic)card.icon).color = WithAlpha(((Graphic)card.icon).color, a);
((Graphic)card.titleText).color = WithAlpha(((Graphic)card.titleText).color, a2);
((Graphic)card.descText).color = WithAlpha(((Graphic)card.descText).color, a2);
}
private static Color WithAlpha(Color c, float a)
{
//IL_0000: 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_000c: 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)
return new Color(c.r, c.g, c.b, a);
}
private static void Layout(int unlocked, int inProgress, int locked)
{
float y = 0f;
float height = 0f;
y = Place(unlockedBox, unlocked, y, ref height);
y = Place(progressBox, inProgress, y, ref height);
Place(lockedBox, locked, y, ref height);
contentHeight = height;
}
private static float Place(RectTransform box, int count, float y, ref float height)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
if (count == 0)
{
box.sizeDelta = Vector2.zero;
((Component)box).gameObject.SetActive(false);
return y;
}
if (height > 0f)
{
y -= 16f;
height += 16f;
}
float num = Mathf.CeilToInt((float)count / 4f) * 310 + 41 + 8;
box.anchoredPosition = new Vector2(0f, y);
box.sizeDelta = new Vector2(0f, num);
((Component)box).gameObject.SetActive(true);
height += num;
return y - num;
}
}
[BepInPlugin("com.yummi.dsp.customachievements", "Custom Achievements", "0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.yummi.dsp.customachievements";
public const string PluginName = "Custom Achievements";
public const string PluginVersion = "0.0.0";
public const string GitHubUrl = "https://github.com/cat-yummi-dspmod/DSP-CustomAchievements";
internal static ManualLogSource Log;
private bool panelFailed;
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
Log.LogInfo((object)"Custom Achievements v0.0.0 loaded");
}
private void Update()
{
if (!Store.Loaded && VFPreload.done)
{
Store.Load();
}
Store.SaveIfDue();
ShowUnlocks();
}
private void LateUpdate()
{
if (panelFailed || !Store.Loaded)
{
return;
}
try
{
PanelView.LateUpdate();
}
catch (Exception ex)
{
panelFailed = true;
Log.LogError((object)("Achievement panel integration disabled: " + ex));
Harness.Report((NoticeLevel)2, "Custom Achievements", "自定义成就无法接入成就面板,成就仍会正常记录。详情见日志。", "Custom achievements could not be added to the achievement panel; progress is still recorded. See the log.", (string)null, (string)null);
}
}
private void OnApplicationQuit()
{
Store.Save();
}
private void OnDestroy()
{
Store.Save();
}
private static void ShowUnlocks()
{
foreach (AchRecord item in Store.TakeJustUnlocked())
{
try
{
if (!UnlockPopup.Show(item))
{
UIRealtimeTip.Popup(Line.op_Implicit(Lang.En("Achievement unlocked: ").ZhCN("成就解锁:")) + item.Name, true, 0);
}
}
catch (Exception ex)
{
Log.LogWarning((object)("Unlock popup failed: " + ex.Message));
}
}
}
}
internal sealed class ModRecord
{
internal string Id;
internal AchText Name;
internal bool Installed;
internal readonly List<AchRecord> Achievements = new List<AchRecord>();
internal AchRecord Find(string key)
{
foreach (AchRecord achievement in Achievements)
{
if (achievement.Key == key)
{
return achievement;
}
}
return null;
}
}
internal sealed class AchRecord
{
internal ModRecord Mod;
internal string Key;
internal AchText Name;
internal AchText Description;
internal long Target = 1L;
internal long Progress;
internal bool Unlocked;
internal long UnlockedUtcTicks;
internal bool Registered;
internal bool AllowSandbox;
internal string IconRef;
internal byte[] IconPng;
internal string FullId => Mod.Id + "#" + Key;
}
internal static class Store
{
private const int Magic = 1751335235;
private const int FormatVersion = 2;
private const double SaveDelaySeconds = 2.0;
internal static readonly object Sync = new object();
private static readonly List<ModRecord> mods = new List<ModRecord>();
private static readonly Queue<AchRecord> justUnlocked = new Queue<AchRecord>();
private static string path;
private static bool dirty;
private static DateTime lastChangeUtc;
internal static bool Loaded { get; private set; }
internal static int Version { get; private set; }
private static string IconDir => Path.Combine(Path.GetDirectoryName(path), "icons");
internal static ModRecord GetOrAddMod(string id, AchText name)
{
lock (Sync)
{
ModRecord modRecord = FindMod(id);
if (modRecord == null)
{
modRecord = new ModRecord
{
Id = id
};
mods.Add(modRecord);
}
modRecord.Name = name;
modRecord.Installed = true;
MarkDirty();
return modRecord;
}
}
internal static AchRecord GetOrAddAchievement(ModRecord mod, string key, AchText name, AchText description, long target, AchIcon icon, bool allowSandbox)
{
lock (Sync)
{
AchRecord achRecord = mod.Find(key);
if (achRecord == null)
{
achRecord = new AchRecord
{
Mod = mod,
Key = key
};
mod.Achievements.Add(achRecord);
}
achRecord.Name = name;
achRecord.Description = description;
achRecord.Target = target;
achRecord.AllowSandbox = allowSandbox;
achRecord.IconRef = icon?.Ref;
achRecord.IconPng = icon?.Png;
achRecord.Registered = true;
MarkDirty();
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)("Registered achievement " + achRecord.FullId));
}
return achRecord;
}
}
internal static bool CanProgress(AchRecord rec)
{
if (!Loaded || rec.Unlocked || !rec.Registered)
{
return false;
}
GameData data = GameMain.data;
if (!rec.AllowSandbox && data != null)
{
return !data.gameDesc.isSandboxMode;
}
return true;
}
internal static void SetProgress(AchRecord rec, long value)
{
lock (Sync)
{
if (CanProgress(rec))
{
if (value < 0)
{
value = 0L;
}
if (value >= rec.Target)
{
UnlockLocked(rec);
}
else if (value != rec.Progress)
{
rec.Progress = value;
MarkDirty();
}
}
}
}
internal static void AddProgress(AchRecord rec, long delta)
{
lock (Sync)
{
SetProgress(rec, rec.Progress + delta);
}
}
internal static void Unlock(AchRecord rec)
{
lock (Sync)
{
if (CanProgress(rec))
{
UnlockLocked(rec);
}
}
}
private static void UnlockLocked(AchRecord rec)
{
rec.Progress = rec.Target;
rec.Unlocked = true;
rec.UnlockedUtcTicks = DateTime.UtcNow.Ticks;
justUnlocked.Enqueue(rec);
MarkDirty();
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)("Achievement unlocked: " + rec.FullId));
}
}
internal static List<AchRecord> TakeJustUnlocked()
{
lock (Sync)
{
List<AchRecord> result = new List<AchRecord>(justUnlocked);
justUnlocked.Clear();
return result;
}
}
internal static List<ModRecord> SnapshotMods()
{
lock (Sync)
{
List<ModRecord> list = new List<ModRecord>(mods);
list.Sort((ModRecord a, ModRecord b) => (a.Installed != b.Installed) ? ((!a.Installed) ? 1 : (-1)) : string.Compare(a.Name.ToString(), b.Name.ToString(), StringComparison.CurrentCultureIgnoreCase));
return list;
}
}
private static ModRecord FindMod(string id)
{
foreach (ModRecord mod in mods)
{
if (mod.Id == id)
{
return mod;
}
}
return null;
}
private static void MarkDirty()
{
dirty = true;
lastChangeUtc = DateTime.UtcNow;
Version++;
}
internal static byte[] ReadIcon(string hash)
{
if (!Loaded || !IsHash(hash))
{
return null;
}
string text = Path.Combine(IconDir, hash + ".png");
if (!File.Exists(text))
{
return null;
}
return File.ReadAllBytes(text);
}
private static bool IsHash(string s)
{
if (s == null || s.Length != 40)
{
return false;
}
foreach (char c in s)
{
if ((c < '0' || c > '9') && (c < 'a' || c > 'f'))
{
return false;
}
}
return true;
}
private static void WriteIcons()
{
foreach (ModRecord mod in mods)
{
foreach (AchRecord achievement in mod.Achievements)
{
if (achievement.IconPng == null || achievement.IconRef == null || !achievement.IconRef.StartsWith("png:", StringComparison.Ordinal))
{
continue;
}
string text = achievement.IconRef.Substring(4);
if (IsHash(text))
{
string text2 = Path.Combine(IconDir, text + ".png");
if (!File.Exists(text2))
{
Directory.CreateDirectory(IconDir);
File.WriteAllBytes(text2, achievement.IconPng);
}
}
}
}
}
private static string ResolvePath()
{
string directoryName = Path.GetDirectoryName(GameConfig.achievementFolder.TrimEnd('/', '\\'));
string text = "local";
try
{
if (!((AccountData)(ref AccountData.me)).isNull)
{
text = ((object)Unsafe.As<ESalePlatform, ESalePlatform>(ref AccountData.me.platform)/*cast due to .constrained prefix*/).ToString() + "_" + AccountData.me.userId;
}
}
catch
{
}
return Path.Combine(Path.Combine(directoryName, "CustomAchievements"), text + ".dat");
}
internal static void Load()
{
lock (Sync)
{
if (Loaded)
{
return;
}
path = ResolvePath();
if (File.Exists(path))
{
try
{
using BinaryReader r = new BinaryReader(File.OpenRead(path));
Read(r);
}
catch (Exception ex)
{
string text = path + ".bad-" + DateTime.Now.ToString("yyyyMMdd-HHmmss");
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogError((object)("Achievement file is unreadable, kept a copy at " + text + "\n" + ex));
}
try
{
File.Copy(path, text, overwrite: true);
}
catch (Exception ex2)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogError((object)("Backup failed: " + ex2.Message));
}
}
}
}
Loaded = true;
dirty = true;
ManualLogSource log3 = Plugin.Log;
if (log3 != null)
{
log3.LogInfo((object)("Achievement file: " + path));
}
foreach (ModRecord mod in mods)
{
int num = 0;
foreach (AchRecord achievement in mod.Achievements)
{
if (achievement.Unlocked)
{
num++;
}
}
string text2 = (mod.Installed ? "installed" : "not installed, frozen");
ManualLogSource log4 = Plugin.Log;
if (log4 != null)
{
log4.LogInfo((object)$" {mod.Id} ({mod.Name.English}, {text2}): {num}/{mod.Achievements.Count} unlocked");
}
}
}
}
internal static void SaveIfDue()
{
if (dirty && Loaded && (DateTime.UtcNow - lastChangeUtc).TotalSeconds >= 2.0)
{
Save();
}
}
internal static void Save()
{
lock (Sync)
{
if (!Loaded || !dirty)
{
return;
}
try
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
WriteIcons();
string sourceFileName = path + ".tmp";
using (BinaryWriter w = new BinaryWriter(File.Create(sourceFileName)))
{
Write(w);
}
if (File.Exists(path))
{
File.Copy(path, path + ".bak", overwrite: true);
File.Delete(path);
}
File.Move(sourceFileName, path);
dirty = false;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)"Achievement file saved");
}
}
catch (Exception ex)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogError((object)("Saving achievements failed: " + ex));
}
lastChangeUtc = DateTime.UtcNow;
}
}
}
private static void Write(BinaryWriter w)
{
w.Write(1751335235);
w.Write(2);
w.Write(mods.Count);
foreach (ModRecord mod in mods)
{
w.Write(mod.Id);
mod.Name.Write(w);
w.Write(mod.Achievements.Count);
foreach (AchRecord achievement in mod.Achievements)
{
w.Write(achievement.Key);
achievement.Name.Write(w);
achievement.Description.Write(w);
w.Write(achievement.Target);
w.Write(achievement.Progress);
w.Write(achievement.Unlocked);
w.Write(achievement.UnlockedUtcTicks);
w.Write(achievement.IconRef ?? "");
}
}
}
private static void Read(BinaryReader r)
{
if (r.ReadInt32() != 1751335235)
{
throw new InvalidDataException("not a custom achievement file");
}
int num = r.ReadInt32();
if (num > 2)
{
throw new InvalidDataException("file version " + num + " is newer than this mod");
}
int num2 = r.ReadInt32();
for (int i = 0; i < num2; i++)
{
string id = r.ReadString();
AchText name = AchText.Read(r);
ModRecord modRecord = FindMod(id);
if (modRecord == null)
{
modRecord = new ModRecord
{
Id = id,
Name = name,
Installed = false
};
mods.Add(modRecord);
}
int num3 = r.ReadInt32();
for (int j = 0; j < num3; j++)
{
string key = r.ReadString();
AchText name2 = AchText.Read(r);
AchText description = AchText.Read(r);
long target = r.ReadInt64();
long progress = r.ReadInt64();
bool unlocked = r.ReadBoolean();
long unlockedUtcTicks = r.ReadInt64();
string iconRef = ((num >= 2) ? r.ReadString() : "");
AchRecord achRecord = modRecord.Find(key);
if (achRecord == null)
{
achRecord = new AchRecord
{
Mod = modRecord,
Key = key,
Name = name2,
Description = description,
Target = target,
IconRef = iconRef
};
modRecord.Achievements.Add(achRecord);
}
achRecord.Progress = progress;
achRecord.Unlocked = unlocked;
achRecord.UnlockedUtcTicks = unlockedUtcTicks;
if (!achRecord.Unlocked && achRecord.Progress >= achRecord.Target)
{
if (achRecord.Registered)
{
UnlockLocked(achRecord);
}
else
{
achRecord.Progress = achRecord.Target;
}
}
}
}
}
}
internal static class UnlockPopup
{
private static readonly FieldInfo cardsField = AccessTools.Field(typeof(UIVariousPopupGroup), "cards");
private static readonly MethodInfo refreshLayout = AccessTools.Method(typeof(UIVariousPopupGroup), "RefreshCardsLayout", (Type[])null, (Type[])null);
private static readonly FieldInfo iconField = AccessTools.Field(typeof(AchievementProto), "_iconSprite");
private static readonly MethodInfo dataSetter = AccessTools.PropertySetter(typeof(ManualBehaviour), "data");
internal static bool Show(AchRecord rec)
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Expected O, but got Unknown
UIRoot instance = UIRoot.instance;
if ((Object)(object)instance == (Object)null || (Object)(object)instance.uiGame == (Object)null)
{
return false;
}
UIVariousPopupGroup variousPopupGroup = instance.uiGame.variousPopupGroup;
if ((Object)(object)variousPopupGroup == (Object)null || !((ManualBehaviour)variousPopupGroup).inited || !(cardsField?.GetValue(variousPopupGroup) is List<UIVariousPopupCard> list) || refreshLayout == null || iconField == null || dataSetter == null)
{
return false;
}
AchievementProto val = new AchievementProto
{
name = rec.Name.ToString(),
description = rec.Description.ToString()
};
iconField.SetValue(val, IconCache.Get(rec.IconRef, rec.IconPng));
UIVariousPopupCard val2 = Object.Instantiate<UIVariousPopupCard>(variousPopupGroup.achievementCardPrefab, ((Transform)variousPopupGroup.achievementCardPrefab.rectTrans).parent);
((ManualBehaviour)val2)._Create();
((ManualBehaviour)val2)._Init((object)val);
((ManualBehaviour)val2)._Open();
dataSetter.Invoke(val2, new object[1]);
((Component)val2).gameObject.AddComponent<PopupClick>().FullId = rec.FullId;
list.Insert(0, val2);
refreshLayout.Invoke(variousPopupGroup, null);
((Component)variousPopupGroup).transform.SetAsLastSibling();
variousPopupGroup.scrollBox.verticalNormalizedPosition = 1f;
return true;
}
}
internal sealed class PopupClick : MonoBehaviour, IPointerUpHandler, IEventSystemHandler
{
internal string FullId;
public void OnPointerUp(PointerEventData eventData)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
if (eventData != null && !eventData.dragging && (int)eventData.button == 0)
{
PanelView.Reveal(FullId);
}
}
}
}