Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of SideHustle v1.0.1
SideHustle.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne.UI.MainMenu; using Il2CppTMPro; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using S1API.UI; using SideHustle; using SideHustle.Config; using SideHustle.Internal; using SideHustle.Menu; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Core), "Side Hustle", "1.0.1", "DooDesch", "https://github.com/DooDesch-Mods/ScheduleOne-SideHustle")] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("SideHustle")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+a45b891494544be0e62deff94f429094b8e23308")] [assembly: AssemblyProduct("SideHustle")] [assembly: AssemblyTitle("SideHustle")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.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 DooDesch.UI { public enum Severity { Info, Success, Warning, Danger } public static class Components { public static void SeverityColors(Severity s, out Color bar, out Color text, out Color bg) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) switch (s) { case Severity.Success: bar = Theme.Success; text = Theme.SuccessText; bg = Theme.SuccessSubtle; break; case Severity.Warning: bar = Theme.Warning; text = Theme.WarningText; bg = Theme.WarningSubtle; break; case Severity.Danger: bar = Theme.Danger; text = Theme.DangerText; bg = Theme.DangerSubtle; break; default: bar = Theme.Info; text = Theme.InfoText; bg = Theme.InfoSubtle; break; } } public static GameObject Divider(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) GameObject obj = UIFactory.Panel("Divider", parent, Theme.Hairline, (Vector2?)null, (Vector2?)null, false); Image component = obj.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).raycastTarget = false; } return obj; } public static float Banner(Transform parent, Severity sev, string text, float y, float height = 30f, float gap = 6f, float inset = 16f) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) SeverityColors(sev, out var bar, out var text2, out var bg); GameObject val = UIFactory.Panel("banner", parent, bg, (Vector2?)null, (Vector2?)null, false); Image component = val.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { component.sprite = Theme.RoundedSprite(); component.type = (Type)1; ((Graphic)component).raycastTarget = false; } RectTransform component2 = val.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(0.5f, 1f); component2.offsetMin = new Vector2(inset, y - height); component2.offsetMax = new Vector2(0f - inset, y); GameObject obj = UIFactory.Panel("bar", val.transform, bar, (Vector2?)null, (Vector2?)null, false); Image component3 = obj.GetComponent<Image>(); if ((Object)(object)component3 != (Object)null) { ((Graphic)component3).raycastTarget = false; } RectTransform component4 = obj.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0f, 0f); component4.anchorMax = new Vector2(0f, 1f); component4.pivot = new Vector2(0f, 0.5f); component4.offsetMin = new Vector2(0f, 4f); component4.offsetMax = new Vector2(3f, -4f); Text obj2 = UIFactory.Text("t", text, val.transform, 13, (TextAnchor)3, (FontStyle)0); ((Graphic)obj2).color = text2; ((Graphic)obj2).raycastTarget = false; obj2.horizontalOverflow = (HorizontalWrapMode)0; obj2.verticalOverflow = (VerticalWrapMode)0; RectTransform rectTransform = ((Graphic)obj2).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.offsetMin = new Vector2(12f, 0f); rectTransform.offsetMax = new Vector2(-8f, 0f); return y - (height + gap); } public static GameObject Segmented(Transform parent, string[] labels, int active, Action<int> onSelect, out Button[] buttons, bool vertical = false, float spacing = 6f, Texture2D[] icons = null) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("segmented"); val.transform.SetParent(parent, false); val.AddComponent<RectTransform>(); if (vertical) { VerticalLayoutGroup obj = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = true; } else { HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = spacing; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = true; } buttons = (Button[])(object)new Button[labels.Length]; for (int i = 0; i < labels.Length; i++) { int idx = i; Texture2D val2 = ((icons != null && i < icons.Length) ? icons[i] : null); ValueTuple<GameObject, Button, Text> valueTuple = UIFactory.ButtonWithLabel("seg_" + i, ((Object)(object)val2 != (Object)null) ? "" : labels[i], val.transform, (i == active) ? Theme.Accent : Theme.Button, 0f, 0f); GameObject item = valueTuple.Item1; Button item2 = valueTuple.Item2; Text item3 = valueTuple.Item3; LayoutElement obj3 = item.AddComponent<LayoutElement>(); obj3.flexibleWidth = 1f; obj3.flexibleHeight = 1f; obj3.minHeight = 28f; if ((Object)(object)item3 != (Object)null) { item3.fontSize = 14; } if ((Object)(object)val2 != (Object)null) { AddCenterIcon(item.transform, val2, 20f); } if (onSelect != null) { ((UnityEvent)item2.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { onSelect(idx); })); } buttons[i] = item2; } return val; } public static void AddCenterIcon(Transform parent, Texture2D tex, float size) { //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) //IL_0021: 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_0047: 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_0069: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)tex == (Object)null)) { GameObject val = new GameObject("icon"); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent<RectTransform>(); obj.anchorMin = new Vector2(0.5f, 0.5f); obj.anchorMax = new Vector2(0.5f, 0.5f); obj.pivot = new Vector2(0.5f, 0.5f); obj.sizeDelta = new Vector2(size, size); obj.anchoredPosition = Vector2.zero; Image obj2 = val.AddComponent<Image>(); obj2.sprite = Sprite.Create(tex, new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height), new Vector2(0.5f, 0.5f), 100f); obj2.preserveAspect = true; ((Graphic)obj2).raycastTarget = false; } } public static void ConfirmDialog(Transform canvasRoot, string title, string message, string confirmLabel, Action onConfirm) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019e: 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_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0252: 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) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029d: 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_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0352: 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_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) GameObject scrim; if (!((Object)(object)canvasRoot == (Object)null)) { scrim = UIFactory.Panel("DD_ConfirmScrim", canvasRoot, new Color(0f, 0f, 0f, 0.6f), (Vector2?)null, (Vector2?)null, true); scrim.transform.SetAsLastSibling(); GameObject val = UIFactory.Panel("catcher", scrim.transform, new Color(0f, 0f, 0f, 0.01f), (Vector2?)null, (Vector2?)null, true); Button obj = val.AddComponent<Button>(); ((Selectable)obj).targetGraphic = (Graphic)(object)val.GetComponent<Image>(); ((UnityEvent)obj.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { Close(); })); GameObject val2 = UIFactory.Panel("card", scrim.transform, Theme.BgElevated, (Vector2?)null, (Vector2?)null, false); Image component = val2.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { component.sprite = Theme.RoundedSprite(); component.type = (Type)1; } RectTransform component2 = val2.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.5f, 0.5f); component2.anchorMax = new Vector2(0.5f, 0.5f); component2.pivot = new Vector2(0.5f, 0.5f); component2.sizeDelta = new Vector2(440f, 190f); Outline obj2 = val2.AddComponent<Outline>(); ((Shadow)obj2).effectColor = Theme.HairlineStrong; ((Shadow)obj2).effectDistance = new Vector2(1f, -1f); Text obj3 = UIFactory.Text("title", title, val2.transform, 16, (TextAnchor)0, (FontStyle)1); ((Graphic)obj3).color = Theme.TextPrimary; ((Graphic)obj3).raycastTarget = false; RectTransform rectTransform = ((Graphic)obj3).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.pivot = new Vector2(0.5f, 1f); rectTransform.offsetMin = new Vector2(20f, -52f); rectTransform.offsetMax = new Vector2(-20f, -18f); Text obj4 = UIFactory.Text("msg", message, val2.transform, 13, (TextAnchor)0, (FontStyle)0); ((Graphic)obj4).color = Theme.TextMuted; ((Graphic)obj4).raycastTarget = false; RectTransform rectTransform2 = ((Graphic)obj4).rectTransform; rectTransform2.anchorMin = new Vector2(0f, 1f); rectTransform2.anchorMax = new Vector2(1f, 1f); rectTransform2.pivot = new Vector2(0.5f, 1f); rectTransform2.offsetMin = new Vector2(20f, -120f); rectTransform2.offsetMax = new Vector2(-20f, -58f); ValueTuple<GameObject, Button, Text> valueTuple = UIFactory.ButtonWithLabel("Cancel", "Cancel", val2.transform, Theme.Button, 140f, 40f); GameObject item = valueTuple.Item1; Button item2 = valueTuple.Item2; RectTransform component3 = item.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0f, 0f); component3.anchorMax = new Vector2(0f, 0f); component3.pivot = new Vector2(0f, 0f); component3.anchoredPosition = new Vector2(20f, 18f); component3.sizeDelta = new Vector2(140f, 40f); ((UnityEvent)item2.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { Close(); })); ValueTuple<GameObject, Button, Text> valueTuple2 = UIFactory.ButtonWithLabel("Confirm", confirmLabel, val2.transform, Theme.Danger, 180f, 40f); GameObject item3 = valueTuple2.Item1; Button item4 = valueTuple2.Item2; RectTransform component4 = item3.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(1f, 0f); component4.anchorMax = new Vector2(1f, 0f); component4.pivot = new Vector2(1f, 0f); component4.anchoredPosition = new Vector2(-20f, 18f); component4.sizeDelta = new Vector2(180f, 40f); ((UnityEvent)item4.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { Close(); onConfirm?.Invoke(); })); Interactions.PolishButtons(val2.transform); } void Close() { Object.Destroy((Object)(object)scrim); } } public static void SetSegmentedActive(Button[] buttons, int active) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (buttons == null) { return; } for (int i = 0; i < buttons.Length; i++) { if (!((Object)(object)buttons[i] == (Object)null)) { Graphic targetGraphic = ((Selectable)buttons[i]).targetGraphic; Image val = (Image)(((object)((targetGraphic is Image) ? targetGraphic : null)) ?? ((object)((Component)buttons[i]).GetComponent<Image>())); if (!((Object)(object)val == (Object)null)) { ((Graphic)val).color = ((i == active) ? Theme.Accent : Theme.Button); Interactions.ApplyStates(buttons[i]); } } } } public static Slider Slider(Transform parent, float min, float max, float value, Action<float> onChange) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00ee: 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_0118: 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_0131: 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_0148: 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_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017e: 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_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0204: 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_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: 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_0249: 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) GameObject val = new GameObject("slider"); val.transform.SetParent(parent, false); val.AddComponent<RectTransform>(); Slider val2 = val.AddComponent<Slider>(); GameObject val3 = new GameObject("Background"); val3.transform.SetParent(val.transform, false); RectTransform obj = val3.AddComponent<RectTransform>(); obj.anchorMin = new Vector2(0f, 0.5f); obj.anchorMax = new Vector2(1f, 0.5f); obj.sizeDelta = new Vector2(0f, 6f); obj.anchoredPosition = Vector2.zero; Image obj2 = val3.AddComponent<Image>(); ((Graphic)obj2).color = Theme.SurfaceInput; obj2.sprite = Theme.RoundedSprite(); obj2.type = (Type)1; GameObject val4 = new GameObject("Fill Area"); val4.transform.SetParent(val.transform, false); RectTransform obj3 = val4.AddComponent<RectTransform>(); obj3.anchorMin = new Vector2(0f, 0.5f); obj3.anchorMax = new Vector2(1f, 0.5f); obj3.sizeDelta = new Vector2(-16f, 6f); obj3.anchoredPosition = Vector2.zero; GameObject val5 = new GameObject("Fill"); val5.transform.SetParent(val4.transform, false); RectTransform val6 = val5.AddComponent<RectTransform>(); val6.anchorMin = new Vector2(0f, 0f); val6.anchorMax = new Vector2(1f, 1f); val6.sizeDelta = Vector2.zero; Image obj4 = val5.AddComponent<Image>(); ((Graphic)obj4).color = Theme.Accent; obj4.sprite = Theme.RoundedSprite(); obj4.type = (Type)1; GameObject val7 = new GameObject("Handle Slide Area"); val7.transform.SetParent(val.transform, false); RectTransform obj5 = val7.AddComponent<RectTransform>(); obj5.anchorMin = new Vector2(0f, 0f); obj5.anchorMax = new Vector2(1f, 1f); obj5.sizeDelta = new Vector2(-16f, 0f); obj5.anchoredPosition = Vector2.zero; GameObject val8 = new GameObject("Handle"); val8.transform.SetParent(val7.transform, false); RectTransform val9 = val8.AddComponent<RectTransform>(); val9.sizeDelta = new Vector2(16f, 16f); Image val10 = val8.AddComponent<Image>(); ((Graphic)val10).color = Theme.AccentBorder; val10.sprite = Theme.RoundedSprite(); val10.type = (Type)1; val2.fillRect = val6; val2.handleRect = val9; ((Selectable)val2).targetGraphic = (Graphic)(object)val10; val2.direction = (Direction)0; val2.minValue = min; val2.maxValue = max; val2.wholeNumbers = false; val2.value = value; if (onChange != null) { ((UnityEvent<float>)(object)val2.onValueChanged).AddListener(UnityAction<float>.op_Implicit((Action<float>)delegate(float v) { onChange(v); })); } return val2; } } public static class Toast { private class Entry { public GameObject go; public CanvasGroup cg; public float expire; } private const float Ttl = 3.4f; private const float FadeFor = 0.45f; private const float Width = 480f; private const float RowH = 40f; private const float Gap = 8f; private const float BaseY = 96f; private static Transform _host; private static readonly List<Entry> _entries = new List<Entry>(); public static void Init(Transform canvasRoot) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)canvasRoot == (Object)null) && !((Object)(object)_host != (Object)null)) { GameObject obj = UIFactory.Panel("DD_ToastHost", canvasRoot, Theme.Clear, (Vector2?)null, (Vector2?)null, true); Image component = obj.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).raycastTarget = false; } obj.transform.SetAsLastSibling(); _host = obj.transform; } } public static void Clear() { _entries.Clear(); if ((Object)(object)_host != (Object)null) { Object.Destroy((Object)(object)((Component)_host).gameObject); _host = null; } } public static void Show(string message, Severity sev = Severity.Info) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_host == (Object)null) && !string.IsNullOrEmpty(message)) { Components.SeverityColors(sev, out var bar, out var _, out var _); GameObject val = UIFactory.Panel("toast", _host, Theme.BgElevated, (Vector2?)null, (Vector2?)null, false); Image component = val.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { component.sprite = Theme.RoundedSprite(); component.type = (Type)1; ((Graphic)component).raycastTarget = false; } RectTransform component2 = val.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.5f, 0f); component2.anchorMax = new Vector2(0.5f, 0f); component2.pivot = new Vector2(0.5f, 0f); component2.sizeDelta = new Vector2(480f, 40f); Outline obj = val.AddComponent<Outline>(); ((Shadow)obj).effectColor = Theme.HairlineStrong; ((Shadow)obj).effectDistance = new Vector2(1f, -1f); GameObject obj2 = UIFactory.Panel("bar", val.transform, bar, (Vector2?)null, (Vector2?)null, false); Image component3 = obj2.GetComponent<Image>(); if ((Object)(object)component3 != (Object)null) { ((Graphic)component3).raycastTarget = false; } RectTransform component4 = obj2.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0f, 0f); component4.anchorMax = new Vector2(0f, 1f); component4.pivot = new Vector2(0f, 0.5f); component4.offsetMin = new Vector2(0f, 6f); component4.offsetMax = new Vector2(4f, -6f); Text obj3 = UIFactory.Text("t", message, val.transform, 13, (TextAnchor)3, (FontStyle)0); ((Graphic)obj3).color = Theme.TextPrimary; ((Graphic)obj3).raycastTarget = false; obj3.horizontalOverflow = (HorizontalWrapMode)0; obj3.verticalOverflow = (VerticalWrapMode)0; RectTransform rectTransform = ((Graphic)obj3).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.offsetMin = new Vector2(16f, 2f); rectTransform.offsetMax = new Vector2(-12f, -2f); CanvasGroup cg = val.AddComponent<CanvasGroup>(); _entries.Add(new Entry { go = val, cg = cg, expire = Time.time + 3.4f }); Reflow(); } } public static void Tick() { if (_entries.Count == 0) { return; } float time = Time.time; for (int num = _entries.Count - 1; num >= 0; num--) { Entry entry = _entries[num]; if ((Object)(object)entry.go == (Object)null) { _entries.RemoveAt(num); } else if (time >= entry.expire) { Object.Destroy((Object)(object)entry.go); _entries.RemoveAt(num); } else { float num2 = entry.expire - time; if ((Object)(object)entry.cg != (Object)null) { entry.cg.alpha = ((num2 < 0.45f) ? Mathf.Clamp01(num2 / 0.45f) : 1f); } } } Reflow(); } private static void Reflow() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) float num = 96f; for (int i = 0; i < _entries.Count; i++) { RectTransform val = (((Object)(object)_entries[i].go != (Object)null) ? _entries[i].go.GetComponent<RectTransform>() : null); if (!((Object)(object)val == (Object)null)) { val.anchoredPosition = new Vector2(0f, num); num += 48f; } } } } public static class Interactions { public static void PolishButtons(Transform root, bool round = true) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } Il2CppArrayBase<Button> componentsInChildren = ((Component)root).GetComponentsInChildren<Button>(true); if (componentsInChildren == null) { return; } for (int i = 0; i < componentsInChildren.Length; i++) { Button val = componentsInChildren[i]; if ((Object)(object)val == (Object)null) { continue; } Graphic targetGraphic = ((Selectable)val).targetGraphic; Image val2 = (Image)(((object)((targetGraphic is Image) ? targetGraphic : null)) ?? ((object)((Component)val).GetComponent<Image>())); if (!((Object)(object)val2 == (Object)null) && !(((Graphic)val2).color.a < 0.02f)) { if (round) { val2.sprite = Theme.RoundedSprite(); val2.type = (Type)1; } ApplyStates(val); } } } public static void ApplyStates(Button btn) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_004e: 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_005d: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) Graphic targetGraphic = ((Selectable)btn).targetGraphic; Image val = (Image)(((object)((targetGraphic is Image) ? targetGraphic : null)) ?? ((object)((Component)btn).GetComponent<Image>())); if (!((Object)(object)val == (Object)null)) { Color color = ((Graphic)val).color; if (!(color.a < 0.02f)) { Color val2 = Theme.Lighten(color, 0.06f); Color target = Theme.Darken(color, 0.06f); Color target2 = Color.Lerp(color, Theme.BgPanel, 0.55f); target2.a = color.a * 0.6f; ((Graphic)val).color = val2; ColorBlock colors = ((Selectable)btn).colors; ((ColorBlock)(ref colors)).normalColor = Ratio(color, val2); ((ColorBlock)(ref colors)).highlightedColor = Color.white; ((ColorBlock)(ref colors)).pressedColor = Ratio(target, val2); ((ColorBlock)(ref colors)).selectedColor = Ratio(color, val2); ((ColorBlock)(ref colors)).disabledColor = Ratio(target2, val2); ((ColorBlock)(ref colors)).colorMultiplier = 1f; ((ColorBlock)(ref colors)).fadeDuration = 0.12f; ((Selectable)btn).colors = colors; ((Selectable)btn).transition = (Transition)1; } } } private static Color Ratio(Color target, Color baseC) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0098: Unknown result type (might be due to invalid IL or missing references) return new Color((baseC.r <= 0.0001f) ? 0f : Mathf.Clamp01(target.r / baseC.r), (baseC.g <= 0.0001f) ? 0f : Mathf.Clamp01(target.g / baseC.g), (baseC.b <= 0.0001f) ? 0f : Mathf.Clamp01(target.b / baseC.b), (baseC.a <= 0.0001f) ? 0f : Mathf.Clamp01(target.a / baseC.a)); } } public static class Theme { public static readonly Color BgDeep = new Color(0.043f, 0.047f, 0.063f, 1f); public static readonly Color BgBase = new Color(0.063f, 0.071f, 0.094f, 1f); public static readonly Color BgPanel = new Color(0.086f, 0.098f, 0.133f, 1f); public static readonly Color BgElevated = new Color(0.114f, 0.129f, 0.173f, 1f); public static readonly Color SurfaceInput = new Color(0.051f, 0.059f, 0.082f, 1f); public static readonly Color Clear = new Color(0f, 0f, 0f, 0f); public static readonly Color Hairline = new Color(1f, 1f, 1f, 0.08f); public static readonly Color HairlineStrong = new Color(1f, 1f, 1f, 0.14f); public static readonly Color TextPrimary = new Color(0.925f, 0.929f, 0.945f, 1f); public static readonly Color TextMuted = new Color(0.541f, 0.561f, 0.62f, 1f); public static readonly Color TextDisabled = new Color(0.337f, 0.357f, 0.408f, 1f); public static readonly Color Accent = new Color(0.369f, 0.416f, 0.824f, 1f); public static readonly Color AccentHover = new Color(0.431f, 0.475f, 0.859f, 1f); public static readonly Color AccentPressed = new Color(0.298f, 0.341f, 0.737f, 1f); public static readonly Color AccentSubtle = new Color(0.125f, 0.133f, 0.227f, 1f); public static readonly Color AccentBorder = new Color(0.486f, 0.525f, 0.91f, 1f); public static readonly Color Button = new Color(0.2f, 0.212f, 0.263f, 1f); public static readonly Color Danger = new Color(0.784f, 0.29f, 0.329f, 1f); public static readonly Color DangerText = new Color(0.945f, 0.439f, 0.478f, 1f); public static readonly Color DangerSubtle = new Color(0.165f, 0.082f, 0.094f, 1f); public static readonly Color Warning = new Color(0.788f, 0.569f, 0.18f, 1f); public static readonly Color WarningText = new Color(0.902f, 0.706f, 0.314f, 1f); public static readonly Color WarningSubtle = new Color(0.165f, 0.133f, 0.071f, 1f); public static readonly Color Success = new Color(0.184f, 0.659f, 0.467f, 1f); public static readonly Color SuccessText = new Color(0.373f, 0.816f, 0.604f, 1f); public static readonly Color SuccessSubtle = new Color(0.071f, 0.165f, 0.125f, 1f); public static readonly Color Info = new Color(0.239f, 0.498f, 0.753f, 1f); public static readonly Color InfoText = new Color(0.435f, 0.659f, 0.902f, 1f); public static readonly Color InfoSubtle = new Color(0.071f, 0.125f, 0.192f, 1f); public const int RadiusMd = 6; public const float Fade = 0.12f; public const int Caption = 11; public const int Body = 13; public const int Label = 14; public const int H3 = 16; public const int H2 = 20; public const int H1 = 28; private static Sprite _rounded; private static Sprite _frame; public static Color Lighten(Color c, float amount) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_002d: Unknown result type (might be due to invalid IL or missing references) return new Color(Mathf.Clamp01(c.r + amount), Mathf.Clamp01(c.g + amount), Mathf.Clamp01(c.b + amount), c.a); } public static Color Darken(Color c, float amount) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) return Lighten(c, 0f - amount); } public 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); } public static Sprite RoundedSprite() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_rounded != (Object)null) { return _rounded; } Texture2D val = new Texture2D(32, 32, (TextureFormat)5, false); ((Object)val).hideFlags = (HideFlags)32; Color32 val2 = default(Color32); ((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0); Color32 val3 = default(Color32); ((Color32)(ref val3))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { bool flag = ((float)j < 6f && (float)i < 6f && Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(6f, 6f)) > 6f) || ((float)j > 25f && (float)i < 6f && Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(25f, 6f)) > 6f) || ((float)j < 6f && (float)i > 25f && Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(6f, 25f)) > 6f) || ((float)j > 25f && (float)i > 25f && Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(25f, 25f)) > 6f); val.SetPixel(j, i, Color32.op_Implicit(flag ? val2 : val3)); } } val.Apply(); _rounded = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(8f, 8f, 8f, 8f)); return _rounded; } public static Sprite FrameSprite() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_00b8: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_frame != (Object)null) { return _frame; } Texture2D val = new Texture2D(32, 32, (TextureFormat)5, false); ((Object)val).hideFlags = (HideFlags)32; Color32 val2 = default(Color32); ((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0); Color32 val3 = default(Color32); ((Color32)(ref val3))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { bool flag = j < 3 || j >= 29 || i < 3 || i >= 29; val.SetPixel(j, i, Color32.op_Implicit(flag ? val3 : val2)); } } val.Apply(); _frame = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(4f, 4f, 4f, 4f)); return _frame; } } } namespace SideHustle { public static class API { public static bool IsReady { get; internal set; } public static IReadOnlyList<GamemodeDescriptor> Registered => Registry.All; public static void Register(GamemodeDescriptor descriptor) { if (descriptor == null) { throw new ArgumentNullException("descriptor"); } if (string.IsNullOrWhiteSpace(descriptor.Id)) { throw new ArgumentException("GamemodeDescriptor.Id is required.", "descriptor"); } if (string.IsNullOrWhiteSpace(descriptor.DisplayName)) { descriptor.DisplayName = descriptor.Id; } bool flag = Registry.Register(descriptor); Instance log = Core.Log; if (log != null) { log.Msg(flag ? $"Gamemode re-registered: '{descriptor.DisplayName}' ({descriptor.Id})." : $"Gamemode registered: '{descriptor.DisplayName}' ({descriptor.Id})."); } } public static bool Unregister(string id) { if (!string.IsNullOrWhiteSpace(id)) { return Registry.Unregister(id); } return false; } } public sealed class GamemodeDescriptor { public string Id; public string DisplayName; public string Description; public string Author; public Sprite Icon; public Texture2D IconTex; public GamemodeSupport Support; public GamemodeSurface Surface; public Action<LaunchContext> OnLaunchSingleplayer; public Action<LaunchContext> OnHostMultiplayer; public Action<LaunchContext> OnJoinMultiplayer; public Action<LaunchContext> OnExitToHub; public bool AllowsSingleplayer { get { if (Support != GamemodeSupport.Singleplayer) { return Support == GamemodeSupport.Hybrid; } return true; } } public bool AllowsMultiplayer { get { if (Support != GamemodeSupport.Multiplayer) { return Support == GamemodeSupport.Hybrid; } return true; } } } public enum GamemodeSupport { Singleplayer, Multiplayer, Hybrid } public enum GamemodeSurface { MenuSpace, World } public sealed class LaunchContext { public GamemodeDescriptor Descriptor { get; internal set; } public bool? IsHost { get; internal set; } public ulong LobbyId { get; internal set; } public bool IsSingleplayer => !IsHost.HasValue; public void ReturnToHub() { HubBridge.RequestReturn(this); } } public sealed class Core : MelonMod { private bool _inMenu; public static Core Instance { get; private set; } public static Instance Log { get; private set; } public override void OnInitializeMelon() { Instance = this; Log = ((MelonBase)this).LoggerInstance; Preferences.Initialize(); API.IsReady = true; Log.Msg($"Side Hustle 1.0.1 ready - {API.Registered.Count} gamemode(s) registered so far."); } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { if (sceneName == "Menu") { _inMenu = true; MenuInjector.Reset(); MenuInjector.TryInject(); } } public override void OnSceneWasUnloaded(int buildIndex, string sceneName) { if (sceneName == "Menu") { _inMenu = false; Hub.Teardown(); MenuInjector.Reset(); } } public override void OnUpdate() { if (_inMenu) { MenuInjector.TickRetry(); } } } } namespace SideHustle.Menu { internal static class Hub { private static bool _initialized; private static MainMenuScreen _home; private static LaunchContext _activeCtx; private static GameObject _clone; private static MainMenuScreen _cloneScreen; private const float SlotHeight = 96f; private const float SlotSpacing = 8f; private const float NameOffsetY = 12f; private const float DescOffsetY = -13f; private const float PanelChrome = 92f; private const float PanelWidth = 800f; internal static void EnsureInit() { if (!_initialized) { _initialized = true; HubBridge.ReturnHandler = OnReturn; } } internal static void RememberHome(MainMenuScreen home) { _home = home; } internal static void Teardown() { try { if ((Object)(object)_clone != (Object)null) { Object.Destroy((Object)(object)_clone); } } catch { } _clone = null; _cloneScreen = null; _activeCtx = null; } internal static void TickInput() { if (!((Object)(object)_cloneScreen == (Object)null) && _cloneScreen.IsOpen && Input.GetMouseButtonDown(1)) { _cloneScreen.Close(true); } } internal static void OpenScreen() { EnsureInit(); EnsureClone(); if ((Object)(object)_cloneScreen == (Object)null) { Instance log = Core.Log; if (log != null) { log.Warning("[hub] gamemode screen unavailable."); } } else { RebuildRows(); _cloneScreen.Open(true); } } internal static void EnsureClone() { if ((Object)(object)_clone != (Object)null && (Object)(object)_cloneScreen != (Object)null) { return; } try { Il2CppArrayBase<NewGameScreen> val = Object.FindObjectsOfType<NewGameScreen>(true); if (val == null || val.Length == 0) { Instance log = Core.Log; if (log != null) { log.Warning("[hub] NewGameScreen not found; cannot build the gamemode screen."); } return; } NewGameScreen val2 = val[0]; _clone = ((Il2CppObjectBase)Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)val2).transform.parent, false)).Cast<GameObject>(); ((Object)_clone).name = "SideHustle_GamemodeScreen"; _cloneScreen = _clone.GetComponent<MainMenuScreen>(); if ((Object)(object)_cloneScreen != (Object)null && (Object)(object)_home != (Object)null) { _cloneScreen.PreviousScreen = _home; } try { Il2CppArrayBase<SaveDisplay> componentsInChildren = _clone.GetComponentsInChildren<SaveDisplay>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } } catch (Exception ex) { Instance log2 = Core.Log; if (log2 != null) { log2.Warning("[hub] remove SaveDisplay: " + ex.Message); } } _clone.SetActive(true); Instance log3 = Core.Log; if (log3 != null) { log3.Msg("[hub] cloned NewGameScreen -> gamemode screen."); } } catch (Exception ex2) { Instance log4 = Core.Log; if (log4 != null) { log4.Warning("[hub] EnsureClone failed: " + ex2); } } } private static void RebuildRows() { //IL_0162: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_clone == (Object)null) { return; } try { SetTmp(_clone.transform, "Title", "Choose a gamemode"); Transform val = _clone.transform.Find("Container"); if ((Object)(object)val == (Object)null) { Instance log = Core.Log; if (log != null) { log.Warning("[hub] slot container not found."); } return; } VerticalLayoutGroup component = ((Component)val).GetComponent<VerticalLayoutGroup>(); if ((Object)(object)component != (Object)null) { ((HorizontalOrVerticalLayoutGroup)component).spacing = 8f; } IReadOnlyList<GamemodeDescriptor> registered = API.Registered; if (val.childCount > 0) { GameObject gameObject = ((Component)val.GetChild(0)).gameObject; int num = 0; while (val.childCount < registered.Count && num++ < 64) { Object.Instantiate<GameObject>(gameObject, val, false); } } int num2 = 0; for (int i = 0; i < val.childCount; i++) { Transform child = val.GetChild(i); if (num2 < registered.Count) { RepurposeSlot(child, registered[num2]); ((Component)child).gameObject.SetActive(true); num2++; } else { ((Component)child).gameObject.SetActive(false); } } int num3 = Mathf.Max(1, registered.Count); float num4 = 92f + (float)num3 * 96f + (float)(num3 - 1) * 8f; RectTransform component2 = _clone.GetComponent<RectTransform>(); if ((Object)(object)component2 != (Object)null) { component2.sizeDelta = new Vector2(800f, num4); } } catch (Exception ex) { Instance log2 = Core.Log; if (log2 != null) { log2.Warning("[hub] RebuildRows failed: " + ex); } } } private static void RepurposeSlot(Transform slot, GamemodeDescriptor desc) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) Transform val = slot.Find("Container/Info"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(true); } RectTransform component = ((Component)slot).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(component.sizeDelta.x, 96f); } LayoutElement val2 = ((Component)slot).GetComponent<LayoutElement>(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)slot).gameObject.AddComponent<LayoutElement>(); } val2.minHeight = 96f; val2.preferredHeight = 96f; Transform val3 = slot.Find("Container/Info/Organisation"); if ((Object)(object)val3 != (Object)null) { CentreRow(val3, 12f); TextMeshProUGUI component2 = ((Component)val3).GetComponent<TextMeshProUGUI>(); if ((Object)(object)component2 != (Object)null) { ((TMP_Text)component2).text = desc.DisplayName; } } Transform val4 = slot.Find("Container/Info/NetWorth"); if ((Object)(object)val4 != (Object)null) { CentreRow(val4, -13f); TextMeshProUGUI component3 = ((Component)val4).GetComponent<TextMeshProUGUI>(); if ((Object)(object)component3 != (Object)null) { ((TMP_Text)component3).text = (string.IsNullOrWhiteSpace(desc.Description) ? "" : desc.Description.Trim()); ((Graphic)component3).color = new Color(0.627f, 0.627f, 0.627f, 1f); ((TMP_Text)component3).enableWordWrapping = false; ((TMP_Text)component3).overflowMode = (TextOverflowModes)1; } HideChild(slot, "Container/Info/NetWorth/Text"); } Transform val5 = slot.Find("Container/Info/Version"); if ((Object)(object)val5 != (Object)null) { TextMeshProUGUI component4 = ((Component)val5).GetComponent<TextMeshProUGUI>(); if ((Object)(object)component4 != (Object)null && !string.IsNullOrWhiteSpace(desc.Author)) { ((TMP_Text)component4).text = "by " + desc.Author.Trim(); ((Component)val5).gameObject.SetActive(true); } else { ((Component)val5).gameObject.SetActive(false); } } HideChild(slot, "Container/Info/Created"); HideChild(slot, "Container/Info/LastPlayed"); HideChild(slot, "Container/Info/Export"); HideChild(slot, "Container/Import"); WireSlotButton(slot, "Button", desc); WireSlotButton(slot, "Container/Button", desc); } private static void WireSlotButton(Transform slot, string path, GamemodeDescriptor desc) { Transform val = slot.Find(path); if ((Object)(object)val == (Object)null) { return; } Button component = ((Component)val).GetComponent<Button>(); if (!((Object)(object)component == (Object)null)) { NeutralizeClick(component); GamemodeDescriptor d = desc; ((UnityEvent)component.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { OnSelectGamemode(d); })); ((Selectable)component).interactable = true; } } private static void OnSelectGamemode(GamemodeDescriptor desc) { if (desc.AllowsSingleplayer) { LaunchSingleplayer(desc); return; } Instance log = Core.Log; if (log != null) { log.Msg("Gamemode '" + desc.Id + "' is multiplayer-only; multiplayer launch is not available yet."); } } private static void LaunchSingleplayer(GamemodeDescriptor desc) { if (desc.OnLaunchSingleplayer == null) { Instance log = Core.Log; if (log != null) { log.Warning("Gamemode '" + desc.Id + "' has no singleplayer launch callback."); } return; } _activeCtx = new LaunchContext { Descriptor = desc, IsHost = null, LobbyId = 0uL }; if ((Object)(object)_cloneScreen != (Object)null) { _cloneScreen.Close(false); } Instance log2 = Core.Log; if (log2 != null) { log2.Msg("Launching gamemode '" + desc.DisplayName + "' (singleplayer)."); } try { desc.OnLaunchSingleplayer(_activeCtx); } catch (Exception value) { Instance log3 = Core.Log; if (log3 != null) { log3.Error($"Gamemode '{desc.Id}' launch threw: {value}"); } OnReturn(_activeCtx); } } private static void OnReturn(LaunchContext ctx) { try { ctx?.Descriptor?.OnExitToHub?.Invoke(ctx); } catch (Exception ex) { Instance log = Core.Log; if (log != null) { log.Warning("OnExitToHub threw: " + ex.Message); } } EnsureClone(); RebuildRows(); if ((Object)(object)_cloneScreen != (Object)null) { _cloneScreen.Open(true); } _activeCtx = null; } private static void SetTmp(Transform root, string path, string text) { Transform val = root.Find(path); if (!((Object)(object)val == (Object)null)) { TextMeshProUGUI component = ((Component)val).GetComponent<TextMeshProUGUI>(); if ((Object)(object)component != (Object)null) { ((TMP_Text)component).text = text; } } } private static void HideChild(Transform root, string path) { Transform val = root.Find(path); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } } private static void CentreRow(Transform t, float dy) { //IL_001c: 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_0046: 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_006c: Unknown result type (might be due to invalid IL or missing references) RectTransform component = ((Component)t).GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null)) { component.anchorMin = new Vector2(0f, 0.5f); component.anchorMax = new Vector2(1f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(30f, dy); component.sizeDelta = new Vector2(-60f, 25f); } } private static void NeutralizeClick(Button btn) { try { ((UnityEventBase)btn.onClick).RemoveAllListeners(); int persistentEventCount = ((UnityEventBase)btn.onClick).GetPersistentEventCount(); for (int i = 0; i < persistentEventCount; i++) { ((UnityEventBase)btn.onClick).SetPersistentListenerState(i, (UnityEventCallState)0); } } catch (Exception ex) { Instance log = Core.Log; if (log != null) { log.Warning("[hub] neutralize click failed: " + ex.Message); } } } } internal static class MenuInjector { private const string MenuButtonName = "SideHustle_MenuButton"; private static bool _injectedThisScene; private static bool _loggedStructure; private static int _retries; private static readonly string[] PreferredLabels = new string[7] { "settings", "options", "load", "continue", "new game", "quit", "exit" }; internal static void Reset() { _injectedThisScene = false; _loggedStructure = false; _retries = 0; } internal static void TickRetry() { if (!_injectedThisScene && _retries++ <= 120) { TryInject(); } } internal static void TryInject() { try { if (_injectedThisScene) { return; } if (!Preferences.Enabled) { _injectedThisScene = true; return; } MainMenuScreen val = FindHomeScreen(); if ((Object)(object)val == (Object)null) { return; } Il2CppArrayBase<Button> componentsInChildren = ((Component)val).GetComponentsInChildren<Button>(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return; } for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)((Component)componentsInChildren[i]).gameObject).name == "SideHustle_MenuButton") { _injectedThisScene = true; Hub.RememberHome(val); return; } } if (!_loggedStructure) { _loggedStructure = true; } Button val2 = PickTemplate(componentsInChildren); if (!((Object)(object)val2 == (Object)null) && BuildEntry(val, val2)) { _injectedThisScene = true; Hub.RememberHome(val); Instance log = Core.Log; if (log != null) { log.Msg("[menu] Side Hustle entry injected."); } } } catch (Exception ex) { Instance log2 = Core.Log; if (log2 != null) { log2.Warning("[menu] inject error: " + ex.Message); } _injectedThisScene = true; } } private static MainMenuScreen FindHomeScreen() { Il2CppArrayBase<MainMenuScreen> val = Object.FindObjectsOfType<MainMenuScreen>(true); if (val == null || val.Length == 0) { return null; } MainMenuScreen val2 = null; for (int i = 0; i < val.Length; i++) { MainMenuScreen val3 = val[i]; if (!((Object)(object)val3 == (Object)null) && val3.OpenOnStart) { val2 = val3; break; } } if ((Object)(object)val2 == (Object)null) { Instance log = Core.Log; if (log != null) { log.Warning($"[menu] no MainMenuScreen with OpenOnStart among {val.Length}; falling back to first."); } } return val2 ?? val[0]; } private static Button PickTemplate(Il2CppArrayBase<Button> buttons) { string[] preferredLabels = PreferredLabels; foreach (string value in preferredLabels) { for (int j = 0; j < buttons.Length; j++) { Button val = buttons[j]; if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { string label = GetLabel(((Component)val).gameObject); if (!string.IsNullOrEmpty(label) && label.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return val; } } } } for (int k = 0; k < buttons.Length; k++) { if ((Object)(object)buttons[k] != (Object)null && ((Component)buttons[k]).gameObject.activeInHierarchy) { return buttons[k]; } } if (buttons.Length <= 0) { return null; } return buttons[0]; } private static bool BuildEntry(MainMenuScreen home, Button template) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Component)template).transform.parent; GameObject val = ((Il2CppObjectBase)Object.Instantiate<GameObject>(((Component)template).gameObject, parent, false)).Cast<GameObject>(); val.transform.localScale = Vector3.one; ((Object)val).name = "SideHustle_MenuButton"; int siblingIndex = ((Component)template).transform.GetSiblingIndex(); val.transform.SetSiblingIndex(siblingIndex); SetLabel(val, "Side Hustle"); Button component = val.GetComponent<Button>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return false; } NeutralizeClick(component); ((UnityEvent)component.onClick).AddListener(UnityAction.op_Implicit((Action)Hub.OpenScreen)); ((Selectable)component).interactable = true; if (!val.activeSelf) { val.SetActive(true); } return true; } private static void NeutralizeClick(Button btn) { try { ((UnityEventBase)btn.onClick).RemoveAllListeners(); int persistentEventCount = ((UnityEventBase)btn.onClick).GetPersistentEventCount(); for (int i = 0; i < persistentEventCount; i++) { ((UnityEventBase)btn.onClick).SetPersistentListenerState(i, (UnityEventCallState)0); } } catch (Exception ex) { Instance log = Core.Log; if (log != null) { log.Warning("[menu] neutralize click failed: " + ex.Message); } } } private static string GetLabel(GameObject go) { TextMeshProUGUI componentInChildren = go.GetComponentInChildren<TextMeshProUGUI>(true); if ((Object)(object)componentInChildren != (Object)null && !string.IsNullOrEmpty(((TMP_Text)componentInChildren).text)) { return ((TMP_Text)componentInChildren).text; } Text componentInChildren2 = go.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren2 != (Object)null && !string.IsNullOrEmpty(componentInChildren2.text)) { return componentInChildren2.text; } return null; } private static void SetLabel(GameObject go, string label) { TextMeshProUGUI componentInChildren = go.GetComponentInChildren<TextMeshProUGUI>(true); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).text = label; return; } Text componentInChildren2 = go.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.text = label; } } } } namespace SideHustle.Config { internal static class Preferences { private const string CategoryId = "SideHustle_01_Main"; private static MelonPreferences_Category _category; private static MelonPreferences_Entry<bool> _enabled; internal static bool Enabled => _enabled?.Value ?? true; internal static void Initialize() { if (_category == null) { _category = MelonPreferences.CreateCategory("SideHustle_01_Main", "Side Hustle (Gamemode Hub)"); _enabled = _category.CreateEntry<bool>("Enabled", true, "Show the Side Hustle menu entry", "When ON, Side Hustle adds its entry to the main menu and lists installed gamemodes. Turn OFF to hide it without uninstalling. Requires returning to the main menu to take effect.", false, false, (ValueValidator)null, (string)null); } } } } namespace SideHustle.Internal { internal static class Registry { private static readonly List<GamemodeDescriptor> _gamemodes = new List<GamemodeDescriptor>(); internal static IReadOnlyList<GamemodeDescriptor> All => _gamemodes; internal static bool Register(GamemodeDescriptor descriptor) { int num = IndexOf(descriptor.Id); if (num >= 0) { _gamemodes[num] = descriptor; return true; } _gamemodes.Add(descriptor); return false; } internal static bool Unregister(string id) { int num = IndexOf(id); if (num < 0) { return false; } _gamemodes.RemoveAt(num); return true; } private static int IndexOf(string id) { for (int i = 0; i < _gamemodes.Count; i++) { if (string.Equals(_gamemodes[i].Id, id, StringComparison.Ordinal)) { return i; } } return -1; } } internal static class HubBridge { internal static Action<LaunchContext> ReturnHandler; internal static void RequestReturn(LaunchContext ctx) { try { ReturnHandler?.Invoke(ctx); } catch (Exception ex) { Instance log = Core.Log; if (log != null) { log.Warning("ReturnToHub failed: " + ex.Message); } } } } }