Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Silksong BingoSync v1.2.2
plugins/BingoAPI.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BingoAPI.Conditions.Attributes; using BingoAPI.Conditions.Factories; using BingoAPI.Conditions.Interfaces; using BingoAPI.Events; using BingoAPI.Events.BuiltIn; using BingoAPI.Goals; using BingoAPI.Helpers; using BingoAPI.Models; using BingoAPI.Models.Settings; using BingoAPI.Networking.Clients; using BingoAPI.Networking.Converters; using BingoAPI.Networking.DTOs; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("WarperSan")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Library that allows to communicate with BingoSync's servers through code")] [assembly: AssemblyFileVersion("0.1.5.0")] [assembly: AssemblyInformationalVersion("0.1.5-alpha+b7cb9dd026341a5c323cf8a1570ec19c245e36bf")] [assembly: AssemblyProduct("BingoAPI")] [assembly: AssemblyTitle("BingoAPI")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/WarperSan/BingoAPI")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 System { [ExcludeFromCodeCoverage] [Embedded] internal readonly struct Index : IEquatable<Index> { private static class ThrowHelper { [DoesNotReturn] public static void ThrowValueArgumentOutOfRange_NeedNonNegNumException() { throw new ArgumentOutOfRangeException("value", "Non-negative number required."); } } private readonly int _value; public static Index Start => new Index(0); public static Index End => new Index(-1); public int Value { get { if (_value < 0) { return ~_value; } return _value; } } public bool IsFromEnd => _value < 0; [MethodImpl(MethodImplOptions.AggressiveInlining)] public Index(int value, bool fromEnd = false) { if (value < 0) { ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException(); } if (fromEnd) { _value = ~value; } else { _value = value; } } private Index(int value) { _value = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Index FromStart(int value) { if (value < 0) { ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException(); } return new Index(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Index FromEnd(int value) { if (value < 0) { ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException(); } return new Index(~value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int GetOffset(int length) { int num = _value; if (IsFromEnd) { num += length + 1; } return num; } public override bool Equals([NotNullWhen(true)] object? value) { if (value is Index) { return _value == ((Index)value)._value; } return false; } public bool Equals(Index other) { return _value == other._value; } public override int GetHashCode() { return _value; } public static implicit operator Index(int value) { return FromStart(value); } public override string ToString() { if (IsFromEnd) { return ToStringFromEnd(); } return ((uint)Value).ToString(); } private string ToStringFromEnd() { return "^" + Value; } } [ExcludeFromCodeCoverage] [Embedded] internal readonly struct Range : IEquatable<Range> { private static class HashHelpers { public static int Combine(int h1, int h2) { uint num = (uint)((h1 << 5) | (h1 >>> 27)); return ((int)num + h1) ^ h2; } } private static class ThrowHelper { [DoesNotReturn] public static void ThrowArgumentOutOfRangeException() { throw new ArgumentOutOfRangeException("length"); } } public Index Start { get; } public Index End { get; } public static Range All => Index.Start..Index.End; public Range(Index start, Index end) { Start = start; End = end; } public override bool Equals([NotNullWhen(true)] object? value) { if (value is Range { Start: var start } range && start.Equals(Start)) { return range.End.Equals(End); } return false; } public bool Equals(Range other) { if (other.Start.Equals(Start)) { return other.End.Equals(End); } return false; } public override int GetHashCode() { return HashHelpers.Combine(Start.GetHashCode(), End.GetHashCode()); } public override string ToString() { return Start.ToString() + ".." + End; } public static Range StartAt(Index start) { return start..Index.End; } public static Range EndAt(Index end) { return Index.Start..end; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public (int Offset, int Length) GetOffsetAndLength(int length) { Index start = Start; int num = ((!start.IsFromEnd) ? start.Value : (length - start.Value)); Index end = End; int num2 = ((!end.IsFromEnd) ? end.Value : (length - end.Value)); if ((uint)num2 > (uint)length || (uint)num > (uint)num2) { ThrowHelper.ThrowArgumentOutOfRangeException(); } return (Offset: num, Length: num2 - num); } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class SetsRequiredMembersAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class MaybeNullWhenAttribute : Attribute { public bool ReturnValue { get; } public MaybeNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class DisallowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class NotNullIfNotNullAttribute : Attribute { public string ParameterName { get; } public NotNullIfNotNullAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class DoesNotReturnAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class UnscopedRefAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class StringSyntaxAttribute : Attribute { public const string CompositeFormat = "CompositeFormat"; public const string DateOnlyFormat = "DateOnlyFormat"; public const string DateTimeFormat = "DateTimeFormat"; public const string EnumFormat = "EnumFormat"; public const string GuidFormat = "GuidFormat"; public const string Json = "Json"; public const string NumericFormat = "NumericFormat"; public const string Regex = "Regex"; public const string TimeOnlyFormat = "TimeOnlyFormat"; public const string TimeSpanFormat = "TimeSpanFormat"; public const string Uri = "Uri"; public const string Xml = "Xml"; public string Syntax { get; } public object?[] Arguments { get; } public StringSyntaxAttribute(string syntax) { Syntax = syntax; Arguments = new object[0]; } public StringSyntaxAttribute(string syntax, params object?[] arguments) { Syntax = syntax; Arguments = arguments; } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ExperimentalAttribute : Attribute { public string DiagnosticId { get; } public string? UrlFormat { get; set; } public ExperimentalAttribute(string diagnosticId) { DiagnosticId = diagnosticId; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ConstantExpectedAttribute : Attribute { public object? Min { get; set; } public object? Max { get; set; } } } namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class RequiresPreviewFeaturesAttribute : Attribute { public string? Message { get; } public string? Url { get; set; } public RequiresPreviewFeaturesAttribute() { } public RequiresPreviewFeaturesAttribute(string? message) { Message = message; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ParamCollectionAttribute : Attribute { } [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] [Embedded] internal static class IsExternalInit { } [EditorBrowsable(EditorBrowsableState.Never)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ExtensionMarkerAttribute : Attribute { public string Name { get; } public ExtensionMarkerAttribute(string name) { Name = name; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class CollectionBuilderAttribute : Attribute { public Type BuilderType { get; } public string MethodName { get; } public CollectionBuilderAttribute(Type builderType, string methodName) { BuilderType = builderType; MethodName = methodName; } } [AttributeUsage(AttributeTargets.Class, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class CompilerLoweringPreserveAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ModuleInitializerAttribute : Attribute { } [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class OverloadResolutionPriorityAttribute : Attribute { public int Priority { get; } public OverloadResolutionPriorityAttribute(int priority) { Priority = priority; } } [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class CompilerFeatureRequiredAttribute : Attribute { public const string RefStructs = "RefStructs"; public const string RequiredMembers = "RequiredMembers"; public string FeatureName { get; } public bool IsOptional { get; set; } public CompilerFeatureRequiredAttribute(string featureName) { FeatureName = featureName; } } [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class SkipLocalsInitAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class RequiresLocationAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class AsyncMethodBuilderAttribute : Attribute { public Type BuilderType { get; } public AsyncMethodBuilderAttribute(Type builderType) { BuilderType = builderType; } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute { public string[] Arguments { get; } public InterpolatedStringHandlerArgumentAttribute(string argument) { Arguments = new string[1] { argument }; } public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) { Arguments = arguments; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class RequiredMemberAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class InterpolatedStringHandlerAttribute : Attribute { } } namespace Microsoft.CodeAnalysis { [Embedded] [AttributeUsage(AttributeTargets.All)] [ExcludeFromCodeCoverage] internal sealed class EmbeddedAttribute : Attribute { } } namespace BingoAPI.Networking { internal sealed class RequestBuilder { private HttpMethod _method = HttpMethod.Get; private string? _endpoint; private HttpContent? _content; private RequestBuilder WithMethod(HttpMethod method) { _method = method; return this; } public RequestBuilder Get() { return WithMethod(HttpMethod.Get); } public RequestBuilder Post() { return WithMethod(HttpMethod.Post); } public RequestBuilder Put() { return WithMethod(HttpMethod.Put); } public RequestBuilder ToEndpoint(string endpoint) { _endpoint = endpoint; return this; } public RequestBuilder WithJson(object json) { string content = JsonConvert.SerializeObject(json); _content = new StringContent(content, Encoding.UTF8, "application/json"); return this; } public RequestBuilder WithForm(object form) { List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); var enumerable = from m in form.GetType().GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(delegate(MemberInfo m) { MemberTypes memberType = m.MemberType; return (memberType == MemberTypes.Field || memberType == MemberTypes.Property) ? true : false; }) select new { Member = m, Attribute = m.GetCustomAttribute<DataMemberAttribute>() } into m where m.Attribute != null select m; foreach (var item in enumerable) { string key = item.Attribute?.Name ?? item.Member.Name; MemberInfo member = item.Member; string text = ((member is FieldInfo fieldInfo) ? fieldInfo.GetValue(form)?.ToString() : ((!(member is PropertyInfo propertyInfo)) ? null : propertyInfo.GetValue(form)?.ToString())); string text2 = text; if (text2 == null) { text2 = ""; } list.Add(new KeyValuePair<string, string>(key, text2)); } _content = new FormUrlEncodedContent(list); return this; } public HttpRequestMessage Build() { HttpRequestMessage httpRequestMessage = new HttpRequestMessage { Method = _method, Content = _content }; if (_endpoint != null) { httpRequestMessage.RequestUri = new Uri(_endpoint, UriKind.Relative); } return httpRequestMessage; } } public sealed class Session : IDisposable { private readonly BingoApiClient _api; private readonly BingoSocketClient _socket; private readonly EventDispatcher _dispatcher; private string? _roomCode; public Team Team { get; private set; } [MemberNotNullWhen(true, "_roomCode")] public bool IsInRoom { [MemberNotNullWhen(true, "_roomCode")] get { return _roomCode != null; } } public Session(EventDispatcher dispatcher, HttpClient client, Uri socketAddress) { _dispatcher = dispatcher; _api = new BingoApiClient(client); _socket = new BingoSocketClient(socketAddress); } public async Task<bool> CreateRoom(CreateRoomSettings settings, CancellationToken ct = default(CancellationToken)) { throw new NotImplementedException(); } public async Task<bool> JoinRoom(JoinRoomSettings settings, CancellationToken ct = default(CancellationToken)) { if (IsInRoom) { Log.Error("Tried to join a room while being connected."); return false; } Log.Info("Joining room '" + settings.Code + "'..."); try { string socketKey = await _api.JoinRoom(settings, ct); await _socket.Connect(socketKey, OnMessageReceived, ct); GetSocketInformationResponse getSocketInformationResponse = await _api.GetSocketInformation(socketKey, ct); _roomCode = getSocketInformationResponse.Code; Team = Team.Red; Player player = new Player { Name = settings.Nickname, Team = Team, UUID = getSocketInformationResponse.PlayerUUID }; _dispatcher.DispatchConnect(player); Log.Info("Room '" + settings.Code + "' was joined."); return true; } catch (Exception arg) { Log.Error($"Failed to join the room '{settings.Code}': {arg}"); return false; } } public async Task<bool> LeaveRoom(CancellationToken ct = default(CancellationToken)) { if (!IsInRoom) { Log.Error("Tried to leave the room before being connected."); return false; } string room = _roomCode; Log.Info("Leaving the room '" + room + "'..."); try { await _socket.Disconnect(ct); _roomCode = null; _dispatcher.DispatchDisconnect(); Log.Info("Left the room '" + room + "'."); return true; } catch (Exception arg) { Log.Error($"Failed to leave the room '{room}: {arg}"); return false; } } public async Task<bool> SendMessage(string message, CancellationToken ct = default(CancellationToken)) { if (!IsInRoom) { Log.Error("Tried to send a message before being connected."); return false; } Log.Info("Sending the following chat message: '" + message + "'..."); try { await _api.SendMessage(_roomCode, message, ct); Log.Info("Sent the following chat message: '" + message + "'."); return true; } catch (Exception arg) { Log.Error($"Failed to sent the chat message: {arg}"); return false; } } public async Task<bool> ChangeTeam(Team team, CancellationToken ct = default(CancellationToken)) { if (!IsInRoom) { Log.Error("Tried to change team before being connected."); return false; } if (team == Team) { Log.Error("Tried to change to the same team."); return false; } Log.Info($"Changing team to '{team}'..."); try { await _api.ChangeTeam(_roomCode, team, ct); Team = team; Log.Info($"Changed team to '{team}'."); return true; } catch (Exception arg) { Log.Error($"Failed to change the team: {arg}"); return false; } } public async Task<Card?> GetCard(GoalPool pool, CancellationToken ct = default(CancellationToken)) { if (!IsInRoom) { Log.Error("Tried to get the squares before being connected."); return null; } Log.Info("Getting the squares of the room '" + _roomCode + "'..."); try { ICollection<Square> collection = await _api.GetSquares(_roomCode, ct); Log.Info($"Got {collection.Count} squares for room '{_roomCode}'."); return new Card(collection, pool); } catch (Exception arg) { Log.Error($"Failed to get squares for room '{_roomCode}': {arg}"); return null; } } public async Task<bool> MarkSquare(int index, CancellationToken ct = default(CancellationToken)) { if (!IsInRoom) { Log.Error("Tried to mark a square before being connected."); return false; } if (Team == Team.None) { Log.Error("Tried to clear a square without being in a team."); return false; } Log.Info($"Marking the square #{index} for the team '{Team}'..."); try { await _api.MarkSquare(_roomCode, Team, index, ct); Log.Info($"Marked the square #{index} for the team '{Team}'."); return true; } catch (Exception arg) { Log.Error($"Failed to mark the square #{index} for the team '{Team}': {arg}"); return false; } } public async Task<bool> ClearSquare(int index, CancellationToken ct = default(CancellationToken)) { if (!IsInRoom) { Log.Error("Tried to clear a square before being connected."); return false; } if (Team == Team.None) { Log.Error("Tried to clear a square without being in a team."); return false; } Log.Info($"Clearing the square #{index} for the team '{Team}'..."); try { await _api.ClearSquare(_roomCode, Team, index, ct); Log.Info($"Cleared the square #{index} for the team '{Team}'."); return true; } catch (Exception arg) { Log.Error($"Failed to clear the square #{index} for the team '{Team}': {arg}"); return false; } } public async Task<bool> RevealCard(CancellationToken ct = default(CancellationToken)) { if (!IsInRoom) { Log.Error("Tried to reveal the card before being connected."); return false; } Log.Info("Revealing the card for the room '" + _roomCode + "'..."); try { await _api.RevealCard(_roomCode, ct); Log.Info("Revealed the card for the room '" + _roomCode + "'."); return true; } catch (Exception arg) { Log.Error($"Failed to reveal the card for the room '{_roomCode}': {arg}"); return false; } } private void OnMessageReceived(string message) { IEvent obj = JsonConvert.DeserializeObject<IEvent>(message); if (obj == null) { Log.Warning($"Failed to deserialize the message into a '{typeof(IEvent)}': {message}"); } else { _dispatcher.Dispatch(obj); } } public void Dispose() { _socket.Dispose(); } } } namespace BingoAPI.Networking.DTOs { internal record ChangeTeamRequest { [JsonProperty("room")] public required string Code { get; init; } [JsonProperty("color")] public required Team Team { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected ChangeTeamRequest(ChangeTeamRequest original) { Code = original.Code; Team = original.Team; } public ChangeTeamRequest() { } } internal record ClearSquareRequest { [JsonProperty("room")] public required string Code { get; init; } [JsonProperty("color")] public required Team Team { get; init; } [JsonProperty("slot")] public required string Index { get; init; } [JsonProperty("remove_color")] public bool RemoveColor => true; [CompilerGenerated] [SetsRequiredMembers] protected ClearSquareRequest(ClearSquareRequest original) { Code = original.Code; Team = original.Team; Index = original.Index; } public ClearSquareRequest() { } } internal record CreateRoomRequest { [DataMember(Name = "game_type")] public int GameType => 18; [DataMember(Name = "lockout_mode")] private int LockoutMode { get { if (!IsLockout) { return 1; } return 2; } } [DataMember(Name = "is_spectator")] public bool IsSpectator => false; [DataMember(Name = "variant_type")] private int VariantType { get { if (!IsRandomized) { return 18; } return 172; } } [DataMember(Name = "hide_card")] public bool HideCard => false; private const int RANDOMIZED_VARIANT_TYPE = 172; private const int FIXED_BOARD_VARIANT_TYPE = 18; private const int LOCKOUT_MODE = 2; private const int NON_LOCKOUT_MODE = 1; [DataMember(Name = "room_name")] public required string RoomName; [DataMember(Name = "passphrase")] public required string Password; [DataMember(Name = "nickname")] public required string Nickname; public required bool IsLockout; [DataMember(Name = "seed")] public required string Seed; public required bool IsRandomized; [DataMember(Name = "custom_json")] public required string Board; [DataMember(Name = "csrfmiddlewaretoken")] public required string CreationToken; [CompilerGenerated] protected virtual bool PrintMembers(StringBuilder builder) { RuntimeHelpers.EnsureSufficientExecutionStack(); builder.Append("RoomName = "); builder.Append((object?)RoomName); builder.Append(", Password = "); builder.Append((object?)Password); builder.Append(", Nickname = "); builder.Append((object?)Nickname); builder.Append(", GameType = "); builder.Append(GameType.ToString()); builder.Append(", IsLockout = "); builder.Append(IsLockout.ToString()); builder.Append(", Seed = "); builder.Append((object?)Seed); builder.Append(", IsSpectator = "); builder.Append(IsSpectator.ToString()); builder.Append(", IsRandomized = "); builder.Append(IsRandomized.ToString()); builder.Append(", Board = "); builder.Append((object?)Board); builder.Append(", HideCard = "); builder.Append(HideCard.ToString()); builder.Append(", CreationToken = "); builder.Append((object?)CreationToken); return true; } [CompilerGenerated] [SetsRequiredMembers] protected CreateRoomRequest(CreateRoomRequest original) { RoomName = original.RoomName; Password = original.Password; Nickname = original.Nickname; IsLockout = original.IsLockout; Seed = original.Seed; IsRandomized = original.IsRandomized; Board = original.Board; CreationToken = original.CreationToken; } public CreateRoomRequest() { } } internal record GetSocketInformationResponse { [JsonProperty("room")] [JsonRequired] public required string Code { get; init; } [JsonProperty("player")] [JsonRequired] public required string PlayerUUID { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected GetSocketInformationResponse(GetSocketInformationResponse original) { Code = original.Code; PlayerUUID = original.PlayerUUID; } public GetSocketInformationResponse() { } } internal record JoinRoomRequest { [JsonProperty("room")] public required string Code { get; init; } [JsonProperty("password")] public required string Password { get; init; } [JsonProperty("nickname")] public required string Username { get; init; } [JsonProperty("is_spectator")] public bool IsSpectator => false; [CompilerGenerated] [SetsRequiredMembers] protected JoinRoomRequest(JoinRoomRequest original) { Code = original.Code; Password = original.Password; Username = original.Username; } public JoinRoomRequest() { } } internal record JoinRoomResponse { [JsonProperty("socket_key")] [JsonRequired] public required string SocketKey { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected JoinRoomResponse(JoinRoomResponse original) { SocketKey = original.SocketKey; } public JoinRoomResponse() { } } internal record MarkSquareRequest { [JsonProperty("room")] public required string Code { get; init; } [JsonProperty("color")] public required Team Team { get; init; } [JsonProperty("slot")] public required string Index { get; init; } [JsonProperty("remove_color")] public bool RemoveColor => false; [CompilerGenerated] [SetsRequiredMembers] protected MarkSquareRequest(MarkSquareRequest original) { Code = original.Code; Team = original.Team; Index = original.Index; } public MarkSquareRequest() { } } internal record RevealCardRequest { [JsonProperty("room")] public required string Code { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected RevealCardRequest(RevealCardRequest original) { Code = original.Code; } public RevealCardRequest() { } } internal record SendMessageRequest { [JsonProperty("room")] public required string Code { get; init; } [JsonProperty("text")] public required string Message { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected SendMessageRequest(SendMessageRequest original) { Code = original.Code; Message = original.Message; } public SendMessageRequest() { } } [JsonConverter(typeof(SlotIndexConverter))] internal record SlotIndex { public readonly int Index; internal SlotIndex(int index) { Index = index; } } internal record Tokens { public required string PublicToken { get; init; } public required string CreationToken { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected Tokens(Tokens original) { PublicToken = original.PublicToken; CreationToken = original.CreationToken; } public Tokens() { } } } namespace BingoAPI.Networking.Converters { internal class EventConverter : JsonConverter { public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { throw new InvalidOperationException(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { JObject val = JObject.Load(reader); string text = ((JToken)val).Value<string>((object)"type"); return text switch { "chat" => ((JToken)val).ToObject<ChatEvent>(), "goal" => ((JToken)val).ToObject<GoalEvent>(), "color" => ((JToken)val).ToObject<ColorEvent>(), "revealed" => ((JToken)val).ToObject<CardRevealedEvent>(), "new-card" => ((JToken)val).ToObject<CardGeneratedEvent>(), "connection" => ((JToken)val).ToObject<ConnectionEvent>(), _ => throw new InvalidOperationException($"No event was found of type '{text}': {val}"), }; } public override bool CanConvert(Type objectType) { return objectType == typeof(IEvent); } } internal class SlotIndexConverter : JsonConverter<SlotIndex> { private const string PREFIX = "slot"; public override void WriteJson(JsonWriter writer, SlotIndex? value, JsonSerializer serializer) { int num = 0; if (value != null) { num = value.Index + 1; } writer.WriteValue(string.Format("{0}{1}", "slot", num)); } public override SlotIndex ReadJson(JsonReader reader, Type objectType, SlotIndex? existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0024: 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_006d: 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) if (!(reader.Value is string text)) { throw new JsonException(string.Format("Expected a '{0}', but got '{1}'.", "String", reader.ValueType)); } if (!text.StartsWith("slot")) { throw new JsonException("Expected value starting with 'slot'."); } string text2 = text.Substring("slot".Length); if (!int.TryParse(text2, out var result)) { throw new JsonException("Could not parse index from '" + text2 + "'."); } if (result <= 0) { throw new JsonException("Index must be greater than 0."); } return new SlotIndex(result - 1); } } internal class StringEqualConverter : JsonConverter<bool> { private readonly string _value; public override bool CanWrite => false; public StringEqualConverter(string value) { _value = value; } public override void WriteJson(JsonWriter writer, bool value, JsonSerializer serializer) { throw new InvalidOperationException(string.Format("Class '{0}' cannot write a '{1}' as '{2}'.", "StringEqualConverter", typeof(bool), typeof(string))); } public override bool ReadJson(JsonReader reader, Type objectType, bool existingValue, bool hasExistingValue, JsonSerializer serializer) { if (!(reader.Value is string a)) { return false; } return string.Equals(a, _value); } } internal class TeamConverter : JsonConverter<Team> { private static readonly Lazy<Dictionary<string, Team>> TeamMappings = new Lazy<Dictionary<string, Team>>(delegate { Dictionary<string, Team> dictionary = new Dictionary<string, Team>(); string[] names = Enum.GetNames(typeof(Team)); string[] array = names; foreach (string text in array) { FieldInfo field = typeof(Team).GetField(text); Team value = (Team)field.GetValue(null); string text2 = (from EnumMemberAttribute a in field.GetCustomAttributes(typeof(EnumMemberAttribute), inherit: false) select a.Value).SingleOrDefault(); dictionary.Add(text2 ?? text, value); } return dictionary; }); public override void WriteJson(JsonWriter writer, Team value, JsonSerializer serializer) { List<string> list = new List<string>(); foreach (KeyValuePair<string, Team> item in TeamMappings.Value) { if ((item.Value != Team.None || value == Team.None) && value.HasFlag(item.Value)) { list.Add(item.Key); } } writer.WriteValue(string.Join(" ", list)); } public override Team ReadJson(JsonReader reader, Type objectType, Team existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!(reader.Value is string text)) { throw new JsonException($"Expected a '{typeof(string)}', but got '{reader.ValueType}'."); } Team team = Team.None; string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text2 in array) { if (!TeamMappings.Value.TryGetValue(text2, out var value)) { throw new InvalidOperationException("Unknown team '" + text2 + "'"); } team |= value; } return team; } } } namespace BingoAPI.Networking.Clients { internal sealed class BingoApiClient { public const Team DEFAULT_TEAM = Team.Red; private readonly HttpClient _client; public BingoApiClient(HttpClient client) { _client = client; } private Task<HttpResponseMessage> Send(HttpRequestMessage request, CancellationToken ct) { return _client.SendAsync(request, ct); } private async Task SendAsync(HttpRequestMessage request, CancellationToken ct) { using HttpResponseMessage httpResponseMessage = await Send(request, ct); httpResponseMessage.EnsureSuccessStatusCode(); } private async Task<T> SendAndParse<T>(HttpRequestMessage request, CancellationToken ct) { using HttpResponseMessage response = await _client.SendAsync(request, ct); response.EnsureSuccessStatusCode(); T val = JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync()); if (val == null) { throw new InvalidOperationException("Failed to deserialize response to " + typeof(T).Name); } return val; } private async Task<Tokens> GetTokens(CancellationToken ct) { using HttpRequestMessage request = new RequestBuilder().Get().ToEndpoint("").Build(); using HttpResponseMessage response = await Send(request, ct); response.EnsureSuccessStatusCode(); CookieContainer cookieContainer = new CookieContainer(); IEnumerable<string> values = response.Headers.GetValues("Set-Cookie"); foreach (string item in values) { cookieContainer.SetCookies(_client.BaseAddress, item); } CookieCollection cookies = cookieContainer.GetCookies(_client.BaseAddress); Cookie publicTokenCookie = cookies["csrftoken"]; if (publicTokenCookie == null) { throw new KeyNotFoundException("No cookie was set for 'csrftoken'."); } Match match = Regex.Match(await response.Content.ReadAsStringAsync(), "<input[^>]*name=\"csrfmiddlewaretoken\"[^>]*value=\"(.*?)\"[^>]*>"); if (!match.Success) { throw new KeyNotFoundException("Could not find any input with 'csrfmiddlewaretoken'."); } return new Tokens { PublicToken = publicTokenCookie.Value, CreationToken = match.Groups[1].Value }; } public async Task<string> CreateRoom(CreateRoomSettings settings, CancellationToken ct) { throw new NotImplementedException(); } public async Task<string> JoinRoom(JoinRoomSettings settings, CancellationToken ct) { JoinRoomRequest json = new JoinRoomRequest { Code = settings.Code, Password = settings.Password, Username = settings.Nickname }; using HttpRequestMessage request = new RequestBuilder().Post().ToEndpoint("/api/join-room").WithJson(json) .Build(); return (await SendAndParse<JoinRoomResponse>(request, ct)).SocketKey; } public async Task MarkSquare(string room, Team team, int index, CancellationToken ct) { MarkSquareRequest json = new MarkSquareRequest { Code = room, Team = team, Index = (index + 1).ToString() }; using HttpRequestMessage request = new RequestBuilder().Put().ToEndpoint("/api/select").WithJson(json) .Build(); await SendAsync(request, ct); } public async Task ClearSquare(string room, Team team, int index, CancellationToken ct) { ClearSquareRequest json = new ClearSquareRequest { Code = room, Team = team, Index = (index + 1).ToString() }; using HttpRequestMessage request = new RequestBuilder().Put().ToEndpoint("/api/select").WithJson(json) .Build(); await SendAsync(request, ct); } public async Task SendMessage(string room, string message, CancellationToken ct) { SendMessageRequest json = new SendMessageRequest { Code = room, Message = message }; using HttpRequestMessage request = new RequestBuilder().Put().ToEndpoint("/api/chat").WithJson(json) .Build(); await SendAsync(request, ct); } public async Task ChangeTeam(string room, Team team, CancellationToken ct) { ChangeTeamRequest json = new ChangeTeamRequest { Code = room, Team = team }; using HttpRequestMessage request = new RequestBuilder().Put().ToEndpoint("/api/color").WithJson(json) .Build(); await SendAsync(request, ct); } public async Task<ICollection<Square>> GetSquares(string room, CancellationToken ct) { using HttpRequestMessage request = new RequestBuilder().Get().ToEndpoint("/room/" + room + "/board").Build(); return await SendAndParse<Square[]>(request, ct); } public async Task RevealCard(string room, CancellationToken ct) { RevealCardRequest json = new RevealCardRequest { Code = room }; using HttpRequestMessage request = new RequestBuilder().Put().ToEndpoint("/api/revealed").WithJson(json) .Build(); await SendAsync(request, ct); } public async Task<GetSocketInformationResponse> GetSocketInformation(string socketKey, CancellationToken ct) { using HttpRequestMessage request = new RequestBuilder().Get().ToEndpoint("/api/socket/" + socketKey).Build(); return await SendAndParse<GetSocketInformationResponse>(request, ct); } } internal sealed class BingoSocketClient : IDisposable { private WebSocket? _socket; private CancellationTokenSource? _cts; private Task? _socketReceiveTask; private readonly Uri _broadcastUri; public BingoSocketClient(Uri socketAddress) { UriBuilder uriBuilder = new UriBuilder(socketAddress) { Path = "broadcast" }; _broadcastUri = uriBuilder.Uri; } public async Task Connect(string socketKey, Action<string> onMessageReceived, CancellationToken ct) { if (_socket != null) { throw new InvalidOperationException("Socket is already connected."); } ClientWebSocket socket = new ClientWebSocket(); try { await socket.ConnectAsync(_broadcastUri, ct); string s = JsonConvert.SerializeObject((object)new { socket_key = socketKey }); await socket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(s)), WebSocketMessageType.Text, endOfMessage: true, ct); _socket = socket; _cts = new CancellationTokenSource(); _socketReceiveTask = ReceiveLoop(_socket, onMessageReceived, _cts.Token); } catch { socket.Dispose(); throw; } } public async Task Disconnect(CancellationToken ct) { if (_socket == null) { return; } _cts?.Cancel(); if (_socket.State == WebSocketState.Open) { try { await _socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Client disconnecting", ct); } catch (Exception ex) { Log.Error("Error closing WebSocket: " + ex.Message); } } if (_socketReceiveTask != null) { try { await _socketReceiveTask; } catch (OperationCanceledException) { } catch (Exception ex3) { Log.Error("Receive loop failed during disconnect: " + ex3.Message); } } CleanUp(); } private static async Task ReceiveLoop(WebSocket socket, Action<string> onReceive, CancellationToken ct) { byte[] buffer = new byte[1024]; using MemoryStream ms = new MemoryStream(); while (!ct.IsCancellationRequested && socket.State == WebSocketState.Open) { WebSocketReceiveResult webSocketReceiveResult; do { webSocketReceiveResult = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), ct); ms.Write(buffer, 0, webSocketReceiveResult.Count); } while (!webSocketReceiveResult.EndOfMessage); if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close) { Log.Debug("Close message was received."); break; } if (webSocketReceiveResult.MessageType == WebSocketMessageType.Text) { string text = Encoding.UTF8.GetString(ms.ToArray()); Log.Debug("Message received:\n" + text); try { onReceive(text); } catch (Exception arg) { Log.Error($"Error handling socket message: {arg}"); } } ms.Seek(0L, SeekOrigin.Begin); ms.SetLength(0L); } } private void CleanUp() { _socket?.Dispose(); _cts?.Dispose(); _socket = null; _cts = null; _socketReceiveTask = null; } public void Dispose() { CleanUp(); } } } namespace BingoAPI.Models { public sealed class Card { private struct CardSquare { public readonly Goal Goal; public Team Teams { get; set; } public CardSquare(Square square, Goal goal) { Goal = goal; Teams = square.Teams; } } private readonly CardSquare[] _squares; public int Size { get; init; } internal Card(ICollection<Square> squares, GoalPool pool) { if (squares.Count == 0) { throw new ArgumentException("Tried to create a card without providing any square."); } int num = (int)Math.Sqrt(squares.Count); if (num * num != squares.Count) { throw new ArgumentException($"Card must be a perfect square, but received '{num}'."); } Size = num; _squares = new CardSquare[squares.Count]; foreach (Square square in squares) { int index = square.Index; if (index < 0 || index >= _squares.Length) { throw new ArgumentOutOfRangeException("square"); } if (!pool.TryGet(square, out Goal goal)) { throw new KeyNotFoundException("Failed to find a goal under the name '" + square.Text + "'."); } _squares[index] = new CardSquare(square, goal); } } public Goal GetGoalAt(int index) { return _squares[index].Goal; } public Goal[] GetAllGoals() { HashSet<Goal> hashSet = new HashSet<Goal>(); CardSquare[] squares = _squares; for (int i = 0; i < squares.Length; i++) { CardSquare cardSquare = squares[i]; hashSet.Add(cardSquare.Goal); } return hashSet.ToArray(); } public int[] FindByGoal(Goal goal) { List<int> list = new List<int>(); for (int i = 0; i < _squares.Length; i++) { if (!(GetGoalAt(i) != goal)) { list.Add(i); } } return list.ToArray(); } public Team GetTeamsAt(int index) { return _squares[index].Teams; } public bool IsMarkedBy(int index, Team team) { return GetTeamsAt(index).HasFlag(team); } public void Mark(int index, Team team) { _squares[index].Teams |= team; } public void Unmark(int index, Team team) { _squares[index].Teams &= (Team)(ushort)(~(int)team); } } public record Player { [JsonProperty("uuid")] [JsonRequired] public required string UUID { get; init; } [JsonProperty("name")] [JsonRequired] public required string Name { get; init; } [JsonProperty("color")] [JsonRequired] public required Team Team { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected Player(Player original) { UUID = original.UUID; Name = original.Name; Team = original.Team; } public Player() { } } public record Square { [JsonProperty("name")] [JsonRequired] public required string Text { get; init; } public int Index => _slot?.Index ?? 0; [JsonProperty("colors")] [JsonRequired] public required Team Teams { get; init; } [JsonProperty("slot")] [JsonRequired] private SlotIndex? _slot; [CompilerGenerated] protected virtual bool PrintMembers(StringBuilder builder) { RuntimeHelpers.EnsureSufficientExecutionStack(); builder.Append("Text = "); builder.Append((object?)Text); builder.Append(", Index = "); builder.Append(Index.ToString()); builder.Append(", Teams = "); builder.Append(Teams.ToString()); return true; } [CompilerGenerated] public override int GetHashCode() { return ((EqualityComparer<Type>.Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Text)) * -1521134295 + EqualityComparer<SlotIndex>.Default.GetHashCode(_slot)) * -1521134295 + EqualityComparer<Team>.Default.GetHashCode(Teams); } [CompilerGenerated] public virtual bool Equals(Square? other) { if ((object)this != other) { if ((object)other != null && EqualityContract == other.EqualityContract && EqualityComparer<string>.Default.Equals(Text, other.Text) && EqualityComparer<SlotIndex>.Default.Equals(_slot, other._slot)) { return EqualityComparer<Team>.Default.Equals(Teams, other.Teams); } return false; } return true; } [CompilerGenerated] [SetsRequiredMembers] protected Square(Square original) { Text = original.Text; _slot = original._slot; Teams = original.Teams; } public Square() { } } [Flags] [JsonConverter(typeof(TeamConverter))] public enum Team : ushort { [EnumMember(Value = "blank")] None = 0, [EnumMember(Value = "pink")] Pink = 1, [EnumMember(Value = "red")] Red = 2, [EnumMember(Value = "orange")] Orange = 4, [EnumMember(Value = "brown")] Brown = 8, [EnumMember(Value = "yellow")] Yellow = 0x10, [EnumMember(Value = "green")] Green = 0x20, [EnumMember(Value = "teal")] Teal = 0x40, [EnumMember(Value = "blue")] Blue = 0x80, [EnumMember(Value = "navy")] Navy = 0x100, [EnumMember(Value = "purple")] Purple = 0x200 } } namespace BingoAPI.Models.Settings { public record CreateRoomSettings { public string Name { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; public string Nickname { get; set; } = string.Empty; public bool IsRandomized { get; set; } public bool IsLockout { get; set; } public string Seed { get; set; } = string.Empty; } public record JoinRoomSettings { public string Code { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; public string Nickname { get; set; } = string.Empty; } } namespace BingoAPI.Helpers { public static class Log { public enum LogLevel { Debug, Info, Warning, Error } public static Action<LogLevel, string>? Logger { private get; set; } private static void LogMessage(LogLevel level, string? message) { Logger?.Invoke(level, message ?? string.Empty); } internal static void Debug(string? message) { LogMessage(LogLevel.Debug, message); } internal static void Info(string? message) { LogMessage(LogLevel.Info, message); } internal static void Warning(string? message) { LogMessage(LogLevel.Warning, message); } internal static void Error(string? message) { LogMessage(LogLevel.Error, message); } } public static class Network { public static bool TryGetRoomCode(string url, [NotNullWhen(true)] out string? code) { Match match = Regex.Match(url, "(?<=/room/)[a-zA-Z\\d-_]+"); if (!match.Success) { code = null; return false; } code = match.Value; return true; } } } namespace BingoAPI.Goals { public sealed record Goal { [JsonProperty("name")] [JsonRequired] public required string Name { get; init; } [JsonProperty("condition")] [JsonRequired] public required ICondition Condition { get; init; } [CompilerGenerated] [SetsRequiredMembers] private Goal(Goal original) { Name = original.Name; Condition = original.Condition; } public Goal() { } } public sealed class GoalPool : IEnumerable<Goal>, IEnumerable { private readonly Dictionary<string, Goal> _goals = new Dictionary<string, Goal>(StringComparer.OrdinalIgnoreCase); public int Count => _goals.Count; public void Add(Goal goal) { if (!TryAdd(goal)) { throw new ArgumentException("The goal has already been added.", "goal"); } } public bool TryAdd(Goal goal) { if (_goals.ContainsKey(goal.Name)) { return false; } _goals.Add(goal.Name, goal); return true; } public bool TryGet(Square square, [NotNullWhen(true)] out Goal? goal) { return _goals.TryGetValue(square.Text, out goal); } public IEnumerator<Goal> GetEnumerator() { return _goals.Values.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public sealed record GoalSet { [JsonProperty("name")] public string Name { get; init; } = string.Empty; [JsonProperty("description")] public string Description { get; init; } = string.Empty; [JsonProperty("goals")] [JsonRequired] public required Goal[] Goals { get; init; } [CompilerGenerated] [SetsRequiredMembers] private GoalSet(GoalSet original) { Name = original.Name; Description = original.Description; Goals = original.Goals; } public GoalSet() { } } public sealed class GoalTracker { public delegate void GoalChangedCallback(Goal goal); private readonly HashSet<Goal> _trackedGoals = new HashSet<Goal>(); private readonly HashSet<Goal> _metGoals = new HashSet<Goal>(); public event GoalChangedCallback? OnGoalMarked; public event GoalChangedCallback? OnGoalCleared; public bool TryAdd(Goal goal) { return _trackedGoals.Add(goal); } public void Clear() { _trackedGoals.Clear(); _metGoals.Clear(); } public void Evaluate() { foreach (Goal trackedGoal in _trackedGoals) { bool wasInitiallyMet = _metGoals.Contains(trackedGoal); bool isCurrentlyMet; try { isCurrentlyMet = trackedGoal.Condition.IsMet(); } catch (Exception arg) { Log.Error($"Error while evaluating '{trackedGoal.Name}': {arg}"); isCurrentlyMet = false; } DispatchChange(wasInitiallyMet, isCurrentlyMet, trackedGoal); } } private void DispatchChange(bool wasInitiallyMet, bool isCurrentlyMet, Goal goal) { if (wasInitiallyMet != isCurrentlyMet) { if (isCurrentlyMet) { _metGoals.Add(goal); this.OnGoalMarked?.Invoke(goal); } else { _metGoals.Remove(goal); this.OnGoalCleared?.Invoke(goal); } } } } } namespace BingoAPI.Events { public sealed class EventDispatcher { public delegate void ConnectionCallback(Player player); public delegate void DisconnectionCallback(Player player); public delegate void MarkCallback(Player player, Square square, Team team); public delegate void ClearCallback(Player player, Square square, Team team); public delegate void ChatCallback(Player player, string message, ulong timestamp); public delegate void TeamCallback(Player player, Team newTeam); public delegate void RevealCallback(Player player); public delegate void GenerateCallback(Player player, bool isHidden); private Player? _localPlayer; public event ConnectionCallback? OnSelfConnected; public event DisconnectionCallback? OnSelfDisconnected; public event MarkCallback? OnSelfSquareMarked; public event ClearCallback? OnSelfSquareCleared; public event ChatCallback? OnSelfMessageSent; public event TeamCallback? OnSelfTeamChanged; public event RevealCallback? OnSelfCardRevealed; public event GenerateCallback? OnSelfCardGenerated; public event ConnectionCallback? OnOtherConnected; public event DisconnectionCallback? OnOtherDisconnected; public event MarkCallback? OnOtherSquareMarked; public event ClearCallback? OnOtherSquareCleared; public event ChatCallback? OnOtherMessageSent; public event TeamCallback? OnOtherTeamChanged; public event RevealCallback? OnOtherCardRevealed; public event GenerateCallback? OnOtherCardGenerated; private bool IsLocal(Player player) { return player.UUID == _localPlayer?.UUID; } internal void DispatchConnect(Player player) { _localPlayer = player; this.OnSelfConnected?.Invoke(player); } internal void DispatchDisconnect() { if (!(_localPlayer == null)) { this.OnSelfDisconnected?.Invoke(_localPlayer); _localPlayer = null; } } internal void Dispatch(IEvent evt) { if (!(evt is ConnectionEvent connectionEvent)) { if (!(evt is ChatEvent evt2)) { if (!(evt is ColorEvent evt3)) { if (!(evt is GoalEvent goalEvent)) { if (!(evt is CardRevealedEvent evt4)) { if (evt is CardGeneratedEvent evt5) { DispatchCardGenerated(evt5); } } else { DispatchCardRevealed(evt4); } } else if (goalEvent.HasBeenCleared) { DispatchGoalCleared(goalEvent); } else { DispatchGoalMarked(goalEvent); } } else { DispatchColorEvent(evt3); } } else { DispatchChatEvent(evt2); } } else if (connectionEvent.IsConnected) { DispatchConnectedEvent(connectionEvent); } else { DispatchDisconnectedEvent(connectionEvent); } } private void DispatchConnectedEvent(ConnectionEvent evt) { if (!IsLocal(evt.Player)) { this.OnOtherConnected?.Invoke(evt.Player); } } private void DispatchDisconnectedEvent(ConnectionEvent evt) { if (!IsLocal(evt.Player)) { this.OnOtherDisconnected?.Invoke(evt.Player); } } private void DispatchChatEvent(ChatEvent evt) { if (IsLocal(evt.Player)) { this.OnSelfMessageSent?.Invoke(evt.Player, evt.Text, evt.Timestamp); } else { this.OnOtherMessageSent?.Invoke(evt.Player, evt.Text, evt.Timestamp); } } private void DispatchColorEvent(ColorEvent evt) { if (IsLocal(evt.Player)) { this.OnSelfTeamChanged?.Invoke(evt.Player, evt.NewColor); } else { this.OnOtherTeamChanged?.Invoke(evt.Player, evt.NewColor); } } private void DispatchGoalMarked(GoalEvent evt) { if (IsLocal(evt.Player)) { this.OnSelfSquareMarked?.Invoke(evt.Player, evt.Square, evt.Team); } else { this.OnOtherSquareMarked?.Invoke(evt.Player, evt.Square, evt.Team); } } private void DispatchGoalCleared(GoalEvent evt) { if (IsLocal(evt.Player)) { this.OnSelfSquareCleared?.Invoke(evt.Player, evt.Square, evt.Team); } else { this.OnOtherSquareCleared?.Invoke(evt.Player, evt.Square, evt.Team); } } private void DispatchCardRevealed(CardRevealedEvent evt) { if (IsLocal(evt.Player)) { this.OnSelfCardRevealed?.Invoke(evt.Player); } else { this.OnOtherCardRevealed?.Invoke(evt.Player); } } private void DispatchCardGenerated(CardGeneratedEvent evt) { if (IsLocal(evt.Player)) { this.OnSelfCardGenerated?.Invoke(evt.Player, evt.IsCardHidden); } else { this.OnOtherCardGenerated?.Invoke(evt.Player, evt.IsCardHidden); } } } internal interface IEvent { } } namespace BingoAPI.Events.BuiltIn { internal record CardGeneratedEvent : IEvent { [JsonProperty("player")] [JsonRequired] public required Player Player { get; init; } [JsonProperty("hide_card")] [JsonRequired] public required bool IsCardHidden { get; init; } [JsonProperty("timestamp")] [JsonRequired] public required ulong Timestamp { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected CardGeneratedEvent(CardGeneratedEvent original) { Player = original.Player; IsCardHidden = original.IsCardHidden; Timestamp = original.Timestamp; } public CardGeneratedEvent() { } } internal record CardRevealedEvent : IEvent { [JsonProperty("player")] [JsonRequired] public required Player Player { get; init; } [JsonProperty("timestamp")] [JsonRequired] public required ulong Timestamp { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected CardRevealedEvent(CardRevealedEvent original) { Player = original.Player; Timestamp = original.Timestamp; } public CardRevealedEvent() { } } internal record ChatEvent : IEvent { [JsonProperty("player")] [JsonRequired] public required Player Player { get; init; } [JsonProperty("timestamp")] [JsonRequired] public required ulong Timestamp { get; init; } [JsonProperty("text")] [JsonRequired] public required string Text { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected ChatEvent(ChatEvent original) { Player = original.Player; Timestamp = original.Timestamp; Text = original.Text; } public ChatEvent() { } } internal record ColorEvent : IEvent { [JsonProperty("player")] [JsonRequired] public required Player Player { get; init; } [JsonProperty("player_color")] [JsonRequired] public required Team PreviousColor { get; init; } [JsonProperty("color")] [JsonRequired] public required Team NewColor { get; init; } [JsonProperty("timestamp")] [JsonRequired] public required ulong Timestamp { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected ColorEvent(ColorEvent original) { Player = original.Player; PreviousColor = original.PreviousColor; NewColor = original.NewColor; Timestamp = original.Timestamp; } public ColorEvent() { } } internal record ConnectionEvent : IEvent { [JsonProperty("player")] [JsonRequired] public required Player Player { get; init; } [JsonProperty("room")] [JsonRequired] public required string RoomId { get; init; } [JsonProperty("timestamp")] [JsonRequired] public required ulong Timestamp { get; init; } [JsonProperty("event_type")] [JsonConverter(typeof(StringEqualConverter), new object[] { "connected" })] public required bool IsConnected { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected ConnectionEvent(ConnectionEvent original) { Player = original.Player; RoomId = original.RoomId; Timestamp = original.Timestamp; IsConnected = original.IsConnected; } public ConnectionEvent() { } } internal record GoalEvent : IEvent { [JsonProperty("player")] [JsonRequired] public required Player Player { get; init; } [JsonProperty("timestamp")] [JsonRequired] public required ulong Timestamp { get; init; } [JsonProperty("square")] [JsonRequired] public required Square Square { get; init; } [JsonProperty("color")] [JsonRequired] public required Team Team { get; init; } [JsonProperty("remove")] [JsonRequired] public required bool HasBeenCleared { get; init; } [CompilerGenerated] [SetsRequiredMembers] protected GoalEvent(GoalEvent original) { Player = original.Player; Timestamp = original.Timestamp; Square = original.Square; Team = original.Team; HasBeenCleared = original.HasBeenCleared; } public GoalEvent() { } } } namespace BingoAPI.Conditions { internal class ConditionConverter : JsonConverter { private const string ACTION_KEY = "action"; private const string PARAMS_KEY = "params"; public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { throw new InvalidOperationException(); } public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { //IL_008d: 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_004b: Unknown result type (might be due to invalid IL or missing references) JObject val = JObject.Load(reader); string text = ((JToken)val).Value<string>((object)"action"); if (text == null) { throw new JsonException(string.Format("Expected '{0}' property: {1}", "action", val)); } JToken val2 = default(JToken); if (!val.TryGetValue("params", ref val2)) { throw new JsonException(string.Format("Expected '{0}' property: {1}", "params", val)); } if (!ConditionRegistry.TryGetFactory(text, out IConditionFactory factory)) { throw new ArgumentException("No factory has been registered under '" + text + "'."); } try { return factory.Generate(val2.CreateReader(), serializer); } catch (Exception ex) { throw new JsonException("Error while parsing the condition.", ex); } } public override bool CanConvert(Type objectType) { return objectType == typeof(ICondition); } } public static class ConditionRegistry { private static readonly Dictionary<string, IConditionFactory> FactoryPerAction = new Dictionary<string, IConditionFactory>(); internal static bool TryGetFactory(string action, [NotNullWhen(true)] out IConditionFactory? factory) { return FactoryPerAction.TryGetValue(action, out factory); } public static void RegisterFactory(string action, IConditionFactory factory) { if (FactoryPerAction.TryGetValue(action, out IConditionFactory value)) { Log.Debug($"Overriding the factory for '{action}' from '{value.GetType()}' to '{factory.GetType()}'."); } FactoryPerAction[action] = factory; } public static void RegisterFactory<T>(string action) where T : IConditionFactory, new() { RegisterFactory(action, new T()); } public static bool TryRegisterFactory(Type type) { if (type.IsAbstract || type.IsInterface) { return false; } ConditionFactoryAttribute customAttribute = type.GetCustomAttribute<ConditionFactoryAttribute>(); if (customAttribute == null) { return false; } if (!typeof(IConditionFactory).IsAssignableFrom(type)) { return false; } if (!(Activator.CreateInstance(type) is IConditionFactory factory)) { throw new InvalidOperationException($"Could not create factory '{type}'."); } try { Log.Debug($"Registering the factory '{type}' under '{customAttribute.Action}'."); RegisterFactory(customAttribute.Action, factory); } catch (Exception arg) { Log.Error($"Error while registering '{type}' under '{customAttribute.Action}': {arg}"); return false; } return true; } internal static void RegisterCondition(string action, Type type) { ConditionJsonFactory factory = new ConditionJsonFactory(type); RegisterFactory(action, factory); } public static void RegisterCondition<T>(string action) where T : ICondition { RegisterCondition(action, typeof(T)); } public static bool TryRegisterCondition(Type type) { if (type.IsAbstract || type.IsInterface) { return false; } ConditionAttribute customAttribute = type.GetCustomAttribute<ConditionAttribute>(); if (customAttribute == null) { return false; } if (!typeof(ICondition).IsAssignableFrom(type)) { return false; } try { Log.Debug($"Registering the condition '{type}' under '{customAttribute.Action}'."); RegisterCondition(customAttribute.Action, type); } catch (Exception arg) { Log.Error($"Error while registering '{type}' under '{customAttribute.Action}': {arg}"); return false; } return true; } public static bool TryRegisterCondition<T>() where T : ICondition { return TryRegisterCondition(typeof(T)); } public static void RegisterAllFromType(Type type) { TryRegisterCondition(type); TryRegisterFactory(type); } public static void RegisterAllFromAssembly(Assembly assembly) { IEnumerable<Type> types; try { types = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } foreach (Type item in types) { if (!(item == null)) { RegisterAllFromType(item); } } } public static void RegisterAll() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { RegisterAllFromAssembly(assembly); } } } } namespace BingoAPI.Conditions.Interfaces { [JsonConverter(typeof(ConditionConverter))] public interface ICondition { bool IsMet(); } public interface IConditionFactory { ICondition Generate(JsonReader reader, JsonSerializer serializer); } } namespace BingoAPI.Conditions.Factories { internal sealed class ConditionJsonFactory : IConditionFactory { private readonly Type _type; public ConditionJsonFactory(Type type) { _type = type; } public ICondition Generate(JsonReader reader, JsonSerializer serializer) { object obj = Activator.CreateInstance(_type); if (!(obj is ICondition condition)) { throw new ArgumentException(string.Format("Type '{0}' cannot be used inside '{1}'.", _type, "ConditionJsonFactory")); } serializer.Populate(reader, (object)condition); return condition; } } public abstract class ParameterizedConditionFactory<TParams> : IConditionFactory { public ICondition Generate(JsonReader reader, JsonSerializer serializer) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) TParams val = serializer.Deserialize<TParams>(reader); if (val == null) { throw new JsonException($"Failed to deserialize the parameters as '{typeof(TParams)}'."); } return Generate(val); } protected abstract ICondition Generate(TParams parameters); } } namespace BingoAPI.Conditions.BuiltIn { [Condition("AND")] public sealed class AndCondition : ICondition { [JsonProperty("conditions")] [JsonRequired] [Description("Conditions that must all be met")] public required IReadOnlyCollection<ICondition> Conditions { get; init; } public bool IsMet() { return Conditions.All((ICondition condition) => condition.IsMet()); } } [Condition("NOT")] public sealed class NotCondition : ICondition { [JsonProperty("condition")] [JsonRequired] [Description("Condition to negate")] public required ICondition Condition { get; init; } public bool IsMet() { return !Condition.IsMet(); } } [Condition("OR")] public sealed class OrCondition : ICondition { [JsonProperty("conditions")] [JsonRequired] [Description("Conditions where at least one must be met")] public required IReadOnlyCollection<ICondition> Conditions { get; init; } public bool IsMet() { return Conditions.Any((ICondition condition) => condition.IsMet()); } } [Condition("SOME")] public sealed class SomeCondition : ICondition { [JsonProperty("conditions")] [JsonRequired] [Description("Conditions that could be met")] public required IReadOnlyCollection<ICondition> Conditions { get; init; } [JsonProperty("amount")] [DefaultValue(1)] [Description("Minimum number of conditions that must be met")] public uint Amount { get; init; } public bool IsMet() { if (Conditions.Count < Amount) { return false; } int num = 0; foreach (ICondition condition in Conditions) { if (condition.IsMet()) { num++; if (num >= Amount) { return true; } } } return false; } } } namespace BingoAPI.Conditions.Attributes { [AttributeUsage(AttributeTargets.Class)] public class ConditionAttribute : Attribute { public readonly string Action; public ConditionAttribute(string action) { Action = action; } } [AttributeUsage(AttributeTargets.Class)] public class ConditionFactoryAttribute : Attribute { public readonly string Action; public ConditionFactoryAttribute(string action) { Action = action; } } }
plugins/Silksong.BingoSync.dll
Decompiled a month 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.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BingoAPI.Conditions; using BingoAPI.Conditions.Attributes; using BingoAPI.Conditions.BuiltIn; using BingoAPI.Conditions.Factories; using BingoAPI.Conditions.Interfaces; using BingoAPI.Events; using BingoAPI.Goals; using BingoAPI.Helpers; using BingoAPI.Models; using BingoAPI.Models.Settings; using BingoAPI.Networking; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Silksong.BingoSync.Conditions; using Silksong.BingoSync.Configurations; using Silksong.BingoSync.Data; using Silksong.BingoSync.Exceptions; using Silksong.BingoSync.Extensions; using Silksong.BingoSync.Helpers; using Silksong.BingoSync.Networking; using Silksong.BingoSync.Patches; using Silksong.BingoSync.UI.Abstract; using Silksong.BingoSync.UI.Components; using Silksong.BingoSync.UI.Constants; using Silksong.BingoSync.UI.Containers; using Silksong.BingoSync.UI.Items; using Silksong.BingoSync.UI.Menus; using Silksong.ModMenu.Elements; using Silksong.ModMenu.Plugin; using Silksong.ModMenu.Screens; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("WarperSan")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Connects Silksong to BingoSync, letting you play bingo directly in-game")] [assembly: AssemblyFileVersion("1.2.2.0")] [assembly: AssemblyInformationalVersion("1.2.2+7a8cc8dd5a9fba0ece2a5b6d060ccb2c843417d9")] [assembly: AssemblyProduct("Silksong.BingoSync")] [assembly: AssemblyTitle("Silksong.BingoSync")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/WarperSan/Silksong.BingoSync")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class RequiresPreviewFeaturesAttribute : Attribute { public string? Message { get; } public string? Url { get; set; } public RequiresPreviewFeaturesAttribute() { } public RequiresPreviewFeaturesAttribute(string? message) { Message = message; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class CompilerFeatureRequiredAttribute : Attribute { public const string RefStructs = "RefStructs"; public const string RequiredMembers = "RequiredMembers"; public string FeatureName { get; } public bool IsOptional { get; set; } public CompilerFeatureRequiredAttribute(string featureName) { FeatureName = featureName; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ParamCollectionAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class RequiredMemberAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class CompilerLoweringPreserveAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class RequiresLocationAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute { public string[] Arguments { get; } public InterpolatedStringHandlerArgumentAttribute(string argument) { Arguments = new string[1] { argument }; } public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) { Arguments = arguments; } } [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class SkipLocalsInitAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ModuleInitializerAttribute : Attribute { } [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class OverloadResolutionPriorityAttribute : Attribute { public int Priority { get; } public OverloadResolutionPriorityAttribute(int priority) { Priority = priority; } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class InterpolatedStringHandlerAttribute : Attribute { } [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] [Embedded] internal static class IsExternalInit { } [EditorBrowsable(EditorBrowsableState.Never)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ExtensionMarkerAttribute : Attribute { public string Name { get; } public ExtensionMarkerAttribute(string name) { Name = name; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class CollectionBuilderAttribute : Attribute { public Type BuilderType { get; } public string MethodName { get; } public CollectionBuilderAttribute(Type builderType, string methodName) { BuilderType = builderType; MethodName = methodName; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class SetsRequiredMembersAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class UnscopedRefAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class StringSyntaxAttribute : Attribute { public const string CompositeFormat = "CompositeFormat"; public const string DateOnlyFormat = "DateOnlyFormat"; public const string DateTimeFormat = "DateTimeFormat"; public const string EnumFormat = "EnumFormat"; public const string GuidFormat = "GuidFormat"; public const string Json = "Json"; public const string NumericFormat = "NumericFormat"; public const string Regex = "Regex"; public const string TimeOnlyFormat = "TimeOnlyFormat"; public const string TimeSpanFormat = "TimeSpanFormat"; public const string Uri = "Uri"; public const string Xml = "Xml"; public string Syntax { get; } public object?[] Arguments { get; } public StringSyntaxAttribute(string syntax) { Syntax = syntax; Arguments = new object[0]; } public StringSyntaxAttribute(string syntax, params object?[] arguments) { Syntax = syntax; Arguments = arguments; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ConstantExpectedAttribute : Attribute { public object? Min { get; set; } public object? Max { get; set; } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] [Embedded] internal sealed class ExperimentalAttribute : Attribute { public string DiagnosticId { get; } public string? UrlFormat { get; set; } public ExperimentalAttribute(string diagnosticId) { DiagnosticId = diagnosticId; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Embedded] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Embedded] [AttributeUsage(AttributeTargets.All)] [ExcludeFromCodeCoverage] internal sealed class EmbeddedAttribute : Attribute { } } namespace Silksong.BingoSync { internal class Controller : IDisposable { public delegate void CardCallback(Card? card); public GoalPool Pool = new GoalPool(); public readonly EventDispatcher Events; private readonly Session _session; private readonly HttpClient _client; private Card? _card; private Task<Card?>? _runningCardUpdate; private readonly GoalTracker _tracker; public Team Team => _session.Team; public bool IsConnected => _session.IsInRoom; public event CardCallback? OnCardUpdated; public Controller() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown Events = new EventDispatcher(); SubscribeToEvents(Events); _tracker = new GoalTracker(); _tracker.OnGoalMarked += new GoalChangedCallback(OnGoalMarked); _tracker.OnGoalCleared += new GoalChangedCallback(OnGoalCleared); _client = new HttpClient(new LoggingHandler(new HttpClientHandler())) { Timeout = TimeSpan.FromSeconds(30.0), BaseAddress = new Uri("https://bingosync.com"), DefaultRequestHeaders = { UserAgent = { new ProductInfoHeaderValue("dev.warpersan.silksong.bingosync", Plugin.Version) } } }; _session = new Session(Events, _client, new Uri("wss://sockets.bingosync.com")); } private void SubscribeToEvents(EventDispatcher events) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown events.OnSelfConnected += new ConnectionCallback(OnConnected); events.OnSelfSquareMarked += new MarkCallback(OnSquareMarked); events.OnOtherSquareMarked += new MarkCallback(OnSquareMarked); events.OnSelfSquareCleared += new ClearCallback(OnSquareCleared); events.OnOtherSquareCleared += new ClearCallback(OnSquareCleared); events.OnSelfCardGenerated += new GenerateCallback(OnCardGenerated); events.OnOtherCardGenerated += new GenerateCallback(OnCardGenerated); } private void UnsubscribeFromEvents(EventDispatcher events) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown events.OnSelfConnected -= new ConnectionCallback(OnConnected); events.OnSelfSquareMarked -= new MarkCallback(OnSquareMarked); events.OnOtherSquareMarked -= new MarkCallback(OnSquareMarked); events.OnSelfSquareCleared -= new ClearCallback(OnSquareCleared); events.OnOtherSquareCleared -= new ClearCallback(OnSquareCleared); events.OnSelfCardGenerated -= new GenerateCallback(OnCardGenerated); events.OnOtherCardGenerated -= new GenerateCallback(OnCardGenerated); } private void OnConnected(Player player) { UpdateCard(); } private void OnGoalMarked(Goal goal) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (_card == null) { return; } int[] array = _card.FindByGoal(goal); int[] array2 = array; foreach (int num in array2) { if (!_card.IsMarkedBy(num, _session.Team)) { _session.MarkSquare(num, default(CancellationToken)); } } } private void OnGoalCleared(Goal goal) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (_card == null) { return; } int[] array = _card.FindByGoal(goal); int[] array2 = array; foreach (int num in array2) { if (_card.IsMarkedBy(num, _session.Team)) { _session.ClearSquare(num, default(CancellationToken)); } } } private void OnSquareMarked(Player player, Square square, Team team) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) Card? card = _card; if (card != null) { card.Mark(square.Index, team); } this.OnCardUpdated?.Invoke(_card); } private void OnSquareCleared(Player player, Square square, Team team) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) Card? card = _card; if (card != null) { card.Unmark(square.Index, team); } this.OnCardUpdated?.Invoke(_card); } private void OnCardGenerated(Player player, bool isHidden) { UpdateCard(); } public Task<bool> Join(JoinRoomSettings settings) { return _session.JoinRoom(settings, default(CancellationToken)); } public Task<bool> Exit() { return _session.LeaveRoom(default(CancellationToken)); } public Task<bool> SetTeam(Team team) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _session.ChangeTeam(team, default(CancellationToken)); } private void UpdateCard() { if (_runningCardUpdate != null && !_runningCardUpdate.IsCompleted) { Log.Warning("An update of 'Card' is already pending."); return; } _runningCardUpdate = Task.Run(() => _session.GetCard(Pool, default(CancellationToken))); _runningCardUpdate.ContinueWith(delegate(Task<Card?> task) { Card result = task.Result; _tracker.Clear(); if (result != null) { Goal[] allGoals = result.GetAllGoals(); foreach (Goal val in allGoals) { _tracker.TryAdd(val); } } _card = result; this.OnCardUpdated?.Invoke(_card); }); } public void Evaluate() { _tracker.Evaluate(); } public void Dispose() { UnsubscribeFromEvents(Events); _client.Dispose(); _session.Dispose(); } } internal static class ConfigMenu { public static AbstractMenuScreen Create(Configuration configuration) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown AbstractMenuScreen[] array = (AbstractMenuScreen[])(object)new AbstractMenuScreen[5] { CreateGeneralConfig(configuration.General), CreateJoinConfig(configuration.Join), CreateBoardConfig(configuration.Board), CreateAccessibilityConfig(configuration.Accessibility), CreateExperimentalConfig(configuration.Experimental) }; PaginatedMenuScreenBuilder val = new PaginatedMenuScreenBuilder(LocalizedText.op_Implicit(Plugin.Name), 8); AbstractMenuScreen[] array2 = array; foreach (AbstractMenuScreen val2 in array2) { TextButton val3 = new TextButton(val2); val.Add((MenuElement)(object)val3); } return (AbstractMenuScreen)(object)val.Build(); } private static AbstractMenuScreen CreateGeneralConfig(GeneralConfig config) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown PaginatedMenuScreenBuilder val = new PaginatedMenuScreenBuilder(LocalizedText.op_Implicit("General"), 8); MenuElement val2 = default(MenuElement); if (ConfigEntryFactory.GenerateBoolElement((ConfigEntryBase)(object)config.UseAdvancedTeams, ref val2)) { val.Add(val2); } return (AbstractMenuScreen)(object)val.Build(); } private static AbstractMenuScreen CreateJoinConfig(JoinConfig config) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown PaginatedMenuScreenBuilder val = new PaginatedMenuScreenBuilder(LocalizedText.op_Implicit("Join"), 8); MenuElement val2 = default(MenuElement); if (ConfigEntryFactory.GenerateStringElement((ConfigEntryBase)(object)config.Nickname, ref val2)) { val.Add(val2); } MenuElement val3 = default(MenuElement); if (ConfigEntryFactory.GenerateStringElement((ConfigEntryBase)(object)config.Code, ref val3)) { val.Add(val3); } MenuElement val4 = default(MenuElement); if (ConfigEntryFactory.GenerateStringElement((ConfigEntryBase)(object)config.Password, ref val4)) { val.Add(val4); } MenuElement val5 = default(MenuElement); if (ConfigEntryFactory.GenerateKeyCodeElement((ConfigEntryBase)(object)config.ToggleUI, ref val5)) { val.Add(val5); } return (AbstractMenuScreen)(object)val.Build(); } private static AbstractMenuScreen CreateBoardConfig(BoardConfig config) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown PaginatedMenuScreenBuilder val = new PaginatedMenuScreenBuilder(LocalizedText.op_Implicit("Board"), 8); MenuElement val2 = default(MenuElement); if (ConfigEntryFactory.GenerateKeyCodeElement((ConfigEntryBase)(object)config.ToggleUI, ref val2)) { val.Add(val2); } return (AbstractMenuScreen)(object)val.Build(); } private static AbstractMenuScreen CreateExperimentalConfig(ExperimentalConfig config) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) PaginatedMenuScreenBuilder val = new PaginatedMenuScreenBuilder(LocalizedText.op_Implicit("Experimental"), 8); TextLabel val2 = new TextLabel(LocalizedText.op_Implicit("Theses settings are experimental and can cause performance issues")); ((Graphic)val2.Text).color = Color.yellow; val2.Text.fontSize = 30; val.Add((MenuElement)(object)val2); MenuElement val3 = default(MenuElement); if (ConfigEntryFactory.GenerateBoolElement((ConfigEntryBase)(object)config.EvaluateOnHeroUpdate, ref val3)) { val.Add(val3); } return (AbstractMenuScreen)(object)val.Build(); } private static AbstractMenuScreen CreateAccessibilityConfig(AccessibilityConfig config) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown PaginatedMenuScreenBuilder val = new PaginatedMenuScreenBuilder(LocalizedText.op_Implicit("Accessibility"), 8); MenuElement val2 = default(MenuElement); if (ConfigEntryFactory.GenerateEnumChoiceElement((ConfigEntryBase)(object)config.BoardCellFont, ref val2)) { val.Add(val2); } MenuElement val3 = default(MenuElement); if (ConfigEntryFactory.GenerateEnumChoiceElement((ConfigEntryBase)(object)config.BoardPosition, ref val3)) { val.Add(val3); } MenuElement val4 = default(MenuElement); if (ConfigEntryFactory.GenerateEnumChoiceElement((ConfigEntryBase)(object)config.BoardScale, ref val4)) { val.Add(val4); } MenuElement val5 = default(MenuElement); if (MenuElementGenerators.CreateIntSliderGenerator().Invoke((ConfigEntryBase)(object)config.BoardOpacity, ref val5)) { val.Add(val5); } return (AbstractMenuScreen)(object)val.Build(); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("dev.warpersan.silksong.bingosync", "Silksong.BingoSync", "1.2.2")] public class Plugin : BaseUnityPlugin, IModMenuCustomMenu, IModMenuInterface { internal static readonly Controller Controller = new Controller(); public const string Id = "dev.warpersan.silksong.bingosync"; public static string Name => "Silksong.BingoSync"; public static string Version => "1.2.2"; public AbstractMenuScreen BuildCustomMenu() { return ConfigMenu.Create(Configuration.SafeInstance); } private void Awake() { Log.Logger = Log.LogCore; Configuration.Load(((BaseUnityPlugin)this).Config); Patch.ApplyAll(); Log.Info("dev.warpersan.silksong.bingosync v" + Version + " has loaded!"); } private void Start() { ConditionRegistry.RegisterAll(); } } } namespace Silksong.BingoSync.UI.Menus { internal class ConnectionMenu : MonoBehaviour { private enum State { Offline, Connecting, Online, Disconnecting } private State _state; private CanvasGroup? _canvasGroup; private Button? _actionButton; private JoinForm? _joinForm; private TeamPicker? _teamPicker; private void SetOnline() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) _state = State.Online; _joinForm?.DisableInputs(); if ((Object)(object)_teamPicker != (Object)null) { _teamPicker.EnableInputs(); _teamPicker.SetTeam(Plugin.Controller.Team); } } private void SetOffline() { _state = State.Offline; _joinForm?.EnableInputs(); if ((Object)(object)_teamPicker != (Object)null) { _teamPicker.DisableInputs(); _teamPicker.SetTeam((Team)0); } } private void OnActionClicked() { State state = _state; if ((state == State.Connecting || state == State.Disconnecting) ? true : false) { Log.Warning($"State '{_state}' has no action assigned."); } else if (_state == State.Offline) { JoinRoom(); } else if (_state == State.Online) { LeaveRoom(); } } private void OnTeamSelected(Team team) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (_state != State.Online) { Log.Warning("Cannot change team without being online."); } else { ChangeTeam(team); } } private void ToggleVisibility() { if (!((Object)(object)_canvasGroup == (Object)null)) { bool flag = _canvasGroup.alpha > 0f; _canvasGroup.alpha = (flag ? 0f : 1f); _canvasGroup.blocksRaycasts = !flag; } } private void Update() { switch (_state) { case State.Offline: _actionButton?.SetText("Join"); break; case State.Connecting: _actionButton?.SetText("Connecting..."); break; case State.Online: _actionButton?.SetText("Leave"); break; case State.Disconnecting: _actionButton?.SetText("Disconnecting..."); break; default: throw new ArgumentOutOfRangeException(); } } private async Task JoinRoom() { if (_state != State.Offline) { throw new InvalidOperationException(); } if ((Object)(object)_joinForm == (Object)null) { throw new NullReferenceException("No 'JoinForm' assigned."); } _joinForm.DisableInputs(); JoinRoomSettings settings = _joinForm.GetSettings(); try { _state = State.Connecting; if (!(await Plugin.Controller.Join(settings))) { SetOffline(); Log.Error("Failed to join the room '" + settings.Code + "'."); } else { SetOnline(); } } catch (Exception arg) { SetOffline(); Log.Error($"Error while joining the room '{settings.Code}': {arg}"); } } private async Task LeaveRoom() { if (_state != State.Online) { throw new InvalidOperationException(); } _teamPicker?.DisableInputs(); try { _state = State.Disconnecting; if (!(await Plugin.Controller.Exit())) { SetOnline(); Log.Error("Failed to exit the room."); } else { SetOffline(); } } catch (Exception arg) { SetOnline(); Log.Error($"Error while joining the room: {arg}"); } } private async Task ChangeTeam(Team team) { //IL_0016: 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) if (_state != State.Online) { throw new InvalidOperationException(); } Controller controller = Plugin.Controller; if (controller == null) { throw new NullReferenceException("No 'Controller' assigned."); } if ((Object)(object)_teamPicker == (Object)null) { throw new NullReferenceException("No 'TeamPicker' assigned."); } _teamPicker.DisableInputs(); try { if (!(await controller.SetTeam(team))) { Log.Error("Failed to change team."); } } catch (Exception arg) { Log.Error($"Error while joining the room: {arg}"); } _teamPicker.SetTeam(controller.Team); _teamPicker.EnableInputs(); } public static ConnectionMenu Create(JoinRoomSettings settings) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001a: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ConnectionMenu"); ConnectionMenu connectionMenu = val.AddComponent<ConnectionMenu>(); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; VerticalLayoutGroup val3 = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val3).spacing = 10f; ((LayoutGroup)val3).childAlignment = (TextAnchor)7; ((HorizontalOrVerticalLayoutGroup)val3).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val3).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val3).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)val3).childForceExpandHeight = false; connectionMenu._canvasGroup = val.AddComponent<CanvasGroup>(); JoinForm joinForm = JoinForm.Create(); ((Component)joinForm).transform.SetParent(((Component)val3).transform, false); joinForm.SetSettings(settings); connectionMenu._joinForm = joinForm; TeamPicker teamPicker = TeamPicker.Create(connectionMenu.OnTeamSelected); ((Component)teamPicker).transform.SetParent(((Component)val3).transform, false); connectionMenu._teamPicker = teamPicker; Button button = Button.Create(connectionMenu.OnActionClicked); ((Component)button).transform.SetParent(val.transform, false); connectionMenu._actionButton = button; CallOnInput callOnInput = val.AddComponent<CallOnInput>(); callOnInput.SetInput(Configuration.SafeInstance.Join.ToggleUI, connectionMenu.ToggleVisibility); connectionMenu.SetOffline(); return connectionMenu; } } } namespace Silksong.BingoSync.UI.Items { internal class BingoCell : MonoBehaviour { private Text? _text; private Dictionary<Team, Image>? _teamMarks; public void SetSquare(Goal goal, Team teams) { //IL_0040: 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_0046: 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) Text? text = _text; if (text != null) { text.text = goal.Name; } if (_teamMarks == null) { return; } foreach (KeyValuePair<Team, Image> teamMark in _teamMarks) { teamMark.Deconstruct(out var key, out var value); Team val = key; Image val2 = value; bool active = ((Enum)teams).HasFlag((Enum)(object)val); ((Component)val2).gameObject.SetActive(active); } } public void AddTeam(Team team) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (_teamMarks != null && _teamMarks.TryGetValue(team, out Image value)) { ((Component)value).gameObject.SetActive(true); } } public void RemoveTeam(Team team) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (_teamMarks != null && _teamMarks.TryGetValue(team, out Image value)) { ((Component)value).gameObject.SetActive(false); } } public static BingoCell Create() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0191: 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_01a7: 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) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BingoCell"); val.AddComponent<RectTransform>(); BingoCell bingoCell = val.AddComponent<BingoCell>(); GameObject val2 = new GameObject("Background"); val2.transform.SetParent(val.transform, false); Image val3 = val2.AddComponent<Image>(); ((Graphic)val3).color = new Color(0.1f, 0.1f, 0.1f, 1f); VerticalLayoutGroup val4 = val2.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)val4).childAlignment = (TextAnchor)4; Dictionary<Team, Image> dictionary = new Dictionary<Team, Image>(); foreach (Team value in Enum.GetValues(typeof(Team))) { if ((int)value != 0) { GameObject val6 = new GameObject(((object)value/*cast due to .constrained prefix*/).ToString()); val6.transform.SetParent(((Component)val4).transform, false); Image val7 = val6.AddComponent<Image>(); ((Graphic)val7).color = Colors.GetColor(value); dictionary.Add(value, val7); } } GameObject val8 = new GameObject("Darkener"); val8.transform.SetParent(val.transform, false); Image val9 = val8.AddComponent<Image>(); ((Graphic)val9).color = new Color(0f, 0f, 0f, 0.4f); GameObject val10 = new GameObject("Text"); val10.transform.SetParent(val.transform, false); RectTransform val11 = val10.AddComponent<RectTransform>(); val11.anchorMin = Vector2.zero; val11.anchorMax = Vector2.one; val11.offsetMin = Vector2.one * 5f; val11.offsetMax = -Vector2.one * 5f; Text val12 = val10.AddComponent<Text>(); val12.fontSize = 12; val12.text = "Placeholder"; val12.alignment = (TextAnchor)3; ((Graphic)val12).color = Color.white; val12.font = Fonts.Normal; AccessibilityTextFont accessibilityTextFont = val10.AddComponent<AccessibilityTextFont>(); accessibilityTextFont.Bind(Configuration.SafeInstance.Accessibility.BoardCellFont); bingoCell._text = val12; bingoCell._teamMarks = dictionary; return bingoCell; } } internal class TeamPickerButton : MonoBehaviour { private Outline? _outline; private Action<Team>? _onClick; private Color _teamColor = Color.white; public Team Team { get; private set; } public void Select() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_outline != (Object)null) { ((Shadow)_outline).effectColor = Color.white; } } public void Unselect() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_outline != (Object)null) { ((Shadow)_outline).effectColor = _teamColor; } } private void OnClick() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) _onClick?.Invoke(Team); } public static TeamPickerButton Create(Team team, Action<Team> onClick) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_002f: 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_003c: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0085: Expected O, but got Unknown //IL_0087: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("TeamPickerButton"); val.AddComponent<RectTransform>(); TeamPickerButton teamPickerButton = val.AddComponent<TeamPickerButton>(); teamPickerButton.Team = team; teamPickerButton._onClick = onClick; Color val2 = (teamPickerButton._teamColor = team.GetColor()); Image val3 = val.AddComponent<Image>(); Color color = val2 * 0.6f; color.a = 1f; ((Graphic)val3).color = color; Button val4 = val.AddComponent<Button>(); ((Selectable)val4).targetGraphic = (Graphic)(object)val3; ((UnityEvent)val4.onClick).AddListener(new UnityAction(teamPickerButton.OnClick)); ColorBlock colors = ((Selectable)val4).colors; ((ColorBlock)(ref colors)).disabledColor = new Color(0.3f, 0.3f, 0.3f, 1f); ((Selectable)val4).colors = colors; teamPickerButton._outline = ((Component)val4).gameObject.AddComponent<Outline>(); GameObject val5 = new GameObject("Text"); val5.transform.SetParent(val.transform, false); RectTransform val6 = val5.AddComponent<RectTransform>(); val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.one; val6.offsetMin = Vector2.zero; val6.offsetMax = Vector2.zero; Text val7 = val5.AddComponent<Text>(); val7.font = Fonts.Normal; val7.fontSize = 17; ((Graphic)val7).color = Color.white; val7.alignment = (TextAnchor)4; val7.text = team.GetDisplayName(); teamPickerButton.Unselect(); return teamPickerButton; } } } namespace Silksong.BingoSync.UI.Containers { public class BingoBoard : MonoBehaviour { private BingoCell[]? _cells; private void Awake() { Subscribe(Plugin.Controller); } private void DisplayCard(Card? card) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (card != null && _cells != null) { for (int i = 0; i < _cells.Length; i++) { Goal goalAt = card.GetGoalAt(i); Team teamsAt = card.GetTeamsAt(i); _cells[i].SetSquare(goalAt, teamsAt); } } } private void Subscribe(Controller controller) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown controller.OnCardUpdated += DisplayCard; EventDispatcher events = controller.Events; events.OnSelfSquareMarked += new MarkCallback(OnSquareMarked); events.OnOtherSquareMarked += new MarkCallback(OnSquareMarked); events.OnSelfSquareCleared += new ClearCallback(OnSquareCleared); events.OnOtherSquareCleared += new ClearCallback(OnSquareCleared); } private void OnSquareMarked(Player player, Square square, Team team) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) BingoCell[]? cells = _cells; if (cells != null) { cells[square.Index].AddTeam(team); } } private void OnSquareCleared(Player player, Square square, Team team) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) BingoCell[]? cells = _cells; if (cells != null) { cells[square.Index].RemoveTeam(team); } } public static BingoBoard Create() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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) GameObject val = new GameObject("BingoBoard"); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMax = Vector2.one; val2.anchorMin = Vector2.one; val2.pivot = Vector2.one; AccessibilityElementPosition accessibilityElementPosition = val.AddComponent<AccessibilityElementPosition>(); accessibilityElementPosition.Bind(Configuration.SafeInstance.Accessibility.BoardPosition); AccessibilityElementScale accessibilityElementScale = val.AddComponent<AccessibilityElementScale>(); accessibilityElementScale.Bind(Configuration.SafeInstance.Accessibility.BoardScale); ContentSizeFitter val3 = val.AddComponent<ContentSizeFitter>(); val3.horizontalFit = (FitMode)2; val3.verticalFit = (FitMode)2; Image val4 = val.AddComponent<Image>(); ((Graphic)val4).color = Color.black; BingoBoard bingoBoard = val.AddComponent<BingoBoard>(); GridLayoutGroup val5 = val.AddComponent<GridLayoutGroup>(); val5.cellSize = Vector2.one * 100f; val5.constraint = (Constraint)1; val5.constraintCount = 5; ((LayoutGroup)val5).childAlignment = (TextAnchor)0; val5.spacing = Vector2.one * 5f; BingoCell[] array = new BingoCell[25]; for (int i = 0; i < array.Length; i++) { BingoCell bingoCell = BingoCell.Create(); ((Component)bingoCell).transform.SetParent(((Component)val5).transform, false); array[i] = bingoCell; } bingoBoard._cells = array; CanvasGroup val6 = val.AddComponent<CanvasGroup>(); val6.blocksRaycasts = false; AccessibilityOpacity accessibilityOpacity = val.AddComponent<AccessibilityOpacity>(); accessibilityOpacity.Bind(Configuration.SafeInstance.Accessibility.BoardOpacity); return bingoBoard; } } internal class BoardContainer : MonoBehaviour { private BingoBoard? _board; private CallOnInput? _toggleInput; private void Awake() { Subscribe(Plugin.Controller.Events); } private void ToggleVisibility() { if (!((Object)(object)_board == (Object)null)) { bool activeInHierarchy = ((Component)_board).gameObject.activeInHierarchy; SetVisibility(!activeInHierarchy); } } private void SetVisibility(bool isVisible) { if (!((Object)(object)_board == (Object)null)) { ((Component)_board).gameObject.SetActive(isVisible); } } private void EnableVisibility() { if ((Object)(object)_toggleInput != (Object)null) { ((Behaviour)_toggleInput).enabled = true; } SetVisibility(isVisible: true); } private void DisableVisibility() { if ((Object)(object)_toggleInput != (Object)null) { ((Behaviour)_toggleInput).enabled = false; } SetVisibility(isVisible: false); } private void Subscribe(EventDispatcher dispatcher) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown dispatcher.OnSelfConnected += (ConnectionCallback)delegate { EnableVisibility(); }; dispatcher.OnSelfDisconnected += (DisconnectionCallback)delegate { DisableVisibility(); }; } public static BoardContainer Create() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001a: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BoardContainer"); BoardContainer boardContainer = val.AddComponent<BoardContainer>(); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; CallOnInput callOnInput = val.AddComponent<CallOnInput>(); callOnInput.SetInput(Configuration.SafeInstance.Board.ToggleUI, boardContainer.ToggleVisibility); boardContainer._toggleInput = callOnInput; BingoBoard bingoBoard = BingoBoard.Create(); ((Component)bingoBoard).transform.SetParent((Transform)(object)val2, false); boardContainer._board = bingoBoard; boardContainer.DisableVisibility(); return boardContainer; } } internal class JoinForm : MonoBehaviour { private CanvasGroup? _canvasGroup; private TextField? _roomCodeInput; private TextField? _nicknameInput; private TextField? _passwordInput; public void SetSettings(JoinRoomSettings settings) { if ((Object)(object)_roomCodeInput != (Object)null) { _roomCodeInput.Text = settings.Code; } if ((Object)(object)_nicknameInput != (Object)null) { _nicknameInput.Text = settings.Nickname; } if ((Object)(object)_passwordInput != (Object)null) { _passwordInput.Text = settings.Password; } } public JoinRoomSettings GetSettings() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown JoinRoomSettings val = new JoinRoomSettings(); if ((Object)(object)_roomCodeInput != (Object)null) { string text = _roomCodeInput.Text; string text2 = default(string); if (Network.TryGetRoomCode(text, ref text2)) { text = text2; } val.Code = text; } if ((Object)(object)_nicknameInput != (Object)null) { val.Nickname = _nicknameInput.Text; } if ((Object)(object)_passwordInput != (Object)null) { val.Password = _passwordInput.Text; } return val; } public void EnableInputs() { if (!((Object)(object)_canvasGroup == (Object)null)) { _canvasGroup.interactable = true; } } public void DisableInputs() { if (!((Object)(object)_canvasGroup == (Object)null)) { _canvasGroup.interactable = false; } } public static JoinForm Create() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("JoinForm"); JoinForm joinForm = val.AddComponent<JoinForm>(); RectTransform val2 = val.AddComponent<RectTransform>(); val2.pivot = new Vector2(0.5f, 0f); ContentSizeFitter val3 = val.AddComponent<ContentSizeFitter>(); val3.verticalFit = (FitMode)2; VerticalLayoutGroup val4 = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val4).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val4).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val4).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)val4).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)val4).spacing = 10f; joinForm._canvasGroup = val.AddComponent<CanvasGroup>(); TextField textField = TextField.Create("Room Code / Link", (ContentType)0); ((Component)textField).transform.SetParent(val.transform, false); joinForm._roomCodeInput = textField; TextField textField2 = TextField.Create("Nickname", (ContentType)0); ((Component)textField2).transform.SetParent(val.transform, false); joinForm._nicknameInput = textField2; TextField textField3 = TextField.Create("Password", (ContentType)7); ((Component)textField3).transform.SetParent(val.transform, false); joinForm._passwordInput = textField3; return joinForm; } } internal class TeamPicker : MonoBehaviour { private CanvasGroup? _canvasGroup; private Dictionary<Team, TeamPickerButton>? _buttons; private Action<Team>? _onTeamSelected; private Team _team; public void SetTeam(Team team) { //IL_0002: 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_0028: 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) if (TryGetButton(_team, out TeamPickerButton button)) { button.Unselect(); } if (TryGetButton(team, out TeamPickerButton button2)) { button2.Select(); } _team = team; } public void EnableInputs() { if (!((Object)(object)_canvasGroup == (Object)null)) { _canvasGroup.interactable = true; } } public void DisableInputs() { if (!((Object)(object)_canvasGroup == (Object)null)) { _canvasGroup.interactable = false; } } private bool TryGetButton(Team team, [NotNullWhen(true)] out TeamPickerButton? button) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (_buttons == null) { button = null; return false; } return _buttons.TryGetValue(team, out button); } private void OnTeamSelected(Team team) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) _onTeamSelected?.Invoke(team); } public static TeamPicker Create(Action<Team> onTeamSelected) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0024: 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_0052: 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_00fe: 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_012f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("TeamPicker"); TeamPicker teamPicker = val.AddComponent<TeamPicker>(); RectTransform val2 = val.AddComponent<RectTransform>(); val2.pivot = new Vector2(0.5f, 0f); GridLayoutGroup val3 = val.AddComponent<GridLayoutGroup>(); ((LayoutGroup)val3).childAlignment = (TextAnchor)4; val3.cellSize = new Vector2(125f, 50f); val3.spacing = Vector2.one * 10f; ContentSizeFitter val4 = val.AddComponent<ContentSizeFitter>(); val4.verticalFit = (FitMode)2; teamPicker._canvasGroup = val.AddComponent<CanvasGroup>(); Dictionary<Team, TeamPickerButton> dictionary = new Dictionary<Team, TeamPickerButton>(); List<Team> list = new List<Team>(4) { (Team)2, (Team)128, (Team)32, (Team)16 }; if (Configuration.SafeInstance.General.UseAdvancedTeams.Value) { list.Add((Team)512); list.Add((Team)256); list.Add((Team)1); list.Add((Team)8); } foreach (Team item in list) { TeamPickerButton teamPickerButton = TeamPickerButton.Create(item, teamPicker.OnTeamSelected); ((Component)teamPickerButton).transform.SetParent(val.transform, false); dictionary[item] = teamPickerButton; } teamPicker._buttons = dictionary; teamPicker._onTeamSelected = onTeamSelected; return teamPicker; } } } namespace Silksong.BingoSync.UI.Constants { internal static class Colors { public static Color GetColor(this Team team) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected I4, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: 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_0154: Unknown result type (might be due to invalid IL or missing references) //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_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_0032: Invalid comparison between Unknown and I4 //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Invalid comparison between Unknown and I4 //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: 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: Invalid comparison between Unknown and I4 //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: 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_003a: Invalid comparison between Unknown and I4 //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if ((int)team <= 32) { switch ((int)team) { default: if ((int)team != 16) { if ((int)team != 32) { break; } return new Color(0.22f, 0.75f, 0.47f); } return new Color(0.89f, 0.63f, 0f); case 4: return new Color(0.96f, 0.6f, 0.2f); case 2: return new Color(1f, 0.28f, 0.27f); case 8: return new Color(0.37f, 0.29f, 0.27f); case 1: return new Color(0.93f, 0.52f, 0.67f); case 0: return Color.black; case 3: case 5: case 6: case 7: break; } } else if ((int)team <= 128) { if ((int)team == 64) { return new Color(0.71f, 0.71f, 0.71f); } if ((int)team == 128) { return new Color(0f, 0.71f, 1f); } } else { if ((int)team == 256) { return new Color(0.16f, 0.33f, 0.53f); } if ((int)team == 512) { return new Color(0.51f, 0.17f, 0.75f); } } throw new ArgumentOutOfRangeException("team", team, null); } public static string GetDisplayName(this Team team) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected I4, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 //IL_00c4: 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_0032: Invalid comparison between Unknown and I4 //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 if ((int)team <= 32) { switch ((int)team) { default: if ((int)team != 16) { if ((int)team != 32) { break; } return "Mossberry"; } return "Flintgem"; case 2: return "Rosary"; case 4: return "Flintstone"; case 1: return "Voltridian"; case 8: return "Pilgrim"; case 0: return "???"; case 3: case 5: case 6: case 7: break; } } else if ((int)team <= 128) { if ((int)team == 64) { return "Growstone"; } if ((int)team == 128) { return "Plasmium"; } } else { if ((int)team == 256) { return "Magnetite"; } if ((int)team == 512) { return "Pollip"; } } throw new ArgumentOutOfRangeException("team", team, null); } } internal static class Fonts { private static readonly Dictionary<string, Font> CachedFonts = new Dictionary<string, Font>(); public static Font? Normal => GetFont("TrajanPro-Regular"); public static Font? Bold => GetFont("TrajanPro-Bold"); public static Font? Arial => GetFont("ARIAL"); public static Font? Default => Font.GetDefault(); private static Font? GetFont(string name) { if (CachedFonts.TryGetValue(name, out Font value)) { return value; } Font[] array = Resources.FindObjectsOfTypeAll<Font>(); foreach (Font val in array) { CachedFonts[((Object)val).name] = val; } return CachedFonts.GetValueOrDefault(name); } } } namespace Silksong.BingoSync.UI.Components { [RequireComponent(typeof(RectTransform))] internal class AccessibilityElementPosition : SettingUpdateNotifier<AccessibilityConfig.ElementPosition> { private RectTransform? _rectTransform; protected override void OnSettingChanged(AccessibilityConfig.ElementPosition value) { //IL_003a: 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_006e: 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_008f: 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_00b0: 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_00eb: 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_011f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rectTransform == (Object)null)) { switch (value) { case AccessibilityConfig.ElementPosition.TopLeft: _rectTransform.anchorMax = new Vector2(0f, 1f); _rectTransform.anchorMin = new Vector2(0f, 1f); _rectTransform.pivot = new Vector2(0f, 1f); break; case AccessibilityConfig.ElementPosition.TopRight: _rectTransform.anchorMax = Vector2.one; _rectTransform.anchorMin = Vector2.one; _rectTransform.pivot = Vector2.one; break; case AccessibilityConfig.ElementPosition.BottomLeft: _rectTransform.anchorMax = Vector2.zero; _rectTransform.anchorMin = Vector2.zero; _rectTransform.pivot = Vector2.zero; break; case AccessibilityConfig.ElementPosition.BottomRight: _rectTransform.anchorMax = new Vector2(1f, 0f); _rectTransform.anchorMin = new Vector2(1f, 0f); _rectTransform.pivot = new Vector2(1f, 0f); break; default: throw new ArgumentOutOfRangeException("value", value, null); } } } private void Awake() { _rectTransform = ((Component)this).GetComponent<RectTransform>(); } } [RequireComponent(typeof(RectTransform))] internal class AccessibilityElementScale : SettingUpdateNotifier<AccessibilityConfig.ElementScale> { private RectTransform? _rectTransform; protected override void OnSettingChanged(AccessibilityConfig.ElementScale value) { //IL_0032: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_0095: 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) if (!((Object)(object)_rectTransform == (Object)null)) { RectTransform rectTransform = _rectTransform; ((Transform)rectTransform).localScale = Vector2.op_Implicit((Vector2)(value switch { AccessibilityConfig.ElementScale.VerySmall => Vector2.one * 0.5f, AccessibilityConfig.ElementScale.Small => Vector2.one * 0.75f, AccessibilityConfig.ElementScale.Normal => Vector2.one, AccessibilityConfig.ElementScale.Large => Vector2.one * 1.25f, AccessibilityConfig.ElementScale.VeryLarge => Vector2.one * 1.5f, _ => throw new ArgumentOutOfRangeException("value", value, null), })); } } private void Awake() { _rectTransform = ((Component)this).GetComponent<RectTransform>(); } } [RequireComponent(typeof(CanvasGroup))] internal class AccessibilityOpacity : SettingUpdateNotifier<int> { private CanvasGroup? _canvasGroup; protected override void OnSettingChanged(int value) { if (!((Object)(object)_canvasGroup == (Object)null)) { _canvasGroup.alpha = Mathf.Clamp((float)value / 100f, 0f, 1f); } } private void Awake() { _canvasGroup = ((Component)this).GetComponent<CanvasGroup>(); } } [RequireComponent(typeof(Text))] internal class AccessibilityTextFont : SettingUpdateNotifier<AccessibilityConfig.TextFont> { private Text? _text; protected override void OnSettingChanged(AccessibilityConfig.TextFont value) { if (!((Object)(object)_text == (Object)null)) { Text text = _text; text.font = (Font)(value switch { AccessibilityConfig.TextFont.Normal => Fonts.Normal, AccessibilityConfig.TextFont.Bold => Fonts.Bold, AccessibilityConfig.TextFont.Arial => Fonts.Arial, AccessibilityConfig.TextFont.Default => Fonts.Default, _ => throw new ArgumentOutOfRangeException("value", value, null), }); } } private void Awake() { _text = ((Component)this).GetComponent<Text>(); } } internal class Button : MonoBehaviour { private Action? _onClick; private Text? _label; public void SetText(string text) { Text? label = _label; if (label != null) { label.text = text; } } private void OnClick() { _onClick?.Invoke(); } public static Button Create(Action onClick) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_009b: 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_00b3: 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_00e9: 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_012c: Expected O, but got Unknown GameObject val = new GameObject("Button"); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.sizeDelta = new Vector2(300f, 50f); Image val3 = val.AddComponent<Image>(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.6f); Button val4 = val.AddComponent<Button>(); ((Selectable)val4).targetGraphic = (Graphic)(object)val3; GameObject val5 = new GameObject("Text"); val5.transform.SetParent(val.transform, false); RectTransform val6 = val5.AddComponent<RectTransform>(); val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.one; val6.offsetMin = Vector2.zero; val6.offsetMax = Vector2.zero; Text val7 = val5.AddComponent<Text>(); val7.font = Fonts.Normal; val7.fontSize = 18; ((Graphic)val7).color = Color.white; val7.alignment = (TextAnchor)4; Button button = val.AddComponent<Button>(); button._onClick = onClick; button._label = val7; ((UnityEvent)val4.onClick).AddListener(new UnityAction(button.OnClick)); return button; } } internal class CallOnInput : MonoBehaviour { private Func<KeyCode>? _key; private Action? _onInput; public void SetInput(ConfigEntry<KeyCode> entry, Action? onInput) { _key = () => entry.Value; _onInput = onInput; } private void Update() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (_key != null) { KeyCode val = _key(); if (Input.GetKeyDown(val)) { _onInput?.Invoke(); } } } } internal class TextField : MonoBehaviour { private InputField? _inputField; public string Text { get { if ((Object)(object)_inputField == (Object)null) { return string.Empty; } return _inputField.text; } set { if (!((Object)(object)_inputField == (Object)null)) { _inputField.text = value; } } } public static TextField Create(string placeholder = "", ContentType type = (ContentType)0) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0024: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00a8: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_0130: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("TextField"); TextField textField = val.AddComponent<TextField>(); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(0f, 0.5f); val2.anchorMax = new Vector2(1f, 0.5f); val2.sizeDelta = new Vector2(300f, 40f); Image val3 = val.AddComponent<Image>(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.6f); GameObject val4 = new GameObject("Text"); val4.transform.SetParent(val.transform, false); RectTransform val5 = val4.AddComponent<RectTransform>(); val5.anchorMin = Vector2.zero; val5.anchorMax = Vector2.one; val5.offsetMin = new Vector2(10f, 5f); val5.offsetMax = new Vector2(-10f, 5f); Text val6 = val4.AddComponent<Text>(); val6.font = Fonts.Normal; val6.fontSize = 18; ((Graphic)val6).color = Color.white; val6.alignment = (TextAnchor)3; val6.supportRichText = false; GameObject val7 = new GameObject("Placeholder"); val7.transform.SetParent(val.transform, false); RectTransform val8 = val7.AddComponent<RectTransform>(); val8.anchorMin = Vector2.zero; val8.anchorMax = Vector2.one; val8.offsetMin = new Vector2(10f, 0f); val8.offsetMax = new Vector2(-10f, 0f); Text val9 = val7.AddComponent<Text>(); val9.font = val6.font; val9.fontSize = val6.fontSize; ((Graphic)val9).color = new Color(1f, 1f, 1f, 0.5f); val9.alignment = (TextAnchor)3; val9.text = placeholder; val9.fontStyle = (FontStyle)2; InputField val10 = val.AddComponent<InputField>(); val10.textComponent = val6; val10.placeholder = (Graphic)(object)val9; ((Selectable)val10).targetGraphic = (Graphic)(object)val3; val10.contentType = type; textField._inputField = val10; return textField; } } } namespace Silksong.BingoSync.UI.Abstract { internal abstract class SettingUpdateNotifier<T> : MonoBehaviour { private ConfigEntry<T>? _config; public void Bind(ConfigEntry<T> config) { Unbind(); _config = config; _config.SettingChanged += OnRawSettingChanged; SettingChanged(_config.Value); } public void Unbind() { ConfigEntry<T>? config = _config; if (config != null) { config.SettingChanged -= OnRawSettingChanged; } _config = null; } private void OnRawSettingChanged(object sender, EventArgs e) { SettingChangedEventArgs e2 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); if (e2 != null && e2.ChangedSetting is ConfigEntry<T> val) { SettingChanged(val.Value); } } private void SettingChanged(T value) { OnSettingChanged(value); } protected abstract void OnSettingChanged(T value); protected virtual void OnDestroy() { Unbind(); } } } namespace Silksong.BingoSync.Patches { [HarmonyPatch(typeof(GameManager))] internal class GameManager_Patches { private static bool hasInitialized; [HarmonyPostfix] [HarmonyPatch("Start")] private static void Start_Postfix(GameManager __instance) { if (hasInitialized) { return; } string absolutePath = Silksong.BingoSync.Helpers.Path.GetAbsolutePath("Goals/"); GoalPool val = GoalLoader.LoadPoolFromFolder(absolutePath); List<object> list = new List<object>(); foreach (Goal item in val) { list.Add(new { name = item.Name }); } Log.Info(JsonConvert.SerializeObject((object)list)); Plugin.Controller.Pool = val; Log.Info($"Loaded '{val.Count}' goals."); hasInitialized = true; } } [HarmonyPatch(typeof(HeroController))] internal class HeroController_Patches { [HarmonyPrefix] [HarmonyPatch("FixedUpdate")] private static void FixedUpdate_Prefix(HeroController __instance) { Configuration instance = Configuration.Instance; if (instance != null && instance.Experimental.EvaluateOnHeroUpdate.Value) { Plugin.Controller.Evaluate(); } } } [HarmonyPatch(typeof(PlayerData))] internal class PlayerData_Patches { [HarmonyPostfix] [HarmonyPatch("SetBool")] private static void SetBool_Postfix() { Plugin.Controller.Evaluate(); } } [HarmonyPatch(typeof(ToolItemManager))] internal class ToolItemManager_Patches { [HarmonyPostfix] [HarmonyPatch("ReportCrestUnlocked")] private static void ReportCrestUnlocked_Postfix() { Plugin.Controller.Evaluate(); } } [HarmonyPatch(typeof(UIManager))] internal class UIManager_Patches { private static Canvas? _bingoCanvas; [HarmonyPostfix] [HarmonyPatch("Awake")] private static void Awake_Postfix(UIManager __instance) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_bingoCanvas != (Object)null)) { GameObject val = new GameObject("BingoSync.Canvas"); Object.DontDestroyOnLoad((Object)(object)val); Canvas val2 = val.AddComponent<Canvas>(); val2.renderMode = (RenderMode)0; CanvasScaler val3 = val.AddComponent<CanvasScaler>(); val3.referenceResolution = __instance.canvasScaler.referenceResolution; val3.uiScaleMode = (ScaleMode)1; val3.screenMatchMode = (ScreenMatchMode)1; val.AddComponent<GraphicRaycaster>(); _bingoCanvas = val2; CreateConnectionMenu(val.transform); BoardContainer boardContainer = BoardContainer.Create(); ((Component)boardContainer).transform.SetParent(val.transform, false); } } private static void CreateConnectionMenu(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002a: 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_0054: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown GameObject val = new GameObject("ConnectionMenu-Container"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(0.75f, 0f); val2.anchorMax = new Vector2(1f, 0.5f); val2.offsetMin = new Vector2(-20f, 0f); val2.offsetMax = new Vector2(0f, 20f); val2.pivot = new Vector2(1f, 0f); JoinConfig joinConfig = Configuration.Instance?.Join; JoinRoomSettings settings = new JoinRoomSettings { Nickname = (joinConfig?.Nickname.Value ?? ""), Code = (joinConfig?.Code.Value ?? ""), Password = (joinConfig?.Password.Value ?? "") }; ConnectionMenu connectionMenu = ConnectionMenu.Create(settings); ((Component)connectionMenu).transform.SetParent(val.transform, false); RectTransform val3 = default(RectTransform); if (((Component)connectionMenu).TryGetComponent<RectTransform>(ref val3)) { Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate(val3); } } } } namespace Silksong.BingoSync.Networking { internal class LoggingHandler : DelegatingHandler { public LoggingHandler(HttpMessageHandler innerHandler) : base(innerHandler) { } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { string arg = ""; if (request.Content != null) { arg = await request.Content.ReadAsStringAsync(); } Log.Debug($"Request:\n{request}\n{arg}"); HttpResponseMessage response = await base.SendAsync(request, cancellationToken); string arg2 = ""; if (response.Content != null) { arg2 = await response.Content.ReadAsStringAsync(); } Log.Debug($"Response:\n{response}\n{arg2}"); return response; } } } namespace Silksong.BingoSync.Helpers { internal static class GoalLoader { public static GoalPool LoadPoolFromFolder(string folder) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown GoalPool val = new GoalPool(); if (!Directory.Exists(folder)) { Log.Warning("Folder '" + folder + "' does not exist."); return val; } string[] files = Directory.GetFiles(folder, "*.json", SearchOption.AllDirectories); string[] array = files; foreach (string text in array) { try { GoalSet val2 = LoadSetFromFile(text); Goal[] goals = val2.Goals; foreach (Goal val3 in goals) { val.TryAdd(val3); } } catch (Exception arg) { Log.Error($"Error while loading '{text}': {arg}"); } } return val; } public static GoalSet LoadSetFromFile(string file) { string text = File.ReadAllText(file); GoalSet val = JsonConvert.DeserializeObject<GoalSet>(text); if (val == (GoalSet)null) { throw new InvalidOperationException("Must parse a valid 'GoalSet'."); } return val; } } internal static class Log { private static readonly Lazy<ManualLogSource> Logger = new Lazy<ManualLogSource>((Func<ManualLogSource>)(() => Logger.CreateLogSource("dev.warpersan.silksong.bingosync"))); public static void LogCore(LogLevel level, string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected I4, but got Unknown switch ((int)level) { case 0: Debug(message); break; case 2: Warning(message); break; case 3: Error(message); break; default: Info(message); break; } } public static void Debug(string? message) { Logger.Value.LogDebug((object)message); } public static void Info(string? message) { Logger.Value.LogInfo((object)message); } public static void Warning(string? message) { Logger.Value.LogWarning((object)message); } public static void Error(string? message) { Logger.Value.LogError((object)message); } } internal static class Patch { public static void ApplyAll() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown Harmony val = new Harmony("dev.warpersan.silksong.bingosync"); val.PatchAll(typeof(UIManager_Patches)); val.PatchAll(typeof(PlayerData_Patches)); val.PatchAll(typeof(ToolItemManager_Patches)); val.PatchAll(typeof(HeroController_Patches)); val.PatchAll(typeof(GameManager_Patches)); Log.Debug("All patches applied."); } } internal static class Path { public static string GetPluginFolder() { string location = Assembly.GetExecutingAssembly().Location; string directoryName = System.IO.Path.GetDirectoryName(location); return directoryName ?? string.Empty; } public static string GetAbsolutePath(string relativePath) { string pluginFolder = GetPluginFolder(); return System.IO.Path.Combine(pluginFolder, relativePath); } } } namespace Silksong.BingoSync.Factories { [ConditionFactory("has_completed_wish_count")] internal sealed class HasCompletedWishCountCondition : ParameterizedConditionFactory<HasCompletedWishCountCondition.Parameters> { public sealed class Parameters { [JsonProperty("amount")] [JsonRequired] [Description("Minimum number of conditions that must be met")] public uint Amount { get; init; } [JsonProperty("type")] [Description("Type of the wish to keep")] public WishType? Type { get; init; } } private static ICondition CreateCondition(Wish wish) { return (ICondition)(object)new HasCompletedWishCondition { Wish = wish }; } private static IEnumerable<Wish> GetWishes(Parameters parameters) { foreach (Wish value in Enum.GetValues(typeof(Wish))) { if (parameters.Type.HasValue) { WishType wishType = value.GetWishType(); if (parameters.Type.Value != wishType) { continue; } } yield return value; } } protected override ICondition Generate(Parameters parameters) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown List<ICondition> conditions = GetWishes(parameters).Select(CreateCondition).ToList(); SomeCondition val = new SomeCondition(); val.set_Amount(parameters.Amount); val.set_Conditions((IReadOnlyCollection<ICondition>)conditions); return (ICondition)val; } } [ConditionFactory("has_found_flea_count")] internal sealed class HasFoundFleaCountCondition : ParameterizedConditionFactory<HasFoundFleaCountCondition.Parameters> { public sealed class Parameters { [JsonProperty("amount")] [JsonRequired] [Description("Minimum number of conditions that must be met")] public uint Amount { get; init; } [JsonProperty("area")] [Description("Area of the fleas to keep")] public Area? Area { get; init; } [JsonProperty("include_unique")] [Description("Defines if the unique fleas must be included")] public bool? IncludeUnique { get; init; } } private static ICondition CreateCondition(Flea flea) { return (ICondition)(object)new HasFoundFleaCondition { Flea = flea }; } private static IEnumerable<Flea> GetFleas(Parameters parameters) { foreach (Flea value in Enum.GetValues(typeof(Flea))) { if (parameters.Area.HasValue) { Area area = value.GetArea(); if (parameters.Area.Value != area) { continue; } } if (!parameters.IncludeUnique.HasValue || !value.IsUnique() || parameters.IncludeUnique.Value) { yield return value; } } } protected override ICondition Generate(Parameters parameters) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown List<ICondition> conditions = GetFleas(parameters).Select(CreateCondition).ToList(); SomeCondition val = new SomeCondition(); val.set_Amount(parameters.Amount); val.set_Conditions((IReadOnlyCollection<ICondition>)conditions); return (ICondition)val; } } [ConditionFactory("has_obtained_tool_count")] internal sealed class HasObtainedToolCountCondition : ParameterizedConditionFactory<HasObtainedToolCountCondition.Parameters> { public sealed class Parameters { [JsonProperty("amount")] [JsonRequired] [Description("Minimum number of conditions that must be met")] public uint Amount { get; init; } [JsonProperty("type")] [Description("Type of the tool to keep")] public ToolType? Type { get; init; } } private static ICondition CreateCondition(Tool tool) { return (ICondition)(object)new HasObtainedToolCondition { Tool = tool }; } private static IEnumerable<Tool> GetTools(Parameters parameters) { foreach (Tool value in Enum.GetValues(typeof(Tool))) { if (parameters.Type.HasValue) { ToolType toolType = value.GetToolType(); if (parameters.Type.Value != toolType) { continue; } } yield return value; } } protected override ICondition Generate(Parameters parameters) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown List<ICondition> conditions = GetTools(parameters).Select(CreateCondition).ToList(); SomeCondition val = new SomeCondition(); val.set_Amount(parameters.Amount); val.set_Conditions((IReadOnlyCollection<ICondition>)conditions); return (ICondition)val; } } } namespace Silksong.BingoSync.Extensions { public static class PlayerDataExtensions { public static bool HasObtainedAncestralArt(this PlayerData data, AncestralArt art) { return art switch { AncestralArt.SwiftStep => data.hasDash, AncestralArt.ClingGrip => data.hasWalljump, AncestralArt.Needolin => data.hasNeedolin, AncestralArt.Clawline => data.hasHarpoonDash, AncestralArt.SilkSoar => data.hasSuperJump, AncestralArt.Sylphsong => data.HasSeenEvaHeal, _ => throw new InvalidCheckException<AncestralArt>(art), }; } public static bool HasObtainedMap(this PlayerData data, Area area) { return area switch { Area.TheAbyss => data.HasAbyssMap, Area.Bellhart => data.HasBellhartMap, Area.Bilewater => data.HasSwampMap, Area.BlastedSteps => data.HasJudgeStepsMap, Area.BoneBottom => data.HasMossGrottoMap, Area.TheCradle => data.HasCradleMap, Area.DeepDocks => data.HasDocksMap, Area.FarFields => data.HasWildsMap, Area.Greymoor => data.HasGreymoorMap, Area.HuntersMarch => data.HasHuntersNestMap, Area.TheMarrow => data.HasBoneforestMap, Area.TheMist => false, Area.MossGrotto => false, Area.MountFay => data.HasPeakMap, Area.PutrifiedDucts => data.HasAqueductMap, Area.RedMemory => false, Area.SandsOfKarak => data.HasCoralMap, Area.Shellwood => data.HasShellwoodMap, Area.SinnersRoad => data.HasDustpensMap, Area.TheSlab => data.HasSlabMap, Area.Underworks => data.HasCitadelUnderstoreMap, Area.Verdania => data.HasCloverMap, Area.WeavenestAtla => data.HasWeavehomeMap, Area.WispThicket => false, Area.Wormways => data.HasCrawlMap, Area.ChoralChambers => data.HasHallsMap, Area.CogworkCore => data.HasCogMap, Area.GrandGate => data.HasSongGateMap, Area.HighHalls => data.HasHangMap, Area.Memorium => data.HasArboriumMap, Area.WhisperingVaults => data.HasLibraryMap, Area.Whiteward => data.HasWardMap, _ => throw new InvalidCheckException<Area>(area), }; } public static bool HasKilledBoss(this PlayerData data, Boss boss) { return boss switch { Boss.BellBeast => data.defeatedBellBeast, Boss.FourthChorus => data.defeatedSongGolem, Boss.GreatConchflies => data.defeatedCoralDrillers, Boss.Lace1 => data.defeatedLace1, Boss.LastJudge => data.defeatedLastJudge, Boss.Moorwing => data.defeatedVampireGnatBoss, Boss.MossMother => data.defeatedMossMother, Boss.MossMothers => data.HasJournalEntry(Boss.MossMothers), Boss.Phantom => data.defeatedPhantom, Boss.SavageBeastfly1 => data.defeatedBoneFlyerGiant, Boss.SisterSplinter => data.defeatedSplinterQueen, Boss.SkullTyrant1 => data.skullKingDefeated, Boss.SkullTyrant2 => data.HasJournalEntry(Boss.SkullTyrant2), Boss.Widow => data.spinnerDefeated, Boss.Broodmother => data.defeatedBroodMother, Boss.CogworkDancers => data.defeatedCogworkDancers, Boss.DisgracedChefLugoli => data.defeatedRoachkeeperChef, Boss.FatherOfTheFlame => data.defeatedWispPyreEffigy, Boss.FirstSinner => data.defeatedFirstWeaver, Boss.Forebrothers => data.defeatedDockForemen, Boss.Garmond => data.HasJournalEntry(Boss.Garmond), Boss.GrandMotherSilk => data.HasCompletedEnding(Ending.WeaverQueen) || data.HasCompletedEnding(Ending.SnaredSilk) || data.HasCompletedEnding(Ending.TwistedChild), Boss.Groal => data.DefeatedSwampShaman, Boss.Lace2 => data.defeatedLaceTower, Boss.RagingConchfly => data.defeatedCoralDrillerSolo, Boss.SavageBeastfly2 => data.defeatedBoneFlyerGiantGolemScene, Boss.SecondSentinel => data.defeatedSongChevalierBoss, Boss.Shakra => data.HasJournalEntry(Boss.Shakra), Boss.TheUnravelled => data.wardBossDefeated, Boss.Trobbio => data.defeatedTrobbio, Boss.Voltvyrm => data.defeatedZapCoreEnemy, Boss.BellEater => data.HasJournalEntry(Boss.BellEater), Boss.CloverDancers => data.defeatedCloverDancers, Boss.Crawfather => data.defeatedCrowCourt, Boss.CrustKingKhann => data.defeatedCoralKing, Boss.GurrTheOutcast => data.defeatedAntTrapper, Boss.LostGarmond => data.garmondBlackThreadDefeated, Boss.LostLace => data.HasCompletedEnding(Ending.SisterOfTheVoid), Boss.Nyleth => data.defeatedFlowerQueen, Boss.Palestag => data.defeatedWhiteCloverstag, Boss.Pinstress => data.HasJournalEntry(Boss.Pinstress), Boss.PlasmifiedZango => data.BlueScientistDead, Boss.ShrineGuardianSeth => data.defeatedSeth, Boss.SkarrsingerKarmelita => data.defeatedAntQueen, Boss.TormentedTrobbio => data.defeatedTormentedTrobbio, Boss.Watcher => data.defeatedGreyWarrior, _ => throw new InvalidCheckException<Boss>(boss), }; } private static string GetCrestId(Crest crest) { return crest switch { Crest.Hunter => "Hunter", Crest.HunterEvolved => "Hunter_v2", Crest.HunterFullyEvolved => "Hunter_v3", Crest.Reaper => "Reaper", Crest.Wanderer => "Wanderer", Crest.Beast => "Warrior", Crest.Cursed => "Cursed", Crest.Witch => "Witch", Crest.Architect => "Toolmaster", Crest.Shaman => "Spell", Crest.Cloakless => "Cloakless", _ => throw new InvalidCheckException<Crest>(crest), }; } private static Data? GetCrestData(this PlayerData data, Crest crest) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) string crestId = GetCrestId(crest); return ((SerializableNamedList<Data, NamedData>)(object)data.ToolEquips).GetData(crestId); } public static bool HasObtainedCrest(this PlayerData data, Crest crest) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) Data? crestData = data.GetCrestData(crest); if (!crestData.HasValue) { return false; } return crestData.Value.IsUnlocked; } public static bool HasCompletedEnding(this PlayerData data, Ending ending) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0068: Unknown result type (might be due to invalid IL or missing references) return ending switch { Ending.WeaverQueen => ((Enum)data.CompletedEndings).HasFlag((Enum)(object)(CompletionState)1), Ending.SnaredSilk => ((Enum)data.CompletedEndings).HasFlag((Enum)(object)(CompletionState)4), Ending.TwistedChild => ((Enum)data.CompletedEndings).HasFlag((Enum)(object)(CompletionState)2), Ending.SisterOfTheVoid => ((Enum)data.CompletedEndings).HasFlag((Enum)(object)(CompletionState)8), Ending.PassingOfTheAge => data.MushroomQuestCompleted, _ => throw new InvalidCheckException<Ending>(ending), }; } public static bool HasFoundFlea(this PlayerData data, Flea flea) { return flea switch { Flea.AboveMarrowBellways => data.SavedFlea_Bone_06, Flea.BehindDeepDocksBellways => data.SavedFlea_Dock_16, Flea.LeftOfSwiftStep => data.SavedFlea_Bone_East_05, Flea.BehindDeepDocksFurnaceGauntlet => data.SavedFlea_Dock_03d, Flea.BehindSkarrgard => data.SavedFlea_Ant_03, Flea.BehindHunterBoobyTrap => data.SavedFlea_Bone_East_17b, Flea.NextToPilgrimsRest => data.SavedFlea_Bone_East_10_Church, Flea.CarriedByAknid => data.SavedFlea_Crawl_06, Flea.AboveCrawLake => data.SavedFlea_Greymoor_15b, Flea.TopOfGreymoorLeftTower => data.SavedFlea_Greymoor_06, Flea.Kratt => data.CaravanLechSaved, Flea.AboveBellhart => data.SavedFlea_Belltown_04, Flea.InGahliaPit => data.SavedFlea_Shellwood_03, Flea.AboveGrindle => data.SavedFlea_Coral_35, Flea.TrappedInSinnersRoad => data.SavedFlea_Dust_12, Flea.GuardedBySnitchflies => data.SavedFlea_Shadow_28, Flea.BesideExhaustOrgan => data.SavedFlea_Dust_09, Flea.AboveSecretBilewaterBench => data.SavedFlea_Shadow_10, Flea.AfterWispThicket => data.SavedFlea_Under_23, Flea.AcrossCogworkHaulersRoom => data.SavedFlea_Under_21, Flea.AfterChoralChambersPlatforming => data.SavedFlea_Song_14, Flea.AfterVerticalSawbladesRoom => data.SavedFlea_Song_11, Flea.HugeFlea => data.tamedGiantFlea, Flea.JailedInSlab => data.SavedFlea_Slab_Cell, Flea.AboveSlabBench => data.SavedFlea_Slab_06, Flea.FrozenInIce => data.SavedFlea_Peak_05c, Flea.UnderVoltnest => data.SavedFlea_Coral_24, Flea.Vog => data.MetTroupeHunterWild, Flea.RightOfSongclave => data.SavedFlea_Library_09, Flea.RightOfBoxPuzzle => data.SavedFlea_Library_01, _ => throw new InvalidCheckException<Flea>(flea), }; } public static Area GetArea(this Flea flea) { return flea switch { Flea.AboveMarrowBellways => Area.TheMarrow, Flea.BehindDeepDocksBellways => Area.DeepDocks, Flea.LeftOfSwiftStep => Area.DeepDocks, Flea.BehindDeepDocksFurnaceGauntlet => Area.DeepDocks, Flea.BehindSkarrgard => Area.HuntersMarch, Flea.BehindHunterBoobyTrap => Area.FarFields