using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InControl;
using SFQoL;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("StickySlots")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("StickySlots")]
[assembly: AssemblyTitle("StickySlots")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace SFQoL
{
internal static class Compat
{
private static bool searched;
private static FieldInfo roundsActive;
private static PropertyInfo roundsArmed;
private static FieldInfo cardPicking;
private static bool cardSearched;
public static bool Rounds
{
get
{
Find();
try
{
if ((object)roundsArmed != null && (bool)roundsArmed.GetValue(null, null))
{
return true;
}
if ((object)roundsActive != null && (bool)roundsActive.GetValue(null))
{
return true;
}
}
catch
{
}
return false;
}
}
public static bool CardScreen
{
get
{
if (!cardSearched)
{
Type type = RoundsType("StickRounds.CardPick");
cardSearched = (object)type != null || Time.frameCount > 1;
if ((object)type != null)
{
cardPicking = type.GetField("Picking", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
}
try
{
return (object)cardPicking != null && (bool)cardPicking.GetValue(null);
}
catch
{
return false;
}
}
}
public static bool RoundsMatch
{
get
{
Find();
try
{
return (object)roundsActive != null && (bool)roundsActive.GetValue(null) && !GameManager.stillInMenu;
}
catch
{
return false;
}
}
}
private static Type RoundsType(string name)
{
if (!Chainloader.PluginInfos.TryGetValue("stickfight.stickrounds", out var value) || (Object)(object)value.Instance == (Object)null)
{
return null;
}
return ((object)value.Instance).GetType().Assembly.GetType(name, throwOnError: false);
}
private static void Find()
{
if (!searched)
{
Type type = RoundsType("StickRounds.RoundsMode");
searched = (object)type != null || Time.frameCount > 1;
if ((object)type != null)
{
roundsActive = type.GetField("Active", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
roundsArmed = type.GetProperty("Armed", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
}
}
public static bool IsBotDevice(InputDevice d)
{
if (d != null)
{
return ((object)d).GetType().Name == "BotDevice";
}
return false;
}
}
internal static class QolConfig
{
public static ConfigEntry<bool> Enabled(ConfigFile config, string section, string description)
{
return config.Bind<bool>(section, "Enabled", true, description);
}
private static Dictionary<ConfigDefinition, string> Orphans(ConfigFile config)
{
return Traverse.Create((object)config).Property("OrphanedEntries", (object[])null).GetValue<Dictionary<ConfigDefinition, string>>();
}
public static string Old(ConfigFile config, string section, string key)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
Dictionary<ConfigDefinition, string> dictionary = Orphans(config);
if (dictionary == null || !dictionary.TryGetValue(new ConfigDefinition(section, key), out var value))
{
return null;
}
return value;
}
public static void SetOld(ConfigFile config, string section, string key, string value)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
Dictionary<ConfigDefinition, string> dictionary = Orphans(config);
if (dictionary != null)
{
dictionary[new ConfigDefinition(section, key)] = value;
}
}
public static void DropOld(ConfigFile config)
{
Dictionary<ConfigDefinition, string> dictionary = Orphans(config);
if (dictionary != null && dictionary.Count != 0)
{
dictionary.Clear();
config.Save();
}
}
}
internal static class Ui
{
public static readonly Color Panel = new Color(0.176f, 0.176f, 0.176f);
public static readonly Color Strip = new Color(0.147f, 0.147f, 0.147f);
public static readonly Color Item = new Color(0.265f, 0.265f, 0.265f);
public static readonly Color Grey = new Color(0.6f, 0.6f, 0.6f);
private static TMP_FontAsset font;
private static Sprite box;
private static bool boxSearched;
private static Camera menuCam;
private static float menuCamSearchAt;
public static TMP_FontAsset Font
{
get
{
if ((Object)(object)font == (Object)null)
{
GameManager instance = GameManager.Instance;
if ((Object)(object)instance != (Object)null && (Object)(object)instance.winText != (Object)null)
{
font = ((TMP_Text)instance.winText).font;
}
if ((Object)(object)font == (Object)null)
{
TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
foreach (TMP_FontAsset val in array)
{
if (((Object)val).name.StartsWith("Anton"))
{
font = val;
break;
}
}
}
}
return font;
}
}
public static Sprite BoxSprite
{
get
{
if ((Object)(object)box == (Object)null && !boxSearched)
{
boxSearched = true;
Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>();
foreach (Sprite val in array)
{
if (((Object)val).name == "box")
{
box = val;
break;
}
}
}
return box;
}
}
public static int MenuLayer
{
get
{
int num = LayerMask.NameToLayer("MENU");
if (num < 0)
{
return 31;
}
return num;
}
}
public static void Attach(Canvas c)
{
//IL_00dd: 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_00aa: Invalid comparison between Unknown and I4
if ((Object)(object)c == (Object)null)
{
return;
}
if (((Object)(object)menuCam == (Object)null || !((Behaviour)menuCam).isActiveAndEnabled) && Time.unscaledTime >= menuCamSearchAt)
{
menuCamSearchAt = Time.unscaledTime + 1f;
menuCam = null;
Camera[] allCameras = Camera.allCameras;
foreach (Camera val in allCameras)
{
if (((Object)val).name == "Camera_Pause" && (val.cullingMask & (1 << MenuLayer)) != 0)
{
menuCam = val;
break;
}
}
}
if ((Object)(object)menuCam != (Object)null && ((Behaviour)menuCam).isActiveAndEnabled)
{
if ((int)c.renderMode != 1 || (Object)(object)c.worldCamera != (Object)(object)menuCam)
{
c.renderMode = (RenderMode)1;
c.worldCamera = menuCam;
c.planeDistance = 1f;
}
}
else if ((int)c.renderMode != 0)
{
c.renderMode = (RenderMode)0;
}
}
public static Canvas MakeCanvas(string name, int order)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name)
{
layer = MenuLayer
};
Object.DontDestroyOnLoad((Object)val);
Canvas val2 = val.AddComponent<Canvas>();
val2.renderMode = (RenderMode)0;
val2.sortingOrder = order;
Attach(val2);
CanvasScaler obj = val.AddComponent<CanvasScaler>();
obj.uiScaleMode = (ScaleMode)1;
obj.referenceResolution = new Vector2(1920f, 1080f);
obj.matchWidthOrHeight = 0.5f;
return val2;
}
public static RectTransform Rect(Transform parent, string name)
{
//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_002a: 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)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) })
{
layer = ((Component)parent).gameObject.layer
};
val.transform.SetParent(parent, false);
RectTransform val2 = (RectTransform)val.transform;
Vector2 val3 = default(Vector2);
((Vector2)(ref val3))..ctor(0.5f, 0.5f);
val2.anchorMax = val3;
val2.anchorMin = val3;
val2.pivot = new Vector2(0.5f, 0.5f);
return val2;
}
public static Image Box(Transform parent, string name, Color color, Vector2 pos, Vector2 size, bool rounded = false)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: 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_0055: Unknown result type (might be due to invalid IL or missing references)
RectTransform obj = Rect(parent, name);
obj.anchoredPosition = pos;
obj.sizeDelta = size;
Image val = ((Component)obj).gameObject.AddComponent<Image>();
((Graphic)val).color = color;
((Graphic)val).raycastTarget = false;
if (rounded && (Object)(object)BoxSprite != (Object)null)
{
val.sprite = BoxSprite;
Vector4 border = BoxSprite.border;
if (((Vector4)(ref border)).sqrMagnitude > 0f)
{
val.type = (Type)1;
}
}
return val;
}
public static void Fill(RectTransform rt, float inset)
{
//IL_0001: 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_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
rt.anchorMin = Vector2.zero;
rt.anchorMax = Vector2.one;
rt.offsetMin = new Vector2(inset, inset);
rt.offsetMax = new Vector2(0f - inset, 0f - inset);
}
public static TextMeshProUGUI Text(Transform parent, string name, string text, float size, Color color, TextAlignmentOptions align)
{
//IL_0032: 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)
TextMeshProUGUI val = ((Component)Rect(parent, name)).gameObject.AddComponent<TextMeshProUGUI>();
if ((Object)(object)Font != (Object)null)
{
((TMP_Text)val).font = Font;
}
((TMP_Text)val).fontSize = size;
((Graphic)val).color = color;
((TMP_Text)val).alignment = align;
((TMP_Text)val).enableWordWrapping = false;
((TMP_Text)val).richText = true;
((Graphic)val).raycastTarget = false;
((TMP_Text)val).text = text;
return val;
}
public static Color PlayerColor(Controller c)
{
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: 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)
if ((Object)(object)c != (Object)null)
{
SpriteRenderer componentInChildren = ((Component)c).GetComponentInChildren<SpriteRenderer>();
SetColorWhenDamaged val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent<SetColorWhenDamaged>() : null);
if ((Object)(object)val == (Object)null)
{
val = ((Component)c).GetComponentInChildren<SetColorWhenDamaged>(true);
}
if ((Object)(object)val != (Object)null && val.startColor.a > 0f)
{
Color startColor = val.startColor;
startColor.a = 1f;
return startColor;
}
ControllerHandler instance = ControllerHandler.Instance;
if ((Object)(object)instance != (Object)null && instance.colors != null && c.playerID >= 0 && c.playerID < instance.colors.Length && (Object)(object)instance.colors[c.playerID] != (Object)null)
{
return instance.colors[c.playerID].color;
}
}
return Color.white;
}
public static Color SlotColor(int id)
{
//IL_0052: 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_0050: Unknown result type (might be due to invalid IL or missing references)
ControllerHandler instance = ControllerHandler.Instance;
if ((Object)(object)instance != (Object)null && instance.colors != null && id >= 0 && id < instance.colors.Length && (Object)(object)instance.colors[id] != (Object)null)
{
Color color = instance.colors[id].color;
color.a = 1f;
return color;
}
return Color.white;
}
public static string Hex(Color c)
{
//IL_0005: 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_0043: Unknown result type (might be due to invalid IL or missing references)
return "#" + ((int)(Mathf.Clamp01(c.r) * 255f)).ToString("X2") + ((int)(Mathf.Clamp01(c.g) * 255f)).ToString("X2") + ((int)(Mathf.Clamp01(c.b) * 255f)).ToString("X2");
}
public static string Colored(string text, Color c)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
return "<color=" + Hex(c) + ">" + text + "</color>";
}
public static Color WithAlpha(Color c, float a)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
c.a = a;
return c;
}
}
}
namespace StickySlots
{
[BepInPlugin("stickfight.stickyslots", "Sticky Controller Slots", "1.0.1")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "stickfight.stickyslots";
public const string Name = "Sticky Controller Slots";
public const string Version = "1.0.1";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> Enabled;
private void Awake()
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
Enabled = QolConfig.Enabled(((BaseUnityPlugin)this).Config, "Slots", "A controller that reconnects gets its slot back. Same colour, same wins. Off = the game's normal joining.");
Enabled.SettingChanged += delegate
{
if (!Enabled.Value)
{
Slots.Clear();
}
};
QolConfig.DropOld(((BaseUnityPlugin)this).Config);
new Harmony("stickfight.stickyslots").PatchAll(typeof(Plugin).Assembly);
SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
if ((int)mode == 0)
{
Slots.Clear();
}
};
((BaseUnityPlugin)this).Logger.LogInfo((object)"Sticky Controller Slots 1.0.1 loaded.");
}
}
internal static class Slots
{
private sealed class Away
{
public int Id;
public InputDevice Device;
public string DeviceType;
public string DeviceName;
public int SortOrder;
public Dictionary<FieldInfo, int> Stats;
}
private static readonly List<Away> away = new List<Away>();
private static readonly FieldInfo[] statFields = typeof(CharacterStats).GetFields(BindingFlags.Instance | BindingFlags.Public);
public static void Clear()
{
away.Clear();
}
public static void Left(Controller c)
{
if ((Object)(object)c == (Object)null || c.isAI || c.PlayerActions == null)
{
return;
}
InputDevice device = ((PlayerActionSet)c.PlayerActions).Device;
if (device == null || Compat.IsBotDevice(device))
{
return;
}
Slots.away.RemoveAll((Away a) => a.Id == c.playerID);
Away away = new Away
{
Id = c.playerID,
Device = device,
DeviceType = ((object)device).GetType().Name,
DeviceName = device.Name,
SortOrder = device.SortOrder,
Stats = new Dictionary<FieldInfo, int>()
};
CharacterStats component = ((Component)c).GetComponent<CharacterStats>();
if ((Object)(object)component != (Object)null)
{
FieldInfo[] array = statFields;
foreach (FieldInfo fieldInfo in array)
{
if ((object)fieldInfo.FieldType == typeof(int))
{
away.Stats[fieldInfo] = (int)fieldInfo.GetValue(component);
}
}
}
Slots.away.Add(away);
Plugin.Log.LogInfo((object)("P" + (c.playerID + 1) + "'s controller disconnected; keeping the slot."));
}
private static bool Same(Away a, InputDevice d)
{
if (d == null)
{
return false;
}
if (a.Device == d)
{
return true;
}
if (a.DeviceType == ((object)d).GetType().Name && a.DeviceName == d.Name)
{
return a.SortOrder == d.SortOrder;
}
return false;
}
private static bool Taken(List<Controller> players, int id, Controller except)
{
foreach (Controller player in players)
{
if ((Object)(object)player != (Object)null && (Object)(object)player != (Object)(object)except && player.playerID == id)
{
return true;
}
}
return false;
}
private static int Lowest(List<Controller> players, Controller c, bool skipKept)
{
for (int i = 0; i < 4; i++)
{
if (Taken(players, i, c))
{
continue;
}
bool flag = false;
if (skipKept)
{
foreach (Away item in away)
{
if (item.Id == i)
{
flag = true;
}
}
}
if (!flag)
{
return i;
}
}
return -1;
}
public static void Joined(ControllerHandler ch, Controller c, InputDevice device)
{
if ((Object)(object)c == (Object)null || (Object)(object)ch == (Object)null)
{
return;
}
List<Controller> players = ch.players;
int num = c.playerID;
Away away = null;
foreach (Away item in Slots.away)
{
if (Same(item, device) && !Taken(players, item.Id, c))
{
away = item;
break;
}
}
if (device != null)
{
Slots.away.RemoveAll((Away a) => Same(a, device));
}
if (away != null)
{
num = away.Id;
}
else if (Slots.away.Count > 0 || Taken(players, num, c))
{
int free = Lowest(players, c, skipKept: true);
if (free < 0)
{
free = Lowest(players, c, skipKept: false);
}
if (free >= 0)
{
num = free;
Slots.away.RemoveAll((Away a) => a.Id == free);
}
}
bool flag = num != c.playerID;
if (flag)
{
SetSlot(ch, c, num);
}
if (away != null)
{
CharacterStats component = ((Component)c).GetComponent<CharacterStats>();
if ((Object)(object)component != (Object)null)
{
foreach (KeyValuePair<FieldInfo, int> stat in away.Stats)
{
stat.Key.SetValue(component, stat.Value);
}
}
Plugin.Log.LogInfo((object)("P" + (num + 1) + "'s controller is back."));
}
if (away != null || flag)
{
players.Sort((Controller x, Controller y) => (((Object)(object)x != (Object)null) ? x.playerID : 99).CompareTo(((Object)(object)y != (Object)null) ? y.playerID : 99));
}
WinCounterUI val = Object.FindObjectOfType<WinCounterUI>();
if ((Object)(object)val != (Object)null)
{
val.RefreshWinTexts();
}
}
private static void SetSlot(ControllerHandler ch, Controller c, int id)
{
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
c.playerID = id;
c.SetCollision(true);
Material val = ch.colors[id];
LineRenderer[] componentsInChildren = ((Component)c).GetComponentsInChildren<LineRenderer>();
for (int i = 0; i < componentsInChildren.Length; i++)
{
((Renderer)componentsInChildren[i]).sharedMaterial = val;
}
SpriteRenderer[] componentsInChildren2 = ((Component)c).GetComponentsInChildren<SpriteRenderer>();
foreach (SpriteRenderer val2 in componentsInChildren2)
{
if (((Component)((Component)val2).transform).tag != "DontChangeColor")
{
val2.color = val.color;
}
}
CharacterInformation component = ((Component)c).GetComponent<CharacterInformation>();
if ((Object)(object)component != (Object)null)
{
component.myMaterial = val;
}
}
}
[HarmonyPatch(typeof(ControllerHandler), "RemovePlayer")]
internal static class RemovePlayerPatch
{
private static void Prefix(Controller player)
{
if (!MatchmakingHandler.IsNetworkMatch && Plugin.Enabled.Value)
{
Slots.Left(player);
}
}
}
[HarmonyPatch(typeof(ControllerHandler), "CreatePlayer")]
internal static class CreatePlayerPatch
{
[HarmonyPriority(800)]
private static void Postfix(ControllerHandler __instance, InputDevice inputDevice, bool keyBoard, Controller __result)
{
if (!MatchmakingHandler.IsNetworkMatch && !((Object)(object)__result == (Object)null) && Plugin.Enabled.Value)
{
Slots.Joined(__instance, __result, inputDevice);
}
}
}
}