Decompiled source of Beetleball Match Rules v0.1.0
Mods/BeetleballMatchRules.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using BeetleballMatchRules; using BeetleballMatchRules.Core; using BeetleballMatchRules.Rules; using BeetleballMatchRules.UI; using HarmonyLib; using Il2Cpp; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Reflection; using Il2CppTMPro; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Mod), "Beetleball Match Rules", "0.1.0", "bbmr", null)] [assembly: MelonGame("Bugfight Studio", "Beetleball")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("BeetleballMatchRules")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("BeetleballMatchRules")] [assembly: AssemblyTitle("BeetleballMatchRules")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BeetleballMatchRules { public class Mod : MelonMod { internal static Instance Log; internal static RuleSet Local; internal static string CurrentScene = ""; private RuleSet _toastedFor; public override void OnInitializeMelon() { Log = ((MelonBase)this).LoggerInstance; PresetStore.EnsureFolder(); PresetStore.DeleteLegacyCurrent(); Local = new RuleSet(); Patcher patcher = new Patcher(((MelonBase)this).HarmonyInstance); DungPatches.Register(patcher); MatchPatches.Register(patcher); KickoffFreeze.Register(patcher); Log.Msg($"Loaded. {patcher.Ok} patches ok, {patcher.Failed} failed. Set rules in the custom lobby: Lobby Config > match rules."); } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { CurrentScene = sceneName; KickoffFreeze.Clear(); Session.ForceReapply(); } public override void OnUpdate() { DungPatches.ResetFlags(); Session.Tick(Local); LobbyRulesPanel.Tick(); KickoffFreeze.Tick(); ArenaWalls.Tick(); if (Session.Role == Role.Client && Session.Received != null && _toastedFor != Session.Received) { _toastedFor = Session.Received; if (Session.Received.ToJson(indented: false) != "{}") { RulesMenu.Toast("The host is using custom match rules (Lobby Config > match rules)."); } } } public override void OnGUI() { RulesMenu.Draw(); } public override void OnDeinitializeMelon() { AssetOverrides.RestoreAll(); } } public sealed class Patcher { private readonly Harmony _harmony; public int Ok { get; private set; } public int Failed { get; private set; } public Patcher(Harmony harmony) { _harmony = harmony; } public void Prefix(Type target, string method, string hook, Type hooks) { Patch(target, method, hook, hooks, prefix: true); } public void Postfix(Type target, string method, string hook, Type hooks) { Patch(target, method, hook, hooks, prefix: false); } private void Patch(Type target, string method, string hook, Type hooks, bool prefix) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(target, method, (Type[])null, (Type[])null); if (methodInfo == null) { throw new MissingMethodException(target.Name, method); } HarmonyMethod val = new HarmonyMethod(hooks, hook, (Type[])null); _harmony.Patch((MethodBase)methodInfo, prefix ? val : null, prefix ? null : val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Ok++; } catch (Exception ex) { Failed++; Mod.Log.Error($"[patch] {target.Name}.{method} -> {hook} failed: {ex.Message}"); } } } } namespace BeetleballMatchRules.UI { public static class LobbyRulesPanel { private sealed class Row { public RuleField Field; public Slider Slider; public Toggle Toggle; public TMP_Text Value; public int Steps; } private const string ContainerName = "BBMR_MatchRules"; private const float Spacing = 14f; private const string ScreenName = "BBMR_MatchRulesScreen"; private const string ButtonName = "Button_MatchRules"; private static GameObject _container; private static GameObject _screen; private static GameObject _button; private static MenuScreen _menu; private static readonly List<Row> Rows = new List<Row>(); private static readonly List<Selectable> Controls = new List<Selectable>(); private static TMP_Text _presetLabel; private static TMP_Text _statusLabel; private static float _nextTick; private const float RowWidth = 900f; private static bool _refreshing; private static bool Editable => Session.Role != Role.Client; private static RuleSet Shown { get { if (Session.Role != Role.Client) { return Mod.Local; } return Session.Received ?? new RuleSet(); } } private static bool Alive(GameObject go) { if ((Object)(object)go != (Object)null) { return !((Il2CppObjectBase)go).WasCollected; } return false; } public static void Tick() { if (Time.unscaledTime < _nextTick) { return; } _nextTick = Time.unscaledTime + 0.25f; try { if (!Alive(_container) || !Alive(_screen) || !Alive(_button)) { TryInject(); } if (Alive(_screen) && _screen.activeInHierarchy) { Refresh(); } } catch (Exception ex) { Mod.Log.Warning("[lobby-ui] " + ex.Message); _nextTick = Time.unscaledTime + 5f; } } private static void TryInject() { //IL_01e6: Unknown result type (might be due to invalid IL or missing references) CustomLobbyBotsUI val = FindInScene<CustomLobbyBotsUI>(); CustomLobbyHostOptionsUI val2 = FindInScene<CustomLobbyHostOptionsUI>(); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return; } GameObject val3 = (((Object)(object)((Component)val).transform.parent != (Object)null) ? ((Component)((Component)val).transform.parent).gameObject : null); ScrollRect componentInChildren = ((Component)val).GetComponentInChildren<ScrollRect>(true); RectTransform val4 = ((componentInChildren != null) ? componentInChildren.content : null); Transform transform = ((Component)val2).transform; Transform obj = transform.Find("Toggle_IsPrivate"); GameObject val5 = ((obj != null) ? ((Component)obj).gameObject : null); Transform obj2 = transform.Find("Slider_MaxPlayers"); GameObject val6 = ((obj2 != null) ? ((Component)obj2).gameObject : null); Transform obj3 = transform.Find("Button_Advanced"); GameObject val7 = ((obj3 != null) ? ((Component)obj3).gameObject : null); object obj4; if (val4 == null) { obj4 = null; } else { Transform obj5 = ((Transform)val4).Find("AddBots/Text (TMP)"); obj4 = ((obj5 != null) ? ((Component)obj5).gameObject : null); } if (obj4 == null) { if (val4 == null) { obj4 = null; } else { Transform obj6 = ((Transform)val4).Find("RemoveBots/Text (TMP)"); obj4 = ((obj6 != null) ? ((Component)obj6).gameObject : null); } } GameObject val8 = (GameObject)obj4; if ((Object)(object)val3 == (Object)null || (Object)(object)val3.GetComponent<MenuScreen>() == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null || (Object)(object)val7 == (Object)null || (Object)(object)val8 == (Object)null) { Mod.Log.Warning("[lobby-ui] UI templates not found; the in-lobby rules screen is disabled."); _nextTick = Time.unscaledTime + 10f; return; } DestroyChildNamed(val3.transform.parent, "BBMR_MatchRulesScreen"); DestroyChildNamed(transform, "Button_MatchRules"); Rows.Clear(); Controls.Clear(); _screen = BuildScreen(val3, out var content); _container = BuildContainer(content); Transform transform2 = _container.transform; _statusLabel = AddHeader(val8, transform2, ""); TMP_Text statusLabel = _statusLabel; statusLabel.fontSize *= 0.7f; ((Graphic)_statusLabel).color = new Color(0.85f, 0.85f, 0.85f); Transform root = HorizontalRow(transform2, 95f); _presetLabel = AddButton(val7, root, "Preset: -", CyclePreset); AddButton(val7, root, "save as preset", SavePreset); AddButton(val7, root, "reset all", ResetAll); foreach (Tab tab in RuleField.VisibleTabs) { AddHeader(val8, transform2, TabInfo.Title(tab)); foreach (RuleField item in RuleField.Visible.Where((RuleField f) => f.Attr.Tab == tab)) { Rows.Add(item.IsBool ? AddToggleRow(val5, transform2, item) : AddSliderRow(val6, transform2, item)); } } FitContainer(content); _button = BuildOpenButton(val7, transform); Mod.Log.Msg($"[lobby-ui] 'match rules' button and screen added ({Rows.Count} rules)."); } private static void DestroyChildNamed(Transform parent, string name) { if ((Object)(object)parent == (Object)null) { return; } for (int num = parent.childCount - 1; num >= 0; num--) { if (((Object)parent.GetChild(num)).name == name) { Object.DestroyImmediate((Object)(object)((Component)parent.GetChild(num)).gameObject); } } } private static GameObject BuildScreen(GameObject advanced, out RectTransform content) { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(advanced, advanced.transform.parent, false); ((Object)val).name = "BBMR_MatchRulesScreen"; val.SetActive(false); val.transform.SetSiblingIndex(advanced.transform.GetSiblingIndex() + 1); StripGameLogic(val, alsoBots: true); content = val.GetComponentInChildren<ScrollRect>(true).content; for (int num = ((Transform)content).childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)((Transform)content).GetChild(num)).gameObject); } foreach (TMP_Text componentsInChild in val.GetComponentsInChildren<TMP_Text>(true)) { if (componentsInChild.text != null && componentsInChild.text.Trim().Equals("ADVANCED SETTINGS", StringComparison.OrdinalIgnoreCase)) { componentsInChild.text = "MATCH RULES"; } } Transform obj = val.transform.Find("ExitButton"); Button val2 = ((obj != null) ? ((Component)obj).GetComponent<Button>() : null); if ((Object)(object)val2 != (Object)null) { val2.onClick = new ButtonClickedEvent(); ((UnityEvent)val2.onClick).AddListener(DelegateSupport.ConvertDelegate<UnityAction>((Delegate)new Action(CloseScreen))); } _menu = val.GetComponent<MenuScreen>(); return val; } private static GameObject BuildOpenButton(GameObject advancedButton, Transform cfg) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown GameObject obj = Clone(advancedButton, cfg); ((Object)obj).name = "Button_MatchRules"; RectTransform component = advancedButton.GetComponent<RectTransform>(); RectTransform component2 = obj.GetComponent<RectTransform>(); Vector2 anchoredPosition = component.anchoredPosition; Rect rect = component.rect; component2.anchoredPosition = anchoredPosition + new Vector2(0f, 0f - (((Rect)(ref rect)).height + 15f)); SetText(obj.GetComponentInChildren<TMP_Text>(true), "match rules"); Button componentInChildren = obj.GetComponentInChildren<Button>(true); componentInChildren.onClick = new ButtonClickedEvent(); ((UnityEvent)componentInChildren.onClick).AddListener(DelegateSupport.ConvertDelegate<UnityAction>((Delegate)new Action(OpenScreen))); return obj; } private static void OpenScreen() { if (!Alive(_screen)) { return; } _screen.SetActive(true); try { MenuScreen menu = _menu; if (menu != null) { menu.Show(true); } } catch (Exception ex) { Mod.Log.Warning("[lobby-ui] Show failed, opening directly: " + ex.Message); CanvasGroup component = _screen.GetComponent<CanvasGroup>(); if ((Object)(object)component != (Object)null) { component.alpha = 1f; component.interactable = true; component.blocksRaycasts = true; } } Refresh(); } private static void CloseScreen() { if (!Alive(_screen)) { return; } try { MenuScreen menu = _menu; if (menu != null) { menu.Hide(false); } } catch { } _screen.SetActive(false); } private static void StripGameLogic(GameObject go, bool alsoBots = false) { foreach (Component item in (Il2CppArrayBase<Component>)(object)go.GetComponentsInChildren(Il2CppType.Of<Component>(), true)) { if (!((Object)(object)item == (Object)null)) { string name = ((MemberInfo)((Object)item).GetIl2CppType()).Name; bool flag; switch (name) { case "LocalizeStringEvent": case "TextAnimator": case "SliderValueText": case "Tooltip": case "DirectedNavigation": flag = true; break; default: flag = false; break; } if (flag || (alsoBots && name == "CustomLobbyBotsUI")) { Object.DestroyImmediate((Object)(object)item); } } } } private static GameObject BuildContainer(RectTransform content) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_00c6: Expected O, but got Unknown GameObject val = new GameObject("BBMR_MatchRules"); RectTransform obj = val.AddComponent<RectTransform>(); ((Transform)obj).SetParent((Transform)(object)content, false); ((Transform)obj).SetAsLastSibling(); obj.anchorMin = new Vector2(0.5f, 1f); obj.anchorMax = new Vector2(0.5f, 1f); obj.pivot = new Vector2(0.5f, 1f); obj.sizeDelta = new Vector2(1000f, 100f); VerticalLayoutGroup obj2 = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 14f; ((LayoutGroup)obj2).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ((LayoutGroup)obj2).padding.top = 30; ((LayoutGroup)obj2).padding.bottom = 30; val.AddComponent<LayoutElement>(); return val; } private static void FitContainer(RectTransform content) { //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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) RectTransform component = _container.GetComponent<RectTransform>(); float num = 60f; Rect rect; for (int i = 0; i < ((Transform)component).childCount; i++) { float num2 = num; rect = ((Component)((Transform)component).GetChild(i)).GetComponent<RectTransform>().rect; num = num2 + (((Rect)(ref rect)).height + 14f); } component.sizeDelta = new Vector2(1000f, num); LayoutElement component2 = _container.GetComponent<LayoutElement>(); component2.minHeight = num; component2.preferredHeight = num; component2.preferredWidth = 1000f; if ((Object)(object)((Component)content).GetComponent<LayoutGroup>() != (Object)null) { return; } float num3 = 0f; for (int j = 0; j < ((Transform)content).childCount; j++) { RectTransform component3 = ((Component)((Transform)content).GetChild(j)).GetComponent<RectTransform>(); if (!((Object)(object)component3 == (Object)null) && !((Object)(object)component3 == (Object)(object)component) && ((Component)component3).gameObject.activeSelf) { float y = component3.anchoredPosition.y; rect = component3.rect; float num4 = y - ((Rect)(ref rect)).height * component3.pivot.y; num3 = Mathf.Min(num3, num4); } } component.anchoredPosition = new Vector2(0f, num3 - 20f); content.sizeDelta = new Vector2(content.sizeDelta.x, Mathf.Max(content.sizeDelta.y, 0f - num3 + 20f + num)); } private static GameObject Clone(GameObject template, Transform parent) { GameObject obj = Object.Instantiate<GameObject>(template, parent, false); obj.SetActive(true); StripGameLogic(obj); return obj; } private static void SetText(TMP_Text t, string text) { if (!((Object)(object)t == (Object)null)) { t.text = text; t.enableAutoSizing = true; t.fontSizeMin = 12f; t.fontSizeMax = Mathf.Max(t.fontSize, 30f); } } private static GameObject Sized(GameObject go, float width, float height) { //IL_0011: 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_0032: Unknown result type (might be due to invalid IL or missing references) RectTransform component = go.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(width, height); LayoutElement obj = go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>(); obj.preferredWidth = width; obj.preferredHeight = height; return go; } private static TMP_Text AddHeader(GameObject tpl, Transform root, string text) { GameObject val = Sized(Clone(tpl, root), 900f, 56f); TMP_Text obj = val.GetComponent<TMP_Text>() ?? val.GetComponentInChildren<TMP_Text>(true); SetText(obj, text); return obj; } private static Transform HorizontalRow(Transform root, float height) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BBMR_Buttons"); ((Transform)val.AddComponent<RectTransform>()).SetParent(root, false); Sized(val, 900f, height); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 20f; ((LayoutGroup)obj).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; return val.transform; } private static TMP_Text AddButton(GameObject tpl, Transform root, string text, Action onClick) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown GameObject obj = Sized(Clone(tpl, root), 285f, 85f); TMP_Text componentInChildren = obj.GetComponentInChildren<TMP_Text>(true); SetText(componentInChildren, text); Button componentInChildren2 = obj.GetComponentInChildren<Button>(true); componentInChildren2.onClick = new ButtonClickedEvent(); ((UnityEvent)componentInChildren2.onClick).AddListener(DelegateSupport.ConvertDelegate<UnityAction>((Delegate)onClick)); Controls.Add((Selectable)(object)componentInChildren2); return componentInChildren; } private static Row AddToggleRow(GameObject tpl, Transform root, RuleField field) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown GameObject obj = Clone(tpl, root); WidenRow(obj, "Label Variant"); Transform obj2 = obj.transform.Find("Label Variant/LabelText"); SetText((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null, field.Attr.Label); Toggle componentInChildren = obj.GetComponentInChildren<Toggle>(true); componentInChildren.onValueChanged = new ToggleEvent(); ((UnityEvent<bool>)(object)componentInChildren.onValueChanged).AddListener(DelegateSupport.ConvertDelegate<UnityAction<bool>>((Delegate)(Action<bool>)delegate(bool on) { Set(field, on ? 1 : 0); })); Controls.Add((Selectable)(object)componentInChildren); return new Row { Field = field, Toggle = componentInChildren }; } private static Row AddSliderRow(GameObject tpl, Transform root, RuleField field) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) bool flag = field.Attr.Choices != null; GameObject obj = Clone(tpl, root); WidenRow(obj, "Label Variant", flag ? 450f : 540f); Transform obj2 = obj.transform.Find("Label Variant/LabelText"); SetText((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null, field.Attr.Label); RuleAttribute a = field.Attr; int num = (int)Math.Round((a.Max - a.Min) / a.Step); Slider componentInChildren = obj.GetComponentInChildren<Slider>(true); componentInChildren.onValueChanged = new SliderEvent(); componentInChildren.wholeNumbers = true; componentInChildren.minValue = 0f; componentInChildren.maxValue = num; ((UnityEvent<float>)(object)componentInChildren.onValueChanged).AddListener(DelegateSupport.ConvertDelegate<UnityAction<float>>((Delegate)(Action<float>)delegate(float v) { Set(field, a.Min + Math.Round(v) * a.Step); })); Controls.Add((Selectable)(object)componentInChildren); float num2 = (flag ? 200f : 110f); Transform obj3 = obj.transform.Find("Label_Value/LabelText"); TMP_Text val = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null); Transform obj4 = obj.transform.Find("Label_Value"); LayoutElement val2 = ((obj4 != null) ? ((Component)obj4).GetComponent<LayoutElement>() : null); if ((Object)(object)val2 != (Object)null) { val2.preferredWidth = num2; val2.minWidth = num2; } RectTransform val3 = ((val != null) ? ((Component)val).GetComponent<RectTransform>() : null); if ((Object)(object)val3 != (Object)null) { val3.sizeDelta = new Vector2(num2, val3.sizeDelta.y); } SetText(val, ""); return new Row { Field = field, Slider = componentInChildren, Value = val, Steps = num }; } private static void WidenRow(GameObject row, string labelName, float labelWidth = 560f) { //IL_000e: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) RectTransform component = row.GetComponent<RectTransform>(); component.sizeDelta = new Vector2(900f, component.sizeDelta.y); Transform val = row.transform.Find(labelName); LayoutElement val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<LayoutElement>() : null); if ((Object)(object)val2 == (Object)null && (Object)(object)val != (Object)null) { val2 = ((Component)val).gameObject.AddComponent<LayoutElement>(); } if ((Object)(object)val2 != (Object)null) { val2.preferredWidth = labelWidth; val2.minWidth = labelWidth; } RectTransform val3 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<RectTransform>() : null); if ((Object)(object)val3 != (Object)null) { val3.sizeDelta = new Vector2(labelWidth, val3.sizeDelta.y); } } private static void Set(RuleField field, double value) { if (Editable && !_refreshing) { field.Set(Mod.Local, (Math.Abs(value - field.Attr.Default) < field.Attr.Step / 2.0) ? ((double?)null) : new double?(value)); RulesMenu.NotifyChanged(); } } private static void CyclePreset() { if (Editable) { List<string> list = PresetStore.List(); if (list.Count != 0) { int num = list.IndexOf(PresetStore.FindMatching(Mod.Local) ?? ""); Mod.Local = PresetStore.Load(list[(num + 1) % list.Count]); RulesMenu.NotifyChanged(); } } } private static void SavePreset() { if (Editable) { string text = PresetStore.SaveNew(Mod.Local); RulesMenu.Toast("Saved preset \"" + text + "\" in UserData/MatchRules", 5f); } } private static void ResetAll() { if (Editable) { Mod.Local = new RuleSet(); RulesMenu.NotifyChanged(); } } private static void Refresh() { //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0163: 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) RuleSet shown = Shown; _refreshing = true; try { foreach (Selectable control in Controls) { if ((Object)(object)control != (Object)null) { control.interactable = Editable; } } foreach (Row row in Rows) { double? num = row.Field.Get(shown); double num2 = num ?? row.Field.Attr.Default; if ((Object)(object)row.Toggle != (Object)null) { row.Toggle.SetIsOnWithoutNotify(num2 >= 0.5); } if ((Object)(object)row.Slider != (Object)null) { row.Slider.SetValueWithoutNotify((float)Math.Round((num2 - row.Field.Attr.Min) / row.Field.Attr.Step)); if ((Object)(object)row.Value != (Object)null) { row.Value.text = row.Field.FormatValue(num2); ((Graphic)row.Value).color = (Color)((!num.HasValue) ? Color.white : new Color(1f, 0.83f, 0.3f)); } } } if ((Object)(object)_presetLabel != (Object)null) { _presetLabel.text = "Preset: " + (PresetStore.FindMatching(shown) ?? "custom"); } if ((Object)(object)_statusLabel != (Object)null) { string text = MissingModWarning(shown); TMP_Text statusLabel = _statusLabel; string text2 = text; if (text2 == null) { text2 = Session.Role switch { Role.Host => "Your rules are active for this room", Role.Client => (Session.Received == null) ? "Host isn't using Match Rules" : "Host's rules (read-only)", _ => "Rules apply when you host", }; } statusLabel.text = text2; ((Graphic)_statusLabel).color = ((text != null) ? new Color(1f, 0.6f, 0.3f) : new Color(0.85f, 0.85f, 0.85f)); } } finally { _refreshing = false; } } private static string MissingModWarning(RuleSet rules) { if (Session.Role == Role.Inactive || !rules.HasAllPlayersRules) { return null; } List<string> list = (from m in Session.Members() where string.IsNullOrEmpty(m.Version) select m.Name).ToList(); if (list.Count == 0) { return null; } string text = string.Join(", ", list.Take(3)) + ((list.Count > 3) ? $" +{list.Count - 3}" : ""); return "Without the mod: " + text + ". Physics & Arena rules won't work for them!"; } private static T FindInScene<T>() where T : Component { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<T>())) { T val = ((Il2CppObjectBase)item).TryCast<T>(); if ((Object)(object)val != (Object)null) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { return val; } } } return default(T); } } public static class RulesMenu { private const string InputLockKey = "bbmr.menu"; private static readonly string[] Tabs = RuleField.VisibleTabs.Select(TabInfo.Short).Concat(new string[2] { "Presets", "Players" }).ToArray(); private static readonly int RuleTabs = RuleField.VisibleTabs.Count; private static int _tab; private static int _row; private static string _flash; private static float _flashUntil; private static string _toast; private static float _toastUntil; private static GUIStyle _label; private static List<string> _presets = new List<string>(); private static int PresetsTab => RuleTabs; private static Tab? CurrentTab { get { if (_tab >= RuleTabs) { return null; } return RuleField.VisibleTabs[_tab]; } } public static bool Open { get; private set; } private static bool Editable => Session.Role != Role.Client; private static RuleSet Shown { get { if (Session.Role != Role.Client) { return Mod.Local; } return Session.Received ?? new RuleSet(); } } public static void Toast(string text, float seconds = 8f) { _toast = text; _toastUntil = Time.unscaledTime + seconds; } private static void Flash(string text) { _flash = text; _flashUntil = Time.unscaledTime + 3f; } public static void Update() { Keyboard current = Keyboard.current; if (current == null) { return; } if (((ButtonControl)current.f6Key).wasPressedThisFrame) { SetOpen(!Open); } if (!Open) { return; } if (((ButtonControl)current.qKey).wasPressedThisFrame || ((ButtonControl)current.pageUpKey).wasPressedThisFrame) { _tab = (_tab + Tabs.Length - 1) % Tabs.Length; _row = 0; } if (((ButtonControl)current.eKey).wasPressedThisFrame || ((ButtonControl)current.pageDownKey).wasPressedThisFrame) { _tab = (_tab + 1) % Tabs.Length; _row = 0; } int num = RowCount(); if (num > 0) { if (((ButtonControl)current.upArrowKey).wasPressedThisFrame) { _row = (_row + num - 1) % num; } if (((ButtonControl)current.downArrowKey).wasPressedThisFrame) { _row = (_row + 1) % num; } _row = Math.Clamp(_row, 0, num - 1); } bool flag = ((ButtonControl)current.leftShiftKey).isPressed || ((ButtonControl)current.rightShiftKey).isPressed; int num2 = (((ButtonControl)current.rightArrowKey).wasPressedThisFrame ? 1 : (((ButtonControl)current.leftArrowKey).wasPressedThisFrame ? (-1) : 0)); if (_tab < RuleTabs) { RuleField ruleField = FieldsFor(_tab).ElementAtOrDefault(_row); if (ruleField == null) { return; } if (!Editable) { if (num2 != 0 || ((ButtonControl)current.backspaceKey).wasPressedThisFrame) { Flash("Only the host can change the rules."); } return; } if (num2 != 0) { double num3 = ruleField.Get(Mod.Local) ?? ruleField.Attr.Default; double value = (ruleField.IsBool ? ((double)((!(num3 >= 0.5)) ? 1 : 0)) : (num3 + (double)num2 * ruleField.Attr.Step * (double)((!flag) ? 1 : 10))); ruleField.Set(Mod.Local, value); Changed(); } if (((ButtonControl)current.backspaceKey).wasPressedThisFrame || ((ButtonControl)current.deleteKey).wasPressedThisFrame) { ruleField.Set(Mod.Local, null); Changed(); } } else if (_tab == PresetsTab && (((ButtonControl)current.enterKey).wasPressedThisFrame || ((ButtonControl)current.numpadEnterKey).wasPressedThisFrame)) { UsePresetRow(); } } public static void NotifyChanged() { Changed(); } private static void Changed() { Session.ForceReapply(); } private static void UsePresetRow() { if (!Editable) { Flash("Only the host can change the rules."); return; } try { if (_row < _presets.Count) { Mod.Local = PresetStore.Load(_presets[_row]); Changed(); Flash("Loaded preset \"" + _presets[_row] + "\""); } else if (_row == _presets.Count) { string text = PresetStore.SaveNew(Mod.Local); RefreshPresets(); Flash("Saved as \"" + text + "\" in UserData/MatchRules"); } } catch (Exception ex) { Flash("Preset error: " + ex.Message); } } private static void RefreshPresets() { _presets = PresetStore.List(); } private static IEnumerable<RuleField> FieldsFor(int tab) { if (tab >= RuleTabs) { return Enumerable.Empty<RuleField>(); } return RuleField.Visible.Where((RuleField f) => f.Attr.Tab == RuleField.VisibleTabs[tab]); } private static int RowCount() { _ = _tab; if (_tab < RuleTabs) { return FieldsFor(_tab).Count(); } if (_tab == PresetsTab) { return _presets.Count + 1; } return 0; } private static void SetOpen(bool open) { if (open == Open) { return; } Open = open; if (open) { RefreshPresets(); } try { PlayerControls controls = PlayerInputManager.Controls; InputActionMap val = ((controls != null) ? controls.Actions.Get() : null); if (val != null) { if (open) { PlayerInputManager.AddKeyedGroupInputLock("bbmr.menu", val, false); } else { PlayerInputManager.RemoveKeyedGroupInputLock("bbmr.menu", val); } } } catch (Exception ex) { Mod.Log.Warning("[menu] input lock failed: " + ex.Message); } } public static void Draw() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) try { EnsureStyle(); float num = Mathf.Max(1f, (float)Screen.height / 1080f); GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f)); if (!Open) { if (_toast != null && Time.unscaledTime < _toastUntil) { Panel(new Rect(20f, 20f, 520f, 40f), "<b>Match Rules</b> " + _toast); } return; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("<size=22><b>Beetleball Match Rules</b></size> <color=#aaaaaa>v0.1.0</color>"); stringBuilder.AppendLine(StatusLine()); stringBuilder.AppendLine(); for (int i = 0; i < Tabs.Length; i++) { stringBuilder.Append((i == _tab) ? ("<color=#ffd34d><b>[" + Tabs[i] + "]</b></color> ") : ("<color=#bbbbbb>" + Tabs[i] + "</color> ")); } stringBuilder.AppendLine(); stringBuilder.AppendLine(); if (_tab < RuleTabs) { DrawRules(stringBuilder); } else if (_tab == PresetsTab) { DrawPresets(stringBuilder); } else { DrawPlayers(stringBuilder); } stringBuilder.AppendLine(); if (_flash != null && Time.unscaledTime < _flashUntil) { StringBuilder stringBuilder2 = stringBuilder; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(23, 1, stringBuilder2); handler.AppendLiteral("<color=#7fff7f>"); handler.AppendFormatted(_flash); handler.AppendLiteral("</color>"); stringBuilder2.AppendLine(ref handler); } stringBuilder.Append("<color=#999999>F6 close · Q/E tab · ↑↓ select · ←→ change (Shift ×10) · Backspace normal · Enter use preset</color>"); Panel(new Rect(20f, 20f, 640f, 700f), stringBuilder.ToString()); } catch (Exception ex) { Mod.Log.Warning("[menu] draw failed: " + ex.Message); Open = false; } } private static string StatusLine() { switch (Session.Role) { case Role.Host: return "<color=#7fff7f>Hosting a custom room: these rules are active and shared with the room.</color>"; case Role.Client: if (Session.Received != null) { return "<color=#7fd4ff>Host's rules (read-only).</color>"; } return "<color=#ffb04d>The host is not using Match Rules: normal rules.</color>"; default: return "<color=#bbbbbb>Not in a custom room. Rules take effect when you host one.</color>"; } } private static void DrawRules(StringBuilder sb) { RuleSet shown = Shown; int num = 0; foreach (RuleField item in FieldsFor(_tab)) { bool flag = num++ == _row; string text = item.Format(shown); string text2 = string.Concat(str2: item.Get(shown).HasValue ? ("<color=#ffd34d>" + text + "</color>") : text, str0: item.Attr.Label, str1: ": "); sb.AppendLine(flag ? ("<color=#ffffff><b>> " + text2 + "</b></color>") : (" <color=#dddddd>" + text2 + "</color>")); } if (CurrentTab == Tab.AllPlayers) { sb.AppendLine(); sb.AppendLine("<color=#ffb04d>Every player needs the mod for these. Players without it will see glitchy balls/movement.</color>"); } else if (CurrentTab == Tab.RoundStart) { sb.AppendLine(); sb.AppendLine("<color=#999999>Applies at match start and after every goal. \"Full grown\" = max dung size (5 normally).</color>"); } else if (CurrentTab == Tab.Match) { sb.AppendLine(); sb.AppendLine("<color=#999999>Match length and goals apply from the next match start.</color>"); } } private static void DrawPresets(StringBuilder sb) { for (int i = 0; i <= _presets.Count; i++) { string text = ((i < _presets.Count) ? _presets[i] : "+ Save current rules as a new preset"); sb.AppendLine((i == _row) ? ("<color=#ffffff><b>> " + text + "</b></color>") : (" <color=#dddddd>" + text + "</color>")); } sb.AppendLine(); sb.AppendLine("<color=#999999>Preset files: UserData/MatchRules/*.json (share them with friends).</color>"); } private static void DrawPlayers(StringBuilder sb) { List<Session.MemberStatus> list = Session.Members(); if (list.Count == 0) { sb.AppendLine("<color=#bbbbbb>Not in a room.</color>"); return; } foreach (Session.MemberStatus item in list) { string value = (string.IsNullOrEmpty(item.Version) ? "<color=#ff7f7f>no mod</color>" : ("<color=#7fff7f>mod v" + item.Version + "</color>")); StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(4, 2, sb); handler.AppendLiteral(" "); handler.AppendFormatted(item.Name); handler.AppendLiteral(": "); handler.AppendFormatted(value); sb.AppendLine(ref handler); } if (Mod.Local.HasAllPlayersRules && list.Any((Session.MemberStatus m) => string.IsNullOrEmpty(m.Version))) { sb.AppendLine("\n<color=#ffb04d>Physics & Arena rules are on, but some players don't have the mod.</color>"); } } private static void EnsureStyle() { if (_label == null) { _label = GUI.skin.label; _label.richText = true; _label.fontSize = 17; _label.wordWrap = true; } } private static void Panel(Rect r, string text) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) GUI.Box(r, ""); GUI.Box(r, ""); GUI.Label(new Rect(((Rect)(ref r)).x + 14f, ((Rect)(ref r)).y + 10f, ((Rect)(ref r)).width - 28f, ((Rect)(ref r)).height - 20f), text); } } public static class WallEditor { private const float MinHeight = 2f; private const float MaxHeight = 60f; private const float HeightStep = 2f; private static readonly string[] MirrorNames = new string[3] { "Off", "Other side of the pitch", "All 4 corners" }; private static WallLayout _layout; private static GameObject _preview; private static GameObject _cursor; private static GameObject _ghost; private static Material _glass; private static Material _rim; private static Material _faint; private static Material _marker; private static Material _ghostMat; private static Vector3? _aim; private static string _flash; private static float _flashUntil; private static float _confirmClearUntil; public static bool Open { get; private set; } private static Material GlassMat => Mat(ref _glass, new Color(0.55f, 0.85f, 1f, 0.3f)); private static Material RimMat => Mat(ref _rim, new Color(0.75f, 0.95f, 1f, 0.8f)); private static Material FaintMat => Mat(ref _faint, new Color(0.55f, 0.85f, 1f, 0.12f)); private static Material MarkerMat => Mat(ref _marker, new Color(1f, 0.8f, 0.2f, 0.95f)); private static Material GhostMat => Mat(ref _ghostMat, new Color(1f, 0.85f, 0.3f, 0.2f)); private static void Flash(string text) { _flash = text; _flashUntil = Time.unscaledTime + 3f; } public static void Update() { //IL_009b: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { return; } if (((ButtonControl)current.f7Key).wasPressedThisFrame) { if (Open) { Close(); } else { TryOpen(); } } if (!Open) { return; } MatchStateController val = null; try { val = MatchStateController.Instance; } catch { } if ((Object)(object)val == (Object)null || Mod.CurrentScene != _layout.Scene) { Close(); } else { if (RulesMenu.Open) { return; } _aim = Aim(); List<float[]> list = CurrentLine(); if (((ButtonControl)current.f8Key).wasPressedThisFrame) { if (_aim.HasValue) { list.Add(WallLayout.P(_aim.Value)); Rebuild(val); } else { Flash("Aim the crosshair at the ground first."); } } if (((ButtonControl)current.f9Key).wasPressedThisFrame) { Undo(); Rebuild(val); } if (((ButtonControl)current.f10Key).wasPressedThisFrame) { if (list.Count > 0) { _layout.Lines.Add(new List<float[]>()); Flash("New wall line started."); } else { Flash("This line is already empty: just place points."); } } if (((ButtonControl)current.f11Key).wasPressedThisFrame) { CloseShape(val); } if (((ButtonControl)current.insertKey).wasPressedThisFrame) { _layout.Mirror = (_layout.Mirror + 1) % MirrorNames.Length; Rebuild(val); Flash("Mirror: " + MirrorNames[_layout.Mirror]); } if (((ButtonControl)current.homeKey).wasPressedThisFrame && !WallLayout.IsInfinite(_layout.Height)) { _layout.Height = ((_layout.Height + 2f > 60f) ? 1000f : (_layout.Height + 2f)); Rebuild(val); } if (((ButtonControl)current.endKey).wasPressedThisFrame) { _layout.Height = (WallLayout.IsInfinite(_layout.Height) ? 60f : Mathf.Max(2f, _layout.Height - 2f)); Rebuild(val); } if (((ButtonControl)current.deleteKey).wasPressedThisFrame) { if (Time.unscaledTime < _confirmClearUntil) { _layout.Lines.Clear(); _layout.Lines.Add(new List<float[]>()); Rebuild(val); Flash("All walls on this map removed."); _confirmClearUntil = 0f; } else { _confirmClearUntil = Time.unscaledTime + 3f; Flash("Press Delete again to remove ALL walls on this map."); } } UpdateCursorAndGhost(); } } private static void TryOpen() { MatchStateController val = null; try { val = MatchStateController.Instance; } catch { } if ((Object)(object)val == (Object)null) { RulesMenu.Toast("Wall editor: start a match on the map you want to edit, then press F7."); return; } _layout = WallLayout.Load(Mod.CurrentScene) ?? new WallLayout { Scene = Mod.CurrentScene }; _layout.Scene = Mod.CurrentScene; if (_layout.Lines.Count != 0) { List<List<float[]>> lines = _layout.Lines; if (lines[lines.Count - 1].Count <= 0) { goto IL_009c; } } _layout.Lines.Add(new List<float[]>()); goto IL_009c; IL_009c: Open = true; ArenaWalls.Invalidate(); Rebuild(val); Mod.Log.Msg("[wall-editor] editing " + _layout.Scene); } private static void Close() { if (!Open) { return; } Open = false; try { _layout.Lines.RemoveAll((List<float[]> l) => l.Count == 0); if (_layout.IsEmpty) { _layout.Delete(); RulesMenu.Toast("No walls on " + _layout.Scene + "."); } else { _layout.Save(); RulesMenu.Toast("Walls saved for " + _layout.Scene + ". They appear when \"Glass walls\" is On."); } Mod.Log.Msg($"[wall-editor] saved {_layout.Scene}: {_layout.Lines.Count} lines, mirror {_layout.Mirror}, height {_layout.Height}"); } catch (Exception ex) { Mod.Log.Warning("[wall-editor] save failed: " + ex.Message); } Destroy(ref _preview); Destroy(ref _cursor); Destroy(ref _ghost); ArenaWalls.Invalidate(); } private static void Destroy(ref GameObject go) { if ((Object)(object)go != (Object)null && !((Il2CppObjectBase)go).WasCollected) { Object.Destroy((Object)(object)go); } go = null; } private static List<float[]> CurrentLine() { if (_layout.Lines.Count == 0) { _layout.Lines.Add(new List<float[]>()); } List<List<float[]>> lines = _layout.Lines; return lines[lines.Count - 1]; } private static void CloseShape(MatchStateController match) { List<float[]> list = CurrentLine(); if (list.Count < 3) { Flash("Place at least 3 points before closing the shape."); return; } float[] array = list[0]; float[] array2 = list[list.Count - 1]; if (array[0] == array2[0] && array[1] == array2[1] && array[2] == array2[2]) { Flash("This shape is already closed."); return; } list.Add((float[])array.Clone()); _layout.Lines.Add(new List<float[]>()); Rebuild(match); Flash("Shape closed. Place points to start a new wall line."); } private static void Undo() { List<float[]> list = CurrentLine(); if (list.Count > 0) { list.RemoveAt(list.Count - 1); } else if (_layout.Lines.Count > 1) { _layout.Lines.RemoveAt(_layout.Lines.Count - 1); List<float[]> list2 = CurrentLine(); if (list2.Count > 0) { list2.RemoveAt(list2.Count - 1); } } } private static Vector3? Aim() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_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_00c6: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return null; } Ray val = main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)); Vector3? result = null; float num = float.MaxValue; foreach (RaycastHit item in (Il2CppArrayBase<RaycastHit>)(object)Physics.RaycastAll(val, 500f, WallLayout.GroundMask())) { RaycastHit current = item; Collider collider = ((RaycastHit)(ref current)).collider; if (!((Object)(object)collider == (Object)null) && !collider.isTrigger && !((Object)(object)collider.attachedRigidbody != (Object)null) && (!((Object)(object)_preview != (Object)null) || !((Component)collider).transform.IsChildOf(_preview.transform)) && ((RaycastHit)(ref current)).distance < num) { num = ((RaycastHit)(ref current)).distance; result = ((RaycastHit)(ref current)).point; } } return result; } private static Material Mat(ref Material m, Color c) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)m != (Object)null) || ((Il2CppObjectBase)m).WasCollected) { return m = WallLayout.MakeMaterial(c); } return m; } private static void Rebuild(MatchStateController match) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_005e: 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_0064: 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_0075: 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_010b: 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) Destroy(ref _preview); _preview = new GameObject("BBMR_WallEditor"); var (layer, surface) = WallLayout.WallPhysics((Session.Active ?? Mod.Local).WallsNotWalkable == true); try { foreach (var (a, b) in _layout.Segments(match)) { WallLayout.AddWall(_preview.transform, a, b, _layout.Height, layer, GlassMat, RimMat, FaintMat, collide: true, surface); } } catch (Exception ex) { Mod.Log.Warning("[wall-editor] preview failed: " + ex.Message); } foreach (List<float[]> line in _layout.Lines) { foreach (float[] item in line) { Marker(_preview.transform, WallLayout.V(item), new Vector3(0.8f, 3f, 0.8f)); } } } private static GameObject Marker(Transform parent, Vector3 groundPos, Vector3 size) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)val).name = "Marker"; Object.Destroy((Object)(object)val.GetComponent<Collider>()); if ((Object)(object)parent != (Object)null) { val.transform.SetParent(parent, false); } val.transform.position = groundPos + Vector3.up * (size.y * 0.5f); val.transform.localScale = size; WallLayout.Style(val, MarkerMat); return val; } private static void UpdateCursorAndGhost() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: 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_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cursor == (Object)null || ((Il2CppObjectBase)_cursor).WasCollected) { _cursor = Marker(null, Vector3.zero, new Vector3(0.5f, 8f, 0.5f)); } _cursor.SetActive(_aim.HasValue); if (_aim.HasValue) { _cursor.transform.position = _aim.Value + Vector3.up * 4f; } List<float[]> list = CurrentLine(); bool flag = _aim.HasValue && list.Count > 0; if ((Object)(object)_ghost == (Object)null || ((Il2CppObjectBase)_ghost).WasCollected) { _ghost = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)_ghost).name = "Ghost"; Object.Destroy((Object)(object)_ghost.GetComponent<Collider>()); WallLayout.Style(_ghost, GhostMat); } _ghost.SetActive(flag); if (flag) { Vector3 val = WallLayout.V(list[list.Count - 1]); Vector3 value = _aim.Value; Vector3 val2 = value - val; val2.y = 0f; if (((Vector3)(ref val2)).magnitude < 0.2f) { _ghost.SetActive(false); return; } bool flag2 = WallLayout.IsInfinite(_layout.Height); float num = Mathf.Min(val.y, value.y) - (flag2 ? 30f : 3f); float num2 = Mathf.Max(val.y, value.y) + (flag2 ? 30f : _layout.Height); Vector3 val3 = (val + value) * 0.5f; _ghost.transform.position = new Vector3(val3.x, (num + num2) * 0.5f, val3.z); _ghost.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up); _ghost.transform.localScale = new Vector3(2f, num2 - num, ((Vector3)(ref val2)).magnitude); } } public static void Draw() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) if (!Open || _layout == null) { return; } try { float num = Mathf.Max(1f, (float)Screen.height / 1080f); GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f)); int num2 = 0; foreach (List<float[]> line in _layout.Lines) { num2 += line.Count; } string value = (_aim.HasValue ? "" : " <color=#ffb04d>(aim at the ground)</color>"); string text = ((Session.Role == Role.Client) ? "\n<color=#ffb04d>You're not the host: your walls are only used in rooms you host.</color>" : ""); string text2 = ((_flash != null && Time.unscaledTime < _flashUntil) ? ("\n<color=#7fff7f>" + _flash + "</color>") : ""); string text3 = $"<size=20><b>WALL EDITOR</b></size> <color=#aaaaaa>{_layout.Scene}</color>{value}\nLines: {_layout.Lines.FindAll((List<float[]> l) => l.Count > 0).Count} Points: {num2} Mirror: <color=#ffd34d>{MirrorNames[_layout.Mirror]}</color> Height: <color=#ffd34d>{WallLayout.HeightText(_layout.Height)}</color>\n" + "<color=#dddddd>F8</color> place point at crosshair <color=#dddddd>F9</color> undo <color=#dddddd>F10</color> new wall line <color=#dddddd>F11</color> close shape\n<color=#dddddd>Insert</color> mirror <color=#dddddd>Home/End</color> height (above 60m = Infinite) <color=#dddddd>Delete</color> x2 clear map <color=#dddddd>F7</color> save & exit" + text + text2; Rect val = default(Rect); ((Rect)(ref val))..ctor(20f, (float)Screen.height / num - 210f, 760f, 190f); GUI.Box(val, ""); GUI.Box(val, ""); GUI.Label(new Rect(((Rect)(ref val)).x + 14f, ((Rect)(ref val)).y + 10f, ((Rect)(ref val)).width - 28f, ((Rect)(ref val)).height - 20f), text3); } catch (Exception ex) { Mod.Log.Warning("[wall-editor] draw failed: " + ex.Message); } } } } namespace BeetleballMatchRules.Rules { public static class ArenaWalls { private const string RootName = "BBMR_ArenaWalls"; public const string LobbyKey = "bbmr.walls"; private static GameObject _root; private static IntPtr _builtFor; private static float _seenAt = -1f; private static float _next; private static string _published; private static Material _glass; private static Material _rim; private static Material _faint; public static Material Glass { get { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!Alive(_glass)) { return _glass = WallLayout.MakeMaterial(new Color(0.65f, 0.9f, 1f, 0.12f)); } return _glass; } } public static Material Rim { get { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!Alive(_rim)) { return _rim = WallLayout.MakeMaterial(new Color(0.75f, 0.95f, 1f, 0.5f)); } return _rim; } } public static Material Faint { get { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!Alive(_faint)) { return _faint = WallLayout.MakeMaterial(new Color(0.65f, 0.9f, 1f, 0.05f)); } return _faint; } } private static bool Alive(Material m) { if ((Object)(object)m != (Object)null) { return !((Il2CppObjectBase)m).WasCollected; } return false; } public static void Invalidate() { Remove(); _builtFor = IntPtr.Zero; _published = null; } public static void Tick() { //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < _next) { return; } _next = Time.unscaledTime + 0.5f; MatchStateController val = null; try { val = MatchStateController.Instance; } catch { } RuleSet active = Session.Active; if (active == null || active.ArenaWalls != true || Session.Role == Role.Inactive || !((Object)(object)val != (Object)null) || WallEditor.Open) { Remove(); _seenAt = -1f; _builtFor = IntPtr.Zero; return; } if (Session.Role == Role.Host) { PublishLayout(); } if ((Object)(object)_root != (Object)null && !((Il2CppObjectBase)_root).WasCollected && _builtFor == ((Il2CppObjectBase)val).Pointer) { return; } if (_builtFor != ((Il2CppObjectBase)val).Pointer) { Remove(); _builtFor = ((Il2CppObjectBase)val).Pointer; _seenAt = Time.unscaledTime; } float num = Time.unscaledTime - _seenAt; if (num < 2f) { return; } WallLayout layout; if (Session.Role == Role.Host) { layout = WallLayout.Load(Mod.CurrentScene); } else if (!TryReadHostLayout(out layout)) { if (num < 10f) { return; } Mod.Log.Warning("[walls] no wall layout received from the host for " + Mod.CurrentScene); } _root = new GameObject("BBMR_ArenaWalls"); if (layout == null || layout.IsEmpty) { Mod.Log.Msg("[walls] " + Mod.CurrentScene + ": this map has no wall layout"); return; } try { (int layer, PhysicsMaterial surface) tuple = WallLayout.WallPhysics(Session.Active.WallsNotWalkable == true); int item = tuple.layer; PhysicsMaterial item2 = tuple.surface; List<(Vector3, Vector3)> list = layout.Segments(val); foreach (var (a, b) in list) { WallLayout.AddWall(_root.transform, a, b, layout.Height, item, Glass, Rim, Faint, collide: true, item2); } Mod.Log.Msg($"[walls] {Mod.CurrentScene}: built {list.Count} wall sections"); } catch (Exception ex) { Mod.Log.Warning("[walls] build failed: " + ex.Message); } } private static void Remove() { if ((Object)(object)_root != (Object)null && !((Il2CppObjectBase)_root).WasCollected) { Object.Destroy((Object)(object)_root); } _root = null; } private static void PublishLayout() { string text = (WallLayout.Load(Mod.CurrentScene) ?? new WallLayout { Scene = Mod.CurrentScene }).ToJson(); if (text == _published) { return; } try { ILobby currentLobby = Session.CurrentLobby; if (currentLobby != null) { currentLobby.SetData("bbmr.walls", text); } _published = text; } catch (Exception ex) { Mod.Log.Warning("[walls] publish failed: " + ex.Message); } } private static bool TryReadHostLayout(out WallLayout layout) { layout = null; try { ILobby currentLobby = Session.CurrentLobby; WallLayout wallLayout = WallLayout.FromJson((currentLobby != null) ? currentLobby.GetData("bbmr.walls") : null); if (wallLayout == null || wallLayout.Scene != Mod.CurrentScene) { return false; } layout = wallLayout; return true; } catch { return false; } } } public static class DungPatches { private static bool _inBunny; private static bool _inStartingBalls; private static bool _spawningExtras; private static bool _kickoffSpawn; private static int _singleBallFrame = -1; private static TeamType _singleBallTeam; private static IntPtr _singleBallMatch; private static int _centerBallFrame = -1; private static DungBallDataSO _data; private static DungBallDataSO Data { get { if ((Object)(object)_data != (Object)null && !((Il2CppObjectBase)_data).WasCollected) { return _data; } _data = null; DungBallDataSO[] array = AssetOverrides.All<DungBallDataSO>(); foreach (DungBallDataSO val in array) { if ((Object)(object)_data == (Object)null || ((Object)val).name == "Data_DungBall") { _data = val; } } return _data; } } public static void Register(Patcher p) { p.Prefix(typeof(BunnySpawner), "SpawnBunnyAndUpdateTime", "BunnySpawnPrefix", typeof(DungPatches)); p.Prefix(typeof(BunnyPathJumper), "Update", "BunnyUpdatePrefix", typeof(DungPatches)); p.Postfix(typeof(BunnyPathJumper), "Update", "BunnyUpdatePostfix", typeof(DungPatches)); p.Prefix(typeof(MatchStateController), "SpawnStartingBallsAtTeam", "StartingPrefix", typeof(DungPatches)); p.Postfix(typeof(MatchStateController), "SpawnStartingBallsAtTeam", "StartingPostfix", typeof(DungPatches)); p.Prefix(typeof(NetworkPrefabSpawner), "SpawnDungBallAsServer", "SpawnPrefix", typeof(DungPatches)); p.Postfix(typeof(NetworkPrefabSpawner), "SpawnDungBallAsServer", "SpawnPostfix", typeof(DungPatches)); p.Prefix(typeof(DungBall), "IncrementSize_ServerRpc", "IncrementSizePrefix", typeof(DungPatches)); } public static void ResetFlags() { _inBunny = false; _inStartingBalls = false; _spawningExtras = false; _kickoffSpawn = false; } public static bool BunnySpawnPrefix(BunnySpawner __instance) { RuleSet active = Session.Active; if (!Session.HostRules) { return true; } if (active.BunniesEnabled == false) { return false; } int? bunnyInterval = active.BunnyInterval; if (bunnyInterval.HasValue) { int valueOrDefault = bunnyInterval.GetValueOrDefault(); __instance.spawnInterval = valueOrDefault; } bunnyInterval = active.BunnyIntervalSuddenDeath; if (bunnyInterval.HasValue) { int valueOrDefault2 = bunnyInterval.GetValueOrDefault(); __instance.spawnIntervalSuddenDeath = valueOrDefault2; } return true; } public static void BunnyUpdatePrefix() { _inBunny = true; } public static void BunnyUpdatePostfix() { _inBunny = false; } public static bool StartingPrefix(MatchStateController __instance, TeamType team) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) _inStartingBalls = true; if (!Session.HostRules) { return true; } if (Session.Active.StartingBallsPerTeam == 0) { return false; } int? singleStartingBall = Session.Active.SingleStartingBall; if (singleStartingBall.HasValue) { int valueOrDefault = singleStartingBall.GetValueOrDefault(); if (valueOrDefault > 0) { return team == SingleBallTeam(__instance, valueOrDefault); } } return true; } private static TeamType SingleBallTeam(MatchStateController match, int mode) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0045: 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_0049: Invalid comparison between Unknown and I4 //IL_000c: 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_006f: 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_0079: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Invalid comparison between Unknown and I4 //IL_00d0: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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) if (_singleBallFrame == Time.frameCount) { return _singleBallTeam; } _singleBallFrame = Time.frameCount; bool flag = _singleBallMatch != ((Il2CppObjectBase)match).Pointer; _singleBallMatch = ((Il2CppObjectBase)match).Pointer; TeamType singleBallTeam = _singleBallTeam; TeamType lastScoringTeam = match.LastScoringTeam; bool flag2 = lastScoringTeam - 1 <= 1; TeamType singleBallTeam2 = (TeamType)((!flag2) ? ((Random.value < 0.5f) ? 1 : 2) : ((int)MatchStateController.GetOppositeTeam(match.LastScoringTeam))); if (flag) { _singleBallTeam = (TeamType)0; } else { flag2 = mode == 1; if (flag2) { bool flag3 = singleBallTeam - 1 <= 1; flag2 = flag3; } if (flag2) { _singleBallTeam = MatchStateController.GetOppositeTeam(singleBallTeam); } else { _singleBallTeam = singleBallTeam2; } } Mod.Log.Msg($"[dung] single starting ball: {(((int)_singleBallTeam == 0) ? "neutral spot" : ((object)Unsafe.As<TeamType, TeamType>(ref _singleBallTeam)/*cast due to .constrained prefix*/).ToString())} (mode {mode})"); return _singleBallTeam; } private static int StartingSize() { RuleSet active = Session.Active; if (active.StartFullGrown == true) { return CurrentMaxSize(); } return active.StartingBallSize ?? 1; } private static Vector3 NeutralSpot(MatchStateController match, int size) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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: 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_0099: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) try { MapInitializer mapInitializer = match.MapInitializer; Vector3? val = ((mapInitializer != null) ? new Vector3?(mapInitializer.GetSuddenDeathStartingBallSpawnPoint()) : ((Vector3?)null)); if (val.HasValue && val.Value != Vector3.zero) { return val.Value; } } catch (Exception ex) { Mod.Log.Warning("[dung] neutral spot lookup failed: " + ex.Message); } return (match.GetGoalPosition((TeamType)1) + match.GetGoalPosition((TeamType)2)) * 0.5f + Vector3.up * (2f + ScaleFor(size) * 0.5f); } private static void SpawnNeutral(MatchStateController match, int size, string what) { //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_0019: 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_007b: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val = NeutralSpot(match, size); _spawningExtras = true; _kickoffSpawn = true; NetworkPrefabSpawner.Instance.SpawnDungBallAsServer(val, Vector3.zero, size, 0uL, 0f, 0f, 0f); Mod.Log.Msg($"[dung] {what} size {size} at {val}"); } catch (Exception ex) { Mod.Log.Warning("[dung] " + what + " failed: " + ex.Message); } finally { _spawningExtras = false; _kickoffSpawn = false; } } public static void StartingPostfix(MatchStateController __instance) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) _inStartingBalls = false; if (!Session.HostRules || _centerBallFrame == Time.frameCount) { return; } _centerBallFrame = Time.frameCount; RuleSet active = Session.Active; int? singleStartingBall = active.SingleStartingBall; if (singleStartingBall.HasValue) { int valueOrDefault = singleStartingBall.GetValueOrDefault(); if (valueOrDefault > 0 && (int)_singleBallTeam == 0 && _singleBallFrame == Time.frameCount) { SpawnNeutral(__instance, StartingSize(), "neutral kickoff ball"); } } singleStartingBall = active.CenterBallSize; if (singleStartingBall.HasValue) { int valueOrDefault2 = singleStartingBall.GetValueOrDefault(); if (valueOrDefault2 > 0) { SpawnNeutral(__instance, valueOrDefault2, "center ball"); } } } public static void SpawnPrefix(ref int size) { if (!Session.HostRules || _spawningExtras) { return; } RuleSet active = Session.Active; if (_inBunny) { int? dropSize = active.DropSize; if (dropSize.HasValue) { int valueOrDefault = dropSize.GetValueOrDefault(); size = valueOrDefault; return; } } if (_inStartingBalls && active.StartFullGrown == true) { size = CurrentMaxSize(); } else if (_inStartingBalls) { int? dropSize = active.StartingBallSize; if (dropSize.HasValue) { int valueOrDefault2 = dropSize.GetValueOrDefault(); size = valueOrDefault2; } } } public static void SpawnPostfix(NetworkPrefabSpawner __instance, DungBall __result, Vector3 pos, Vector3 force, int size, ulong ownerClientId) { //IL_00f1: 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_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_010d: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) if (!Session.HostRules) { return; } RuleSet active = Session.Active; if ((_inStartingBalls || _kickoffSpawn) && active.FreezeKickoffBall == true && (Object)(object)__result != (Object)null) { KickoffFreeze.Freeze(__result, (_spawningExtras && _inStartingBalls) ? 1.5f : 0f); } if (_spawningExtras) { return; } int num = (_inBunny ? ((active.DungPerDrop ?? 1) - 1) : (_inStartingBalls ? ((active.StartingBallsPerTeam ?? 1) - 1) : 0)); if (num <= 0) { return; } _spawningExtras = true; try { float num2 = ScaleFor(size) * 1.3f + 1f; Vector3 val = default(Vector3); for (int i = 0; i < num; i++) { float num3 = (float)(i + 1) * (float)Math.PI * 2f / (float)(num + 1) + Random.Range(-0.3f, 0.3f); ((Vector3)(ref val))..ctor(Mathf.Cos(num3), 0f, Mathf.Sin(num3)); Vector3 val2 = force + val * Random.Range(6f, 12f) + Vector3.up * 4f; __instance.SpawnDungBallAsServer(pos + val * num2, val2, size, ownerClientId, 0f, 1.5f, 0f); } } catch (Exception ex) { Mod.Log.Warning("[dung] extra spawn failed: " + ex.Message); } finally { _spawningExtras = false; } } public static void IncrementSizePrefix(DungBall __instance, ref int increment) { if (Session.HostRules && Session.Active.IndestructibleDung == true && increment > 0) { increment = Math.Max(0, Math.Min(increment, CurrentMaxSize() - __instance.Size)); } } private static int CurrentMaxSize() { int? num = Session.Active?.DungMaxSize; if (!num.HasValue) { DungBallDataSO data = Data; if (data == null) { return 5; } return data.MaxSize; } return num.GetValueOrDefault(); } private static float ScaleFor(int size) { DungBallDataSO data = Data; if ((Object)(object)data == (Object)null) { return 1.5f + (float)size; } int num = Math.Max(2, CurrentMaxSize()); return Mathf.Lerp(data.MinLocalScale, data.MaxLocalScale, Mathf.Clamp01(((float)size - 1f) / ((float)num - 1f))); } } public static class KickoffFreeze { private sealed class Entry { public DungBall Ball; public Rigidbody Body; public RigidbodyConstraints Original; public float ApplyAt; public bool Applied; } private const RigidbodyConstraints Lock = (RigidbodyConstraints)122; private static readonly Dictionary<IntPtr, Entry> Balls = new Dictionary<IntPtr, Entry>(); public static void Register(Patcher p) { string[] array = new string[8] { "TryTakePossession_ServerRpc", "AddForceAndTryChangeOwnership_ServerRpc", "ChangeOwnership_ServerRpc", "ReportPlayerForceTouch_ServerRpc", "TrySetLastTouchedPlayers", "AddForce", "IRigidbodyForceRpcTarget_TryApplyForce", "OnReleaseCalled_ServerRpc" }; foreach (string method in array) { p.Prefix(typeof(DungBall), method, "TouchedPrefix", typeof(KickoffFreeze)); } p.Prefix(typeof(DungBall), "OnCollisionEnter", "CollisionPrefix", typeof(KickoffFreeze)); } public static void Freeze(DungBall ball, float delay) { //IL_003c: 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) try { Rigidbody val = ((Component)ball).GetComponent<Rigidbody>() ?? ((Component)ball).GetComponentInChildren<Rigidbody>(); if (!((Object)(object)val == (Object)null)) { Balls[((Il2CppObjectBase)ball).Pointer] = new Entry { Ball = ball, Body = val, Original = val.constraints, ApplyAt = Time.time + delay }; } } catch (Exception ex) { Mod.Log.Warning("[kickoff] freeze failed: " + ex.Message); } } public static void Tick() { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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) if (Balls.Count == 0) { return; } List<IntPtr> list = null; foreach (var (item, entry2) in Balls) { if ((Object)(object)entry2.Ball == (Object)null || ((Il2CppObjectBase)entry2.Ball).WasCollected || (Object)(object)entry2.Body == (Object)null || ((Il2CppObjectBase)entry2.Body).WasCollected) { (list ?? (list = new List<IntPtr>())).Add(item); } else if (!entry2.Applied && !(Time.time < entry2.ApplyAt)) { try { Vector3 linearVelocity = entry2.Body.linearVelocity; entry2.Body.linearVelocity = new Vector3(0f, linearVelocity.y, 0f); entry2.Body.angularVelocity = Vector3.zero; entry2.Body.constraints = (RigidbodyConstraints)(entry2.Original | 0x7A); entry2.Applied = true; } catch { (list ?? (list = new List<IntPtr>())).Add(item); } } } if (list == null) { return; } foreach (IntPtr item2 in list) { Balls.Remove(item2); } } public static void Clear() { Balls.Clear(); } private static void Release(DungBall ball, string how) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ball == (Object)null || !Balls.Remove(((Il2CppObjectBase)ball).Pointer, out var value)) { return; } try { if ((Object)(object)value.Body != (Object)null && !((Il2CppObjectBase)value.Body).WasCollected) { value.Body.constraints = value.Original; } } catch { } Mod.Log.Msg("[kickoff] ball released (" + how + ")"); } public static void TouchedPrefix(DungBall __instance) { if (Balls.Count > 0) { Release(__instance, "player action"); } } public static void CollisionPrefix(DungBall __instance, Collision collision) { if (Balls.Count == 0 || !Balls.ContainsKey(((Il2CppObjectBase)__instance).Pointer) || collision == null) { return; } try { Rigidbody rigidbody = collision.rigidbody; GameObject val = (((Object)(object)rigidbody != (Object)null) ? ((Component)rigidbody).gameObject : collision.gameObject); if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponentInParent<BeetleActor>() != (Object)null) { Release(__instance, "bumped by a beetle"); } } catch { } } } public static class MatchPatches { private static IntPtr _timerSetFor; public static void Register(Patcher p) { p.Prefix(typeof(MatchStateController), "InitializeMatch", "InitializeMatchPrefix", typeof(MatchPatches)); p.Prefix(typeof(MatchStateController), "StartMatchTimerCountdown", "StartTimerPrefix", typeof(MatchPatches)); p.Prefix(typeof(MatchStateController), "BallEnteredGoalHandler", "GoalPrefix", typeof(MatchPatches)); } public static void InitializeMatchPrefix(MatchStateController __instance) { if (Session.HostRules) { RuleSet active = Session.Active; int? goalsToWin = active.GoalsToWin; if (goalsToWin.HasValue) { int valueOrDefault = goalsToWin.GetValueOrDefault(); __instance.goalsRequired = valueOrDefault; } float? resetAfterGoalDelay = active.ResetAfterGoalDelay; if (resetAfterGoalDelay.HasValue) { float valueOrDefault2 = resetAfterGoalDelay.GetValueOrDefault(); __instance.resetAfterGoalDelay = valueOrDefault2; } Mod.Log.Msg($"[match] start: goalsRequired={__instance.goalsRequired} resetDelay={__instance.resetAfterGoalDelay}"); } } public static void StartTimerPrefix(MatchStateController __instance) { if (!Session.HostRules) { return; } int? matchSeconds = Session.Active.MatchSeconds; if (matchSeconds.HasValue) { int valueOrDefault = matchSeconds.GetValueOrDefault(); if (!(_timerSetFor == ((Il2CppObjectBase)__instance).Pointer)) { _timerSetFor = ((Il2CppObjectBase)__instance).Pointer; __instance.MatchSecondsRemaining.Value = valueOrDefault; Mod.Log.Msg($"[match] timer set to {valueOrDefault}s"); } } } public static void GoalPrefix(ref int points) { if (Session.HostRules) { int? pointsPerGoal = Session.Active.PointsPerGoal; if (pointsPerGoal.HasValue) { int valueOrDefault = pointsPerGoal.GetValueOrDefault(); points = valueOrDefault; } } } } public sealed class WallLayout { public const float Infinite = 1000f; private const float VisibleGlass = 30f; private const float FadedGlass = 80f; public static readonly string Folder = Path.Combine(MelonEnvironment.UserDataDirectory, "MatchRules", "Walls"); private static readonly JsonSerializerOptions Json = new JsonSerializerOptions { WriteIndented = true }; private const float Thickness = 2f; private static PhysicsMaterial _slippery; private static int? _nonWalkableLayer; private static bool _nonWalkableSearched; public string Scene { get; set; } = ""; public int Mirror { get; set; } = 1; public float Height { get; set; } = 1000f; public List<List<float[]>> Lines { get; set; } = new List<List<float[]>>(); public bool IsEmpty { get { foreach (List<float[]> line in Lines) { if (line.Count >= 2) { return false; } } return true; } } private static PhysicsMaterial Slippery { get { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0058: Expected O, but got Unknown if ((Object)(object)_slippery != (Object)null && !((Il2CppObjectBase)_slippery).WasCollected) { return _slippery; } _slippery = new PhysicsMaterial { dynamicFriction = 0f, staticFriction = 0f, frictionCombine = (PhysicsMaterialCombine)2, bounciness = 0f, bounceCombine = (PhysicsMaterialCombine)0 }; ((Object)_slippery).hideFlags = (HideFlags)32; return _slippery; } } public static bool IsInfinite(float height) { return height >= 1000f; } public static string HeightText(float height) { if (!IsInfinite(height)) { return $"{height:0}m"; } return "Infinite"; } public static string PathFor(string scene) { return Path.Combine(Folder, scene + ".json"); } public static WallLayout Load(string scene) { try { string path = PathFor(scene); if (File.Exists(path)) { return FromJson(File.ReadAllText(path)); } return BuiltIn(scene); } catch (Exception ex) { Mod.Log.Warning("[walls] could not read layout for " + scene + ": " + ex.Message); return null; } } private static WallLayout BuiltIn(string scene) { using Stream stream = typeof(WallLayout).Assembly.GetManifestResourceStream("Walls." + scene + ".json"); if (stream == null) { return null; } using StreamReader streamReader = new StreamReader(stream); return FromJson(streamReader.ReadToEnd()); } public void Save() { Directory.CreateDirectory(Folder); File.WriteAllText(PathFor(Scene), ToJson(indented: true)); } public void Delete() { string path = PathFor(Scene); if (File.Exists(path)) { File.Delete(path); } } public string ToJson(bool indented = false) { return JsonSerializer.Serialize(this, indented ? Json : new JsonSerializerOptions()); } public static WallLayout FromJson(string json) { if (!string.IsNullOrWhiteSpace(json)) { return JsonSerializer.Deserialize<WallLayout>(json); } return null; } public static float[] P(Vector3 v) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) return new float[3] { (float)Math.Round(v.x, 2), (float)Math.Round(v.y, 2), (float)Math.Round(v.z, 2) }; } public static Vector3 V(float[] p) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) return new Vector3(p[0], p[1], p[2]); } public List<(Vector3 a, Vector3 b)> Segments(MatchStateController match) { //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_0057: 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_005f: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) List<(Vector3, Vector3)> list = new List<(Vector3, Vector3)>(); Func<Vector3, Vector3>[] array = new Func<Vector3, Vector3>[1] { (Vector3 p) => p }; Vector3 c; Vector3 axis; Vector3 perp; if (Mirror > 0 && (Object)(object)match != (Object)null) { Vector3 goalPosition = match.GetGoalPosition((TeamType)1); Vector3 goalPosition2 = match.GetGoalPosition((TeamType)2); c = (goalPosition + goalPosition2) * 0.5f; axis = goalPosition2 - goalPosition; axis.y = 0f; ((Vector3)(ref axis)).Normalize(); perp = new Vector3(0f - axis.z, 0f, axis.x); array = ((Mirror != 1) ? new Func<Vector3, Vector3>[4] { (Vector3 p) => p, (Vector3 p) => Flip(p, 1f, -1f), (Vector3 p) => Flip(p, -1f, 1f), (Vector3 p) => Flip(p, -1f, -1f) } : new Func<Vector3, Vector3>[2] { (Vector3 p) => p, (Vector3 p) => Flip(p, 1f, -1f) }); } foreach (List<float[]> line in Lines) { for (int num = 0; num + 1 < line.Count; num++) { Func<Vector3, Vector3>[] array2 = array; foreach (Func<Vector3, Vector3> func in array2) { list.Add((func(V(line[num])), func(V(line[num + 1])))); } } } return list; Vector3 Flip(Vector3 p, float sa, float sp) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_002c: 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_0037: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_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_005a: 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) Vector3 val = p - c; return c + axis * (Vector3.Dot(val, axis) * sa) + perp * (Vector3.Dot(val, perp) * sp) + Vector3.up * val.y; } } public static void AddWall(Transform root, Vector3 a, Vector3 b, float height, int layer, Material glass, Material rim, Material faint, bool collide = true, PhysicsMaterial surface = null) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_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_0078: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) Vector3 val = b - a; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.2f) { return; } float num = Mathf.Min(a.y, b.y); float num2 = Mathf.Max(a.y, b.y); bool flag = IsInfinite(height); float bottom = (flag ? (num - 1000f) : (num - 3f)); Vector3 mid = (a + b) * 0.5f; Quaternion rot = Quaternion.LookRotation(val / magnitude, Vector3.up); float length = magnitude + 1f; if (collide) { GameObject val2 = new GameObject("WallCollider") { layer = layer }; val2.transform.SetParent(root, false); Place(val2.transform, mid, rot, bottom, num2 + (flag ? 1000f : height), 2f, length); BoxCollider val3 = val2.AddComponent<BoxCollider>(); if ((Object)(object)surface != (Object)null) { ((Collider)val3).sharedMaterial = surface; } } if (flag) { Panel(root, "GlassFadeDown", mid, rot, num - 80f, num - 30f, 2f, length, faint); Panel(root, "Glass", mid, rot, num - 30f, num2 + 30f, 2f, length, glass); Panel(root, "GlassFadeUp", mid, rot, num2 + 30f, num2 + 80f, 2f, length, faint); } else { Panel(root, "Glass", mid, rot, bottom, num2 + height, 2f, length, glass); Panel(root, "Rim", mid, rot, num2 + height - 0.15f, num2 + height + 0.15f, 2.1f, length, rim); } } private static void Place(Transform t, Vector3 mid, Quaternion rot, float bottom, float top, float thickness, float length) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0031: Unknown result type (might be due to invalid IL or missing references) t.position = new Vector3(mid.x, (bottom + top) * 0.5f, mid.z); t.rotation = rot; t.localScale = new Vector3(thickness, top - bottom, length); } private static void Panel(Transform root, string name, Vector3 mid, Quaternion rot, float bottom, float top, float thickness, float length, Material mat) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)mat == (Object)null)) { GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)obj).name = name; Object.Destroy((Object)(object)obj.GetComponent<Collider>()); obj.transform.SetParent(root, false); Place(obj.transform, mid, rot, bottom, top, thickness, length); Style(obj, mat); } } public static void Style(GameObject go, Material mat) { MeshRenderer component = go.GetComponent<MeshRenderer>(); if (!((Object)(object)component == (Object)null)) { if ((Object)(object)mat == (Object)null) { ((Renderer)component).enabled = false; return; } ((Renderer)component).sharedMaterial = mat; ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; } } public static Material MakeMaterial(Color color) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown resul