Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CityBuilderBetaTracker v1.3.6
CityBuilderBetaTracker.dll
Decompiled 5 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; using ValheimAnno; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CityBuilderBeta { [BepInPlugin("1day2die.citybuilder.betatracker", "CityBuilder Beta Tracker", "1.3.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class BetaTracker : BaseUnityPlugin { [Serializable] public class Entry { public string id; public string mode; public string ver; public int uses; public int verdict; public string note = ""; } [Serializable] public class State { public List<Entry> queue = new List<Entry>(); public List<string> seen = new List<string>(); public List<string> rated = new List<string>(); } [Serializable] public class ReportBody { public string p_code; public string p_version; public string p_valheim; public List<Entry> p_entries; } [Serializable] public class RegisterBody { public string p_name; } public const string Guid = "1day2die.citybuilder.betatracker"; public const string Version = "1.3.6"; private const int MaxNameLength = 32; private const float SteamNameRetrySeconds = 10f; public const string Site = "https://valheimcitybuilder.com/beta"; private const string Api = "https://valheimcitybuilder.com/api/rpc/"; private static readonly string[] ModeNames = new string[4] { "sp", "mp_host", "mp_client", "dedicated" }; private static bool open; private ConfigEntry<string> cfgName; private ConfigEntry<string> cfgCode; private ConfigEntry<bool> cfgSteamName; private float steamNameRetryAt; private ConfigEntry<Key> cfgKey; private ConfigEntry<bool> cfgPopups; private ConfigEntry<float> cfgPopupSeconds; private ConfigEntry<Key> cfgWorksKey; private ConfigEntry<Key> cfgProblemKey; private State state = new State(); private string statePath; private readonly List<string> pending = new List<string>(); private string mode; private float inWorldT = -1f; private float sendT = 20f; private bool busy; private string lastResult = "nothing sent yet"; private bool placed; private Rect win = new Rect(0f, 0f, 900f, 660f); private Vector2 scroll; private int area; private string noteFor; private string noteText = ""; private int noteVerdict; private string nameField = ""; private readonly List<string> popups = new List<string>(); private float popT; private string popAction; private string focusId; private GUIStyle sWin; private GUIStyle sText; private GUIStyle sDim; private GUIStyle sHead; private GUIStyle sRow; private GUIStyle sRowAlt; private GUIStyle sBox; private GUIStyle sTab; private GUIStyle sBtn; private GUIStyle sField; private bool active; private static readonly FieldInfo fiOverlayRect = typeof(Features).GetField("OverlayRect"); private static readonly FieldInfo fiOverlayFrame = typeof(Features).GetField("OverlayFrame"); private bool Named { get { if (!string.IsNullOrEmpty(cfgName.Value)) { return cfgName.Value.Trim().Length >= 2; } return false; } } private void Awake() { if (AccessTools.TypeByName("ValheimAnno.Features")?.Assembly.GetName().Name != "WorldEdit") { ((BaseUnityPlugin)this).Logger.LogWarning((object)"This Valheim City Builder is older than 1.8.0 (no beta hooks in World Edit), the Beta Tracker stays off. Update the mod to take part."); ((Behaviour)this).enabled = false; } else { active = true; Init(); } } [MethodImpl(MethodImplOptions.NoInlining)] private void Init() { //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown cfgName = ((BaseUnityPlugin)this).Config.Bind<string>("Tester", "Name", "", "Your tester name on the website. Nothing is sent while it is empty."); cfgCode = ((BaseUnityPlugin)this).Config.Bind<string>("Tester", "Code", "", "Filled in by the tracker when it first reaches the website. Keep it to stay the same tester."); cfgSteamName = ((BaseUnityPlugin)this).Config.Bind<bool>("Tester", "UseSteamName", true, "When Name is empty, takes your Steam name as tester name. False: nothing is sent until you set a name yourself."); cfgKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Tester", "PanelKey", (Key)102, "Opens the list of features to rate"); cfgPopups = ((BaseUnityPlugin)this).Config.Bind<bool>("Popup", "Enabled", true, "Show a popup the first time you use a feature in a game mode, to rate it right away"); cfgPopupSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Popup", "Seconds", 20f, "How long each popup stays before the next one (it stays in the F9 list either way)"); cfgWorksKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Popup", "WorksKey", (Key)67, "Rates the feature in the popup as working (None = off)"); cfgProblemKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Popup", "ProblemKey", (Key)66, "Opens the panel to describe a problem with the feature in the popup (None = off)"); nameField = cfgName.Value; statePath = Path.Combine(Paths.ConfigPath, "citybuilder_beta_state.json"); Load(); Features.Used += OnUsed; Harmony h = new Harmony("1day2die.citybuilder.betatracker"); Patch(h, typeof(Player), "TakeInput", "NoInput", prefix: false); Patch(h, typeof(PlayerController), "TakeInput", "NoInput", prefix: false); Patch(h, typeof(GameCamera), "UpdateMouseCapture", "SkipCapture", prefix: true); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Beta Tracker 1.3.6 for Valheim City Builder " + Features.Version + ", " + Features.All.features.Count + " features" + (Named ? (", tester " + cfgName.Value) : " – set a tester name (F9 or config) to take part"))); } private void Patch(Harmony h, Type t, string method, string patch, bool prefix) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown try { HarmonyMethod val = new HarmonyMethod(typeof(BetaTracker), patch, (Type[])null); h.Patch((MethodBase)AccessTools.Method(t, method, (Type[])null, (Type[])null), prefix ? val : null, prefix ? null : val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Patch " + t.Name + "." + method + ": " + ex.Message)); } } private static void NoInput(ref bool __result) { if (open) { __result = false; } } private static bool SkipCapture() { return !open; } private void OnUsed(string id) { if (pending.Count < 1000) { pending.Add(id); } } private static string Mode() { if (ZNet.IsSinglePlayer) { return "sp"; } if (ZNet.instance.IsServer()) { return "mp_host"; } if (!ZNet.instance.IsCurrentServerDedicated()) { return "mp_client"; } return "dedicated"; } private void Update() { //IL_010c: Unknown result type (might be due to invalid IL or missing references) TryTakeSteamName(); if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null) { inWorldT = -1f; mode = null; } else { if (inWorldT < 0f) { inWorldT = Time.time; } if (mode == null && Time.time - inWorldT > 8f) { mode = Mode(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Game mode: " + ModeText(mode))); } } if (mode != null && pending.Count > 0) { foreach (string item in pending) { Add(item, mode, 1, 0, ""); } pending.Clear(); Save(); } Keyboard current2 = Keyboard.current; if (current2 != null && ((ButtonControl)current2[cfgKey.Value]).wasPressedThisFrame && !Typing()) { open = !open; noteFor = null; focusId = null; } if (open) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } TickPopup(current2); sendT -= Time.unscaledDeltaTime; if (sendT <= 0f && !busy) { sendT = 60f; Send(); } } private void TryTakeSteamName() { if (!Named && cfgSteamName.Value && string.IsNullOrWhiteSpace(cfgName.Value) && !(Time.unscaledTime < steamNameRetryAt)) { steamNameRetryAt = Time.unscaledTime + 10f; string text = SteamPersonaName(); if (text.Length >= 2) { cfgName.Value = text; nameField = text; ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Tester name taken from Steam: " + text)); } } } private static string SteamPersonaName() { try { string text = (((AccessTools.TypeByName("Steamworks.SteamFriends")?.GetMethod("GetPersonaName", BindingFlags.Static | BindingFlags.Public))?.Invoke(null, null) as string) ?? "").Trim(); return text.Substring(0, Math.Min(32, text.Length)); } catch (Exception) { return ""; } } private static bool Typing() { try { if (((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || Console.IsVisible() || TextInput.IsVisible()) { return true; } } catch { } return false; } private void TickPopup(Keyboard kb) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) if (popups.Count == 0 || open) { return; } if (mode == null || !cfgPopups.Value) { popups.Clear(); return; } string text = popAction; popAction = null; switch (text) { case "works": RateWorks(popups[0]); return; case "problem": AskProblem(popups[0]); return; case "later": NextPopup(); return; case "skip": popups.Clear(); return; } if (kb != null && !Typing()) { if (Pressed(kb, cfgWorksKey.Value)) { RateWorks(popups[0]); return; } if (Pressed(kb, cfgProblemKey.Value)) { AskProblem(popups[0]); return; } } popT -= Time.unscaledDeltaTime; if (popT <= 0f) { NextPopup(); } } private static bool Pressed(Keyboard kb, Key k) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) if ((int)k != 0) { return ((ButtonControl)kb[k]).wasPressedThisFrame; } return false; } private void NextPopup() { if (popups.Count > 0) { popups.RemoveAt(0); } popT = Mathf.Max(5f, cfgPopupSeconds.Value); } private void RateWorks(string id) { Add(id, mode, 0, 1, ""); Save(); NextPopup(); } private void AskProblem(string id) { NextPopup(); open = true; focusId = id; noteFor = id; noteVerdict = -1; noteText = ""; } private bool Rated(string id, string m) { return RatingOf(id, m) != null; } private string RatingOf(string id, string m) { Info val = FeatureInfo(id); string since = ((val != null && !string.IsNullOrEmpty(val.changed)) ? val.changed : Features.Version); string text = id + "|" + m + "|"; return (from r in state.rated where r.StartsWith(text) && VerAtLeast(r.Substring(text.Length).Split('|')[0], since) orderby ParseVer(r.Substring(text.Length).Split('|')[0]) descending select r).FirstOrDefault(); } private static Version ParseVer(string v) { if (!System.Version.TryParse(v, out Version result)) { return new Version(0, 0); } return result; } private static bool VerAtLeast(string a, string b) { return ParseVer(a) >= ParseVer(b); } private void Add(string id, string m, int uses, int verdict, string note) { string ver = Features.Version; string text = id + "|" + m + "|" + ver; if (uses > 0 && !state.seen.Contains(text)) { state.seen.Add(text); if (verdict == 0 && cfgPopups.Value && !Rated(id, m) && !popups.Contains(id) && popups.Count < 50) { if (popups.Count == 0) { popT = Mathf.Max(5f, cfgPopupSeconds.Value); } popups.Add(id); } } if (verdict != 0) { state.rated.RemoveAll((string r) => r.StartsWith(text + "|")); state.rated.Add(text + "|" + verdict); } Entry entry = ((verdict == 0) ? state.queue.FirstOrDefault((Entry e) => e.id == id && e.mode == m && e.ver == ver && e.verdict == 0) : null); if (entry != null) { entry.uses += uses; } else if (state.queue.Count < 2000) { state.queue.Add(new Entry { id = id, mode = m, ver = ver, uses = uses, verdict = verdict, note = (note ?? "").Trim() }); } if (verdict != 0) { sendT = Mathf.Min(sendT, 2f); } } private void Send() { if (!Named) { return; } if (string.IsNullOrEmpty(cfgCode.Value)) { ((MonoBehaviour)this).StartCoroutine(Register()); } else { if (state.queue.Count == 0) { return; } string ver = state.queue[0].ver; List<Entry> batch = state.queue.Where((Entry e) => e.ver == ver).Take(200).ToList(); ReportBody reportBody = new ReportBody { p_code = cfgCode.Value, p_version = ver, p_valheim = Version.GetVersionString(false), p_entries = batch }; ((MonoBehaviour)this).StartCoroutine(Post("report", MiniJson.Write((object)reportBody), delegate(bool ok, string text) { if (ok) { foreach (Entry item in batch) { state.queue.Remove(item); } lastResult = "sent " + batch.Count + " at " + DateTime.Now.ToString("HH:mm"); Save(); if (state.queue.Count > 0) { sendT = 5f; } } else { lastResult = "not sent: " + Short(text); if (text.Contains("unknown tester code")) { cfgCode.Value = ""; sendT = 5f; } else { sendT = 120f; } } })); } } private IEnumerator Register() { string p_name = cfgName.Value.Trim(); yield return Post("register_tester", MiniJson.Write((object)new RegisterBody { p_name = p_name }), delegate(bool ok, string answer) { string text = answer.Trim().Trim('"'); if (ok && text.Length >= 16) { cfgCode.Value = text; ((BaseUnityPlugin)this).Config.Save(); lastResult = "registered as " + cfgName.Value.Trim() + " – on the website once 1Day2Die approves you"; sendT = 2f; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered as beta tester " + cfgName.Value.Trim())); } else { lastResult = "registration failed: " + Short(answer); sendT = 300f; } }); } private IEnumerator Post(string fn, string json, Action<bool, string> done) { busy = true; UnityWebRequest req = new UnityWebRequest("https://valheimcitybuilder.com/api/rpc/" + fn, "POST"); try { req.uploadHandler = (UploadHandler)new UploadHandlerRaw(Encoding.UTF8.GetBytes(json)); req.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); req.SetRequestHeader("Content-Type", "application/json"); req.timeout = 20; yield return req.SendWebRequest(); bool arg = (int)req.result == 1; string arg2 = ((req.downloadHandler != null && !string.IsNullOrEmpty(req.downloadHandler.text)) ? req.downloadHandler.text : (req.error ?? "")); busy = false; try { done(arg, arg2); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Beta tracker: " + ex.Message)); } } finally { busy = false; req.Dispose(); } } private static string Short(string s) { s = (s ?? "").Replace("\n", " "); if (s.Length <= 90) { return s; } return s.Substring(0, 90) + "…"; } private void Load() { try { if (File.Exists(statePath)) { state = MiniJson.Read<State>(File.ReadAllText(statePath)) ?? new State(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Beta tracker state: " + ex.Message)); state = new State(); } } private void Save() { try { File.WriteAllText(statePath, MiniJson.Write((object)state)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Beta tracker state: " + ex.Message)); } } private void OnDestroy() { if (active) { Save(); } } private static string ModeText(string m) { return m switch { "sp" => "singleplayer", "mp_host" => "multiplayer (host)", "mp_client" => "multiplayer (client)", "dedicated" => "dedicated server", _ => "not in a world", }; } private static Texture2D Tex(Color c) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1) { hideFlags = (HideFlags)61 }; val.SetPixel(0, 0, c); val.Apply(); return val; } private void Styles() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //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_008c: Expected O, but got Unknown //IL_0091: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Expected O, but got Unknown //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_01a4: 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_01b3: Expected O, but got Unknown //IL_01b8: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Expected O, but got Unknown //IL_0226: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_029d: 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_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: 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_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Expected O, but got Unknown //IL_02fd: 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_035c: 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_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Expected O, but got Unknown if (sWin == null) { Color val = default(Color); ((Color)(ref val))..ctor(0.94f, 0.91f, 0.85f); Color textColor = default(Color); ((Color)(ref textColor))..ctor(0.76f, 0.73f, 0.67f); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.98f, 0.83f, 0.48f); sWin = new GUIStyle(GUI.skin.window) { fontSize = 16, fontStyle = (FontStyle)1, padding = new RectOffset(16, 16, 34, 14), border = new RectOffset(0, 0, 0, 0) }; GUIStyleState normal = sWin.normal; Texture2D background = (sWin.onNormal.background = Tex(new Color(0.09f, 0.085f, 0.075f, 0.98f))); normal.background = background; GUIStyleState normal2 = sWin.normal; Color textColor2 = (sWin.onNormal.textColor = val2); normal2.textColor = textColor2; sText = new GUIStyle(GUI.skin.label) { fontSize = 15, richText = true, alignment = (TextAnchor)3 }; sText.normal.textColor = val; sDim = new GUIStyle(sText) { fontSize = 13, wordWrap = true }; sDim.normal.textColor = textColor; sHead = new GUIStyle(sText) { fontSize = 16 }; sHead.normal.textColor = val2; sRow = new GUIStyle { padding = new RectOffset(8, 8, 2, 2), margin = new RectOffset(0, 0, 0, 0) }; sRow.normal.background = Tex(new Color(1f, 1f, 1f, 0.06f)); sRowAlt = new GUIStyle(sRow); sRowAlt.normal.background = null; sBox = new GUIStyle { padding = new RectOffset(14, 14, 10, 10) }; sBox.normal.background = Tex(new Color(0.15f, 0.14f, 0.12f, 0.98f)); sBtn = new GUIStyle(GUI.skin.button) { fontSize = 14, fixedHeight = 26f }; GUIStyleState normal3 = sBtn.normal; GUIStyleState hover = sBtn.hover; Color val5 = (sBtn.active.textColor = val); textColor2 = (hover.textColor = val5); normal3.textColor = textColor2; sTab = new GUIStyle(sBtn); GUIStyleState onNormal = sTab.onNormal; GUIStyleState onHover = sTab.onHover; Texture2D val8 = (sTab.onActive.background = Tex(new Color(0.78f, 0.62f, 0.3f, 1f))); background = (onHover.background = val8); onNormal.background = background; GUIStyleState onNormal2 = sTab.onNormal; GUIStyleState onHover2 = sTab.onHover; GUIStyleState onActive = sTab.onActive; ((Color)(ref val5))..ctor(0.1f, 0.09f, 0.07f); onActive.textColor = val5; textColor2 = (onHover2.textColor = val5); onNormal2.textColor = textColor2; sField = new GUIStyle(GUI.skin.textField) { fontSize = 14, fixedHeight = 26f }; } } private void OnGUI() { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_00ed: 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_00f8: Unknown result type (might be due to invalid IL or missing references) Styles(); GUI.depth = -1000; if (open) { if (!placed) { placed = true; ((Rect)(ref win)).width = Mathf.Min(((Rect)(ref win)).width, (float)Screen.width - 20f); ((Rect)(ref win)).height = Mathf.Min(((Rect)(ref win)).height, (float)Screen.height - 20f); ((Rect)(ref win)).x = ((float)Screen.width - ((Rect)(ref win)).width) / 2f; ((Rect)(ref win)).y = ((float)Screen.height - ((Rect)(ref win)).height) / 2f; } win = GUI.Window(1128749, win, new WindowFunction(DrawWindow), "CityBuilder Beta Tracker 1.3.6 · mod " + Features.Version, sWin); Block(win); } else if (popups.Count > 0 && mode != null && cfgPopups.Value) { DrawPopup(); } } private static void Block(Rect r) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!(fiOverlayRect == null) && !(fiOverlayFrame == null)) { fiOverlayRect.SetValue(null, r); fiOverlayFrame.SetValue(null, Time.frameCount); } } private static Info FeatureInfo(string id) { return ((IEnumerable<Info>)Features.All.features).FirstOrDefault((Func<Info, bool>)((Info f) => f.id == id)); } private unsafe static string KeyHint(Key k) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)k != 0) { return " (" + ((object)(*(Key*)(&k))/*cast due to .constrained prefix*/).ToString() + ")"; } return ""; } private void DrawPopup() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: 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_02a4: Invalid comparison between Unknown and I4 Info val = FeatureInfo(popups[0]); if (val == null) { popAction = "later"; return; } float num = Mathf.Min(640f, (float)Screen.width - 40f); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((float)Screen.width - num) / 2f, 90f, num, 122f); Block(val2); GUILayout.BeginArea(val2, sBox); GUILayout.Label("Tested: <b>" + val.title_en + "</b>" + ((popups.Count > 1) ? (" <color=#b3b0a3>(" + (popups.Count - 1) + " more)</color>") : ""), sHead, Array.Empty<GUILayoutOption>()); GUILayout.Label(val.desc_en + " <color=#8d8a80>· " + ModeText(mode) + "</color>", sDim, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Works" + KeyHint(cfgWorksKey.Value), sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) })) { popAction = "works"; } if (GUILayout.Button("Problem" + KeyHint(cfgProblemKey.Value), sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(190f) })) { popAction = "problem"; } if (GUILayout.Button("Later", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { popAction = "later"; } GUILayout.FlexibleSpace(); if (popups.Count > 1 && GUILayout.Button("Skip all", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { popAction = "skip"; } GUILayout.EndHorizontal(); GUILayout.EndArea(); float num2 = Mathf.Clamp01(popT / Mathf.Max(5f, cfgPopupSeconds.Value)); GUI.DrawTexture(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).yMax - 3f, ((Rect)(ref val2)).width * num2, 3f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.98f, 0.83f, 0.48f, 0.8f), 0f, 0f); Event current = Event.current; if ((current.isMouse || (int)current.type == 6) && ((Rect)(ref val2)).Contains(current.mousePosition)) { current.Use(); } } private bool Used(string id, params string[] modes) { string ver = Features.Version; return modes.Any((string m) => state.seen.Contains(id + "|" + m + "|" + ver)); } private string Badge(string label, string id, params string[] modes) { if (!Used(id, modes)) { return "<color=#8d8a80>" + label + "</color>"; } return "<color=#7ddc6a><b>" + label + "</b></color>"; } private void NoteRow(Info feature) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label((noteVerdict > 0) ? "Works – note (optional):" : "What went wrong?", sText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); noteText = GUILayout.TextField(noteText ?? "", 300, sField, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(470f) }); if (GUILayout.Button("Send", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }) && mode != null) { Add(feature.id, mode, 0, noteVerdict, noteText); Save(); sendT = Mathf.Min(sendT, 2f); noteFor = null; if (focusId == feature.id) { focusId = null; open = false; } } if (GUILayout.Button("×", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) })) { noteFor = null; focusId = null; } GUILayout.EndHorizontal(); } private void DrawWindow(int id) { //IL_02ea: 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_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_066a: Unknown result type (might be due to invalid IL or missing references) //IL_066f: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_04aa: Expected O, but got Unknown GUILayout.Label("Tester: <b>" + (Named ? cfgName.Value.Trim() : "–") + "</b> · Mode: <b>" + ModeText(mode) + "</b> · " + state.queue.Count + " waiting, " + lastResult, sText, Array.Empty<GUILayoutOption>()); if (!Named || string.IsNullOrEmpty(cfgCode.Value)) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(Named ? "Registering soon – or change the name:" : "Pick a tester name to take part:", sText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) }); nameField = GUILayout.TextField(nameField ?? "", 32, sField, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); if (GUILayout.Button("Save name", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }) && nameField.Trim().Length >= 2) { cfgName.Value = nameField.Trim(); cfgCode.Value = ""; ((BaseUnityPlugin)this).Config.Save(); sendT = 1f; } GUILayout.EndHorizontal(); } Info val = ((focusId != null) ? FeatureInfo(focusId) : null); if (val != null) { GUILayout.BeginVertical(sBox, Array.Empty<GUILayoutOption>()); GUILayout.Label("Problem with: <b>" + val.title_en + "</b> <color=#8d8a80>(" + ModeText(mode) + ")</color>", sHead, Array.Empty<GUILayoutOption>()); GUILayout.Label(val.desc_en, sDim, Array.Empty<GUILayoutOption>()); NoteRow(val); GUILayout.EndVertical(); GUILayout.Space(6f); } List<string> list = new List<string> { "All" }; list.AddRange(Features.All.features.Select((Info f) => f.area).Distinct()); area = GUILayout.SelectionGrid(Mathf.Clamp(area, 0, list.Count - 1), list.ToArray(), 5, sTab, Array.Empty<GUILayoutOption>()); GUILayout.Space(4f); GUILayout.Label("Green = you used it in this mode with this version. Works / Problem: your verdict for " + ModeText(mode) + " (kept until the feature changes).", sDim, Array.Empty<GUILayoutOption>()); scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>()); int num = 0; foreach (Info feature in Features.All.features) { if (area <= 0 || !(feature.area != list[area])) { string text = ((mode != null) ? RatingOf(feature.id, mode) : null); GUILayout.BeginHorizontal((num++ % 2 == 0) ? sRow : sRowAlt, Array.Empty<GUILayoutOption>()); GUILayout.Label(Badge("SP", feature.id, "sp") + " " + Badge("MP", feature.id, "mp_host", "mp_client") + " " + Badge("DS", feature.id, "dedicated"), sText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); GUILayout.Label(new GUIContent(feature.title_en + ((feature.kind == "fix") ? " <color=#8d8a80>(fix)</color>" : "") + ((text == null) ? "" : (text.EndsWith("|1") ? " <color=#7ddc6a>works</color>" : " <color=#ff7a62>problem</color>")), feature.desc_en), sText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(530f) }); GUI.enabled = mode != null; if (GUILayout.Button("Works", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { noteFor = feature.id; noteVerdict = 1; noteText = ""; } if (GUILayout.Button("Problem", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { noteFor = feature.id; noteVerdict = -1; noteText = ""; } GUI.enabled = true; GUILayout.EndHorizontal(); if (noteFor == feature.id && focusId != feature.id) { NoteRow(feature); } } } GUILayout.EndScrollView(); GUILayout.BeginVertical(sBox, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(44f) }); GUILayout.Label(string.IsNullOrEmpty(GUI.tooltip) ? "Point at a feature to read what it does." : GUI.tooltip, sDim, Array.Empty<GUILayoutOption>()); GUILayout.EndVertical(); GUILayout.Space(4f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Open website", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) })) { Application.OpenURL("https://valheimcitybuilder.com/beta"); } if (GUILayout.Button("Send now", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) })) { sendT = 0f; } GUILayout.FlexibleSpace(); if (GUILayout.Button("Close (" + ((object)cfgKey.Value/*cast due to .constrained prefix*/).ToString() + ")", sBtn, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) })) { open = false; focusId = null; } GUILayout.EndHorizontal(); GUI.DragWindow(); } } }