using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using InControl; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using Steamworks; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.Rendering.PostProcessing; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("PhotonRealtime")] [assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")] [assembly: AssemblyCompany("CompetitiveRounds")] [assembly: AssemblyConfiguration("Thunderstore")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+297d79046324c6db5231e1bf5776ee47a55497ba")] [assembly: AssemblyProduct("CompetitiveRounds")] [assembly: AssemblyTitle("CompetitiveRounds")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CompetitiveRounds { public static class ApiClient { public class RecentSeriesEntry { public string winner_name; public string p1_name; public string p2_name; public int p1_wins; public int p2_wins; public int p1_rating; public int p2_rating; public float p1_rating_change; public float p2_rating_change; public string winner_steam_id; public string p1_steam_id; public string p2_steam_id; public string completed_at; public List bets = new List(); } public class SeriesBetEntry { public string bettor_name; public string bet_on_name; public string bettor_steam_id; public string bet_on_steam_id; public int amount; public int payout; public float odds_multiplier; public bool won; } [Serializable] public class MatchResponse { public string match_id; public string winner_steam_id; public string message; } [Serializable] public class LeaderboardData { public LeaderboardEntry[] entries; public int total_players; } [Serializable] public class LeaderboardEntry { public int rank; public string steam_id; public string display_name; public int rating; public int rd; public int total_matches; public int wins; public int losses; public float win_rate; public int level; public int gold; public string title; public string title_color; public string rank_name; public string rank_color; } [Serializable] public class PlayerStatsData { public string steam_id; public string display_name; public float rating; public float rating_deviation; public float peak_rating; public int total_matches; public int wins; public int losses; public float win_rate; public bool ranked_enabled; public int level; public int total_xp; public int xp_into_level; public int xp_for_next_level; public int best_ranked_streak; public int best_casual_streak; public int lfp_seconds_left; public int best_ranked_game_streak; public int current_ranked_game_streak; public int best_ranked_series_streak; public int current_ranked_series_streak; public int ranked_series_wins; public int ranked_series_losses; public int ranked_dc_count; public string discord_id; public string discord_username; public int gold_earned; public int gold_spent; public long bullets_fired; public long bullets_hit; public long blocks_activated; public long blocks_successful; public string active_title; public string active_title_color; public string active_title_sku; public string active_trail_sku; public string active_trail_color; public int active_trail_price; public string active_color_sku; public List active_color_skus; public string active_player_color_sku; public string active_player_color_hex; public string active_player_color_name; public string active_cursor_color_sku; public string active_cursor_color_hex; public string active_player_effect_sku; public bool hide_gold; public bool appear_offline; public string discord_display_name; public bool show_discord; public List active_nametag_skus; public List top_card_names; public List top_card_picks; public List top_card_win_rates; public List recent_form; public List rating_history; public List rating_history_times; public int avg_fps; public float avg_cards_per_game; public int achievements_unlocked; public List worst_card_names; public List worst_card_picks; public List worst_card_win_rates; public List region_names; public List region_matches; public string mod_version; public int h2h_ranked_wins; public int h2h_ranked_losses; public int h2h_casual_wins; public int h2h_casual_losses; public int h2h_series_wins; public int h2h_series_losses; public float avg_keys_per_sec; public int avg_keys_per_game; public int avg_game_seconds; public int bets_won; public int bets_lost; public int bet_gold_net; public int sweeps_given; public int sweeps_taken; public int casual_wins; public int casual_losses; public string rank_name; public string rank_color; public float team_rating; public int team_completed_series; public int ovt_solo_wins; public int ovt_solo_losses; public int ovt_duo_wins; public int ovt_duo_losses; public int ffa_games; public int ffa_wins; public int ffa_top3; public float ffa_avg_placement; public float ffa_avg_kills; public float ffa_avg_damage; public int ffa_damage_games; } [Serializable] public class CardStatData { public string card_name; public string card_rarity; public int times_picked; public int wins_with_card; public float win_rate; public int times_offered; public float pass_rate; } [Serializable] private class CardStatsWrapper { public CardStatData[] items; } [Serializable] public class ModCheckResponse { public bool registered; public bool ranked; public string display_name; public bool banned; public string ban_reason; } [Serializable] public class MatchHistoryEntry { public string match_id; public string opponent_steam_id; public string opponent_name; public string opponent_title; public string opponent_title_color; public int player_rounds_won; public int opponent_rounds_won; public int player_points; public int opponent_points; public bool won; public bool is_ranked; public string ended_at; public string cards_display; public string opp_cards_display; public string series_id; public string series_score; public float series_rating_change; public int xp_gained; public int gold_gained; public int series_gold_gained; public int player_fps_avg; public int opponent_fps_avg; public int player_bullets_fired; public int player_bullets_hit; public int player_blocks_activated; public int player_blocks_successful; public int player_keys_pressed; public float player_active_seconds; public int opp_bullets_fired; public int opp_bullets_hit; public int opp_blocks_activated; public int opp_blocks_successful; public int opp_keys_pressed; public float opp_active_seconds; public string player_fps_timeline; public string opp_fps_timeline; public int player_ping_avg; public int opponent_ping_avg; public string player_ping_timeline; public string opp_ping_timeline; public string player_hit_timeline; public string opp_hit_timeline; public string player_block_timeline; public string opp_block_timeline; public string point_times; public string point_timeline; public int duration_seconds; } [Serializable] private class MatchHistoryWrapper { public MatchHistoryEntry[] items; } [Serializable] public class AchievementData { public string achievement_key; public bool unlocked; public string unlocked_at; public float global_pct; public int gold; } private class PendingReport { public string url; public string json; public int attempts; public float nextAt; } [Serializable] public class ActiveSeriesEntry { public string series_id; public string p1_steam_id; public string p1_name; public int p1_rating; public int p1_wins; public float p1_odds; public string p2_steam_id; public string p2_name; public int p2_rating; public int p2_wins; public float p2_odds; public int live_p1_points; public int live_p2_points; public bool bets_locked; public string lock_reason; public bool is_private; public bool is_tournament; public string tournament_kind; public string phase; } public class MyBetEntry { public string series_id; public string bet_on_steam_id; public string bet_on_name; public string series_status; public string series_score; public int amount; public float odds_multiplier; public bool settled; public int payout; public string vs_name; public string created_at; } public class RankTierEntry { public float floor; public string name; public string color; } public class MultimodeSeriesEntry { public string mode; public string id; public string ended_at; public string left_label; public string right_label; public string score; public float left_rating_change; public float right_rating_change; public List bets = new List(); } public class MultimodeBet { public string bettor_name; public string bettor_steam_id; public string bet_on_label; public int amount; public int payout; public float odds_multiplier; public string state; } [Serializable] public class ActiveTeamSeriesEntry { public string series_id; public string t1a_steam; public string t1a_name; public string t1b_steam; public string t1b_name; public string t2a_steam; public string t2a_name; public string t2b_steam; public string t2b_name; public int t1_rating; public int t2_rating; public int t1a_rating; public int t1b_rating; public int t2a_rating; public int t2b_rating; public int t1_wins; public int t2_wins; public float t1_odds; public float t2_odds; public bool bets_locked; public string lock_reason; public string started_at; public string dc_grace_until; } [Serializable] public class ShopItemData { public long id; public string sku; public string kind; public string name; public string description; public int price; public string rarity; public string preview_color; public bool owned; public string artist_steam_id; public string artist_name; public int stock_limit; public int stock_sold; } public class FlaggedMatchEntry { public string id; public string match_id; public string game_code; public string series_id; public string flag_reason; public string p1_name; public string p2_name; public string p1_steam_id; public string p2_steam_id; public string suspect_steam_text; public List player_steam_ids = new List(); public bool auto_invalidated; public bool match_invalidated; public bool is_ranked; public bool restoration_required; public int duration_seconds; public int discord_evidence_revision; public string duration_text; public string review_action; public string match_invalidation_reason; public string created_at; public string score_summary; public string cards_summary; public string point_progress; public string evidence_summary; public string telemetry_summary; public string connection_summary; public string match_context; } public class BannedUserEntry { public string id; public string steam_id; public string display_name; public string reason; public string banned_by_steam_id; public string banned_at; } public class QuarantineReportEntry { public string id; public string mode; public string reason; public string created_at; public string score; public string room; public string status; public int http_status; public List player_names = new List(); public bool can_accept; public string accept_blocked_reason; } public class ArtistItemEntry { public string sku; public string kind; public string name; public string rarity; public string description; public int price; public int stock_limit; public int sold; public int gifted; public bool catalog_ready; public int earned; } public class ArtistBlockEntry { public string steam_id; public string display_name; } public class ArtistSaleEntry { public string item; public string buyer; public string when; public int price; public int earned; } public class PlayerSearchResult { public string steam_id; public string display_name; public int rating; } public class CosmeticSubmission { public int id; public float render_scale = 1f; public float render_offset_x; public float render_offset_y; public int placement_revision = 1; public string placement_status; public string placement_review_note; public string review_kind; public float approved_render_scale; public float approved_render_offset_x; public float approved_render_offset_y; public int approved_placement_revision; public int published_placement_revision; public string name; public string slot; public string status; public string review_note; public string shop_sku; public string created_at; public string artist_name; public string artist_steam_id; public string png_base64; } public class CosmeticReleaseCandidate { public int id; public int placement_revision; public int published_placement_revision; public int png_bytes; public string shop_sku; public string name; public string slot; public string artist_name; public string artist_steam_id; public string approved_at; public float render_scale; public float render_offset_x; public float render_offset_y; public bool catalog_ready; } public class AdminSeriesEntry { public string ladder; public string series_id; public string status; public string created_at; public string completed_at; public string score; public int series_number; public int winner_team; public int num_players; public bool incomplete; public string dc_name; public string dc_steam; public string p1_name; public string p1_steam; public string p1_cards; public int p1_team; public string p2_name; public string p2_steam; public string p2_cards; public int p2_team; public string p3_name; public string p3_steam; public string p3_cards; public int p3_team; public string p4_name; public string p4_steam; public string p4_cards; public int p4_team; } [Serializable] public class BugReportSummary { public string id; public int bug_number; public string created_at; public string steam_id; public string display_name; public string mod_version; public string severity; public string category; public string status; public string description; public bool has_log; public int log_bytes; } [Serializable] public class BugReportEventEntry { public string id; public string actor_steam_id; public string actor_name; public string event_type; public string old_status; public string new_status; public string comment; public string created_at; } [Serializable] public class BugReportDetail { public string id; public int bug_number; public string steam_id; public string display_name; public string mod_version; public string game_version; public string severity; public string category; public string description; public string repro_steps; public string status; public string triage_notes; public string created_at; public string log_text; public int log_bytes; public List events = new List(); } public enum QueueState { Idle, Searching, Matched, ReadySent, Leaving } [Serializable] public class QueuePollData { public string status; public int wait_time; public int queue_size; public int elo_range; public string opponent_steam_id; public string opponent_name; public float opponent_rating; public bool opponent_ready; public string room_name; public string photon_region; } public class OnlinePlayerEntry { public string name; public int rating; public int minutesAgo; public string title; public string titleColor; } public class NewestCosmeticEntry { public string sku; public string kind; public string name; public string rarity; public int price; public string previewColor; public string artistName; public string added; public bool onSale; } public class ReleaseNoteEntry { public string tag; public string title; public string date; public string body; } public enum TeamQueueState { Idle, Searching, Matched, ReadySent, Leaving } [Serializable] public class TeamQueueMember { public string steam_id; public string display_name; public int rating; public string region; public int team_assigned; public bool using_fallback_rating; public int balance_rating; public int completed_series; public bool ready; } [Serializable] public class TeamQueuePollData { public string status; public int queue_count; public int elo_range; public string series_id; public int team_assigned; public List teammates = new List(); public List opponents = new List(); public string room_name; public string room_region; public int match_age_seconds; public bool my_ready; } [Serializable] public class TeamQueueListEntry { public string steam_id; public string display_name; public int rating; public int balance_rating; public bool using_fallback_rating; public int completed_series; public string region; public string status; public int team_assigned; public string series_id; public int wait_seconds; public bool manual_pick_enabled; public int preferred_team; public string queue_type; } public class TeamTelemetry { public string fpsTimeline; public string pingTimeline; public string hitTimeline; public string blockTimeline; public int pingAvg; public int bulletsFired; public int bulletsHit; public int blocksActivated; public int blocksSuccessful; public int keysPressed; public float activeSeconds; } [Serializable] public class TeamLeaderboardEntry { public int rank; public string steam_id; public string display_name; public int rating; public int rd; public int completed_series; public int series_wins; public int series_losses; public float win_rate; public int level; public string title; public string title_color; public int avg_teammate_elo; public int team_gold_earned; public int team_xp_earned; } [Serializable] public class TeamSeriesSlot { public string steam_id; public string name; public string title; public string title_color; public int rating; public float rating_change; public int gold_earned; public int xp_earned; } [Serializable] public class TeamPlayerTele { public string fps_timeline; public string ping_timeline; public string hit_timeline; public string block_timeline; public int ping_avg; public int bullets_fired; public int bullets_hit; public int blocks_activated; public int blocks_successful; } [Serializable] public class TeamSeriesMatch { public string match_id; public string ended_at; public int t1_rounds_won; public int t2_rounds_won; public int t1_points_total; public int t2_points_total; public int duration_seconds; public Dictionary fps_by_player = new Dictionary(); public Dictionary telemetry_by_player = new Dictionary(); public Dictionary> cards_by_player = new Dictionary>(); } [Serializable] public class TeamSeriesPagedEntry { public string series_id; public string completed_at; public int winner_team; public int t1_series_wins; public int t2_series_wins; public TeamSeriesSlot t1a; public TeamSeriesSlot t1b; public TeamSeriesSlot t2a; public TeamSeriesSlot t2b; public List matches = new List(); } public class TeamMatchHistoryEntry { public string match_id; public string series_id; public string ended_at; public bool won; public int my_team; public string t1a_steam_id; public string t1a_name; public string t1b_steam_id; public string t1b_name; public string t2a_steam_id; public string t2a_name; public string t2b_steam_id; public string t2b_name; public int t1_rounds_won; public int t2_rounds_won; public int t1_points_total; public int t2_points_total; public string series_score; public float series_rating_change; public Dictionary fps_by_player = new Dictionary(); public Dictionary> cards_by_player = new Dictionary>(); } [Serializable] public class TeamStatsData { public string steam_id; public string display_name; public float rating; public float rating_deviation; public float peak_rating; public int completed_series; public int series_wins; public int series_losses; public float series_win_rate; public int match_wins; public int match_losses; public int current_streak; } public class OvtLeaderboardEntry { public int rank; public string steam_id; public string display_name; public int games_played; public int wins; public int losses; public int solo_games; public int duo_games; public int level; public int solo_wins; public int solo_losses; public int duo_wins; public int duo_losses; public float win_rate; public string title; public string title_color; public string last_played; } public class OvtQueueListEntry { public string steam_id; public string display_name; public string status; public string region; public int rating_1v1; public int rating_2v2; public int preferred_side; public int side_assigned; public int wait_seconds; public bool solo_extra_pick; } public class OvtRecentMatch { public string match_id; public string ended_at; public int winner_side; public int solo_rounds; public int duo_rounds; public int solo_points; public int duo_points; public int duration_seconds; public Dictionary fps_by_steam = new Dictionary(); public Dictionary> cards_by_steam = new Dictionary>(); } public class OvtRecentSeries { public string series_id; public string status; public string created_at; public string completed_at; public int winner_side; public int solo_wins; public int duo_wins; public bool solo_extra_pick; public string solo_steam; public string solo_name; public string duo_a_steam; public string duo_a_name; public string duo_b_steam; public string duo_b_name; public Dictionary gold_by_steam = new Dictionary(); public Dictionary xp_by_steam = new Dictionary(); public List matches = new List(); } public class FfaLeaderboardEntry { public int rank; public int rating; public int rd; public int games_played; public int wins; public int top3; public int level; public string steam_id; public string display_name; public string title; public string title_color; public float avg_placement; public float win_rate; public int ffa_gold_earned; public int ffa_xp_earned; } public class FfaRecentPlayer { public string steam_id; public string display_name; public string title; public string title_color; public int slot; public int placement; public int rounds_won; public int points_total; public int kills; public int fps_avg; public int xp_gained; public int gold_gained; public bool left_early; public float rating_change; public bool has_rating_change; public List cards = new List(); } public class FfaRecentCard { public string name; public bool rolled; } public class FfaRecentMatch { public string match_id; public string photon_room_id; public string ended_at; public string winner_steam_id; public string timeline; public int player_count; public int duration_seconds; public bool is_ranked; public List players = new List(); } public class PlayerTeamHistoryEntry { public string series_id; public string score; public string mate; public string completed_at; public bool won; public bool has_rating_change; public float rating_change; public List opponents = new List(); } public class PlayerOvtHistoryEntry { public string match_id; public string role; public string score; public string solo; public string ended_at; public bool won; public List duo = new List(); public int gold_gained; public int series_gold_gained; } public class PlayerFfaHistoryEntry { public string match_id; public string ended_at; public int player_count; public int placement; public int kills; public int rounds_won; public int points_total; public bool has_rating_change; public float rating_change; public List participants = new List(); } public class FfaBettablePlayer { public string steam_id; public string display_name; public int rating; public float odds_multiplier; public bool bettable; } public class FfaBettableLobby { public string lobby_id; public int player_count; public int game_number; public bool is_member; public bool already_bet; public bool bets_open; public List players = new List(); } public class FfaLobbyMemberEntry { public string steam_id; public string display_name; public int rating; public int rating_1v1; public int wait_seconds; public bool is_host; } public class FfaOpenLobbyEntry { public string lobby_id; public string host_name; public int player_count; public int max_players; public int age_seconds; } public class FfaQueueListEntry { public string steam_id; public string display_name; public string status; public string region; public int rating; public int rating_1v1; public int slot; public int wait_seconds; } public class FfaReportPlayer { public string steamId; public string displayName; public int slot; public int rounds; public int points; public int kills; public int fps; public bool leftEarly; public bool absent; public List cards; public TeamTelemetry telemetry; public int damageDealt; public string killTimeline; public string damageTimeline; } public class AchEarnerData { public string display_name; public int rating; public string unlocked_at; public string title; public string title_color; } [Serializable] public class TournamentSnapshot { public string tournament_id; public string status; public string kind; public string default_start_ts; public string scheduled_start_ts; public string lock_at; public string started_at; public string ended_at; public int min_players; public int max_players; public int prize_players; public int prize_gold_1; public int prize_gold_2; public int prize_gold_3; public int prize_xp_1; public int prize_xp_2; public int prize_xp_3; public string my_signup_id; public bool my_ready; public float my_penalty_pct; public bool my_discord_linked; public int force_vote_count; public string photon_region; public string[] my_votes; public string[] time_slot_options; public TimeVoteTally[] time_slot_tallies; public TournamentSignupRow[] signups; public TournamentMatchRow[] matches; } [Serializable] public class TimeVoteTally { public string slot_ts; public int votes; } [Serializable] public class TournamentSignupRow { public string signup_id; public string steam_id; public string display_name; public bool is_speculative; public int seed; public float penalty_at_signup; public bool ready; public bool forfeited; public int placed_rank; public string progress_label; } [Serializable] public class TournamentMatchRow { public string match_id; public int round; public string bracket_side; public int slot_idx; public string p1_signup_id; public string p2_signup_id; public string p1_display_name; public string p2_display_name; public bool is_bye; public string status; public string series_id; public string winner_signup_id; public int p1_series_wins; public int p2_series_wins; public string deadline_at; public string[] prereq_match_ids; public string photon_room_name; } [Serializable] public class PlayerTournamentHistory { public string steam_id; public int winner_count; public int runner_up_count; public int third_place_count; public int participant_count; public PlayerTournamentEntry[] recent; } [Serializable] public class PlayerTournamentEntry { public string tournament_id; public string ended_at; public int placed_rank; public string kind; public int signup_count; public string winner_display_name; } [Serializable] public class ActiveTournamentMatch { public string tournament_id; public string kind; public string match_id; public string status; public string bracket_side; public int round; public string opponent_steam_id; public string opponent_display_name; public string photon_room_name; public string photon_region; public bool my_ready; public bool opp_ready; public int ready_seconds_left; public int scheduled_seconds_left; public bool my_early_ok; public bool opp_early_ok; public float fetched_at_realtime; } private static string baseUrl = ""; private static float lastFetchTime = 0f; private static float fetchCooldown = 5f; public static readonly Dictionary AchievementDefs = new Dictionary { { "untouchable", new string[2] { "Untouchable", "Win a game without taking any damage" } }, { "silent_assassin", new string[2] { "Silent Assassin", "5-0 someone with Sneaky" } }, { "total_mayhem", new string[2] { "Total Mayhem", "5-0 someone with Mayhem" } }, { "fragile_perfection", new string[2] { "Fragile Perfection", "5-0 someone with Glass Cannon" } }, { "no_escape", new string[2] { "No Escape", "5-0 someone with Chase" } }, { "rise_from_the_ashes", new string[2] { "Rise from the Ashes", "Win 5-0 with Phoenix without losing a life" } }, { "the_comeback_kid", new string[2] { "The Comeback Kid", "Win after being down 0-4" } }, { "stacked_deck", new string[2] { "Stacked Deck", "Get 5 copies of one card in a game" } }, { "regicide", new string[2] { "Sid Slayer", "Win against Sid in a ranked series" } }, { "stan_slayer", new string[2] { "Stan Slayer", "Win against Stan in a ranked series" } }, { "pacifist", new string[2] { "Pacifist", "Win a game without firing a single shot" } }, { "immovable_object", new string[2] { "Immovable Object", "Win a game without moving or jumping" } }, { "master_rank", new string[2] { "Master", "Reach 1980 rating in ranked (1v1 or 2v2)" } }, { "team_sweep", new string[2] { "Tag Team Sweep", "Win a 2v2 game 5-0" } }, { "grand_master", new string[2] { "Grand Master", "Reach 2330 rating in ranked (1v1 or 2v2)" } }, { "flawless", new string[2] { "Flawless", "Win five games 5-0 in a row" } }, { "bullet_hell", new string[2] { "Bullet Hell", "Win a game 5-0 with Barrage in your build" } }, { "spray_and_pray", new string[2] { "Spray and Pray", "Win a game 5-0 with Spray in your build" } }, { "demolitionist", new string[2] { "Demolitionist", "Win a game 5-0 with Explosive Bullet in your build" } }, { "controlled_burst", new string[2] { "Controlled Burst", "Win a game 5-0 with Burst in your build" } }, { "field_medic", new string[2] { "Field Medic", "Win a game 5-0 with Healing Field in your build" } }, { "god_build", new string[2] { "God Build", "Win with Shields Up, exactly 1 ammo, and a lightning-fast reload" } }, { "double_nova", new string[2] { "Double Nova", "Win with two or more Supernovas" } }, { "lumberjack", new string[2] { "Lumberjack", "Win with two or more Saws" } }, { "pristine_perfection", new string[2] { "Pristine Perfection", "Win with two or more Pristines" } }, { "silent_drill", new string[2] { "Silly Drill", "Win with Sneaky and Drill together" } }, { "double_glass", new string[2] { "Living on the Edge", "Win with two Glass Cannons in your build" } }, { "sustained_power", new string[2] { "Sustained Power", "Win with Empower and Healing Field together" } }, { "deep_end", new string[2] { "Into the Deep End", "Win with Abyssal Countdown as your FIRST pick, activating it every round" } }, { "clutch", new string[2] { "Clutch", "Win a game after being down 0-3" } }, { "collector", new string[2] { "Collector", "Win with four copies of the same card" } }, { "grounded", new string[2] { "Grounded", "Win a game without ever jumping" } }, { "instinct", new string[2] { "Instinct", "Win taking only the left-most card on every pick, without ever looking at the others" } }, { "rising_star", new string[2] { "Rising Star", "Reach 1700 rating in ranked (1v1 or 2v2)" } }, { "on_fire", new string[2] { "On Fire", "Win 25 ranked series in a row" } }, { "unstoppable", new string[2] { "Unstoppable", "Win 50 ranked series in a row" } }, { "immortal", new string[2] { "Immortal", "Win 100 ranked series in a row" } }, { "casual_century", new string[2] { "Century Club", "Win 100 casual games in a row" } }, { "casual_conqueror", new string[2] { "Casual Conqueror", "Win 200 casual games in a row" } }, { "touch_grass", new string[2] { "Touch Grass", "Win 500 casual games in a row" } }, { "twins", new string[2] { "Twins!", "Finish a game with the exact same 5 cards (and copies) as your opponent" } } }; private static readonly List _pendingReports = new List(); private static bool _outboxLoopStarted; private const int OUTBOX_MAX_ATTEMPTS = 20; private const float OUTBOX_RETRY_SECONDS = 60f; private static readonly HashSet _heartbeatDispatchedMatches = new HashSet(); private static readonly Dictionary _heartbeatDispatchTime = new Dictionary(); private static int _hbTournamentCurrentTick; private const string GITHUB_API_LATEST = "https://api.github.com/repos/SidNDeed/SidsCompetitiveRounds/releases/latest"; private static readonly byte[] _hkE = new byte[48] { 226, 96, 125, 70, 209, 29, 174, 212, 243, 51, 60, 47, 71, 237, 154, 50, 215, 106, 11, 24, 165, 4, 227, 236, 220, 80, 34, 24, 21, 166, 231, 46, 216, 70, 3, 51, 167, 90, 209, 209, 253, 120, 28, 58, 2, 144, 239, 45 }; private static readonly byte[] _hkX = new byte[16] { 178, 25, 79, 119, 230, 111, 150, 181, 186, 10, 106, 95, 119, 223, 174, 75 }; private static bool _adminSecretWarned = false; public static List CachedRankTiers = null; private static bool _rankTiersInFlight; private static float _rankTiersAt = -99999f; private const float RANK_TIERS_TTL = 420f; public static List CachedRecentMultimode = null; private static bool _multimodeInFlight; private static string _lastPublishedCosmeticSig; private static string selectedAchSteamId = ""; public static readonly Dictionary> CompareAchievements = new Dictionary>(); public static readonly Dictionary AchievementDisplayNames = new Dictionary(); private static readonly HashSet _compareAchFetching = new HashSet(); public const int HISTORY_CHUNK = 400; public static bool MatchHistoryLoadedAll; private static bool _historyFetchInFlight; public static int HistoryTotalMatches = -1; public static int HistoryTotalRankedGroups = -1; public static int HistoryTotalCasual = -1; public static readonly Dictionary CachedOppLifetime = new Dictionary(); private static readonly HashSet _oppLifetimeRequested = new HashSet(); private static readonly Dictionary _oppLifetimeRefetchAfter = new Dictionary(); public static string ActiveRankedSeriesId; private static float queuePollTimer = 0f; private static float queuePollInterval = 3f; private const float LEAVE_STUCK_TIMEOUT = 45f; private static float rankedLeavingSince = -999f; private static int queueGen = 0; private static float _ffaRoomlessSince = -1f; private const string ESCAPE_PREF = "cr_escape_pending"; private static float _escapeRetryAt = -999f; private static float queueCountTimer = 0f; private static float queueCountInterval = 10f; public static List CachedOnlinePlayers; public static List CachedRecentPlayers; public static int CachedOnlineListCount; public static List CachedNewestCosmetics; public static List CachedReleaseNotes; private static bool _releasesFetchInFlight; private const string GITHUB_API_RELEASES = "https://api.github.com/repos/SidNDeed/SidsCompetitiveRounds/releases?per_page=3"; private static float teamQueueListTimer = 0f; private const float TEAM_QUEUE_LIST_INTERVAL = 2f; private static float teamLeavingSince = -999f; private static int teamGen = 0; private static float teamQueuePollTimer = 0f; private static float teamQueueCountTimer = 0f; private const float TEAM_QUEUE_POLL_INTERVAL = 3f; private const float TEAM_QUEUE_COUNT_INTERVAL = 10f; public static string LastSeriesStateStatus = null; public static string LastSeriesStateReason = null; public static int LastSeriesStateConfirmations = 0; public static int LastSeriesDcGraceSeconds = 0; public static int LastSeriesDcTeamRemaining = 0; public static int LastSeriesT1Wins = 0; public static int LastSeriesT2Wins = 0; private static float teamSeriesStateTimer = 0f; private const float TEAM_SERIES_STATE_INTERVAL = 2f; public static List CachedOvtLeaderboard = null; public static int CachedOvtLeaderboardTotal = 0; public static List CachedOvtLeaderboardSolo = null; public static List CachedOvtLeaderboardDuo = null; public static string OvtQueueStatus = ""; public static int OvtQueueCount = 0; public static string ActiveOvt1v2SeriesId = null; public static int OvtMySide = 0; public static bool OvtSoloExtraPick = false; public static bool IsOvtQueuePolling = false; private static float _ovtLastPollAt = -999f; public static string OvtLockedSoloName = null; public static List OvtLockedDuo = null; public static List CachedOvtQueueList = null; private static float _ovtListLastAt = -999f; private static int _ovtLastPreferredSide = 0; private static bool _ovtLastSoloExtraPick = false; private static float _ovtLastAutoRejoinAt = -999f; private static float _ovtLeavingSince = -999f; private static int ovtGen = 0; public static List CachedOvtRecent = null; public static int CachedOvtRecentTotal = 0; public static int CachedOvtRecentPages = 0; public static List CachedFfaLeaderboard = null; public static int CachedFfaLeaderboardTotal = 0; public static List CachedFfaRecent = null; public static int CachedFfaRecentTotal = 0; public static int CachedFfaRecentPages = 0; public static readonly Dictionary> CachedPlayerTeamHistory = new Dictionary>(); public static readonly Dictionary> CachedPlayerOvtHistory = new Dictionary>(); public static readonly Dictionary> CachedPlayerFfaHistory = new Dictionary>(); private static readonly HashSet _playerTeamHistoryInFlight = new HashSet(); private static readonly HashSet _playerOvtHistoryInFlight = new HashSet(); private static readonly HashSet _playerFfaHistoryInFlight = new HashSet(); public static List CachedFfaBettable = null; private static bool _ffaBettableInFlight; public static string FfaQueueStatus = ""; public static int FfaQueueCount = 0; public static int FfaGatherSecondsLeft = -1; public static string ActiveFfaLobbyId = null; public static int FfaMySlot = -1; public static int FfaLobbyPlayerCount = 0; public static bool IsFfaQueuePolling = false; public static List FfaLockedRoster = null; private static float _ffaLastPollAt = -999f; public static string OpenFfaLobbyId = null; public static bool FfaLobbyIsHost = false; public static bool FfaLobbyCanStart = false; public static int FfaLobbyMemberCount = 0; public static int FfaLobbyMinPlayers = 3; public static int FfaLobbyMaxPlayers = 10; public static List FfaLobbyMembers = null; public static List CachedFfaLobbies = null; public static bool FfaLobbiesUnavailable = false; private static float _ffaLobbiesLastAt = -999f; private static float _ffaLobbyRejoinAt = -999f; private static bool _ffaLobbyActionInFlight = false; private static float _ffaLobbyActionAt = -999f; private static int _ffaLobbyActionGen = 0; private static bool _ffaLeaveIntent = false; private static float _ffaLeaveRetryAt = -999f; private static string _ffaLeaveTargetLobby = null; private static float _ffaAmbiguousPollUntil = -999f; public static List CachedFfaQueueList = null; private static float _ffaListLastAt = -999f; private static float _ffaLastAutoRejoinAt = -999f; private static string _ffaLastReadyFireKey = null; private static int _ffaReadyFireCount = 0; private static string _ovtLastReadyFireKey = null; private static int _ovtReadyFireCount = 0; private static float _ffaLeavingSince = -999f; private static int ffaGen = 0; private static bool _ffaProbed = false; private static string _ffaJoinCountdownKey; private static int _ffaJoinCountdownToken; private static int _ffaJoinCountdownActiveToken; private static float _ffaJoinCountdownArmedAt = -999f; private static bool blocksLoaded = false; public static float LastApiSuccessAt = -999f; public static float LastApiAttemptAt = -999f; public static bool LastResponseWasMaintenance = false; private static bool _earnersInFlight; private static string _earnersWantedKey; public const int BUG_REPORT_LOG_CAP_CHARS = 3500000; public static string CachedTournamentJson; public static TournamentSnapshot CachedTournament; private static float _tournamentRefreshAt; public static string TournamentKind = "sync"; public static readonly Dictionary CachedPlayerTournaments = new Dictionary(); public static List CachedMyActiveTournamentMatches = new List(); private static float _myActiveMatchesRefreshAt; public static PlayerTournamentEntry[] CachedSiteTournamentHistory; public static string[] CachedSiteTournamentHistoryNames; public static LeaderboardData CachedLeaderboard { get; private set; } public static PlayerStatsData CachedPlayerStats { get; private set; } public static List CachedCardStats { get; private set; } public static bool IsLoading { get; private set; } = false; public static string LastError { get; private set; } = ""; public static string LatestModVersion { get; private set; } = null; public static string MinModVersion { get; private set; } = null; public static bool ForceUpdateRequired { get; private set; } = false; public static List CachedRecentSeries { get; private set; } public static List CachedMatchHistory { get; private set; } public static Dictionary CachedAchievements { get; private set; } public static bool UsingLegacyFallback { get; private set; } private static string OutboxPath => Path.Combine(Paths.ConfigPath, "CompetitiveRounds.pending-reports.jsonl"); public static bool IsUpdating { get; private set; } = false; public static bool UpdateReady { get; private set; } = false; public static List CachedActiveSeries { get; private set; } public static List CachedMyBets { get; private set; } = new List(); public static List CachedActiveTeamSeries { get; private set; } = new List(); public static List CachedShopItems { get; private set; } public static List CachedInventory { get; private set; } public static bool IsAdmin { get; private set; } public static List CachedFlaggedMatches { get; private set; } = new List(); public static List CachedBannedUsers { get; private set; } = new List(); public static List CachedQuarantineReports { get; private set; } = new List(); public static bool IsAdminQuarantineLoading { get; private set; } public static bool AdminQuarantineLoaded { get; private set; } public static string AdminQuarantineError { get; private set; } = ""; public static bool IsArtist { get; private set; } public static List CachedArtistItems { get; private set; } = new List(); public static List CachedArtistBlocks { get; private set; } = new List(); public static List CachedArtistSales { get; private set; } = new List(); public static List CachedAllArtists { get; private set; } = new List(); public static List CachedMySubmissions { get; private set; } = new List(); public static List CachedAdminSeries { get; private set; } = new List(); public static List CachedBugReports { get; private set; } = new List(); public static BugReportDetail CachedBugReportDetail { get; set; } public static Dictionary SelectedPlayerAchievements { get; private set; } public static QueueState CurrentQueueState { get; private set; } = QueueState.Idle; public static QueuePollData LastPollData { get; private set; } public static bool IsQueuePolling { get; private set; } = false; public static bool EscapePending { get { try { return PlayerPrefs.GetInt("cr_escape_pending", 0) == 1; } catch { return false; } } private set { try { PlayerPrefs.SetInt("cr_escape_pending", value ? 1 : 0); PlayerPrefs.Save(); } catch { } } } public static int CachedQueueSearching { get; private set; } = 0; public static int CachedQueueTotal { get; private set; } = 0; public static int CachedOnlineCount { get; private set; } = 0; public static List CachedTeamQueueList { get; private set; } = new List(); public static List CachedTeamQueueAuto { get; private set; } = new List(); public static List CachedTeamQueueManual { get; private set; } = new List(); public static TeamQueueState CurrentTeamQueueState { get; private set; } = TeamQueueState.Idle; public static TeamQueuePollData LastTeamPollData { get; private set; } public static string ActiveTeamSeriesId { get; set; } public static bool IsTeamQueuePolling { get; private set; } = false; public static int CachedTeamQueueSearching { get; private set; } = 0; public static string CurrentTeamQueueType { get; private set; } = "auto"; public static List CachedTeamLeaderboard { get; private set; } = new List(); public static int CachedTeamLeaderboardTotal { get; private set; } = 0; public static string CachedTeamLeaderboardSort { get; private set; } = "rating"; public static List CachedTeamSeriesPaged { get; private set; } = new List(); public static int CachedTeamSeriesTotal { get; private set; } = 0; public static int CachedTeamSeriesPage { get; private set; } = 0; public static int CachedTeamSeriesPageSize { get; private set; } = 3; public static int CachedTeamSeriesTotalPages { get; private set; } = 0; public static List CachedTeamMatchHistory { get; private set; } = new List(); public static TeamStatsData CachedTeamStats { get; private set; } public static HashSet BlockedSteamIds { get; private set; } = new HashSet(); public static bool ApiLooksDown { get { if (LastApiAttemptAt < 0f) { return false; } float unscaledTime = Time.unscaledTime; if (unscaledTime - LastApiAttemptAt > 15f) { return false; } return unscaledTime - LastApiSuccessAt > 10f; } } public static string EarnersKey { get; private set; } public static List CachedEarners { get; private set; } public static int CachedEarnersTotal { get; private set; } public static void Initialize(string url) { baseUrl = url.TrimEnd('/'); Plugin.Log.LogInfo((object)("API client initialized: " + baseUrl)); if (string.Equals(baseUrl, "https://competitive-rounds.duckdns.org:8444".TrimEnd('/'), StringComparison.OrdinalIgnoreCase)) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ProbeEndpointThenStart()); } else { CheckModVersion(); } ((MonoBehaviour)Plugin.Instance).StartCoroutine(TournamentHeartbeatLoop()); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PresenceLoop()); ((MonoBehaviour)Plugin.Instance).StartCoroutine(SteamAuthLoop()); LoadOutbox(); } private static IEnumerator SteamAuthLoop() { yield return (object)new WaitForSecondsRealtime(2f); while (true) { try { SteamAuth.MaybeRefresh(); } catch { } yield return (object)new WaitForSecondsRealtime(SteamAuth.HasFreshToken ? 30f : 3f); } } public static void EnqueueFailedReport(string url, string json) { //IL_010f: Unknown result type (might be due to invalid IL or missing references) try { if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(json)) { return; } foreach (PendingReport pendingReport in _pendingReports) { if (pendingReport.url == url && pendingReport.json == json) { return; } } float num = (IsSilentOutboxUrl(url) ? 120f : 30f); _pendingReports.Add(new PendingReport { url = url, json = json, attempts = 0, nextAt = Time.realtimeSinceStartup + num }); PersistOutbox(); EnsureOutboxLoop(); if (!IsSilentOutboxUrl(url)) { Plugin.Log.LogWarning((object)$"[OUTBOX] report queued for retry ({_pendingReports.Count} pending)"); CompetitiveUI.ShowNotification("Report failed — will retry in background", new Color(1f, 0.75f, 0.3f), 4f); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[OUTBOX] enqueue failed: " + ex.Message)); } } private static bool IsSilentOutboxUrl(string url) { return !string.IsNullOrEmpty(url) && url.EndsWith("/api/v1/matches/macro-evidence", StringComparison.Ordinal); } private static void RemovePendingReport(string url, string json) { bool flag = false; for (int num = _pendingReports.Count - 1; num >= 0; num--) { PendingReport pendingReport = _pendingReports[num]; if (!(pendingReport.url != url) && !(pendingReport.json != json)) { _pendingReports.RemoveAt(num); flag = true; } } if (flag) { PersistOutbox(); } } private static void PersistOutbox() { try { StringBuilder stringBuilder = new StringBuilder(); foreach (PendingReport pendingReport in _pendingReports) { stringBuilder.Append(pendingReport.url).Append('\t').Append(pendingReport.json.Replace("\n", " ").Replace("\r", " ")) .Append('\n'); } if (stringBuilder.Length == 0) { if (File.Exists(OutboxPath)) { File.Delete(OutboxPath); } } else { File.WriteAllText(OutboxPath, stringBuilder.ToString()); } } catch { } } private static void LoadOutbox() { try { if (!File.Exists(OutboxPath)) { return; } string[] array = File.ReadAllLines(OutboxPath); foreach (string text in array) { int num = text.IndexOf('\t'); if (num > 0 && num < text.Length - 1) { _pendingReports.Add(new PendingReport { url = text.Substring(0, num), json = text.Substring(num + 1), attempts = 0, nextAt = Time.realtimeSinceStartup + 20f }); } } if (_pendingReports.Count > 0) { Plugin.Log.LogInfo((object)$"[OUTBOX] loaded {_pendingReports.Count} unsent report(s) from previous session"); EnsureOutboxLoop(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[OUTBOX] load failed: " + ex.Message)); } } private static void EnsureOutboxLoop() { if (!_outboxLoopStarted && !((Object)(object)Plugin.Instance == (Object)null)) { _outboxLoopStarted = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(OutboxLoop()); } } private static IEnumerator OutboxLoop() { while (true) { yield return (object)new WaitForSecondsRealtime(10f); if (_pendingReports.Count == 0) { continue; } float now = Time.realtimeSinceStartup; bool changed = false; for (int i = _pendingReports.Count - 1; i >= 0; i--) { PendingReport p = _pendingReports[i]; if (!(p.nextAt > now)) { p.attempts++; p.nextAt = now + 60f * (float)Math.Min(4, p.attempts); bool done = false; bool ok = false; string resp = null; yield return PostRequest(p.url, p.json, delegate(bool s, string r) { done = true; ok = s; resp = r; }); while (!done) { yield return null; } if (ok) { Plugin.Log.LogInfo((object)$"[OUTBOX] queued report delivered on retry {p.attempts}"); if (!IsSilentOutboxUrl(p.url)) { CompetitiveUI.ShowNotification("Match report delivered", new Color(0.4f, 1f, 0.5f), 4f); } _pendingReports.RemoveAt(i); changed = true; } else { bool retryableMacroResponse = IsSilentOutboxUrl(p.url) && resp != null && (resp.Contains("401") || resp.Contains("409") || resp.Contains("429")); bool retryableTransient = resp != null && (resp.Contains("HTTP 429") || resp.Contains("HTTP/1.1 429") || resp.Contains("HTTP 401") || resp.Contains("HTTP/1.1 401")); if ((!retryableMacroResponse && !retryableTransient && resp != null && (resp.StartsWith("HTTP 4", StringComparison.Ordinal) || resp.Contains("HTTP/1.1 4") || resp.Contains("duplicate key"))) || p.attempts >= 20) { Plugin.Log.LogWarning((object)string.Format("[OUTBOX] dropping report after {0} attempt(s): {1}", p.attempts, Trunc(resp ?? "(no response)", 160))); _pendingReports.RemoveAt(i); changed = true; } } } } if (changed || _pendingReports.Count > 0) { PersistOutbox(); } } } private static string Trunc(string s, int n) { return (string.IsNullOrEmpty(s) || s.Length <= n) ? s : (s.Substring(0, n) + ".."); } private static IEnumerator TournamentHeartbeatLoop() { yield return (object)new WaitForSeconds(10f); while (true) { yield return (object)new WaitForSeconds(20f); string sid = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(sid) || sid == "unknown") { continue; } if (++_hbTournamentCurrentTick >= 3) { _hbTournamentCurrentTick = 0; try { FetchTournamentCurrent(sid); } catch { } } FetchMyActiveTournamentMatches(sid); if (CachedMyActiveTournamentMatches == null) { continue; } HashSet seen = new HashSet(); foreach (ActiveTournamentMatch m in CachedMyActiveTournamentMatches) { if (string.IsNullOrEmpty(m.tournament_id) || seen.Contains(m.tournament_id)) { continue; } seen.Add(m.tournament_id); TournamentReady(m.tournament_id, sid); yield return (object)new WaitForSeconds(0.2f); bool isSyncReady = m.kind == "sync" && m.status == "ready" && m.my_ready && m.opp_ready && !string.IsNullOrEmpty(m.photon_room_name) && !string.IsNullOrEmpty(m.match_id); if (isSyncReady && !_heartbeatDispatchedMatches.Contains(m.match_id)) { if (Plugin.PendingRankedRoom != m.photon_room_name) { _heartbeatDispatchedMatches.Add(m.match_id); _heartbeatDispatchTime[m.match_id] = Time.unscaledTime; Plugin.SetPendingRoom(m.photon_room_name, m.photon_region); Plugin.Log.LogInfo((object)("[TOURNAMENT-HB] Dispatch from heartbeat loop: room=" + m.photon_room_name + " region=" + (m.photon_region ?? "default") + " match=" + m.match_id)); } } else if (isSyncReady && _heartbeatDispatchedMatches.Contains(m.match_id)) { float at; bool oldEnough = !_heartbeatDispatchTime.TryGetValue(m.match_id, out at) || Time.unscaledTime - at > 60f; bool inTargetRoom = false; try { inTargetRoom = PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.Name == m.photon_room_name; } catch { } if (oldEnough && !inTargetRoom && Plugin.PendingRankedRoom != m.photon_room_name) { _heartbeatDispatchedMatches.Remove(m.match_id); Plugin.Log.LogInfo((object)("[TOURNAMENT-HB] Not in match room 60s after dispatch — re-arming auto-connect for " + m.match_id)); } } } if (CachedMyActiveTournamentMatches.Count == 0) { _heartbeatDispatchedMatches.Clear(); continue; } HashSet stillActive = new HashSet(); foreach (ActiveTournamentMatch m2 in CachedMyActiveTournamentMatches) { if (!string.IsNullOrEmpty(m2.match_id)) { stillActive.Add(m2.match_id); } } _heartbeatDispatchedMatches.RemoveWhere((string id) => !stillActive.Contains(id)); } } private static IEnumerator ProbeEndpointThenStart() { bool reachable = false; for (int i = 0; i < 2; i++) { if (reachable) { break; } UnityWebRequest probe = UnityWebRequest.Get(baseUrl + "/api/v1/mod-version"); try { probe.timeout = 8; StampVersionHeader(probe); yield return probe.SendWebRequest(); object obj; if ((int)probe.result != 1) { obj = ""; } else { DownloadHandler downloadHandler = probe.downloadHandler; obj = ((downloadHandler != null) ? downloadHandler.text : null) ?? ""; } string body = (string)obj; if (!string.IsNullOrEmpty(ExtractJsonString(body, "version"))) { reachable = true; } else { Plugin.Log.LogWarning((object)($"[API] TLS endpoint probe {i + 1}/{2} unusable: " + $"result={probe.result} code={probe.responseCode} err={probe.error}")); } } finally { ((IDisposable)probe)?.Dispose(); } } if (!reachable) { baseUrl = "http://competitive-rounds.duckdns.org:8443".TrimEnd('/'); UsingLegacyFallback = true; Plugin.Log.LogWarning((object)("[API] https://competitive-rounds.duckdns.org:8444 unreachable — falling back to " + baseUrl + " for this session. Config is left untouched, so TLS is retried on next launch.")); try { ChatClient.Retarget(baseUrl); } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogWarning((object)("[API] chat retarget failed: " + ex2.Message)); } } CheckModVersion(); } public static void CheckModVersion() { ((MonoBehaviour)Plugin.Instance).StartCoroutine(DoCheckModVersion()); } private static IEnumerator DoCheckModVersion() { UnityWebRequest req = UnityWebRequest.Get(baseUrl + "/api/v1/mod-version"); yield return req.SendWebRequest(); if ((int)req.result != 1) { yield break; } string ver = ExtractJsonString(req.downloadHandler.text, "version"); string minVer = ExtractJsonString(req.downloadHandler.text, "min_version"); if (!string.IsNullOrEmpty(ver)) { LatestModVersion = ver; if (ver != "1.35.5") { Plugin.Log.LogWarning((object)("[VERSION] Update available: v1.35.5 → v" + ver)); } else { Plugin.Log.LogInfo((object)("[VERSION] Mod is up to date (v" + ver + ")")); } } if (!string.IsNullOrEmpty(minVer)) { MinModVersion = minVer; if (CompareVersion("1.35.5", minVer) < 0) { ForceUpdateRequired = true; Plugin.Log.LogWarning((object)("[VERSION] Mod is BELOW server minimum (v1.35.5 < v" + minVer + ") — update required")); } } if (!string.IsNullOrEmpty(LatestModVersion) && CompareVersion("1.35.5", LatestModVersion) < 0 && !IsUpdating && !UpdateReady) { Plugin.Log.LogInfo((object)"[VERSION] Auto-firing update on launch"); StartAutoUpdate(); } } private static int CompareVersion(string a, string b) { if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b)) { return 0; } string[] array = a.Split('.'); string[] array2 = b.Split('.'); int num = Math.Max(array.Length, array2.Length); for (int i = 0; i < num; i++) { int.TryParse((i < array.Length) ? array[i] : "0", out var result); int.TryParse((i < array2.Length) ? array2[i] : "0", out var result2); if (result != result2) { return (result >= result2) ? 1 : (-1); } } return 0; } public static void StartAutoUpdate() { if (!IsUpdating && !UpdateReady) { IsUpdating = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(DoAutoUpdate()); } } private static IEnumerator DoAutoUpdate() { Plugin.Log.LogInfo((object)"[UPDATE] Thunderstore build — auto-update disabled, use mod manager"); CompetitiveUI.ShowNotification("Update available — update through your mod manager", Color.cyan, 6f); IsUpdating = false; NativeUI.MarkDirty(); yield break; } private static byte[] GetHmacKeyBytes() { byte[] array = new byte[_hkE.Length]; for (int i = 0; i < _hkE.Length; i++) { array[i] = (byte)(_hkE[i] ^ _hkX[i % _hkX.Length]); } return array; } private static string ComputeHmac(string p1SteamId, string p2SteamId, int p1Rounds, int p2Rounds, bool isRanked, string reporterSteamId, string roomId) { string s = $"{p1SteamId}:{p2SteamId}:{p1Rounds}:{p2Rounds}:" + (isRanked ? "true" : "false") + ":" + reporterSteamId + ":" + roomId; try { using HMACSHA256 hMACSHA = new HMACSHA256(GetHmacKeyBytes()); byte[] array = hMACSHA.ComputeHash(Encoding.UTF8.GetBytes(s)); StringBuilder stringBuilder = new StringBuilder(array.Length * 2); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2")); } return stringBuilder.ToString(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[HMAC] Computation failed: " + ex.Message)); return ""; } } private static string ComputeHmacHex(string message) { try { using HMACSHA256 hMACSHA = new HMACSHA256(GetHmacKeyBytes()); byte[] array = hMACSHA.ComputeHash(Encoding.UTF8.GetBytes(message)); StringBuilder stringBuilder = new StringBuilder(array.Length * 2); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2")); } return stringBuilder.ToString(); } catch { return ""; } } private static string ComputeAdminHmacHex(string message) { string text = null; try { text = Plugin.AdminHmacSecret?.Value; } catch { } if (string.IsNullOrWhiteSpace(text)) { if (!_adminSecretWarned) { _adminSecretWarned = true; Plugin.Log.LogWarning((object)"[ADMIN] AdminSecret is not set in the config — admin actions will be rejected by the server (security A2)."); } return ""; } try { using HMACSHA256 hMACSHA = new HMACSHA256(Encoding.UTF8.GetBytes(text.Trim())); byte[] array = hMACSHA.ComputeHash(Encoding.UTF8.GetBytes(message)); StringBuilder stringBuilder = new StringBuilder(array.Length * 2); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2")); } return stringBuilder.ToString(); } catch { return ""; } } private static string ComputeSha256Hex(string value) { try { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(value ?? "")); StringBuilder stringBuilder = new StringBuilder(array.Length * 2); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2")); } return stringBuilder.ToString(); } catch { return ""; } } public static void FetchActiveSeries() { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/series/active", delegate(bool ok, string resp) { if (ok) { List list = new List(); try { string[] array = resp.Split(new string[1] { "\"series_id\":" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = "\"series_id\":" + array[i]; ActiveSeriesEntry activeSeriesEntry = new ActiveSeriesEntry { series_id = ExtractJsonString(text, "series_id"), p1_steam_id = ExtractJsonString(text, "p1_steam_id"), p1_name = ExtractJsonString(text, "p1_name"), p1_rating = ExtractJsonInt(text, "p1_rating"), p1_wins = ExtractJsonInt(text, "p1_wins"), p1_odds = ExtractJsonFloat(text, "p1_odds"), p2_steam_id = ExtractJsonString(text, "p2_steam_id"), p2_name = ExtractJsonString(text, "p2_name"), p2_rating = ExtractJsonInt(text, "p2_rating"), p2_wins = ExtractJsonInt(text, "p2_wins"), p2_odds = ExtractJsonFloat(text, "p2_odds"), live_p1_points = ExtractJsonInt(text, "live_p1_points"), live_p2_points = ExtractJsonInt(text, "live_p2_points"), bets_locked = (text.Contains("\"bets_locked\":true") || text.Contains("\"bets_locked\": true")), lock_reason = ExtractJsonString(text, "lock_reason"), is_private = (text.Contains("\"is_private\":true") || text.Contains("\"is_private\": true")), is_tournament = (text.Contains("\"is_tournament\":true") || text.Contains("\"is_tournament\": true")), tournament_kind = ExtractJsonString(text, "tournament_kind"), phase = ExtractJsonString(text, "phase") }; if (!string.IsNullOrEmpty(activeSeriesEntry.series_id)) { list.Add(activeSeriesEntry); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BET] active-series parse: " + ex.Message)); } CachedActiveSeries = list; NativeUI.MarkDirty(); } })); } public static void FetchRankTiers() { if (_rankTiersInFlight || (CachedRankTiers != null && Time.realtimeSinceStartup - _rankTiersAt < 420f)) { return; } _rankTiersAt = Time.realtimeSinceStartup; _rankTiersInFlight = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/rank-tiers", delegate(bool ok, string resp) { _rankTiersInFlight = false; if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = resp.IndexOf("\"tiers\":", StringComparison.Ordinal); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { RankTierEntry rankTierEntry = new RankTierEntry { floor = ExtractJsonInt(item, "floor"), name = ExtractJsonString(item, "name"), color = ExtractJsonString(item, "color") }; if (!string.IsNullOrEmpty(rankTierEntry.name)) { list.Add(rankTierEntry); } } if (list.Count > 0) { CachedRankTiers = list; NativeUI.MarkDirty(); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[RANK-TIERS] parse failed: " + ex.Message)); } })); } public static void FetchRecentMultimodeSeries(int limit = 60) { if (_multimodeInFlight) { return; } _multimodeInFlight = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/series/recent-multimode?limit={limit}", delegate(bool ok, string resp) { _multimodeInFlight = false; if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = resp.IndexOf("\"entries\":", StringComparison.Ordinal); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { MultimodeSeriesEntry multimodeSeriesEntry = new MultimodeSeriesEntry { mode = ExtractJsonString(item, "mode"), id = ExtractJsonString(item, "id"), ended_at = ExtractJsonString(item, "ended_at"), left_label = ExtractJsonString(item, "left_label"), right_label = ExtractJsonString(item, "right_label"), score = ExtractJsonString(item, "score"), left_rating_change = ExtractJsonFloat(item, "left_rating_change"), right_rating_change = ExtractJsonFloat(item, "right_rating_change") }; int num4 = item.IndexOf("\"bets\":", StringComparison.Ordinal); int num5 = ((num4 >= 0) ? item.IndexOf('[', num4) : (-1)); int num6 = ((num5 >= 0) ? FindMatchingBracketStringAware(item, num5) : (-1)); if (num5 >= 0 && num6 > num5) { foreach (string item2 in SliceTopLevelObjects(item.Substring(num5 + 1, num6 - num5 - 1))) { MultimodeBet multimodeBet = new MultimodeBet { bettor_name = ExtractJsonString(item2, "bettor_name"), bettor_steam_id = ExtractJsonString(item2, "bettor_steam_id"), bet_on_label = ExtractJsonString(item2, "bet_on_label"), amount = ExtractJsonInt(item2, "amount"), payout = ExtractJsonInt(item2, "payout"), odds_multiplier = ExtractJsonFloat(item2, "odds_multiplier"), state = ExtractJsonString(item2, "state") }; if (!string.IsNullOrEmpty(multimodeBet.bettor_name)) { multimodeSeriesEntry.bets.Add(multimodeBet); } } } if (!string.IsNullOrEmpty(multimodeSeriesEntry.mode)) { list.Add(multimodeSeriesEntry); } } CachedRecentMultimode = list; Plugin.Log.LogInfo((object)$"Recent multimode series loaded: {list.Count}"); NativeUI.MarkDirty(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MULTIMODE] parse failed: " + ex.Message)); } })); } public static void FetchMyBets(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + steamId + "/bets?limit=50", delegate(bool ok, string resp) { if (ok) { List list = new List(); try { string[] array = resp.Split(new string[1] { "\"id\":" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string json = array[i]; MyBetEntry myBetEntry = new MyBetEntry { amount = ExtractJsonInt(json, "amount"), odds_multiplier = ExtractJsonFloat(json, "odds_multiplier"), series_id = ExtractJsonString(json, "series_id"), bet_on_steam_id = ExtractJsonString(json, "bet_on_steam_id"), bet_on_name = ExtractJsonString(json, "bet_on_name"), series_status = ExtractJsonString(json, "series_status"), series_score = ExtractJsonString(json, "series_score"), settled = !string.IsNullOrEmpty(ExtractJsonString(json, "settled_at")), payout = ExtractJsonInt(json, "payout"), vs_name = ExtractJsonString(json, "vs_name"), created_at = ExtractJsonString(json, "created_at") }; if (!string.IsNullOrEmpty(myBetEntry.series_id)) { list.Add(myBetEntry); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BET] my-bets parse: " + ex.Message)); } CachedMyBets = list; NativeUI.MarkDirty(); } })); } public static MyBetEntry GetMyBetForSeries(string seriesId) { if (string.IsNullOrEmpty(seriesId) || CachedMyBets == null) { return null; } foreach (MyBetEntry cachedMyBet in CachedMyBets) { if (cachedMyBet.series_id == seriesId) { return cachedMyBet; } } return null; } public static void PostLivePoints(string seriesId, string reporterSteamId, int p1Points, int p2Points) { if (!string.IsNullOrEmpty(seriesId) && !string.IsNullOrEmpty(reporterSteamId)) { string text = ComputeHmacHex($"live-points:{seriesId}:{reporterSteamId}:{p1Points}:{p2Points}"); string url = baseUrl + "/api/v1/series/" + Escape(seriesId) + "/live-points" + $"?p1_points={p1Points}&p2_points={p2Points}" + "&reporter_steam_id=" + Escape(reporterSteamId) + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[LIVE-POINTS] series={seriesId.Substring(0, Math.Min(8, seriesId.Length))} {p1Points}-{p2Points} ok={ok}"); })); } } public static void PlaceBet(string bettorSteamId, string seriesId, string betOnSteamId, int amount, Action callback) { string text = ComputeHmacHex($"bet:{bettorSteamId}:{seriesId}:{betOnSteamId}:{amount}"); string url = $"{baseUrl}/api/v1/bets?steam_id={Escape(bettorSteamId)}&series_id={Escape(seriesId)}&bet_on_steam_id={Escape(betOnSteamId)}&amount={amount}&sig={text}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[BET] place {amount} on {betOnSteamId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(bettorSteamId); FetchActiveSeries(); } })); } public static void FetchActiveTeamSeries() { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/team/series/active", delegate(bool success, string response) { if (!success) { return; } try { ParseActiveTeamSeries(response); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TEAM-BET] active parse: " + ex.Message)); } })); } private static void ParseActiveTeamSeries(string response) { List list = new List(); int num = response.IndexOf("\"series\""); if (num < 0) { CachedActiveTeamSeries = list; return; } int num2 = response.IndexOf('[', num); int num3 = FindMatchingBracket(response, num2); if (num2 < 0 || num3 < 0) { CachedActiveTeamSeries = list; return; } string text = response.Substring(num2 + 1, num3 - num2 - 1); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = 1; int i; for (i = num5 + 1; i < text.Length; i++) { if (num6 <= 0) { break; } if (text[i] == '{') { num6++; } else if (text[i] == '}') { num6--; } } if (num6 != 0) { break; } string json = text.Substring(num5, i - num5); list.Add(new ActiveTeamSeriesEntry { series_id = ExtractJsonString(json, "series_id"), t1a_steam = ExtractJsonString(json, "t1a_steam"), t1a_name = ExtractJsonString(json, "t1a_name"), t1b_steam = ExtractJsonString(json, "t1b_steam"), t1b_name = ExtractJsonString(json, "t1b_name"), t2a_steam = ExtractJsonString(json, "t2a_steam"), t2a_name = ExtractJsonString(json, "t2a_name"), t2b_steam = ExtractJsonString(json, "t2b_steam"), t2b_name = ExtractJsonString(json, "t2b_name"), t1_rating = ExtractJsonInt(json, "t1_rating"), t2_rating = ExtractJsonInt(json, "t2_rating"), t1a_rating = ExtractJsonInt(json, "t1a_rating"), t1b_rating = ExtractJsonInt(json, "t1b_rating"), t2a_rating = ExtractJsonInt(json, "t2a_rating"), t2b_rating = ExtractJsonInt(json, "t2b_rating"), t1_wins = ExtractJsonInt(json, "t1_wins"), t2_wins = ExtractJsonInt(json, "t2_wins"), t1_odds = ExtractJsonFloat(json, "t1_odds"), t2_odds = ExtractJsonFloat(json, "t2_odds"), bets_locked = ExtractJsonBool(json, "bets_locked"), lock_reason = ExtractJsonString(json, "lock_reason"), started_at = ExtractJsonString(json, "started_at"), dc_grace_until = ExtractJsonString(json, "dc_grace_until") }); num4 = i; } CachedActiveTeamSeries = list; } public static void PlaceTeamBet(string bettorSteamId, string seriesId, int betOnTeam, int amount, Action callback) { string text = ComputeHmacHex($"team-bet:{bettorSteamId}:{seriesId}:{betOnTeam}:{amount}"); string url = $"{baseUrl}/api/v1/team-bets?steam_id={Escape(bettorSteamId)}&team_series_id={Escape(seriesId)}&bet_on_team={betOnTeam}&amount={amount}&sig={text}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[TEAM-BET] place {amount} on team {betOnTeam}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(bettorSteamId); FetchActiveTeamSeries(); } })); } public static void FetchShopItems(string steamId = null) { string text = baseUrl + "/api/v1/shop/items"; if (!string.IsNullOrEmpty(steamId)) { text = text + "?steam_id=" + Escape(steamId); } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(text, delegate(bool success, string response) { if (!success) { Plugin.Log.LogWarning((object)("[SHOP] list failed: " + response)); } else { CachedShopItems = ParseShopItems(response); Plugin.Log.LogInfo((object)$"[SHOP] loaded {CachedShopItems.Count} items"); NativeUI.MarkDirty(); } })); } public static void FetchInventory(string steamId) { if (string.IsNullOrEmpty(steamId)) { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + steamId + "/inventory", delegate(bool success, string response) { if (success) { CachedInventory = ParseShopItems(response); NativeUI.MarkDirty(); } })); } public static void PurchaseItem(string steamId, string sku, Action callback) { Plugin.Log.LogInfo((object)("[SHOP] PurchaseItem ENTRY sku=" + sku + " steamId=" + steamId)); try { string text = ComputeHmacHex("buy:" + steamId + ":" + sku); Plugin.Log.LogInfo((object)$"[SHOP] sig computed ({text?.Length ?? 0} chars)"); string text2 = baseUrl + "/api/v1/shop/purchase?steam_id=" + steamId + "&sku=" + sku + "&sig=" + text; Plugin.Log.LogInfo((object)("[SHOP] POST " + text2.Substring(0, Math.Min(text2.Length, 100)) + "...")); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(text2, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)string.Format("[SHOP] purchase callback {0}: ok={1} resp={2}", sku, ok, (resp != null && resp.Length > 120) ? (resp.Substring(0, 120) + "...") : resp)); try { callback?.Invoke(ok, resp); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[SHOP] callback threw: " + ex2.Message)); } if (ok) { FetchPlayerStats(steamId); FetchShopItems(steamId); FetchInventory(steamId); } })); Plugin.Log.LogInfo((object)"[SHOP] coroutine dispatched"); } catch (Exception ex) { Plugin.Log.LogError((object)$"[SHOP] PurchaseItem threw: {ex}"); try { callback?.Invoke(arg1: false, ex.Message); } catch { } } } public static void SetActiveTitle(string steamId, long itemId, Action callback = null) { string text = ComputeHmacHex($"title:{steamId}:{itemId}"); string text2 = baseUrl + "/api/v1/players/" + steamId + "/active-title?sig=" + text; if (itemId > 0) { text2 += $"&item_id={itemId}"; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(text2, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] set title {itemId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } public static void SetActiveTrail(string steamId, long itemId, Action callback = null) { string text = ComputeHmacHex($"trail:{steamId}:{itemId}"); string text2 = baseUrl + "/api/v1/players/" + steamId + "/active-trail?sig=" + text; if (itemId > 0) { text2 += $"&item_id={itemId}"; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(text2, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] set trail {itemId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } public static void SetActiveColor(string steamId, long itemId, Action callback = null) { string text = ComputeHmacHex($"color:{steamId}:{itemId}"); string text2 = baseUrl + "/api/v1/players/" + steamId + "/active-color?sig=" + text; if (itemId > 0) { text2 += $"&item_id={itemId}"; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(text2, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] set color {itemId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } public static void SetActivePlayerColor(string steamId, long itemId, Action callback = null) { string text = ComputeHmacHex($"player_color:{steamId}:{itemId}"); string text2 = baseUrl + "/api/v1/players/" + steamId + "/active-player-color?sig=" + text; if (itemId > 0) { text2 += $"&item_id={itemId}"; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(text2, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] set player_color {itemId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } public static void SetActiveCursorColor(string steamId, long itemId, Action callback = null) { string text = ComputeHmacHex($"cursor_color:{steamId}:{itemId}"); string text2 = baseUrl + "/api/v1/players/" + steamId + "/active-cursor-color?sig=" + text; if (itemId > 0) { text2 += $"&item_id={itemId}"; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(text2, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] set cursor_color {itemId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } public static void SetActivePlayerEffect(string steamId, long itemId, Action callback = null) { string text = ComputeHmacHex($"player_effect:{steamId}:{itemId}"); string text2 = baseUrl + "/api/v1/players/" + steamId + "/active-player-effect?sig=" + text; if (itemId > 0) { text2 += $"&item_id={itemId}"; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(text2, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] set player_effect {itemId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } public static void SetHideGold(string steamId, bool on, Action callback = null) { string text = ComputeHmacHex($"hide_gold:{steamId}:{(on ? 1 : 0)}"); string url = baseUrl + "/api/v1/players/" + steamId + "/hide-gold?on=" + (on ? "true" : "false") + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] set hide_gold {on}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); FetchLeaderboard(); } })); } public static void SetAppearOffline(string steamId, bool on, Action callback = null) { string text = ComputeHmacHex($"appear_offline:{steamId}:{(on ? 1 : 0)}"); string url = baseUrl + "/api/v1/players/" + steamId + "/appear-offline?on=" + (on ? "true" : "false") + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[HOME] set appear_offline {on}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); FetchOnlinePlayers(); } })); } public static void SetShowDiscord(string steamId, bool on, Action callback = null) { string text = ComputeHmacHex($"show_discord:{steamId}:{(on ? 1 : 0)}"); string url = baseUrl + "/api/v1/players/" + steamId + "/show-discord?on=" + (on ? "true" : "false") + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SETTINGS] set show_discord {on}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } public static void ToggleNametagStyle(string steamId, long itemId, Action callback = null) { string text = ComputeHmacHex($"nametag:{steamId}:{itemId}"); string url = $"{baseUrl}/api/v1/players/{steamId}/nametag-toggle?item_id={itemId}&sig={text}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] toggle nametag {itemId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } public static void ToggleMapColor(string steamId, long itemId, Action callback = null) { string text = ComputeHmacHex($"color:{steamId}:{itemId}"); string url = $"{baseUrl}/api/v1/players/{steamId}/color-toggle?item_id={itemId}&sig={text}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] toggle color {itemId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(steamId); } })); } private static List ParseShopItems(string response) { List list = new List(); if (string.IsNullOrEmpty(response)) { return list; } string[] array = response.Split(new string[1] { "{\"id\":" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string json = "{\"id\":" + array[i]; ShopItemData shopItemData = new ShopItemData(); shopItemData.id = ExtractJsonInt(json, "id"); shopItemData.sku = ExtractJsonString(json, "sku"); shopItemData.kind = ExtractJsonString(json, "kind"); shopItemData.name = ExtractJsonString(json, "name"); shopItemData.description = ExtractJsonString(json, "description"); shopItemData.price = ExtractJsonInt(json, "price"); shopItemData.rarity = ExtractJsonString(json, "rarity"); shopItemData.preview_color = ExtractJsonString(json, "preview_color"); shopItemData.owned = ExtractJsonBool(json, "owned"); shopItemData.artist_steam_id = ExtractJsonString(json, "artist_steam_id"); shopItemData.artist_name = ExtractJsonString(json, "artist_name"); shopItemData.stock_limit = ExtractJsonInt(json, "stock_limit"); shopItemData.stock_sold = ExtractJsonInt(json, "stock_sold"); if (!string.IsNullOrEmpty(shopItemData.sku) || !string.IsNullOrEmpty(shopItemData.name)) { list.Add(shopItemData); } } return list; } public static void FetchRecentChat(int limit = 50) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/chat/recent?limit={limit}", delegate(bool success, string response) { if (!success || string.IsNullOrEmpty(response)) { return; } try { string[] array = response.Split(new string[1] { "{\"source\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = "{\"source\"" + array[i]; int num = text.IndexOf("\"}"); if (num >= 0) { string obj = text.Substring(0, num + 2); try { ChatClient.OnMessage?.Invoke(obj); } catch { } } } Plugin.Log.LogInfo((object)$"[CHAT] Scrollback loaded: {array.Length - 1} messages"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CHAT] Scrollback parse error: " + ex.Message)); } })); } public static void DeletePlayerData(string steamId, Action callback) { if (string.IsNullOrEmpty(steamId)) { callback(arg1: false, "no-steam-id"); return; } string text = ComputeHmacHex("delete:" + steamId); string url = baseUrl + "/api/v1/players/" + steamId + "/data?sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(DoDelete(url, callback)); } private static IEnumerator DoDelete(string url, Action callback) { UnityWebRequest request = UnityWebRequest.Delete(url); try { request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); string sentToken = SteamAuth.SessionToken; StampVersionHeader(request); request.timeout = 20; yield return request.SendWebRequest(); bool success = (int)request.result == 1; if (!success) { HandleSessionReject(request, sentToken); } object arg; if (!success) { arg = request.error; } else { DownloadHandler downloadHandler = request.downloadHandler; arg = ((downloadHandler != null) ? downloadHandler.text : null) ?? ""; } callback(success, (string)arg); } finally { ((IDisposable)request)?.Dispose(); } } public static void CheckAdminStatus(string steamId, Action callback = null) { if (string.IsNullOrEmpty(steamId)) { IsAdmin = false; callback?.Invoke(obj: false); return; } string url = baseUrl + "/api/v1/admin/check-status?steam_id=" + steamId; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string body) { bool flag = false; if (ok && !string.IsNullOrEmpty(body)) { flag = body.Contains("\"is_admin\":true") || body.Contains("\"is_admin\": true"); } IsAdmin = flag; Plugin.Log.LogInfo((object)$"[ADMIN] check-status for {steamId}: is_admin={flag}"); callback?.Invoke(flag); CheckArtistStatus(steamId); })); } public static void CheckArtistStatus(string steamId, Action callback = null) { if (string.IsNullOrEmpty(steamId)) { IsArtist = false; callback?.Invoke(obj: false); return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/artist/status/" + steamId, delegate(bool ok, string body) { bool flag = false; if (ok && !string.IsNullOrEmpty(body)) { flag = body.Contains("\"is_artist\":true") || body.Contains("\"is_artist\": true"); } IsArtist = flag; if (flag) { Plugin.Log.LogInfo((object)("[ARTIST] " + steamId + " is an artist")); } callback?.Invoke(flag); })); } public static void FetchArtistItems(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/artist/" + steamId + "/items", delegate(bool ok, string resp) { if (!ok) { Plugin.Log.LogWarning((object)("[ARTIST] items fetch failed: " + resp)); } else { List list = new List(); List list2 = new List(); try { int num = resp.IndexOf("\"blocked\"", StringComparison.Ordinal); string text = ((num > 0) ? resp.Substring(0, num) : resp); string text2 = ((num > 0) ? resp.Substring(num) : ""); string[] array = text.Split(new string[1] { "\"sku\":" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string json = "\"sku\":" + array[i]; ArtistItemEntry artistItemEntry = new ArtistItemEntry { sku = ExtractJsonString(json, "sku"), kind = ExtractJsonString(json, "kind"), name = ExtractJsonString(json, "name"), description = ExtractJsonString(json, "description"), rarity = ExtractJsonString(json, "rarity"), price = ExtractJsonInt(json, "price"), stock_limit = ExtractJsonInt(json, "stock_limit"), catalog_ready = ExtractJsonBool(json, "catalog_ready"), sold = ExtractJsonInt(json, "sold"), gifted = ExtractJsonInt(json, "gifted"), earned = ExtractJsonInt(json, "earned") }; if (!string.IsNullOrEmpty(artistItemEntry.sku)) { list.Add(artistItemEntry); } } string[] array2 = text2.Split(new string[1] { "\"steam_id\":" }, StringSplitOptions.None); for (int j = 1; j < array2.Length; j++) { string json2 = "\"steam_id\":" + array2[j]; ArtistBlockEntry artistBlockEntry = new ArtistBlockEntry { steam_id = ExtractJsonString(json2, "steam_id"), display_name = ExtractJsonString(json2, "display_name") }; if (!string.IsNullOrEmpty(artistBlockEntry.steam_id)) { list2.Add(artistBlockEntry); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ARTIST] items parse: " + ex.Message)); } CachedArtistItems = list; CachedArtistBlocks = list2; NativeUI.MarkDirty(); } })); } public static void FetchArtistSales(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/artist/" + steamId + "/sales?limit=50", delegate(bool ok, string resp) { if (!ok) { Plugin.Log.LogWarning((object)("[ARTIST] sales fetch failed: " + resp)); } else { List list = new List(); try { int num = resp.IndexOf("\"sales\"", StringComparison.Ordinal); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { ArtistSaleEntry artistSaleEntry = new ArtistSaleEntry { item = ExtractJsonString(item, "item"), buyer = ExtractJsonString(item, "buyer"), when = ExtractJsonString(item, "when"), price = ExtractJsonInt(item, "price"), earned = ExtractJsonInt(item, "earned") }; if (!string.IsNullOrEmpty(artistSaleEntry.item)) { list.Add(artistSaleEntry); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ARTIST] sales parse: " + ex.Message)); } CachedArtistSales = list; NativeUI.MarkDirty(); } })); } public static void ArtistSetPrice(string steamId, string sku, int price, Action callback = null) { string text = ComputeHmacHex($"artist:{steamId}:set-price:{sku}:{price}"); string url = $"{baseUrl}/api/v1/artist/set-price?steam_id={Escape(steamId)}&sku={Escape(sku)}&price={price}&sig={text}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[ARTIST] set-price {sku}={price}: ok={ok}"); if (ok) { FetchArtistItems(steamId); FetchShopItems(steamId); } callback?.Invoke(ok, resp); })); } public static void ArtistSetName(string steamId, string sku, string value, Action callback = null) { string text = ComputeHmacHex("artist:" + steamId + ":set-name:" + sku); string url = baseUrl + "/api/v1/artist/set-name?steam_id=" + Escape(steamId) + "&sku=" + Escape(sku) + "&value=" + UnityWebRequest.EscapeURL(value ?? "") + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[ARTIST] set-name {sku}: ok={ok}"); if (ok) { FetchArtistItems(steamId); FetchShopItems(steamId); } callback?.Invoke(ok, resp); })); } public static void ArtistSetDesc(string steamId, string sku, string value, Action callback = null) { string text = ComputeHmacHex("artist:" + steamId + ":set-desc:" + sku); string url = baseUrl + "/api/v1/artist/set-desc?steam_id=" + Escape(steamId) + "&sku=" + Escape(sku) + "&value=" + UnityWebRequest.EscapeURL(value ?? "") + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[ARTIST] set-desc {sku}: ok={ok}"); if (ok) { FetchArtistItems(steamId); FetchShopItems(steamId); } callback?.Invoke(ok, resp); })); } public static void FetchArtistsList(Action callback = null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/artists", delegate(bool ok, string resp) { if (ok) { List list = new List(); try { string[] array = resp.Split(new string[1] { "\"steam_id\":" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string json = "\"steam_id\":" + array[i]; ArtistBlockEntry artistBlockEntry = new ArtistBlockEntry { steam_id = ExtractJsonString(json, "steam_id"), display_name = ExtractJsonString(json, "display_name") }; if (!string.IsNullOrEmpty(artistBlockEntry.steam_id)) { list.Add(artistBlockEntry); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ARTIST] roster parse: " + ex.Message)); } CachedAllArtists = list; } callback?.Invoke(ok); })); } public static void SearchPlayers(string query, Action> callback) { string url = baseUrl + "/api/v1/players/search?q=" + UnityWebRequest.EscapeURL(query ?? "") + "&limit=8"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string resp) { List list = new List(); if (ok) { try { string[] array = resp.Split(new string[1] { "\"steam_id\":" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string json = "\"steam_id\":" + array[i]; PlayerSearchResult playerSearchResult = new PlayerSearchResult { steam_id = ExtractJsonString(json, "steam_id"), display_name = ExtractJsonString(json, "display_name"), rating = ExtractJsonInt(json, "rating") }; if (!string.IsNullOrEmpty(playerSearchResult.steam_id)) { list.Add(playerSearchResult); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SEARCH] parse: " + ex.Message)); } } callback?.Invoke(ok, list); })); } public static void ArtistSetStock(string steamId, string sku, int stock, Action callback = null) { string text = ComputeHmacHex($"artist:{steamId}:set-stock:{sku}:{stock}"); string url = $"{baseUrl}/api/v1/artist/set-stock?steam_id={Escape(steamId)}&sku={Escape(sku)}&stock={stock}&sig={text}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[ARTIST] set-stock {sku}={stock}: ok={ok}"); if (ok) { FetchArtistItems(steamId); FetchShopItems(steamId); } callback?.Invoke(ok, resp); })); } private static void QuantizeCosmeticPlacement(float renderScale, float renderOffsetX, float renderOffsetY, out int scaleCenti, out int offsetXMilli, out int offsetYMilli) { //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) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) scaleCenti = Mathf.RoundToInt(Mathf.Clamp(renderScale, 0.5f, 2.25f) * 100f); Vector2 val = Vector2.ClampMagnitude(new Vector2(renderOffsetX, renderOffsetY), 4.5f); offsetXMilli = Mathf.RoundToInt(val.x * 1000f); offsetYMilli = Mathf.RoundToInt(val.y * 1000f); while ((long)offsetXMilli * (long)offsetXMilli + (long)offsetYMilli * (long)offsetYMilli > 20250000) { if (Math.Abs(offsetXMilli) >= Math.Abs(offsetYMilli)) { offsetXMilli -= Math.Sign(offsetXMilli); } else { offsetYMilli -= Math.Sign(offsetYMilli); } } } public static void ArtistSubmitCosmetic(string steamId, string name, string slot, string pngBase64, float renderScale, float renderOffsetX, float renderOffsetY, Action callback = null) { QuantizeCosmeticPlacement(renderScale, renderOffsetX, renderOffsetY, out var scaleCenti, out var offsetXMilli, out var offsetYMilli); string text = ComputeSha256Hex(name ?? ""); string text2 = ComputeSha256Hex(pngBase64 ?? ""); string retryHash = ComputeSha256Hex($"{steamId}:{slot}:{scaleCenti}:{offsetXMilli}:{offsetYMilli}:" + text + ":" + text2); string requestId = ""; if (PlayerPrefs.GetString("cr_cosmetic_upload_retry_hash", "") == retryHash) { requestId = PlayerPrefs.GetString("cr_cosmetic_upload_retry_id", ""); } if (!Regex.IsMatch(requestId ?? "", "^[0-9a-f]{32}$")) { requestId = Guid.NewGuid().ToString("N"); PlayerPrefs.SetString("cr_cosmetic_upload_retry_hash", retryHash); PlayerPrefs.SetString("cr_cosmetic_upload_retry_id", requestId); PlayerPrefs.Save(); } string message = $"artist:{steamId}:submit-v2:{requestId}:{slot}:{pngBase64.Length}:" + $"{scaleCenti}:{offsetXMilli}:{offsetYMilli}:{text}:{text2}"; string text3 = ComputeHmacHex(message); string text4 = ((float)scaleCenti / 100f).ToString("F2", CultureInfo.InvariantCulture); string text5 = ((float)offsetXMilli / 1000f).ToString("F3", CultureInfo.InvariantCulture); string text6 = ((float)offsetYMilli / 1000f).ToString("F3", CultureInfo.InvariantCulture); string json = "{\"steam_id\":\"" + Escape(steamId) + "\",\"name\":\"" + JsonEscapeFull(name) + "\",\"slot\":\"" + slot + "\",\"png_base64\":\"" + pngBase64 + "\",\"signature_version\":2,\"upload_request_id\":\"" + requestId + "\",\"scale_centi\":" + scaleCenti + ",\"offset_x_milli\":" + offsetXMilli + ",\"offset_y_milli\":" + offsetYMilli + ",\"render_scale\":" + text4 + ",\"render_offset_x\":" + text5 + ",\"render_offset_y\":" + text6 + ",\"sig\":\"" + text3 + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/artist/submit-cosmetic", json, delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[COSMETIC] submit '{name}' ({slot}, {pngBase64.Length} b64): ok={ok}"); if (ok) { if (PlayerPrefs.GetString("cr_cosmetic_upload_retry_hash", "") == retryHash && PlayerPrefs.GetString("cr_cosmetic_upload_retry_id", "") == requestId) { PlayerPrefs.DeleteKey("cr_cosmetic_upload_retry_hash"); PlayerPrefs.DeleteKey("cr_cosmetic_upload_retry_id"); PlayerPrefs.Save(); } FetchMySubmissions(steamId); } callback?.Invoke(ok, resp); })); } private static CosmeticSubmission ParseCosmeticSubmissionObject(string chunk) { CosmeticSubmission cosmeticSubmission = new CosmeticSubmission(); cosmeticSubmission.id = ExtractJsonInt(chunk, "id"); cosmeticSubmission.name = ExtractJsonString(chunk, "name"); cosmeticSubmission.slot = ExtractJsonString(chunk, "slot"); cosmeticSubmission.status = ExtractJsonString(chunk, "status"); cosmeticSubmission.review_note = ExtractJsonString(chunk, "review_note"); cosmeticSubmission.shop_sku = ExtractJsonString(chunk, "shop_sku"); cosmeticSubmission.artist_steam_id = ExtractJsonString(chunk, "artist_steam_id"); cosmeticSubmission.artist_name = ExtractJsonString(chunk, "artist_name"); cosmeticSubmission.render_scale = ExtractJsonFloat(chunk, "render_scale"); if (cosmeticSubmission.render_scale <= 0f) { cosmeticSubmission.render_scale = 1f; } cosmeticSubmission.render_offset_x = ExtractJsonFloat(chunk, "render_offset_x"); cosmeticSubmission.render_offset_y = ExtractJsonFloat(chunk, "render_offset_y"); cosmeticSubmission.placement_revision = ExtractJsonInt(chunk, "placement_revision"); if (cosmeticSubmission.placement_revision < 1) { cosmeticSubmission.placement_revision = 1; } cosmeticSubmission.placement_status = ExtractJsonString(chunk, "placement_status"); cosmeticSubmission.placement_review_note = ExtractJsonString(chunk, "placement_review_note"); cosmeticSubmission.review_kind = ExtractJsonString(chunk, "review_kind"); cosmeticSubmission.approved_render_scale = ExtractJsonFloat(chunk, "approved_render_scale"); cosmeticSubmission.approved_render_offset_x = ExtractJsonFloat(chunk, "approved_render_offset_x"); cosmeticSubmission.approved_render_offset_y = ExtractJsonFloat(chunk, "approved_render_offset_y"); cosmeticSubmission.approved_placement_revision = ExtractJsonInt(chunk, "approved_placement_revision"); cosmeticSubmission.published_placement_revision = ExtractJsonInt(chunk, "published_placement_revision"); cosmeticSubmission.created_at = ExtractJsonString(chunk, "created_at"); cosmeticSubmission.png_base64 = ExtractJsonString(chunk, "png_base64"); return cosmeticSubmission; } private static List ParseCosmeticSubmissionArray(string json) { List list = new List(); if (string.IsNullOrEmpty(json)) { return list; } int num = json.IndexOf("\"submissions\":", StringComparison.Ordinal); int num2 = ((num >= 0) ? json.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(json, num2) : (-1)); if (num2 < 0 || num3 <= num2) { return list; } foreach (string item in SliceTopLevelObjects(json.Substring(num2 + 1, num3 - num2 - 1))) { CosmeticSubmission cosmeticSubmission = ParseCosmeticSubmissionObject(item); if (cosmeticSubmission.id > 0) { list.Add(cosmeticSubmission); } } return list; } public static void FetchMySubmissions(string steamId, Action callback = null) { string text = ComputeHmacHex("artist:" + steamId + ":my-submissions"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/artist/my-submissions?steam_id=" + Escape(steamId) + "&sig=" + text, delegate(bool ok, string resp) { if (ok) { try { CachedMySubmissions = ParseCosmeticSubmissionArray(resp); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] my-subs parse: " + ex.Message)); } NativeUI.MarkDirty(); } callback?.Invoke(ok); })); } public static void FetchCosmeticSubmissionsAdmin(string adminSteamId, Action> callback) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":cosmetic-subs:list"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/admin/cosmetic-submissions?admin_steam_id=" + Escape(adminSteamId) + "&sig=" + text, delegate(bool ok, string resp) { List arg = new List(); if (ok) { try { arg = ParseCosmeticSubmissionArray(resp); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] admin-subs parse: " + ex.Message)); } } callback?.Invoke(ok, arg); })); } public static void FetchCosmeticSubmissionPreview(string steamId, int submissionId, Action callback) { string arg = ComputeHmacHex($"artist:{steamId}:cosmetic-preview:{submissionId}"); string url = baseUrl + "/api/v1/artist/cosmetic-preview?steam_id=" + Escape(steamId) + $"&submission_id={submissionId}&sig={arg}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string resp) { CosmeticSubmission cosmeticSubmission = null; if (ok) { try { cosmeticSubmission = ParseCosmeticSubmissionObject(resp); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] preview parse: " + ex.Message)); ok = false; } } callback?.Invoke(ok && cosmeticSubmission != null && cosmeticSubmission.id > 0, cosmeticSubmission, resp); })); } public static void ArtistUpdateCosmeticPlacement(string steamId, int submissionId, int expectedRevision, float renderScale, float renderOffsetX, float renderOffsetY, Action callback = null) { QuantizeCosmeticPlacement(renderScale, renderOffsetX, renderOffsetY, out var scaleCenti, out var offsetXMilli, out var offsetYMilli); string message = $"artist:{steamId}:cosmetic-placement:{submissionId}:{expectedRevision}:" + $"{scaleCenti}:{offsetXMilli}:{offsetYMilli}"; string text = ComputeHmacHex(message); string json = "{\"steam_id\":\"" + Escape(steamId) + "\",\"submission_id\":" + submissionId + ",\"expected_revision\":" + expectedRevision + ",\"scale_centi\":" + scaleCenti + ",\"offset_x_milli\":" + offsetXMilli + ",\"offset_y_milli\":" + offsetYMilli + ",\"sig\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/artist/cosmetic-placement", json, delegate(bool ok, string resp) { if (ok) { FetchMySubmissions(steamId); } callback?.Invoke(ok, resp); })); } public static void ArtistStartCatalogPlacementRevision(string steamId, string sku, string slot, string pngBase64, float publishedScale, float publishedOffsetX, float publishedOffsetY, float proposedScale, float proposedOffsetX, float proposedOffsetY, Action callback = null) { string text = pngBase64 ?? ""; QuantizeCosmeticPlacement(publishedScale, publishedOffsetX, publishedOffsetY, out var scaleCenti, out var offsetXMilli, out var offsetYMilli); QuantizeCosmeticPlacement(proposedScale, proposedOffsetX, proposedOffsetY, out var scaleCenti2, out var offsetXMilli2, out var offsetYMilli2); string text2 = ComputeSha256Hex(text); string message = $"artist:{steamId}:catalog-placement:{sku}:{slot}:{text.Length}:" + $"{scaleCenti}:{offsetXMilli}:{offsetYMilli}:" + $"{scaleCenti2}:{offsetXMilli2}:{offsetYMilli2}:{text2}"; string text3 = ComputeHmacHex(message); string json = "{\"steam_id\":\"" + Escape(steamId) + "\",\"sku\":\"" + JsonEscapeFull(sku) + "\",\"slot\":\"" + JsonEscapeFull(slot) + "\",\"png_base64\":\"" + text + "\",\"published_scale_centi\":" + scaleCenti + ",\"published_offset_x_milli\":" + offsetXMilli + ",\"published_offset_y_milli\":" + offsetYMilli + ",\"proposed_scale_centi\":" + scaleCenti2 + ",\"proposed_offset_x_milli\":" + offsetXMilli2 + ",\"proposed_offset_y_milli\":" + offsetYMilli2 + ",\"png_hash\":\"" + text2 + "\",\"sig\":\"" + text3 + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/artist/catalog-cosmetic-placement", json, delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[COSMETIC] catalog placement {sku}: ok={ok}"); if (ok) { FetchMySubmissions(steamId); } callback?.Invoke(ok, resp); })); } public static void FetchCosmeticReleaseCandidatesAdmin(string adminSteamId, Action, string> callback) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":cosmetic-releases:list"); string url = baseUrl + "/api/v1/admin/cosmetic-release-candidates?admin_steam_id=" + Escape(adminSteamId) + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string resp) { List list = new List(); if (ok) { try { int num = resp.IndexOf("\"candidates\":", StringComparison.Ordinal); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { CosmeticReleaseCandidate cosmeticReleaseCandidate = new CosmeticReleaseCandidate { id = ExtractJsonInt(item, "id"), shop_sku = ExtractJsonString(item, "shop_sku"), name = ExtractJsonString(item, "name"), slot = ExtractJsonString(item, "slot"), artist_name = ExtractJsonString(item, "artist_name"), artist_steam_id = ExtractJsonString(item, "artist_steam_id"), render_scale = ExtractJsonFloat(item, "render_scale"), render_offset_x = ExtractJsonFloat(item, "render_offset_x"), render_offset_y = ExtractJsonFloat(item, "render_offset_y"), placement_revision = ExtractJsonInt(item, "placement_revision"), published_placement_revision = ExtractJsonInt(item, "published_placement_revision"), png_bytes = ExtractJsonInt(item, "png_bytes"), catalog_ready = ExtractJsonBool(item, "catalog_ready"), approved_at = ExtractJsonString(item, "approved_at") }; if (cosmeticReleaseCandidate.id > 0 && !string.IsNullOrEmpty(cosmeticReleaseCandidate.shop_sku)) { list.Add(cosmeticReleaseCandidate); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] release queue parse: " + ex.Message)); ok = false; } } callback?.Invoke(ok, list, resp); })); } public static void AdminReviewCosmetic(string adminSteamId, int submissionId, bool approve, int expectedRevision, float renderScale, float renderOffsetX, float renderOffsetY, string note, Action callback = null) { string action = (approve ? "approve" : "deny"); QuantizeCosmeticPlacement(renderScale, renderOffsetX, renderOffsetY, out var scaleCenti, out var offsetXMilli, out var offsetYMilli); string text = $"{submissionId}:{action}:{expectedRevision}:" + $"{scaleCenti}:{offsetXMilli}:{offsetYMilli}"; string text2 = ComputeAdminHmacHex("admin:" + adminSteamId + ":cosmetic-review:" + text); string url = baseUrl + "/api/v1/admin/cosmetic-review?admin_steam_id=" + Escape(adminSteamId) + $"&submission_id={submissionId}&action={action}" + $"&expected_revision={expectedRevision}&scale_centi={scaleCenti}" + $"&offset_x_milli={offsetXMilli}&offset_y_milli={offsetYMilli}" + "¬e=" + UnityWebRequest.EscapeURL(note ?? "") + "&sig=" + text2; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[COSMETIC] review #{submissionId} {action}: ok={ok}"); callback?.Invoke(ok, resp); })); } public static void ArtistGift(string steamId, string sku, string targetSteamId, Action callback = null) { string text = ComputeHmacHex("artist:" + steamId + ":gift:" + sku + ":" + targetSteamId); string url = baseUrl + "/api/v1/artist/gift?steam_id=" + Escape(steamId) + "&sku=" + Escape(sku) + "&target_steam_id=" + Escape(targetSteamId) + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[ARTIST] gift {sku} -> {targetSteamId}: ok={ok} resp={Trunc120(resp)}"); if (ok) { FetchArtistItems(steamId); } callback?.Invoke(ok, resp); })); } public static void ArtistBlock(string steamId, string targetSteamId, bool block, Action callback = null) { string text = ComputeHmacHex($"artist:{steamId}:block:{targetSteamId}:{(block ? 1 : 0)}"); string url = baseUrl + "/api/v1/artist/block?steam_id=" + Escape(steamId) + "&target_steam_id=" + Escape(targetSteamId) + "&block=" + (block ? "true" : "false") + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)string.Format("[ARTIST] {0} {1}: ok={2}", block ? "block" : "unblock", targetSteamId, ok)); if (ok) { FetchArtistItems(steamId); } callback?.Invoke(ok, resp); })); } private static string Trunc120(string s) { return string.IsNullOrEmpty(s) ? "" : ((s.Length > 120) ? (s.Substring(0, 120) + "...") : s); } public static void AdminSetArtist(string adminSteamId, string targetSteamId, bool grant, Action callback = null) { string text = ComputeAdminHmacHex($"admin:{adminSteamId}:artist-set:{targetSteamId}:{(grant ? 1 : 0)}"); string url = baseUrl + "/api/v1/admin/artists/set?admin_steam_id=" + Escape(adminSteamId) + "&target_steam_id=" + Escape(targetSteamId) + "&grant=" + (grant ? "true" : "false") + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[ADMIN] artist-set {targetSteamId} grant={grant}: ok={ok} resp={Trunc120(resp)}"); callback?.Invoke(ok, resp); })); } public static void AdminSetItemArtist(string adminSteamId, string sku, string artistSteamId, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":item-artist:" + sku + ":" + artistSteamId); string url = baseUrl + "/api/v1/admin/shop/set-artist?admin_steam_id=" + Escape(adminSteamId) + "&sku=" + Escape(sku) + "&artist_steam_id=" + Escape(artistSteamId ?? "") + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[ADMIN] item-artist {sku} -> {artistSteamId}: ok={ok} resp={Trunc120(resp)}"); if (ok) { FetchShopItems(adminSteamId); } callback?.Invoke(ok, resp); })); } public static void FetchFlaggedMatches(string adminSteamId, bool includeReviewed = false, Action callback = null) { if (string.IsNullOrEmpty(adminSteamId)) { callback?.Invoke(obj: false); return; } string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":list_flagged:"); string url = baseUrl + "/api/v1/admin/flagged-matches?admin_steam_id=" + adminSteamId + "&hmac_signature=" + text + "&include_reviewed=" + (includeReviewed ? "true" : "false") + "&limit=50"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string body) { if (!ok) { Plugin.Log.LogWarning((object)("[ADMIN] flagged fetch failed: " + body)); callback?.Invoke(obj: false); return; } try { CachedFlaggedMatches = ParseFlaggedMatches(body); NativeUI.MarkDirty(); callback?.Invoke(obj: true); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ADMIN] flagged parse: " + ex.Message)); callback?.Invoke(obj: false); } })); } public static void FetchBannedUsers(string adminSteamId, Action callback = null) { if (string.IsNullOrEmpty(adminSteamId)) { callback?.Invoke(obj: false); return; } string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":list_bans:"); string url = baseUrl + "/api/v1/admin/banned-users?admin_steam_id=" + adminSteamId + "&hmac_signature=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string body) { if (!ok) { Plugin.Log.LogWarning((object)("[ADMIN] bans fetch failed: " + body)); callback?.Invoke(obj: false); return; } try { CachedBannedUsers = ParseBannedUsers(body); callback?.Invoke(obj: true); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ADMIN] bans parse: " + ex.Message)); callback?.Invoke(obj: false); } })); } public static void FetchAdminQuarantine(string adminSteamId, Action callback = null) { if (string.IsNullOrEmpty(adminSteamId)) { callback?.Invoke(obj: false); return; } IsAdminQuarantineLoading = true; AdminQuarantineError = ""; NativeUI.MarkDirty(); string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":quarantine:list"); string url = baseUrl + "/api/v1/admin/quarantine?admin_steam_id=" + UnityWebRequest.EscapeURL(adminSteamId) + "&hmac_signature=" + UnityWebRequest.EscapeURL(text); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string body) { IsAdminQuarantineLoading = false; if (!ok) { AdminQuarantineError = (string.IsNullOrEmpty(body) ? "request failed" : body); Plugin.Log.LogWarning((object)("[ADMIN] quarantine fetch failed: " + body)); NativeUI.MarkDirty(); callback?.Invoke(obj: false); return; } try { CachedQuarantineReports = ParseQuarantineReports(body); AdminQuarantineLoaded = true; AdminQuarantineError = ""; NativeUI.MarkDirty(); callback?.Invoke(obj: true); } catch (Exception ex) { AdminQuarantineError = "response parse failed"; Plugin.Log.LogWarning((object)("[ADMIN] quarantine parse: " + ex.Message)); NativeUI.MarkDirty(); callback?.Invoke(obj: false); } })); } public static void AdminQuarantineDiscard(string adminSteamId, string reportId, string note, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":quarantine_action:" + reportId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"hmac_signature\":\"" + text + "\",\"note\":\"" + JsonEscapeFull(note ?? "") + "\"}"; string url = baseUrl + "/api/v1/admin/quarantine/" + UnityWebRequest.EscapeURL(reportId ?? "") + "/discard"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void AdminQuarantineAccept(string adminSteamId, string reportId, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":quarantine_action:" + reportId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"hmac_signature\":\"" + text + "\"}"; string url = baseUrl + "/api/v1/admin/quarantine/" + UnityWebRequest.EscapeURL(reportId ?? "") + "/accept"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } private static List ParseQuarantineReports(string body) { List list = new List(); if (string.IsNullOrEmpty(body)) { return list; } int num = body.IndexOf("\"reports\"", StringComparison.Ordinal); int num2 = ((num >= 0) ? body.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(body, num2) : (-1)); if (num2 < 0 || num3 < 0) { return list; } foreach (string item in SliceTopLevelObjects(body.Substring(num2 + 1, num3 - num2 - 1))) { QuarantineReportEntry quarantineReportEntry = new QuarantineReportEntry { id = ExtractJsonString(item, "id"), mode = ExtractJsonString(item, "mode"), reason = ExtractJsonString(item, "reason"), http_status = ExtractJsonInt(item, "http_status"), created_at = ExtractJsonString(item, "created_at"), player_names = ExtractStringListStringAware(item, "player_names"), score = ExtractJsonString(item, "score"), room = ExtractJsonString(item, "room"), status = ExtractJsonString(item, "status"), can_accept = ExtractJsonBool(item, "can_accept"), accept_blocked_reason = ExtractJsonString(item, "accept_blocked_reason") }; if (!string.IsNullOrEmpty(quarantineReportEntry.id)) { list.Add(quarantineReportEntry); } } return list; } public static void AdminBan(string adminSteamId, string targetSteamId, string reason, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":ban:" + targetSteamId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"target_steam_id\":\"" + Escape(targetSteamId) + "\",\"reason\":\"" + Escape(reason) + "\",\"hmac_signature\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/admin/ban", json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void AdminUnban(string adminSteamId, string targetSteamId, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":unban:" + targetSteamId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"target_steam_id\":\"" + Escape(targetSteamId) + "\",\"hmac_signature\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/admin/unban", json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void AdminGrantAchievement(string adminSteamId, string targetSteamId, string achievementKey, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":grant_achievement:" + targetSteamId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"target_steam_id\":\"" + Escape(targetSteamId) + "\",\"achievement_key\":\"" + Escape(achievementKey) + "\",\"hmac_signature\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/admin/grant-achievement", json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void AdminReverseSeries(string adminSteamId, string seriesId, string reason, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":reverse_series:" + seriesId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"series_id\":\"" + Escape(seriesId) + "\",\"reason\":\"" + Escape(reason) + "\",\"hmac_signature\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/admin/reverse-series", json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void AdminReviewFlag(string adminSteamId, string flagId, string action, int evidenceRevision, Action callback = null) { if (evidenceRevision < 1) { callback?.Invoke(arg1: false, "missing evidence revision; refresh flagged matches"); return; } string text = ComputeAdminHmacHex($"admin:{adminSteamId}:review_flag:{flagId}:{action}:{evidenceRevision}"); string json = $"{{\"admin_steam_id\":\"{Escape(adminSteamId)}\",\"flag_id\":\"{Escape(flagId)}\",\"review_action\":\"{Escape(action)}\",\"evidence_revision\":{evidenceRevision},\"signature_version\":3,\"hmac_signature\":\"{text}\"}}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/admin/review-flag", json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void AdminResolveFlagRestoration(string adminSteamId, string flagId, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":resolve_flag_restoration:" + flagId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"flag_id\":\"" + Escape(flagId) + "\",\"hmac_signature\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/admin/resolve-flag-restoration", json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void FetchAdminRecentSeries(string adminSteamId, Action callback = null) { if (string.IsNullOrEmpty(adminSteamId)) { callback?.Invoke(obj: false); return; } string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":list_recent_series:"); string url = baseUrl + "/api/v1/admin/recent-series?admin_steam_id=" + adminSteamId + "&hmac_signature=" + text + "&limit=40"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string body) { if (!ok) { Plugin.Log.LogWarning((object)("[ADMIN] recent-series fetch failed: " + body)); callback?.Invoke(obj: false); return; } try { CachedAdminSeries = ParseAdminSeries(body); callback?.Invoke(obj: true); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ADMIN] recent-series parse: " + ex.Message)); callback?.Invoke(obj: false); } })); } public static void AdminResolveTeamSeries(string adminSteamId, string seriesId, string action, int winnerTeam, Action callback = null) { string text = $"{seriesId}:{action}:{winnerTeam}"; string text2 = ComputeAdminHmacHex("admin:" + adminSteamId + ":resolve_team_series:" + text); string text3 = "action=" + action + "&admin_steam_id=" + adminSteamId + "&hmac_signature=" + text2; if (action == "complete") { text3 += $"&winner_team={winnerTeam}"; } string url = baseUrl + "/api/v1/admin/team/series/" + seriesId + "/resolve?" + text3; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(url, "{}", delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void AdminReverseTeamSeries(string adminSteamId, string seriesId, string reason, Action callback = null) { string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":reverse_team_series:" + seriesId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"series_id\":\"" + Escape(seriesId) + "\",\"reason\":\"" + Escape(reason) + "\",\"hmac_signature\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/admin/team/reverse-series", json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } private static List ParseAdminSeries(string body) { List list = new List(); if (string.IsNullOrEmpty(body)) { return list; } int num = body.IndexOf("\"series\""); if (num < 0) { return list; } int num2 = body.IndexOf('[', num); if (num2 < 0) { return list; } int num3 = FindMatchingBracket(body, num2); if (num3 < 0) { num3 = body.Length - 1; } int num4 = num2 + 1; while (num4 < num3) { int num5 = body.IndexOf('{', num4); if (num5 < 0 || num5 >= num3) { break; } int num6 = FindMatchingBrace(body, num5); if (num6 < 0 || num6 > num3) { break; } string json = body.Substring(num5, num6 - num5 + 1); list.Add(new AdminSeriesEntry { ladder = ExtractJsonString(json, "ladder"), series_id = ExtractJsonString(json, "series_id"), status = ExtractJsonString(json, "status"), created_at = ExtractJsonString(json, "created_at"), completed_at = ExtractJsonString(json, "completed_at"), score = ExtractJsonString(json, "score"), series_number = ExtractJsonInt(json, "series_number"), winner_team = ExtractJsonInt(json, "winner_team"), num_players = ExtractJsonInt(json, "num_players"), incomplete = ExtractJsonBool(json, "incomplete"), dc_name = ExtractJsonString(json, "dc_name"), dc_steam = ExtractJsonString(json, "dc_steam"), p1_name = ExtractJsonString(json, "p1_name"), p1_steam = ExtractJsonString(json, "p1_steam"), p1_team = ExtractJsonInt(json, "p1_team"), p1_cards = ExtractJsonString(json, "p1_cards"), p2_name = ExtractJsonString(json, "p2_name"), p2_steam = ExtractJsonString(json, "p2_steam"), p2_team = ExtractJsonInt(json, "p2_team"), p2_cards = ExtractJsonString(json, "p2_cards"), p3_name = ExtractJsonString(json, "p3_name"), p3_steam = ExtractJsonString(json, "p3_steam"), p3_team = ExtractJsonInt(json, "p3_team"), p3_cards = ExtractJsonString(json, "p3_cards"), p4_name = ExtractJsonString(json, "p4_name"), p4_steam = ExtractJsonString(json, "p4_steam"), p4_team = ExtractJsonInt(json, "p4_team"), p4_cards = ExtractJsonString(json, "p4_cards") }); num4 = num6 + 1; } return list; } public static void FetchBugReports(string adminSteamId, Action callback = null) { if (string.IsNullOrEmpty(adminSteamId)) { callback?.Invoke(obj: false); return; } string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":bug_reports:list"); string url = baseUrl + "/api/v1/bug-reports?admin_steam_id=" + adminSteamId + "&hmac_signature=" + text + "&limit=100"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string body) { if (!ok) { Plugin.Log.LogWarning((object)("[BUG-REPORTS] fetch failed: " + body)); callback?.Invoke(obj: false); return; } try { CachedBugReports = ParseBugReportList(body); callback?.Invoke(obj: true); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BUG-REPORTS] parse: " + ex.Message)); callback?.Invoke(obj: false); } })); } public static void FetchBugReportDetail(string adminSteamId, string reportId, Action callback = null) { if (string.IsNullOrEmpty(adminSteamId) || string.IsNullOrEmpty(reportId)) { callback?.Invoke(obj: false); return; } string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":bug_reports:" + reportId); string url = baseUrl + "/api/v1/bug-reports/" + reportId + "?admin_steam_id=" + adminSteamId + "&hmac_signature=" + text + "&include_log=true"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string body) { if (!ok) { Plugin.Log.LogWarning((object)("[BUG-REPORTS] detail fetch failed: " + body)); callback?.Invoke(obj: false); return; } try { CachedBugReportDetail = ParseBugReportDetail(body); callback?.Invoke(obj: true); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BUG-REPORTS] detail parse: " + ex.Message)); callback?.Invoke(obj: false); } })); } private static List ParseBugReportList(string json) { List list = new List(); if (string.IsNullOrEmpty(json)) { return list; } int num = json.IndexOf("\"reports\":["); if (num < 0) { return list; } int num2 = num + "\"reports\":[".Length; int num3 = 1; int i; for (i = num2; i < json.Length; i++) { if (num3 <= 0) { break; } if (json[i] == '[') { num3++; } else if (json[i] == ']') { num3--; } } if (num3 != 0) { return list; } string text = json.Substring(num2, i - num2 - 1); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = 1; int j; for (j = num5 + 1; j < text.Length; j++) { if (num6 <= 0) { break; } if (text[j] == '{') { num6++; } else if (text[j] == '}') { num6--; } } if (num6 != 0) { break; } string json2 = text.Substring(num5, j - num5); list.Add(new BugReportSummary { id = ExtractJsonString(json2, "id"), bug_number = ExtractJsonInt(json2, "bug_number"), created_at = ExtractJsonString(json2, "created_at"), steam_id = ExtractJsonString(json2, "steam_id"), display_name = ExtractJsonString(json2, "display_name"), mod_version = ExtractJsonString(json2, "mod_version"), severity = ExtractJsonString(json2, "severity"), category = ExtractJsonString(json2, "category"), status = ExtractJsonString(json2, "status"), description = ExtractJsonString(json2, "description"), has_log = ExtractJsonBool(json2, "has_log"), log_bytes = ExtractJsonInt(json2, "log_bytes") }); num4 = j; } return list; } private static BugReportDetail ParseBugReportDetail(string json) { BugReportDetail bugReportDetail = new BugReportDetail { id = ExtractJsonString(json, "id"), bug_number = ExtractJsonInt(json, "bug_number"), steam_id = ExtractJsonString(json, "steam_id"), display_name = ExtractJsonString(json, "display_name"), mod_version = ExtractJsonString(json, "mod_version"), game_version = ExtractJsonString(json, "game_version"), severity = ExtractJsonString(json, "severity"), category = ExtractJsonString(json, "category"), description = ExtractJsonString(json, "description"), repro_steps = ExtractJsonString(json, "repro_steps"), status = ExtractJsonString(json, "status"), triage_notes = ExtractJsonString(json, "triage_notes"), created_at = ExtractJsonString(json, "created_at"), log_text = ExtractJsonString(json, "log_text"), log_bytes = ExtractJsonInt(json, "log_bytes") }; try { int num = json.IndexOf("\"events\":["); if (num >= 0) { int num2 = num + "\"events\":[".Length; int num3 = 1; int i; for (i = num2; i < json.Length; i++) { if (num3 <= 0) { break; } if (json[i] == '[') { num3++; } else if (json[i] == ']') { num3--; } } if (num3 == 0) { string text = json.Substring(num2, i - num2 - 1); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = 1; int j; for (j = num5 + 1; j < text.Length; j++) { if (num6 <= 0) { break; } if (text[j] == '{') { num6++; } else if (text[j] == '}') { num6--; } } if (num6 != 0) { break; } string json2 = text.Substring(num5, j - num5); bugReportDetail.events.Add(new BugReportEventEntry { id = ExtractJsonString(json2, "id"), actor_steam_id = ExtractJsonString(json2, "actor_steam_id"), actor_name = ExtractJsonString(json2, "actor_name"), event_type = ExtractJsonString(json2, "event_type"), old_status = ExtractJsonString(json2, "old_status"), new_status = ExtractJsonString(json2, "new_status"), comment = ExtractJsonString(json2, "comment"), created_at = ExtractJsonString(json2, "created_at") }); num4 = j; } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BUG-REPORTS] events parse: " + ex.Message)); } return bugReportDetail; } public static void AdminBugReportComment(string adminSteamId, string reportId, string comment, Action callback = null) { if (string.IsNullOrEmpty(adminSteamId) || string.IsNullOrEmpty(reportId)) { callback?.Invoke(arg1: false, "missing args"); return; } string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":bug_reports_comment:" + reportId); string json = "{\"admin_steam_id\":\"" + Escape(adminSteamId) + "\",\"hmac_signature\":\"" + text + "\",\"comment\":\"" + Escape(comment ?? "") + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/bug-reports/" + reportId + "/comment", json, delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } public static void AdminBugReportStatus(string adminSteamId, string reportId, string newStatus, string comment, Action callback = null) { if (string.IsNullOrEmpty(adminSteamId) || string.IsNullOrEmpty(reportId) || string.IsNullOrEmpty(newStatus)) { callback?.Invoke(arg1: false, "missing args"); return; } string text = ComputeAdminHmacHex("admin:" + adminSteamId + ":bug_reports_status:" + reportId); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); stringBuilder.Append("\"admin_steam_id\":\"" + Escape(adminSteamId) + "\""); stringBuilder.Append(",\"hmac_signature\":\"" + text + "\""); stringBuilder.Append(",\"new_status\":\"" + Escape(newStatus) + "\""); if (!string.IsNullOrEmpty(comment)) { stringBuilder.Append(",\"comment\":\"" + Escape(comment) + "\""); } stringBuilder.Append("}"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/bug-reports/" + reportId + "/status", stringBuilder.ToString(), delegate(bool ok, string resp) { callback?.Invoke(ok, resp); })); } private static List ParseFlaggedMatches(string json) { List list = new List(); if (string.IsNullOrEmpty(json)) { return list; } int num = json.IndexOf("\"flags\":", StringComparison.Ordinal); int num2 = ((num >= 0) ? json.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(json, num2) : (-1)); if (num2 < 0 || num3 <= num2) { return list; } foreach (string item in SliceTopLevelObjects(json.Substring(num2 + 1, num3 - num2 - 1))) { FlaggedMatchEntry flaggedMatchEntry = new FlaggedMatchEntry(); flaggedMatchEntry.id = ExtractJsonString(item, "id"); flaggedMatchEntry.match_id = ExtractJsonString(item, "match_id"); flaggedMatchEntry.game_code = ExtractJsonString(item, "game_code"); flaggedMatchEntry.series_id = ExtractJsonString(item, "series_id"); flaggedMatchEntry.flag_reason = ExtractJsonString(item, "flag_reason"); flaggedMatchEntry.p1_name = ExtractJsonString(item, "p1_name"); flaggedMatchEntry.p2_name = ExtractJsonString(item, "p2_name"); flaggedMatchEntry.p1_steam_id = ExtractJsonString(item, "p1_steam_id"); flaggedMatchEntry.p2_steam_id = ExtractJsonString(item, "p2_steam_id"); flaggedMatchEntry.suspect_steam_text = ExtractJsonString(item, "suspect_steam_text"); if (!string.IsNullOrEmpty(flaggedMatchEntry.p1_steam_id)) { flaggedMatchEntry.player_steam_ids.Add(flaggedMatchEntry.p1_steam_id); } if (!string.IsNullOrEmpty(flaggedMatchEntry.p2_steam_id)) { flaggedMatchEntry.player_steam_ids.Add(flaggedMatchEntry.p2_steam_id); } flaggedMatchEntry.auto_invalidated = item.Contains("\"auto_invalidated\":true") || item.Contains("\"auto_invalidated\": true"); flaggedMatchEntry.match_invalidated = item.Contains("\"match_invalidated\":true") || item.Contains("\"match_invalidated\": true"); flaggedMatchEntry.is_ranked = item.Contains("\"is_ranked\":true") || item.Contains("\"is_ranked\": true"); flaggedMatchEntry.restoration_required = item.Contains("\"restoration_required\":true") || item.Contains("\"restoration_required\": true"); flaggedMatchEntry.duration_seconds = ExtractJsonInt(item, "duration_seconds"); flaggedMatchEntry.discord_evidence_revision = ExtractJsonInt(item, "discord_evidence_revision"); flaggedMatchEntry.duration_text = ExtractJsonString(item, "duration_text"); flaggedMatchEntry.review_action = ExtractJsonString(item, "review_action"); flaggedMatchEntry.match_invalidation_reason = ExtractJsonString(item, "match_invalidation_reason"); flaggedMatchEntry.created_at = ExtractJsonString(item, "created_at"); flaggedMatchEntry.score_summary = ExtractJsonString(item, "score_summary"); flaggedMatchEntry.cards_summary = ExtractJsonString(item, "cards_summary"); flaggedMatchEntry.point_progress = ExtractJsonString(item, "point_progress"); flaggedMatchEntry.evidence_summary = ExtractJsonString(item, "evidence_summary"); flaggedMatchEntry.telemetry_summary = ExtractJsonString(item, "telemetry_summary"); flaggedMatchEntry.connection_summary = ExtractJsonString(item, "connection_summary"); flaggedMatchEntry.match_context = ExtractJsonString(item, "match_context"); if (!string.IsNullOrEmpty(flaggedMatchEntry.id)) { list.Add(flaggedMatchEntry); } } return list; } private static List ParseBannedUsers(string json) { List list = new List(); if (string.IsNullOrEmpty(json)) { return list; } string[] array = json.Split(new string[1] { "\"id\":\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = array[i]; int num = text.IndexOf('"'); if (num >= 0) { BannedUserEntry bannedUserEntry = new BannedUserEntry(); bannedUserEntry.id = text.Substring(0, num); bannedUserEntry.steam_id = ExtractJsonString(text, "steam_id"); bannedUserEntry.display_name = ExtractJsonString(text, "display_name"); bannedUserEntry.reason = ExtractJsonString(text, "reason"); bannedUserEntry.banned_by_steam_id = ExtractJsonString(text, "banned_by_steam_id"); bannedUserEntry.banned_at = ExtractJsonString(text, "banned_at"); list.Add(bannedUserEntry); } } return list; } public static void CheckOpponentRanked(string steamId, Action callback) { if (string.IsNullOrEmpty(steamId) || steamId.StartsWith("photon_") || steamId == "unknown") { callback(obj: false); return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/mod/check/" + steamId, delegate(bool success, string response) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (success) { try { ModCheckResponse modCheckResponse = JsonUtility.FromJson(response); if (modCheckResponse.banned) { Plugin.Log.LogWarning((object)("[BAN] Opponent " + steamId + " is mod-banned (" + modCheckResponse.ban_reason + ") — leaving match")); CompetitiveUI.ShowNotification("Opponent is banned from the mod for cheating - leaving match.", new Color(1f, 0.3f, 0.3f), 8f); try { if (PhotonNetwork.InRoom) { PhotonNetwork.LeaveRoom(true); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BAN] LeaveRoom failed: " + ex.Message)); } callback(obj: false); } else { bool obj = modCheckResponse.registered && modCheckResponse.ranked; Plugin.Log.LogInfo((object)$"Opponent ranked check: registered={modCheckResponse.registered}, ranked={modCheckResponse.ranked}"); callback(obj); } return; } catch { callback(obj: false); return; } } Plugin.Log.LogWarning((object)("Opponent rank check failed: " + response)); callback(obj: false); })); } public static void ReportMacroEvidence(string p1SteamId, string p2SteamId, int p1RoundsWon, int p2RoundsWon, string photonRoomId, DateTime matchStartedAt, int durationSeconds, bool sharedGameTokenUsed, string reporterSteamId, int suspectSeconds, int peakKps, int peakCps, int peakEps, string suspectTimeline) { if (suspectSeconds < 10 || string.IsNullOrEmpty(reporterSteamId)) { return; } string text = ClampTimeline(suspectTimeline, 1024); string arg = ComputeSha256Hex(photonRoomId ?? ""); string text2 = matchStartedAt.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture); string arg2 = ComputeSha256Hex(text2); string text3 = ComputeSha256Hex(text); string message = "macro-evidence:" + reporterSteamId + ":" + p1SteamId + ":" + p2SteamId + ":" + $"{arg}:{arg2}:{durationSeconds}:" + $"{(sharedGameTokenUsed ? 1 : 0)}:" + $"{p1RoundsWon}:{p2RoundsWon}:{suspectSeconds}:" + $"{peakKps}:{peakCps}:{peakEps}:{text3}"; string text4 = ComputeHmacHex(message); string body = "{\"reporter_steam_id\":\"" + Escape(reporterSteamId) + "\",\"p1_steam_id\":\"" + Escape(p1SteamId) + "\",\"p2_steam_id\":\"" + Escape(p2SteamId) + "\",\"p1_rounds_won\":" + p1RoundsWon + ",\"p2_rounds_won\":" + p2RoundsWon + ",\"photon_room_id\":\"" + Escape(photonRoomId) + "\",\"match_started_at\":\"" + text2 + "\",\"duration_seconds\":" + durationSeconds + ",\"shared_game_token\":" + (sharedGameTokenUsed ? "true" : "false") + ",\"macro_suspect_seconds\":" + suspectSeconds + ",\"peak_keys_per_second\":" + peakKps + ",\"peak_clicks_per_second\":" + peakCps + ",\"peak_events_per_second\":" + peakEps + ",\"suspect_windows\":\"" + Escape(text) + "\",\"hmac_signature\":\"" + text4 + "\"}"; string url = baseUrl + "/api/v1/matches/macro-evidence"; EnqueueFailedReport(url, body); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(url, body, delegate(bool ok, string resp) { if (ok) { RemovePendingReport(url, body); } else { Plugin.Log.LogWarning((object)("[INPUT] exact macro evidence was not attached: " + Trunc120(resp))); } }, 6)); } public static void ReportMatch(string p1SteamId, string p1Name, string p2SteamId, string p2Name, int p1RoundsWon, int p2RoundsWon, int p1PointsTotal, int p2PointsTotal, List p1Cards, List p2Cards, List p1Offers, List p2Offers, string photonRoomId, string region, int durationSeconds, DateTime startedAt, string reporterSteamId, bool isRanked, int localShotsFired = 0, int localBlocksRaised = 0, int localBulletsFired = 0, int localBulletsHit = 0, int localBlocksActivated = 0, int localBlocksSuccessful = 0, int localAvgFps = 0, int opponentAvgFps = 0, int localKeysPressed = 0, float localActiveSeconds = 0f, int localMacroSuspectSeconds = 0, int localMacroPeakKps = 0, int localMacroPeakCps = 0, int localMacroPeakEps = 0, string localMacroTimeline = null, int oppMacroSuspectSeconds = 0, int oppMacroPeakKps = 0, int oppMacroPeakCps = 0, int oppMacroPeakEps = 0, string oppMacroTimeline = null, int oppBulletsFired = 0, int oppBulletsHit = 0, int oppBlocksActivated = 0, int oppBlocksSuccessful = 0, int oppKeysPressed = 0, float oppActiveSeconds = 0f, string pointTimeline = null, string localFpsTimeline = null, string oppFpsTimeline = null, int localFreezeCount = 0, int localFreezeFocusedCount = 0, float localFreezeTotalSec = 0f, int localPingAvg = 0, int localPingMax = 0, int localRecvGapCount = 0, int localRecvGapMaxMs = 0, int oppHbGapCount = 0, int oppFreezeCount = 0, int oppFreezeFocusedCount = 0, int oppRecvGapCount = 0, string localPingTimeline = null, string oppPingTimeline = null, int oppPingAvg = 0, string localHitTimeline = null, string oppHitTimeline = null, string localBlockTimeline = null, string oppBlockTimeline = null, string pointTimes = null) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); stringBuilder.Append("\"player1\":{\"steam_id\":\"" + Escape(p1SteamId) + "\",\"display_name\":\"" + Escape(p1Name) + "\",\"cards\":["); AppendCards(stringBuilder, p1Cards); stringBuilder.Append("],\"card_offers\":["); AppendOffers(stringBuilder, p1Offers); stringBuilder.Append("]},"); stringBuilder.Append("\"player2\":{\"steam_id\":\"" + Escape(p2SteamId) + "\",\"display_name\":\"" + Escape(p2Name) + "\",\"cards\":["); AppendCards(stringBuilder, p2Cards); stringBuilder.Append("],\"card_offers\":["); AppendOffers(stringBuilder, p2Offers); stringBuilder.Append("]},"); stringBuilder.Append($"\"p1_rounds_won\":{p1RoundsWon},"); stringBuilder.Append($"\"p2_rounds_won\":{p2RoundsWon},"); stringBuilder.Append($"\"p1_points_total\":{p1PointsTotal},"); stringBuilder.Append($"\"p2_points_total\":{p2PointsTotal},"); stringBuilder.Append("\"photon_room_id\":\"" + Escape(photonRoomId) + "\","); stringBuilder.Append("\"game_version\":\"v" + Application.version + "\","); stringBuilder.Append("\"region\":\"" + Escape(region) + "\","); stringBuilder.Append($"\"match_duration\":{durationSeconds},"); stringBuilder.Append("\"started_at\":\"" + startedAt.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture) + "\","); stringBuilder.Append("\"is_ranked\":" + (isRanked ? "true" : "false") + ","); stringBuilder.Append("\"reported_by_steam_id\":\"" + Escape(reporterSteamId) + "\","); stringBuilder.Append($"\"local_shots_fired\":{localShotsFired},"); stringBuilder.Append($"\"local_blocks_raised\":{localBlocksRaised},"); stringBuilder.Append($"\"local_bullets_fired\":{localBulletsFired},"); stringBuilder.Append($"\"local_bullets_hit\":{localBulletsHit},"); stringBuilder.Append($"\"local_blocks_activated\":{localBlocksActivated},"); stringBuilder.Append($"\"local_blocks_successful\":{localBlocksSuccessful},"); stringBuilder.Append($"\"local_avg_fps\":{localAvgFps},"); stringBuilder.Append($"\"opponent_avg_fps\":{opponentAvgFps},"); stringBuilder.Append($"\"local_keys_pressed\":{localKeysPressed},"); stringBuilder.Append("\"local_active_seconds\":" + localActiveSeconds.ToString("F1", CultureInfo.InvariantCulture) + ","); stringBuilder.Append($"\"local_macro_suspect_seconds\":{localMacroSuspectSeconds},"); stringBuilder.Append($"\"local_macro_peak_kps\":{localMacroPeakKps},"); stringBuilder.Append($"\"local_macro_peak_cps\":{localMacroPeakCps},"); stringBuilder.Append($"\"local_macro_peak_eps\":{localMacroPeakEps},"); stringBuilder.Append("\"local_macro_timeline\":\"" + Escape(ClampTimeline(localMacroTimeline, 1024)) + "\","); stringBuilder.Append($"\"opp_macro_suspect_seconds\":{oppMacroSuspectSeconds},"); stringBuilder.Append($"\"opp_macro_peak_kps\":{oppMacroPeakKps},"); stringBuilder.Append($"\"opp_macro_peak_cps\":{oppMacroPeakCps},"); stringBuilder.Append($"\"opp_macro_peak_eps\":{oppMacroPeakEps},"); stringBuilder.Append("\"opp_macro_timeline\":\"" + Escape(ClampTimeline(oppMacroTimeline, 1024)) + "\","); stringBuilder.Append($"\"opp_bullets_fired\":{oppBulletsFired},"); stringBuilder.Append($"\"opp_bullets_hit\":{oppBulletsHit},"); stringBuilder.Append($"\"opp_blocks_activated\":{oppBlocksActivated},"); stringBuilder.Append($"\"opp_blocks_successful\":{oppBlocksSuccessful},"); stringBuilder.Append($"\"opp_keys_pressed\":{oppKeysPressed},"); stringBuilder.Append("\"opp_active_seconds\":" + oppActiveSeconds.ToString("F1", CultureInfo.InvariantCulture) + ","); stringBuilder.Append("\"point_timeline\":\"" + Escape(pointTimeline ?? "") + "\","); string s = ClampTimeline(localFpsTimeline); string s2 = ClampTimeline(oppFpsTimeline); stringBuilder.Append("\"local_fps_timeline\":\"" + Escape(s) + "\","); stringBuilder.Append("\"opp_fps_timeline\":\"" + Escape(s2) + "\","); stringBuilder.Append($"\"local_freeze_count\":{localFreezeCount},"); stringBuilder.Append($"\"local_freeze_focused_count\":{localFreezeFocusedCount},"); stringBuilder.Append("\"local_freeze_total_sec\":" + localFreezeTotalSec.ToString("F1", CultureInfo.InvariantCulture) + ","); stringBuilder.Append($"\"local_ping_avg\":{localPingAvg},"); stringBuilder.Append($"\"local_ping_max\":{localPingMax},"); stringBuilder.Append($"\"local_recv_gap_count\":{localRecvGapCount},"); stringBuilder.Append($"\"local_recv_gap_max_ms\":{localRecvGapMaxMs},"); stringBuilder.Append($"\"opp_hb_gap_count\":{oppHbGapCount},"); stringBuilder.Append($"\"opp_freeze_count\":{oppFreezeCount},"); stringBuilder.Append($"\"opp_freeze_focused_count\":{oppFreezeFocusedCount},"); stringBuilder.Append($"\"opp_recv_gap_count\":{oppRecvGapCount},"); stringBuilder.Append("\"local_ping_timeline\":\"" + Escape(ClampTimeline(localPingTimeline)) + "\","); stringBuilder.Append("\"opp_ping_timeline\":\"" + Escape(ClampTimeline(oppPingTimeline)) + "\","); stringBuilder.Append($"\"opp_ping_avg\":{oppPingAvg},"); stringBuilder.Append("\"local_hit_timeline\":\"" + Escape(ClampTimeline(localHitTimeline, 1024)) + "\","); stringBuilder.Append("\"opp_hit_timeline\":\"" + Escape(ClampTimeline(oppHitTimeline, 1024)) + "\","); stringBuilder.Append("\"local_block_timeline\":\"" + Escape(ClampTimeline(localBlockTimeline, 1024)) + "\","); stringBuilder.Append("\"opp_block_timeline\":\"" + Escape(ClampTimeline(oppBlockTimeline, 1024)) + "\","); stringBuilder.Append("\"point_times\":\"" + Escape(ClampTimeline(pointTimes)) + "\","); string text = ComputeHmac(p1SteamId, p2SteamId, p1RoundsWon, p2RoundsWon, isRanked, reporterSteamId, photonRoomId); stringBuilder.Append("\"hmac_signature\":\"" + text + "\""); stringBuilder.Append("}"); string json = stringBuilder.ToString(); string text2 = (isRanked ? "RANKED" : "CASUAL"); Plugin.Log.LogInfo((object)("Reporting " + text2 + " match to API...")); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/matches", json, delegate(bool success, string response) { //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03da: Unknown result type (might be due to invalid IL or missing references) if (success) { Plugin.Log.LogInfo((object)("Match reported successfully: " + response)); int num = ExtractJsonInt(response, "xp_gained"); int num2 = ExtractJsonInt(response, "level"); int num3 = ExtractJsonInt(response, "total_xp"); int lastKnownLevel = CompetitiveUI.LastKnownLevel; string text3 = $"+{num} XP"; List list = new List(); int num4 = response.IndexOf("\"xp_bonuses\":"); if (num4 >= 0) { int num5 = response.IndexOf('[', num4); int num6 = ((num5 >= 0) ? response.IndexOf(']', num5) : (-1)); if (num5 >= 0 && num6 > num5) { string text4 = response.Substring(num5 + 1, num6 - num5 - 1); string[] array = text4.Split(','); foreach (string text5 in array) { string text6 = text5.Trim().Trim('"').Trim(); if (!string.IsNullOrEmpty(text6)) { list.Add(text6); } } } } if (list.Count > 0) { text3 = text3 + " [" + string.Join(", ", list.ToArray()) + "]"; } CompetitiveUI.ShowNotification(text3, new Color(0.4f, 0.8f, 1f), 4f); int num7 = ExtractJsonInt(response, "gold_gained"); if (num7 > 0) { List list2 = new List(); int num8 = response.IndexOf("\"gold_bonuses\":"); if (num8 >= 0) { int num9 = response.IndexOf('[', num8); int num10 = ((num9 >= 0) ? response.IndexOf(']', num9) : (-1)); if (num9 >= 0 && num10 > num9) { string text7 = response.Substring(num9 + 1, num10 - num9 - 1); string[] array2 = text7.Split(','); foreach (string text8 in array2) { string text9 = text8.Trim().Trim('"').Trim(); if (!string.IsNullOrEmpty(text9)) { list2.Add(text9); } } } } string text10 = $"+{num7} gold"; if (list2.Count > 0) { text10 = text10 + " [" + string.Join(", ", list2.ToArray()) + "]"; } CompetitiveUI.QueueNotification(text10, new Color(1f, 0.85f, 0.3f), 4f); } if (num2 > lastKnownLevel && lastKnownLevel >= 0) { CompetitiveUI.QueueNotification($"LEVEL UP! Level {num2}", new Color(1f, 0.85f, 0.3f), 4f); } CompetitiveUI.LastKnownLevel = num2; FetchPlayerStats(MatchTracker.LocalSteamId); FetchMatchHistory(MatchTracker.LocalSteamId); if (isRanked) { string text11 = ExtractJsonString(response, "series_status"); string text12 = ExtractJsonString(response, "series_score"); ActiveRankedSeriesId = null; if (text11 == "active") { CompetitiveUI.QueueNotification("Series: " + text12, new Color(1f, 0.85f, 0.3f), 3f); } else if (text11 == "completed") { CompetitiveUI.QueueNotification("SERIES COMPLETE " + text12 + "!", new Color(0.3f, 1f, 0.3f), 4f); try { string localSteamId = MatchTracker.LocalSteamId; bool won = ((!string.IsNullOrEmpty(localSteamId) && localSteamId == p1SteamId) ? (p1RoundsWon > p2RoundsWon) : (p2RoundsWon > p1RoundsWon)); GameStateWatcher.IncrementSessionRankedSeries(won); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SESSION] series tally update failed: " + ex.Message)); } GameStateWatcher.pendingRegicideCheck = false; } } } else { Plugin.Log.LogError((object)("Failed to report match: " + response)); CompetitiveUI.ShowNotification("Failed to report match", Color.red); EnqueueFailedReport(baseUrl + "/api/v1/matches", json); } })); } private static void AppendCards(StringBuilder sb, List cards) { for (int i = 0; i < cards.Count; i++) { if (i > 0) { sb.Append(","); } MatchTracker.CardPickData cardPickData = cards[i]; sb.Append("{"); sb.Append("\"card_name\":\"" + Escape(cardPickData.CardName) + "\","); sb.Append("\"card_rarity\":\"" + Escape(cardPickData.CardRarity ?? "Unknown") + "\","); sb.Append($"\"pick_order\":{cardPickData.PickOrder},"); sb.Append($"\"round_number\":{cardPickData.RoundNumber}"); if (cardPickData.Rolled) { sb.Append(",\"rolled\":true"); } sb.Append("}"); } } private static void AppendOffers(StringBuilder sb, List offers) { if (offers == null) { return; } for (int i = 0; i < offers.Count; i++) { if (i > 0) { sb.Append(","); } MatchTracker.CardOfferData cardOfferData = offers[i]; sb.Append("{"); sb.Append("\"card_name\":\"" + Escape(cardOfferData.CardName) + "\","); sb.Append($"\"round_number\":{cardOfferData.RoundNumber},"); sb.Append("\"was_picked\":" + (cardOfferData.WasPicked ? "true" : "false")); sb.Append("}"); } } public static void FetchLeaderboard(int limit = 500, int minMatches = 1) { IsLoading = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/leaderboard?limit={limit}&min_matches={minMatches}", delegate(bool success, string response) { IsLoading = false; if (success) { try { LeaderboardData leaderboardData = new LeaderboardData { total_players = ExtractJsonInt(response, "total_players") }; List list = new List(); string[] array = response.Split(new string[1] { "\"rank\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = array[i]; LeaderboardEntry leaderboardEntry = new LeaderboardEntry(); try { int num = text.IndexOf(':'); if (num < 0) { num = -1; } int num2 = text.IndexOf(',', num + 1); if (num >= 0 && num2 > num) { string s = text.Substring(num + 1, num2 - num - 1).Trim(); leaderboardEntry.rank = int.Parse(s); } } catch { leaderboardEntry.rank = i; } leaderboardEntry.steam_id = ExtractJsonString(text, "steam_id"); leaderboardEntry.display_name = ExtractJsonString(text, "display_name"); leaderboardEntry.rating = ExtractJsonInt(text, "rating"); leaderboardEntry.rd = ExtractJsonInt(text, "rd"); leaderboardEntry.total_matches = ExtractJsonInt(text, "total_matches"); leaderboardEntry.wins = ExtractJsonInt(text, "wins"); leaderboardEntry.losses = ExtractJsonInt(text, "losses"); try { int num3 = text.IndexOf("\"win_rate\":"); if (num3 >= 0) { for (num3 += "\"win_rate\":".Length; num3 < text.Length && text[num3] == ' '; num3++) { } int j; for (j = num3; j < text.Length && (char.IsDigit(text[j]) || text[j] == '.' || text[j] == '-'); j++) { } if (j > num3) { leaderboardEntry.win_rate = float.Parse(text.Substring(num3, j - num3), CultureInfo.InvariantCulture); } } } catch { leaderboardEntry.win_rate = 0f; } leaderboardEntry.level = ExtractJsonInt(text, "level"); leaderboardEntry.gold = ExtractJsonInt(text, "gold"); leaderboardEntry.title = ExtractJsonString(text, "title"); leaderboardEntry.title_color = ExtractJsonString(text, "title_color"); leaderboardEntry.rank_name = ExtractJsonString(text, "rank_name"); leaderboardEntry.rank_color = ExtractJsonString(text, "rank_color"); if (!string.IsNullOrEmpty(leaderboardEntry.steam_id)) { list.Add(leaderboardEntry); } } leaderboardData.entries = list.ToArray(); CachedLeaderboard = leaderboardData; ManualLogSource log = Plugin.Log; LeaderboardEntry[] entries = CachedLeaderboard.entries; log.LogInfo((object)$"Leaderboard loaded: {((entries != null) ? entries.Length : 0)} entries"); NativeUI.MarkDirty(); return; } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to parse leaderboard: " + ex.Message)); LastError = "Failed to parse leaderboard data"; return; } } LastError = "Failed to fetch leaderboard: " + response; Plugin.Log.LogError((object)LastError); })); } public static void FetchRecentSeries(int limit = 100) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/series/recent?minutes=10080&limit={limit}", delegate(bool success, string response) { if (success) { try { List list = new List(); string[] array = response.Split(new string[1] { "\"series_id\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { if (list.Count >= limit) { break; } RecentSeriesEntry recentSeriesEntry = new RecentSeriesEntry { winner_name = ExtractJsonString(array[i], "winner_name"), p1_name = ExtractJsonString(array[i], "p1_name"), p2_name = ExtractJsonString(array[i], "p2_name"), p1_wins = ExtractJsonInt(array[i], "p1_series_wins"), p2_wins = ExtractJsonInt(array[i], "p2_series_wins"), winner_steam_id = ExtractJsonString(array[i], "winner_steam_id"), p1_steam_id = ExtractJsonString(array[i], "p1_steam_id"), p2_steam_id = ExtractJsonString(array[i], "p2_steam_id") }; try { int num = array[i].IndexOf("\"p1_rating_change\":"); if (num >= 0) { num += "\"p1_rating_change\":".Length; int j; for (j = num; j < array[i].Length && (char.IsDigit(array[i][j]) || array[i][j] == '.' || array[i][j] == '-'); j++) { } if (j > num) { recentSeriesEntry.p1_rating_change = float.Parse(array[i].Substring(num, j - num), CultureInfo.InvariantCulture); } } } catch { } try { int num2 = array[i].IndexOf("\"p2_rating_change\":"); if (num2 >= 0) { num2 += "\"p2_rating_change\":".Length; int k; for (k = num2; k < array[i].Length && (char.IsDigit(array[i][k]) || array[i][k] == '.' || array[i][k] == '-'); k++) { } if (k > num2) { recentSeriesEntry.p2_rating_change = float.Parse(array[i].Substring(num2, k - num2), CultureInfo.InvariantCulture); } } } catch { } recentSeriesEntry.p1_rating = ExtractJsonInt(array[i], "p1_rating"); recentSeriesEntry.p2_rating = ExtractJsonInt(array[i], "p2_rating"); recentSeriesEntry.completed_at = ExtractJsonString(array[i], "completed_at"); int num3 = array[i].IndexOf("\"bets\":"); if (num3 >= 0) { int num4 = array[i].IndexOf('[', num3); int num5 = ((num4 >= 0) ? FindMatchingBracketStringAware(array[i], num4) : (-1)); if (num4 >= 0 && num5 > num4) { string text = array[i].Substring(num4, num5 - num4 + 1); string[] array2 = text.Split(new string[1] { "\"bettor_name\":" }, StringSplitOptions.None); for (int l = 1; l < array2.Length; l++) { string text2 = "\"bettor_name\":" + array2[l]; SeriesBetEntry seriesBetEntry = new SeriesBetEntry { bettor_name = ExtractJsonString(text2, "bettor_name"), bettor_steam_id = ExtractJsonString(text2, "bettor_steam_id"), bet_on_name = ExtractJsonString(text2, "bet_on_name"), bet_on_steam_id = ExtractJsonString(text2, "bet_on_steam_id"), amount = ExtractJsonInt(text2, "amount"), payout = ExtractJsonInt(text2, "payout"), odds_multiplier = ExtractJsonFloat(text2, "odds_multiplier"), won = (text2.Contains("\"won\":true") || text2.Contains("\"won\": true")) }; if (!string.IsNullOrEmpty(seriesBetEntry.bettor_name)) { recentSeriesEntry.bets.Add(seriesBetEntry); } } } } if (!string.IsNullOrEmpty(recentSeriesEntry.p1_name)) { list.Add(recentSeriesEntry); } } CachedRecentSeries = list; Plugin.Log.LogInfo((object)$"Recent series loaded: {list.Count}"); NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Recent series parse error: " + ex.Message)); } } })); } private static string BuildCosmeticSig(PlayerStatsData s) { if (s == null) { return ""; } try { return string.Join("|", s.active_trail_sku ?? "", s.active_trail_color ?? "", s.active_player_color_sku ?? "", s.active_player_color_hex ?? "", s.active_player_effect_sku ?? "", s.active_cursor_color_sku ?? "", s.active_cursor_color_hex ?? "", s.active_title ?? "", s.active_title_color ?? "", s.display_name ?? "", (s.active_nametag_skus != null) ? string.Join(",", s.active_nametag_skus) : ""); } catch { return Guid.NewGuid().ToString(); } } public static void InvalidateCosmeticSig() { _lastPublishedCosmeticSig = null; } public static void FetchPlayerStats(string steamId, bool force = false) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown" || (!force && IsLoading)) { return; } IsLoading = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + steamId, delegate(bool success, string response) { IsLoading = false; if (success) { try { CachedPlayerStats = JsonUtility.FromJson(response); ParseTopCards(CachedPlayerStats, response); Plugin.Log.LogInfo((object)("Player stats loaded for " + CachedPlayerStats.display_name)); string text = BuildCosmeticSig(CachedPlayerStats); if (text != _lastPublishedCosmeticSig) { _lastPublishedCosmeticSig = text; try { TrailCosmetic.PublishLocalProps(); } catch { } try { PlayerColorCosmetic.PublishLocalProps(); } catch { } try { PlayerEffectCosmetic.PublishLocalProps(); } catch { } try { CursorColorCosmetic.ApplyFromStats(); } catch { } try { NametagStyler.PublishToPhoton(); return; } catch { return; } } return; } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to parse player stats: " + ex.Message)); return; } } if (!response.Contains("404")) { Plugin.Log.LogError((object)("Failed to fetch player stats: " + response)); } })); } public static void FetchPlayerStatsForView(string steamId, Action callback) { if (string.IsNullOrEmpty(steamId)) { callback(null); return; } string localSteamId = MatchTracker.LocalSteamId; string text = ((!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown" && localSteamId != steamId) ? ("?viewer_steam_id=" + Escape(localSteamId)) : ""); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + steamId + text, delegate(bool success, string response) { if (success) { try { PlayerStatsData playerStatsData = JsonUtility.FromJson(response); ParseTopCards(playerStatsData, response); callback(playerStatsData); return; } catch { callback(null); return; } } callback(null); })); } private static void ParseTopCards(PlayerStatsData data, string response) { data.top_card_names = new List(); data.top_card_picks = new List(); data.top_card_win_rates = new List(); data.recent_form = new List(); data.worst_card_names = new List(); data.worst_card_picks = new List(); data.worst_card_win_rates = new List(); data.region_names = new List(); data.region_matches = new List(); try { int num = response.IndexOf("\"top_cards\""); if (num >= 0) { int num2 = response.IndexOf("[", num); int num3 = FindMatchingBracket(response, num2); if (num2 >= 0 && num3 >= 0) { string text = response.Substring(num2, num3 - num2 + 1); if (text != "[]") { string[] array = text.Split(new string[1] { "\"card_name\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length && i <= 10; i++) { string text2 = ExtractJsonString(array[i], ""); int item = ExtractJsonInt(array[i], "times_picked"); float item2 = 0f; try { int num4 = array[i].IndexOf("\"win_rate\":"); if (num4 >= 0) { for (num4 += "\"win_rate\":".Length; num4 < array[i].Length && array[i][num4] == ' '; num4++) { } int j; for (j = num4; j < array[i].Length && (char.IsDigit(array[i][j]) || array[i][j] == '.' || array[i][j] == '-'); j++) { } if (j > num4) { item2 = float.Parse(array[i].Substring(num4, j - num4), CultureInfo.InvariantCulture); } } } catch { } if (!string.IsNullOrEmpty(text2)) { data.top_card_names.Add(text2); data.top_card_picks.Add(item); data.top_card_win_rates.Add(item2); } } } } } } catch { } try { int num5 = response.IndexOf("\"worst_cards\""); if (num5 >= 0) { int num6 = response.IndexOf("[", num5); int num7 = FindMatchingBracket(response, num6); if (num6 >= 0 && num7 >= 0) { string text3 = response.Substring(num6, num7 - num6 + 1); if (text3 != "[]") { string[] array2 = text3.Split(new string[1] { "\"card_name\"" }, StringSplitOptions.None); for (int k = 1; k < array2.Length && k <= 10; k++) { string text4 = ExtractJsonString(array2[k], ""); int item3 = ExtractJsonInt(array2[k], "times_picked"); float item4 = ExtractJsonFloat(array2[k], "win_rate"); if (!string.IsNullOrEmpty(text4)) { data.worst_card_names.Add(text4); data.worst_card_picks.Add(item3); data.worst_card_win_rates.Add(item4); } } } } } } catch { } try { int num8 = response.IndexOf("\"region_breakdown\""); if (num8 >= 0) { int num9 = response.IndexOf("[", num8); int num10 = FindMatchingBracket(response, num9); if (num9 >= 0 && num10 >= 0) { string text5 = response.Substring(num9, num10 - num9 + 1); if (text5 != "[]") { string[] array3 = text5.Split(new string[1] { "\"region\"" }, StringSplitOptions.None); for (int l = 1; l < array3.Length; l++) { string text6 = ExtractJsonString(array3[l], ""); int item5 = ExtractJsonInt(array3[l], "matches"); if (!string.IsNullOrEmpty(text6)) { data.region_names.Add(text6); data.region_matches.Add(item5); } } } } } } catch { } try { int num11 = response.IndexOf("\"recent_form\""); if (num11 >= 0) { int num12 = response.IndexOf("[", num11); int num13 = FindMatchingBracket(response, num12); if (num12 >= 0 && num13 >= 0) { string text7 = response.Substring(num12, num13 - num12 + 1); if (text7 != "[]") { string[] array4 = text7.Split(new string[1] { "\"result\"" }, StringSplitOptions.None); for (int m = 1; m < array4.Length; m++) { string text8 = ExtractJsonString(array4[m], ""); if (!string.IsNullOrEmpty(text8)) { data.recent_form.Add(text8); } } } } } } catch { } data.active_color_skus = new List(); try { int num14 = response.IndexOf("\"active_color_skus\""); if (num14 >= 0) { int num15 = response.IndexOf("[", num14); int num16 = FindMatchingBracket(response, num15); if (num15 >= 0 && num16 >= 0 && num16 > num15) { string text9 = response.Substring(num15 + 1, num16 - num15 - 1); int num17 = 0; while (num17 < text9.Length) { int num18 = text9.IndexOf('"', num17); if (num18 < 0) { break; } int num19 = text9.IndexOf('"', num18 + 1); if (num19 < 0) { break; } string text10 = text9.Substring(num18 + 1, num19 - num18 - 1); if (!string.IsNullOrEmpty(text10)) { data.active_color_skus.Add(text10); } num17 = num19 + 1; } } } } catch { } data.active_nametag_skus = new List(); try { int num20 = response.IndexOf("\"active_nametag_skus\""); if (num20 >= 0) { int num21 = response.IndexOf("[", num20); int num22 = FindMatchingBracket(response, num21); if (num21 >= 0 && num22 >= 0 && num22 > num21) { string text11 = response.Substring(num21 + 1, num22 - num21 - 1); int num23 = 0; while (num23 < text11.Length) { int num24 = text11.IndexOf('"', num23); if (num24 < 0) { break; } int num25 = text11.IndexOf('"', num24 + 1); if (num25 < 0) { break; } string text12 = text11.Substring(num24 + 1, num25 - num24 - 1); if (!string.IsNullOrEmpty(text12)) { data.active_nametag_skus.Add(text12); } num23 = num25 + 1; } } } } catch { } data.rating_history = new List(); data.rating_history_times = new List(); try { int num26 = response.IndexOf("\"recent_rating_history\""); if (num26 >= 0) { int num27 = response.IndexOf("[", num26); int num28 = FindMatchingBracket(response, num27); if (num27 >= 0 && num28 >= 0) { string text13 = response.Substring(num27, num28 - num27 + 1); if (text13 != "[]") { DateTime dateTime = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc); float num29 = 0f; string[] array5 = text13.Split(new string[1] { "\"rating\"" }, StringSplitOptions.None); for (int n = 1; n < array5.Length; n++) { int num30 = array5[n].IndexOf(':'); if (num30 < 0) { continue; } int num31; for (num31 = num30 + 1; num31 < array5[n].Length && array5[n][num31] == ' '; num31++) { } int num32; for (num32 = num31; num32 < array5[n].Length && (char.IsDigit(array5[n][num32]) || array5[n][num32] == '.' || array5[n][num32] == '-'); num32++) { } if (num32 <= num31) { continue; } float item6 = float.Parse(array5[n].Substring(num31, num32 - num31), CultureInfo.InvariantCulture); data.rating_history.Add(item6); float num33 = num29 + 0.01f; try { string text14 = ExtractJsonString(array5[n], "date"); if (!string.IsNullOrEmpty(text14)) { DateTime dateTime2 = DateTime.Parse(text14, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); num33 = (float)(dateTime2 - dateTime).TotalDays; } } catch { } num29 = num33; data.rating_history_times.Add(num33); } } } } } catch { } if (data.rating_history.Count > 0 && data.rating_history[0] != 1500f) { data.rating_history.Insert(0, 1500f); if (data.rating_history_times.Count > 0) { data.rating_history_times.Insert(0, data.rating_history_times[0] - 1f); } } Plugin.Log.LogInfo((object)$"[STATS] Parsed {data.rating_history.Count} rating history points for {data.display_name} (oldest→newest, 1500 baseline prepended)"); } public static void FetchAchievementsForView(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown" || (steamId == selectedAchSteamId && SelectedPlayerAchievements != null)) { return; } selectedAchSteamId = steamId; SelectedPlayerAchievements = null; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/achievements/" + steamId, delegate(bool success, string response) { if (success) { try { Dictionary dictionary = new Dictionary(); string[] array = response.Split(new string[1] { "\"achievement_key\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = ExtractJsonString(array[i], ""); if (!string.IsNullOrEmpty(text)) { bool unlocked = array[i].Contains("\"unlocked\":true") || array[i].Contains("\"unlocked\": true"); dictionary[text] = new AchievementData { achievement_key = text, unlocked = unlocked }; } } SelectedPlayerAchievements = dictionary; NativeUI.MarkDirty(); } catch { } } })); } public static void FetchAchievementsForCompare(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown" || CompareAchievements.ContainsKey(steamId) || _compareAchFetching.Contains(steamId)) { return; } _compareAchFetching.Add(steamId); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/achievements/" + steamId, delegate(bool success, string response) { _compareAchFetching.Remove(steamId); if (!success) { return; } try { Dictionary dictionary = new Dictionary(); string[] array = response.Split(new string[1] { "\"achievement_key\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = ExtractJsonString(array[i], ""); if (!string.IsNullOrEmpty(text)) { bool unlocked = array[i].Contains("\"unlocked\":true") || array[i].Contains("\"unlocked\": true"); dictionary[text] = new AchievementData { achievement_key = text, unlocked = unlocked }; string value = ExtractJsonString(array[i], "name"); if (!string.IsNullOrEmpty(value)) { AchievementDisplayNames[text] = value; } } } CompareAchievements[steamId] = dictionary; NativeUI.MarkDirty(); } catch { } })); } private static int FindMatchingBracket(string s, int openPos) { if (openPos < 0 || openPos >= s.Length) { return -1; } int num = 0; for (int i = openPos; i < s.Length; i++) { if (s[i] == '[') { num++; } else if (s[i] == ']') { num--; if (num == 0) { return i; } } } return -1; } private static int FindMatchingBrace(string s, int openPos) { if (openPos < 0 || openPos >= s.Length) { return -1; } int num = 0; for (int i = openPos; i < s.Length; i++) { if (s[i] == '{') { num++; } else if (s[i] == '}') { num--; if (num == 0) { return i; } } } return -1; } public static void FetchCardTiers(string steamId, string filter, Action> onLoaded) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { onLoaded?.Invoke(new Dictionary()); return; } string url = baseUrl + "/api/v1/players/" + Escape(steamId) + "/card-tiers?filter=" + Escape(filter); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool success, string response) { Dictionary dictionary = new Dictionary(); if (!success || string.IsNullOrEmpty(response)) { onLoaded?.Invoke(dictionary); } else { try { int num = response.IndexOf("\"tiers\""); if (num < 0) { onLoaded?.Invoke(dictionary); return; } int num2 = response.IndexOf('{', num); int num3 = FindMatchingBrace(response, num2); if (num2 < 0 || num3 < 0) { onLoaded?.Invoke(dictionary); return; } string text = response.Substring(num2 + 1, num3 - num2 - 1); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('"', num4); if (num5 < 0) { break; } int num6 = text.IndexOf('"', num5 + 1); if (num6 < 0) { break; } string text2 = text.Substring(num5 + 1, num6 - num5 - 1); int num7 = text.IndexOf(':', num6); if (num7 < 0) { break; } int num8 = text.IndexOf('"', num7); if (num8 < 0) { break; } int num9 = text.IndexOf('"', num8 + 1); if (num9 < 0) { break; } string value = text.Substring(num8 + 1, num9 - num8 - 1); dictionary[text2.ToLower()] = value; num4 = num9 + 1; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CARD-TIER] parse: " + ex.Message)); } onLoaded?.Invoke(dictionary); } })); } public static void SetCardTier(string steamId, string cardName, string filter, string tier) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } string text = ComputeHmacHex("card-tier:" + steamId + ":" + cardName + ":" + filter + ":" + tier); string url = baseUrl + "/api/v1/players/" + Escape(steamId) + "/card-tiers?card_name=" + Escape(cardName) + "&filter=" + Escape(filter) + "&tier=" + Escape(tier) + "&sig=" + text; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { if (!ok) { Plugin.Log.LogWarning((object)("[CARD-TIER] set failed: " + resp)); } })); } public static void FetchCardStats(int limit = 30, string steamId = null, string sortBy = "times_picked", string isRanked = null) { IsLoading = true; string text = $"{baseUrl}/api/v1/cards?limit={limit}&sort_by={sortBy}&min_picks=1"; if (!string.IsNullOrEmpty(steamId) && steamId != "unknown") { text = text + "&steam_id=" + steamId; } if (!string.IsNullOrEmpty(isRanked)) { text = text + "&is_ranked=" + isRanked; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(text, delegate(bool success, string response) { IsLoading = false; if (success) { try { if (string.IsNullOrEmpty(response) || response.Trim() == "[]") { CachedCardStats = new List(); Plugin.Log.LogInfo((object)"Card stats: no data yet"); } else { List list = new List(); string[] array = response.Split(new string[1] { "\"card_name\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text2 = array[i]; CardStatData cardStatData = new CardStatData { card_name = ExtractJsonString(text2, ""), card_rarity = ExtractJsonString(text2, "card_rarity"), times_picked = ExtractJsonInt(text2, "times_picked"), wins_with_card = ExtractJsonInt(text2, "wins_with_card"), times_offered = ExtractJsonInt(text2, "times_offered"), pass_rate = ExtractJsonFloat(text2, "pass_rate") }; try { string text3 = text2; int num = text3.IndexOf("\"win_rate\":"); if (num >= 0) { for (num += "\"win_rate\":".Length; num < text3.Length && text3[num] == ' '; num++) { } int j; for (j = num; j < text3.Length && (char.IsDigit(text3[j]) || text3[j] == '.' || text3[j] == '-'); j++) { } if (j > num) { cardStatData.win_rate = float.Parse(text3.Substring(num, j - num), CultureInfo.InvariantCulture); } } } catch { cardStatData.win_rate = 0f; } if (!string.IsNullOrEmpty(cardStatData.card_name)) { list.Add(cardStatData); } } CachedCardStats = list; Plugin.Log.LogInfo((object)$"Card stats loaded: {CachedCardStats.Count} cards"); } return; } catch (Exception ex) { CachedCardStats = new List(); Plugin.Log.LogError((object)("Failed to parse card stats: " + ex.Message)); return; } } Plugin.Log.LogError((object)("Failed to fetch card stats: " + response)); })); } public static void FetchMatchHistory(string steamId, int limit = 400) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown" || _historyFetchInFlight) { return; } _historyFetchInFlight = true; FetchMatchSummary(steamId); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/players/{steamId}/matches?limit={limit}", delegate(bool success, string response) { if (!success) { _historyFetchInFlight = false; } else { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ParseMatchHistoryChunked(response, append: false, limit)); } })); } public static void FetchMoreMatchHistory(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown" || _historyFetchInFlight || MatchHistoryLoadedAll) { return; } if (CachedMatchHistory == null) { FetchMatchHistory(steamId); return; } _historyFetchInFlight = true; int count = CachedMatchHistory.Count; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/players/{steamId}/matches?limit={400}&offset={count}", delegate(bool success, string response) { if (!success) { _historyFetchInFlight = false; } else { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ParseMatchHistoryChunked(response, append: true, 400)); } })); } public static void FetchMatchSummary(string steamId) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + steamId + "/matches/summary", delegate(bool ok, string resp) { if (ok && !string.IsNullOrEmpty(resp)) { HistoryTotalMatches = ExtractJsonInt(resp, "total"); HistoryTotalRankedGroups = ExtractJsonInt(resp, "ranked_groups"); HistoryTotalCasual = ExtractJsonInt(resp, "casual_matches"); NativeUI.MarkDirty(); } })); } private static IEnumerator ParseMatchHistoryChunked(string response, bool append, int requested) { if (string.IsNullOrEmpty(response) || response.Trim() == "[]") { if (!append) { CachedMatchHistory = new List(); } MatchHistoryLoadedAll = true; _historyFetchInFlight = false; yield break; } string[] parts; try { parts = response.Split(new string[1] { "\"match_id\"" }, StringSplitOptions.None); } catch (Exception ex) { Exception ex2 = ex; if (!append) { CachedMatchHistory = new List(); } _historyFetchInFlight = false; Plugin.Log.LogError((object)("Failed to parse match history: " + ex2.Message)); yield break; } List entries = new List(Math.Max(0, parts.Length - 1)); for (int i = 1; i < parts.Length; i++) { try { entries.Add(ParseMatchHistoryChunkEntry(parts[i])); } catch { } if (i % 80 == 0) { yield return null; } } MatchHistoryLoadedAll = entries.Count < requested; if (append && CachedMatchHistory != null) { HashSet seen = new HashSet(); foreach (MatchHistoryEntry m in CachedMatchHistory) { if (!string.IsNullOrEmpty(m.match_id)) { seen.Add(m.match_id); } } int added = 0; foreach (MatchHistoryEntry m2 in entries) { if (string.IsNullOrEmpty(m2.match_id) || seen.Add(m2.match_id)) { CachedMatchHistory.Add(m2); added++; } } Plugin.Log.LogInfo((object)$"Match history extended: +{added} (total {CachedMatchHistory.Count}, all={MatchHistoryLoadedAll})"); } else { CachedMatchHistory = entries; Plugin.Log.LogInfo((object)$"Match history loaded: {CachedMatchHistory.Count} matches (chunked parse, all={MatchHistoryLoadedAll})"); } _historyFetchInFlight = false; NativeUI.MarkDirty(); } public static void OnSeriesCompletedVsOpponent(string oppSteamId, bool won) { if (string.IsNullOrEmpty(oppSteamId) || oppSteamId.StartsWith("photon_")) { return; } if (CachedOppLifetime.TryGetValue(oppSteamId, out var value) && value != null && value.Length >= 4) { if (won) { value[2]++; } else { value[3]++; } } _oppLifetimeRefetchAfter[oppSteamId] = Time.realtimeSinceStartup + 90f; _oppLifetimeRequested.Remove(oppSteamId); } public static void FetchOpponentLifetime(string oppSteamId) { string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(oppSteamId) || string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown" || oppSteamId == localSteamId || (_oppLifetimeRefetchAfter.TryGetValue(oppSteamId, out var value) && Time.realtimeSinceStartup < value) || !_oppLifetimeRequested.Add(oppSteamId)) { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + oppSteamId + "?viewer_steam_id=" + localSteamId, delegate(bool ok, string resp) { if (!ok || string.IsNullOrEmpty(resp)) { _oppLifetimeRefetchAfter[oppSteamId] = Time.realtimeSinceStartup + 10f; _oppLifetimeRequested.Remove(oppSteamId); } else { int num = ExtractJsonInt(resp, "h2h_ranked_wins") + ExtractJsonInt(resp, "h2h_casual_wins"); int num2 = ExtractJsonInt(resp, "h2h_ranked_losses") + ExtractJsonInt(resp, "h2h_casual_losses"); int num3 = ExtractJsonInt(resp, "h2h_series_wins"); int num4 = ExtractJsonInt(resp, "h2h_series_losses"); CachedOppLifetime[oppSteamId] = new int[4] { num, num2, num3, num4 }; NativeUI.MarkDirty(); } })); } private static MatchHistoryEntry ParseMatchHistoryChunkEntry(string chunk) { MatchHistoryEntry matchHistoryEntry = new MatchHistoryEntry(); matchHistoryEntry.match_id = ExtractJsonString(chunk, ""); matchHistoryEntry.opponent_name = ExtractJsonString(chunk, "opponent_name"); matchHistoryEntry.opponent_steam_id = ExtractJsonString(chunk, "opponent_steam_id"); matchHistoryEntry.opponent_title = ExtractJsonString(chunk, "opponent_title"); matchHistoryEntry.opponent_title_color = ExtractJsonString(chunk, "opponent_title_color"); matchHistoryEntry.player_rounds_won = ExtractJsonInt(chunk, "player_rounds_won"); matchHistoryEntry.opponent_rounds_won = ExtractJsonInt(chunk, "opponent_rounds_won"); matchHistoryEntry.player_points = ExtractJsonInt(chunk, "player_points"); matchHistoryEntry.opponent_points = ExtractJsonInt(chunk, "opponent_points"); matchHistoryEntry.won = chunk.Contains("\"won\":true") || chunk.Contains("\"won\": true"); matchHistoryEntry.is_ranked = chunk.Contains("\"is_ranked\":true") || chunk.Contains("\"is_ranked\": true"); matchHistoryEntry.ended_at = ExtractJsonString(chunk, "ended_at"); matchHistoryEntry.cards_display = ExtractCardNames(chunk); matchHistoryEntry.opp_cards_display = ExtractCardNames(chunk, "opponent_cards_picked"); matchHistoryEntry.series_id = ExtractJsonString(chunk, "series_id"); matchHistoryEntry.series_score = ExtractJsonString(chunk, "series_score"); matchHistoryEntry.series_rating_change = ExtractJsonFloat(chunk, "series_rating_change"); matchHistoryEntry.xp_gained = ExtractJsonInt(chunk, "xp_gained"); matchHistoryEntry.gold_gained = ExtractJsonInt(chunk, "gold_gained"); matchHistoryEntry.series_gold_gained = ExtractJsonInt(chunk, "series_gold_gained"); matchHistoryEntry.player_fps_avg = ExtractJsonInt(chunk, "player_fps_avg"); matchHistoryEntry.opponent_fps_avg = ExtractJsonInt(chunk, "opponent_fps_avg"); matchHistoryEntry.player_bullets_fired = ExtractJsonInt(chunk, "player_bullets_fired"); matchHistoryEntry.player_bullets_hit = ExtractJsonInt(chunk, "player_bullets_hit"); matchHistoryEntry.player_blocks_activated = ExtractJsonInt(chunk, "player_blocks_activated"); matchHistoryEntry.player_blocks_successful = ExtractJsonInt(chunk, "player_blocks_successful"); matchHistoryEntry.player_keys_pressed = ExtractJsonInt(chunk, "player_keys_pressed"); matchHistoryEntry.player_active_seconds = ExtractJsonFloat(chunk, "player_active_seconds"); matchHistoryEntry.opp_bullets_fired = ExtractJsonInt(chunk, "opp_bullets_fired"); matchHistoryEntry.opp_bullets_hit = ExtractJsonInt(chunk, "opp_bullets_hit"); matchHistoryEntry.opp_blocks_activated = ExtractJsonInt(chunk, "opp_blocks_activated"); matchHistoryEntry.opp_blocks_successful = ExtractJsonInt(chunk, "opp_blocks_successful"); matchHistoryEntry.opp_keys_pressed = ExtractJsonInt(chunk, "opp_keys_pressed"); matchHistoryEntry.opp_active_seconds = ExtractJsonFloat(chunk, "opp_active_seconds"); matchHistoryEntry.point_timeline = ExtractJsonString(chunk, "point_timeline"); matchHistoryEntry.player_fps_timeline = ExtractJsonString(chunk, "player_fps_timeline"); matchHistoryEntry.opp_fps_timeline = ExtractJsonString(chunk, "opp_fps_timeline"); matchHistoryEntry.player_ping_avg = ExtractJsonInt(chunk, "player_ping_avg"); matchHistoryEntry.opponent_ping_avg = ExtractJsonInt(chunk, "opponent_ping_avg"); matchHistoryEntry.player_ping_timeline = ExtractJsonString(chunk, "player_ping_timeline"); matchHistoryEntry.opp_ping_timeline = ExtractJsonString(chunk, "opp_ping_timeline"); matchHistoryEntry.player_hit_timeline = ExtractJsonString(chunk, "player_hit_timeline"); matchHistoryEntry.opp_hit_timeline = ExtractJsonString(chunk, "opp_hit_timeline"); matchHistoryEntry.player_block_timeline = ExtractJsonString(chunk, "player_block_timeline"); matchHistoryEntry.opp_block_timeline = ExtractJsonString(chunk, "opp_block_timeline"); matchHistoryEntry.point_times = ExtractJsonString(chunk, "point_times"); matchHistoryEntry.duration_seconds = ExtractJsonInt(chunk, "duration_seconds"); return matchHistoryEntry; } private static List ParseMatchHistoryJson(string response) { List list = new List(); if (string.IsNullOrEmpty(response) || response.Trim() == "[]") { return list; } string[] array = response.Split(new string[1] { "\"match_id\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { MatchHistoryEntry matchHistoryEntry = new MatchHistoryEntry(); string text = array[i]; matchHistoryEntry.match_id = ExtractJsonString(text, ""); matchHistoryEntry.opponent_name = ExtractJsonString(text, "opponent_name"); matchHistoryEntry.opponent_steam_id = ExtractJsonString(text, "opponent_steam_id"); matchHistoryEntry.opponent_title = ExtractJsonString(text, "opponent_title"); matchHistoryEntry.opponent_title_color = ExtractJsonString(text, "opponent_title_color"); matchHistoryEntry.player_rounds_won = ExtractJsonInt(text, "player_rounds_won"); matchHistoryEntry.opponent_rounds_won = ExtractJsonInt(text, "opponent_rounds_won"); matchHistoryEntry.player_points = ExtractJsonInt(text, "player_points"); matchHistoryEntry.opponent_points = ExtractJsonInt(text, "opponent_points"); matchHistoryEntry.won = text.Contains("\"won\":true") || text.Contains("\"won\": true"); matchHistoryEntry.is_ranked = text.Contains("\"is_ranked\":true") || text.Contains("\"is_ranked\": true"); matchHistoryEntry.ended_at = ExtractJsonString(text, "ended_at"); matchHistoryEntry.cards_display = ExtractCardNames(text); matchHistoryEntry.opp_cards_display = ExtractCardNames(text, "opponent_cards_picked"); matchHistoryEntry.series_id = ExtractJsonString(text, "series_id"); matchHistoryEntry.series_score = ExtractJsonString(text, "series_score"); matchHistoryEntry.series_rating_change = ExtractJsonFloat(text, "series_rating_change"); matchHistoryEntry.xp_gained = ExtractJsonInt(text, "xp_gained"); matchHistoryEntry.gold_gained = ExtractJsonInt(text, "gold_gained"); matchHistoryEntry.series_gold_gained = ExtractJsonInt(text, "series_gold_gained"); matchHistoryEntry.player_fps_avg = ExtractJsonInt(text, "player_fps_avg"); matchHistoryEntry.opponent_fps_avg = ExtractJsonInt(text, "opponent_fps_avg"); matchHistoryEntry.duration_seconds = ExtractJsonInt(text, "duration_seconds"); list.Add(matchHistoryEntry); } return list; } public static void FetchMatchHistoryForView(string steamId, Action> callback, int limit = 400) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { callback?.Invoke(new List()); return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/players/{steamId}/matches?limit={limit}", delegate(bool success, string response) { List obj; try { obj = (success ? ParseMatchHistoryJson(response) : new List()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[LBVIEW] match parse failed: " + ex.Message)); obj = new List(); } try { callback?.Invoke(obj); } catch { } })); } private static string ExtractJsonString(string json, string key) { try { string text = (string.IsNullOrEmpty(key) ? ":\"" : ("\"" + key + "\":\"")); int num = json.IndexOf(text); if (num < 0) { return ""; } num += text.Length; int num2 = num; StringBuilder stringBuilder = new StringBuilder(); while (num2 < json.Length) { char c = json[num2]; if (c == '\\' && num2 + 1 < json.Length) { char c2 = json[num2 + 1]; switch (c2) { case '"': stringBuilder.Append('"'); num2 += 2; break; case '\\': stringBuilder.Append('\\'); num2 += 2; break; case '/': stringBuilder.Append('/'); num2 += 2; break; case 'n': stringBuilder.Append('\n'); num2 += 2; break; case 'r': stringBuilder.Append('\r'); num2 += 2; break; case 't': stringBuilder.Append('\t'); num2 += 2; break; case 'b': stringBuilder.Append('\b'); num2 += 2; break; case 'f': stringBuilder.Append('\f'); num2 += 2; break; case 'u': if (num2 + 5 < json.Length) { string s = json.Substring(num2 + 2, 4); if (int.TryParse(s, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result)) { stringBuilder.Append((char)result); num2 += 6; break; } } stringBuilder.Append(c2); num2 += 2; break; default: stringBuilder.Append(c2); num2 += 2; break; } } else { if (c == '"') { break; } stringBuilder.Append(c); num2++; } } return stringBuilder.ToString(); } catch { return ""; } } public static string ExtractJsonStringPublic(string json, string key) { return ExtractJsonString(json, key); } public static int ExtractJsonIntPublic(string json, string key) { return ExtractJsonInt(json, key); } private static List ExtractJsonStringArray(string json, string key) { List list = new List(); try { if (string.IsNullOrEmpty(json)) { return list; } int num = json.IndexOf("\"" + key + "\":", StringComparison.Ordinal); if (num < 0) { return list; } int num2 = json.IndexOf('[', num); if (num2 < 0) { return list; } bool flag = false; bool flag2 = false; StringBuilder stringBuilder = new StringBuilder(32); for (int i = num2 + 1; i < json.Length; i++) { char c = json[i]; if (flag) { if (flag2) { stringBuilder.Append(c); flag2 = false; continue; } switch (c) { case '\\': flag2 = true; break; case '"': flag = false; if (stringBuilder.Length > 0) { list.Add(stringBuilder.ToString()); } stringBuilder.Length = 0; break; default: stringBuilder.Append(c); break; } continue; } switch (c) { case '"': flag = true; continue; case ']': break; default: continue; } break; } } catch { } return list; } public static float ExtractJsonFloatPublic(string json, string key) { return ExtractJsonFloat(json, key); } private static int ExtractJsonInt(string json, string key) { try { string text = "\"" + key + "\":"; int num = json.IndexOf(text); if (num < 0) { return 0; } for (num += text.Length; num < json.Length && (json[num] == ' ' || json[num] == '\t'); num++) { } int i; for (i = num; i < json.Length && (char.IsDigit(json[i]) || json[i] == '-'); i++) { } if (i == num) { return 0; } return int.Parse(json.Substring(num, i - num)); } catch { return 0; } } private static float ExtractJsonFloat(string json, string key) { try { string text = "\"" + key + "\":"; int num = json.IndexOf(text); if (num < 0) { return 0f; } for (num += text.Length; num < json.Length && (json[num] == ' ' || json[num] == '\t'); num++) { } if (num < json.Length && json[num] == 'n') { return 0f; } int i; for (i = num; i < json.Length && (char.IsDigit(json[i]) || json[i] == '.' || json[i] == '-'); i++) { } if (i == num) { return 0f; } return float.Parse(json.Substring(num, i - num), CultureInfo.InvariantCulture); } catch { return 0f; } } private static bool ExtractJsonBool(string json, string key) { try { string text = "\"" + key + "\":"; int num = json.IndexOf(text); if (num < 0) { return false; } for (num += text.Length; num < json.Length && (json[num] == ' ' || json[num] == '\t'); num++) { } return num < json.Length && json[num] == 't'; } catch { return false; } } private static string ExtractCardNames(string chunk, string key = "cards_picked") { try { int num = chunk.IndexOf("\"" + key + "\""); if (num < 0) { return ""; } int num2 = chunk.IndexOf("[", num); int num3 = chunk.IndexOf("]", num2); if (num2 < 0 || num3 < 0) { return ""; } string text = chunk.Substring(num2, num3 - num2 + 1); if (text == "[]") { return ""; } List list = new List(); string[] array = text.Split(new string[1] { "\"card_name\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text2 = ExtractJsonString(array[i], ""); if (!string.IsNullOrEmpty(text2) && text2 != "Unknown") { list.Add(text2); } } return (list.Count > 0) ? string.Join(", ", list.ToArray()) : ""; } catch { return ""; } } public static void TriggerGlickoRecalc() { string text = (Plugin.ApiBaseUrl.Value.Contains("192.168") ? "dev" : "dev"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/glicko/recalculate?api_key=" + text, "", delegate(bool success, string response) { if (success) { Plugin.Log.LogInfo((object)("Glicko-2 recalculation triggered: " + response)); FetchPlayerStats(MatchTracker.LocalSteamId); } else { Plugin.Log.LogWarning((object)("Glicko recalc failed: " + response)); } })); } public static void SendSeriesPreflight(string mySteamId, string oppSteamId) { if (string.IsNullOrEmpty(mySteamId) || string.IsNullOrEmpty(oppSteamId)) { return; } string text = ((string.Compare(mySteamId, oppSteamId, StringComparison.Ordinal) <= 0) ? mySteamId : oppSteamId); string text2 = ((text == mySteamId) ? oppSteamId : mySteamId); string text3 = ComputeHmacHex("preflight:" + text + ":" + text2); string s = MatchTracker.LocalDisplayName ?? mySteamId; string s2 = GameStateWatcher.OpponentDisplayName ?? oppSteamId; string text4 = ""; try { Room currentRoom = PhotonNetwork.CurrentRoom; text4 = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; } catch { } string url = baseUrl + "/api/v1/series/preflight?p1_steam_id=" + Escape(mySteamId) + "&p2_steam_id=" + Escape(oppSteamId) + "&p1_name=" + Escape(s) + "&p2_name=" + Escape(s2) + "&room_id=" + UnityWebRequest.EscapeURL(text4) + "&sig=" + text3; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { //IL_010a: Unknown result type (might be due to invalid IL or missing references) if (ok) { string text5 = ExtractJsonString(resp, "series_id"); if (!string.IsNullOrEmpty(text5)) { ActiveRankedSeriesId = text5; Plugin.Log.LogInfo((object)("[PREFLIGHT] series_id=" + text5 + " status=" + ExtractJsonString(resp, "status"))); try { string text6 = ExtractJsonString(resp, "status"); if (text6 == "exists") { int num = (int)ExtractJsonFloat(resp, "p1_wins"); int num2 = (int)ExtractJsonFloat(resp, "p2_wins"); if (num > 0 || num2 > 0) { string text7 = ExtractJsonString(resp, "p1_steam_id"); bool flag = text7 == mySteamId; int num3 = (flag ? num : num2); int num4 = (flag ? num2 : num); GameStateWatcher.AdoptSeriesScore(num3, num4); CompetitiveUI.QueueNotification($"Resuming series at {num3}-{num4}", new Color(1f, 0.85f, 0.3f), 4f); } } return; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PREFLIGHT] score adopt failed: " + ex.Message)); return; } } string text8 = ExtractJsonString(resp, "status"); if (text8 == "not_ranked") { Plugin.Log.LogInfo((object)"[PREFLIGHT] server says not_ranked (a player has ranked disabled) — treating match as casual"); try { GameStateWatcher.DowngradeToCasual("opponent has ranked disabled"); return; } catch { return; } } Plugin.Log.LogInfo((object)("[PREFLIGHT] response: " + resp)); } else { Plugin.Log.LogWarning((object)("[PREFLIGHT] failed: " + resp)); } })); } public static void ToggleRanked(string steamId, bool enabled, int attempt = 1, string displayName = null) { string text = displayName; if (string.IsNullOrEmpty(text)) { try { text = MatchTracker.LocalDisplayName; } catch { text = null; } } if (GameStateWatcher.IsPlaceholderName(text, steamId)) { text = null; } string text2 = (string.IsNullOrEmpty(text) ? "" : ("&display_name=" + UnityWebRequest.EscapeURL(text) + "&name_sig=" + ComputeHmacHex("toggle-ranked-name:" + steamId + ":" + text))); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/mod/toggle-ranked/" + steamId + "?enabled=" + enabled.ToString().ToLower() + "&sig=" + ComputeHmacHex("toggle-ranked:" + steamId + ":" + enabled.ToString().ToLower()) + text2, "", delegate(bool success, string response) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (success) { Plugin.Log.LogInfo((object)$"Ranked mode set to {enabled}"); CompetitiveUI.ShowNotification(enabled ? "Ranked mode ON" : "Ranked mode OFF", enabled ? Color.green : Color.yellow); } else if ((response ?? "").Contains("401") && attempt < 3) { Plugin.Log.LogWarning((object)$"[RANKED] toggle got 401 (attempt {attempt}) — retrying after session establishes"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(RetryToggleRanked(steamId, enabled, attempt + 1)); } else { Plugin.Log.LogError((object)("Failed to toggle ranked: " + response)); } })); } private static IEnumerator RetryToggleRanked(string steamId, bool enabled, int attempt) { float t = 0f; while (t < 6f && !SteamAuth.HasFreshToken) { t += 0.5f; yield return (object)new WaitForSeconds(0.5f); } yield return (object)new WaitForSeconds(0.3f); ToggleRanked(steamId, enabled, attempt); } public static void TickLeaveRecovery() { TickEscapeRetry(); float realtimeSinceStartup = Time.realtimeSinceStartup; if (CurrentQueueState == QueueState.Leaving && realtimeSinceStartup - rankedLeavingSince > 45f) { queueGen++; CurrentQueueState = QueueState.Idle; Plugin.Log.LogWarning((object)"[QUEUE] Leaving state stuck past timeout -- recovered to Idle"); NativeUI.MarkDirty(); } if (CurrentTeamQueueState == TeamQueueState.Leaving && realtimeSinceStartup - teamLeavingSince > 45f) { teamGen++; CurrentTeamQueueState = TeamQueueState.Idle; Plugin.Log.LogWarning((object)"[TEAM-QUEUE] Leaving state stuck past timeout -- recovered to Idle"); NativeUI.MarkDirty(); } if (OvtQueueStatus == "leaving" && realtimeSinceStartup - _ovtLeavingSince > 45f) { ovtGen++; OvtQueueStatus = ""; Plugin.Log.LogWarning((object)"[1v2] Leaving state stuck past timeout -- recovered"); NativeUI.MarkDirty(); } if (FfaQueueStatus == "leaving" && realtimeSinceStartup - _ffaLeavingSince > 45f) { ffaGen++; FfaQueueStatus = ""; if (_ffaLeaveIntent && string.IsNullOrEmpty(OpenFfaLobbyId) && !string.IsNullOrEmpty(_ffaLeaveTargetLobby)) { OpenFfaLobbyId = _ffaLeaveTargetLobby; } Plugin.Log.LogWarning((object)("[FFA] Leaving state stuck past timeout -- recovered" + (_ffaLeaveIntent ? (" (leave retry re-armed for " + OpenFfaLobbyId + ")") : ""))); NativeUI.MarkDirty(); } if ((!string.IsNullOrEmpty(ActiveFfaLobbyId) || !string.IsNullOrEmpty(OpenFfaLobbyId)) && !IsFfaQueuePolling && FfaQueueStatus != "leaving") { bool flag = false; try { flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode; } catch { } bool flag2 = false; try { flag2 = flag && !CompetitiveRoomDetect.IsCompetitiveRoom() && !string.IsNullOrEmpty(OpenFfaLobbyId) && string.IsNullOrEmpty(ActiveFfaLobbyId); } catch { } if (flag2) { Plugin.Log.LogInfo((object)"[FFA-LOBBY] waiting in a casual game with an open lobby seat -- resuming poll to catch the host's Start"); IsFfaQueuePolling = true; _ffaRoomlessSince = -1f; } else if (!flag) { if (_ffaRoomlessSince < 0f) { _ffaRoomlessSince = realtimeSinceStartup; } if (realtimeSinceStartup - _ffaRoomlessSince > 20f) { Plugin.Log.LogInfo((object)"[FFA] holding a lobby but not in a room -- resuming queue poll so the server can free us"); IsFfaQueuePolling = true; _ffaRoomlessSince = -1f; } } else { _ffaRoomlessSince = -1f; } } else { _ffaRoomlessSince = -1f; } } public static void EscapeAllQueues(Action done = null) { EscapePending = true; TearDownAllQueueBeliefs(); SendEscapeRequest(done); } private static void TearDownAllQueueBeliefs() { try { queueGen++; teamGen++; ovtGen++; ffaGen++; CurrentQueueState = QueueState.Idle; IsQueuePolling = false; IsTeamQueuePolling = false; ActiveTeamSeriesId = null; IsOvtQueuePolling = false; OvtQueueStatus = ""; ActiveOvt1v2SeriesId = null; IsFfaQueuePolling = false; FfaQueueStatus = ""; FfaQueueCount = 0; FfaGatherSecondsLeft = -1; ActiveFfaLobbyId = null; OpenFfaLobbyId = null; FfaLockedRoster = null; FfaMySlot = -1; FfaLobbyPlayerCount = 0; FfaLobbyIsHost = false; FfaLobbyCanStart = false; FfaLobbyMembers = null; FfaLobbyMemberCount = 0; _ffaLeaveIntent = false; _ffaLeaveTargetLobby = null; _ffaJoinCountdownKey = null; _ffaJoinCountdownActiveToken = 0; _ffaRoomlessSince = -1f; try { CompetitiveUI.CancelFfaStartCountdown(); } catch { } try { Plugin.ClearPendingFfaSlot(); } catch { } try { string text = Plugin.PendingRankedRoom ?? ""; if (text.StartsWith("ranked_") || text.StartsWith("team_") || text.StartsWith("ovt_") || text.StartsWith("ffa_") || text.StartsWith("sct-")) { Plugin.ClearPendingRoom(); } } catch { } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ESCAPE] teardown: " + ex.Message)); } NativeUI.MarkDirty(); } private static void SendEscapeRequest(Action done) { string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { done?.Invoke(arg1: false, "identity not resolved yet"); return; } _escapeRetryAt = Time.unscaledTime; string url = baseUrl + "/api/v1/queues/escape?steam_id=" + UnityWebRequest.EscapeURL(localSteamId); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(url, "", delegate(bool ok, string resp) { //IL_006d: 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) if (ok) { EscapePending = false; TearDownAllQueueBeliefs(); Plugin.Log.LogInfo((object)("[ESCAPE] released from all queues: " + resp)); CompetitiveUI.ShowNotification("Left all queues.", Color.green, 4f); } else { Plugin.Log.LogWarning((object)("[ESCAPE] failed, will keep retrying: " + resp)); CompetitiveUI.ShowNotification("Couldn't reach the server - retrying in the background.", new Color(1f, 0.6f, 0.2f)); } done?.Invoke(ok, resp); })); } private static void TickEscapeRetry() { if (EscapePending && !(Time.unscaledTime - _escapeRetryAt < 15f)) { SendEscapeRequest(null); } } public static void JoinQueue(string steamId, string displayName, string region, bool rankedOnly) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (CurrentQueueState == QueueState.Leaving) { if (Time.realtimeSinceStartup - rankedLeavingSince < 45f) { CompetitiveUI.ShowNotification("Still leaving the queue — try again in a moment.", new Color(1f, 0.6f, 0.2f)); return; } CurrentQueueState = QueueState.Idle; } if (string.IsNullOrEmpty(region)) { try { region = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { region = ""; } } string text = Escape(displayName ?? steamId); string json = "{\"steam_id\":\"" + Escape(steamId) + "\",\"display_name\":\"" + text + "\",\"region\":\"" + Escape(region ?? "") + "\",\"ranked_only\":" + (rankedOnly ? "true" : "false") + "}"; int gen = ++queueGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/queue/join", json, delegate(bool success, string response) { //IL_00b1: 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) if (gen != queueGen) { Plugin.Log.LogInfo((object)"[QUEUE] stale join ack ignored (lifecycle moved on)"); } else if (success) { CurrentQueueState = QueueState.Searching; IsQueuePolling = true; queuePollTimer = 0f; Plugin.Log.LogInfo((object)"[QUEUE] Joined ranked queue"); CompetitiveUI.ShowNotification("Searching for ranked match...", new Color(0.4f, 0.8f, 1f)); NativeUI.MarkDirty(); } else { Plugin.Log.LogWarning((object)("[QUEUE] Failed to join queue: " + response)); CompetitiveUI.ShowNotification("Failed to join queue", new Color(1f, 0.4f, 0.4f)); } })); } public static void LeaveQueue(string steamId) { if (CurrentQueueState == QueueState.Leaving || (CurrentQueueState == QueueState.Idle && !IsQueuePolling)) { return; } int gen = ++queueGen; CurrentQueueState = QueueState.Leaving; rankedLeavingSince = Time.realtimeSinceStartup; IsQueuePolling = false; LastPollData = null; NativeUI.MarkDirty(); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/queue/leave?steam_id=" + Escape(steamId), "", delegate(bool success, string response) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (gen == queueGen) { if (success) { Plugin.Log.LogInfo((object)"[QUEUE] Left ranked queue"); } else { Plugin.Log.LogWarning((object)("[QUEUE] Leave failed after retries: " + response + " — server will prune the stale row")); CompetitiveUI.ShowNotification("Couldn't confirm queue leave — the server will clear you shortly.", new Color(1f, 0.6f, 0.2f)); } if (CurrentQueueState == QueueState.Leaving) { CurrentQueueState = QueueState.Idle; } NativeUI.MarkDirty(); } })); } public static void DeclineMatch(string steamId) { string oppSteamId = LastPollData?.opponent_steam_id ?? ""; CurrentQueueState = QueueState.Searching; LastPollData = null; Plugin.ClearPendingRoom(); NativeUI.MarkDirty(); if (string.IsNullOrEmpty(oppSteamId)) { Plugin.Log.LogInfo((object)"[QUEUE] Decline without opponent data — leaving queue as fallback"); LeaveQueue(steamId); return; } string json = "{\"steam_id\":\"" + Escape(steamId) + "\",\"opponent_steam_id\":\"" + Escape(oppSteamId) + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/queue/decline", json, delegate(bool success, string response) { if (success) { Plugin.Log.LogInfo((object)("[QUEUE] Declined match vs " + oppSteamId + ", searching for new opponent")); } else { Plugin.Log.LogWarning((object)("[QUEUE] Decline failed: " + response)); } })); } public static void ReadyUp(string steamId) { if (CurrentQueueState != QueueState.Matched) { return; } CurrentQueueState = QueueState.ReadySent; NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)"[QUEUE] Ready Up sent"); int gen = queueGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/queue/ready?steam_id=" + Escape(steamId), "", delegate(bool success, string response) { //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if (gen == queueGen && CurrentQueueState == QueueState.ReadySent) { if (success) { string text = ExtractJsonString(response, "status"); if (text == "both_ready") { string text2 = ExtractJsonString(response, "room_name"); string text3 = ExtractJsonString(response, "photon_region"); ActiveRankedSeriesId = ExtractJsonString(response, "series_id"); if (!string.IsNullOrEmpty(text2)) { IsQueuePolling = false; CurrentQueueState = QueueState.Idle; LastPollData = null; Plugin.SetPendingRoom(text2, text3); Plugin.Log.LogInfo((object)("[QUEUE] Both ready! Joining room: " + text2 + " (region: " + (text3 ?? "auto") + ") series=" + ActiveRankedSeriesId)); CompetitiveUI.ShowNotification("Both ready! Joining match...", Color.green); FetchActiveSeries(); NativeUI.MarkDirty(); } } else { string text4 = ExtractJsonString(response, "status") ?? "(no status)"; string text5 = ExtractJsonString(response, "message") ?? ""; Plugin.Log.LogInfo((object)("[QUEUE] Waiting for opponent to ready up (server: " + text4 + " — " + text5 + ")")); } } else { Plugin.Log.LogWarning((object)("[QUEUE] Ready failed after retries: " + response)); CompetitiveUI.ShowNotification("Ready-up failed — retrying search", new Color(1f, 0.6f, 0.2f)); CurrentQueueState = QueueState.Searching; NativeUI.MarkDirty(); } } })); } public static void UpdateQueuePoll(string steamId) { if (!IsQueuePolling) { return; } queuePollTimer += Time.deltaTime; if (queuePollTimer < queuePollInterval) { return; } queuePollTimer = 0f; int gen = queueGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/queue/poll/" + steamId, delegate(bool success, string response) { //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) if (!success || !IsQueuePolling || gen != queueGen) { return; } try { string text = ExtractJsonString(response, "status"); switch (text) { case "ready_join": { string text2 = ExtractJsonString(response, "room_name"); string text3 = ExtractJsonString(response, "photon_region"); string text4 = ExtractJsonString(response, "series_id"); if (!string.IsNullOrEmpty(text4)) { ActiveRankedSeriesId = text4; } IsQueuePolling = false; CurrentQueueState = QueueState.Idle; LastPollData = null; Plugin.SetPendingRoom(text2, text3); Plugin.Log.LogInfo((object)("[QUEUE] Both ready! Joining room: " + text2 + " (region: " + (text3 ?? "auto") + ") series=" + (ActiveRankedSeriesId ?? "(none)"))); CompetitiveUI.ShowNotification("Both ready! Joining match...", Color.green); NativeUI.MarkDirty(); break; } case "matched": { bool opponent_ready = ExtractJsonBool(response, "opponent_ready"); if (CurrentQueueState == QueueState.Searching) { CurrentQueueState = QueueState.Matched; Plugin.Log.LogInfo((object)string.Format("[QUEUE] MATCHED! vs {0} ({1:F0})", ExtractJsonString(response, "opponent_name"), ExtractJsonFloat(response, "opponent_rating"))); CompetitiveUI.ShowNotification(string.Format("MATCH FOUND! vs {0} ({1:F0})", ExtractJsonString(response, "opponent_name"), ExtractJsonFloat(response, "opponent_rating")), Color.green, 8f); CompetitiveUI.PlayMatchFoundSound(); TaskbarFlash.Flash(); } LastPollData = new QueuePollData { status = "matched", wait_time = ExtractJsonInt(response, "wait_time"), opponent_steam_id = ExtractJsonString(response, "opponent_steam_id"), opponent_name = ExtractJsonString(response, "opponent_name"), opponent_rating = ExtractJsonFloat(response, "opponent_rating"), opponent_ready = opponent_ready }; NativeUI.MarkDirty(); break; } case "searching": if (CurrentQueueState == QueueState.Matched || CurrentQueueState == QueueState.ReadySent) { Plugin.Log.LogInfo((object)"[QUEUE] Match canceled — back to searching"); CompetitiveUI.ShowNotification("Match canceled — searching...", Color.yellow); } CurrentQueueState = QueueState.Searching; LastPollData = new QueuePollData { status = "searching", wait_time = ExtractJsonInt(response, "wait_time"), queue_size = ExtractJsonInt(response, "queue_size"), elo_range = ExtractJsonInt(response, "elo_range") }; NativeUI.MarkDirty(); break; default: if (!(text == "not_in_queue")) { break; } goto case "expired"; case "expired": CurrentQueueState = QueueState.Idle; IsQueuePolling = false; LastPollData = null; CompetitiveUI.ShowNotification((text == "expired") ? "Removed from queue after 30 minutes of searching - rejoin if you're still here!" : "Queue search ended", Color.yellow, 7f); NativeUI.MarkDirty(); break; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[QUEUE] Poll parse error: " + ex.Message)); } })); } public static void ResetQueueState() { CurrentQueueState = QueueState.Idle; IsQueuePolling = false; LastPollData = null; } public static void UpdateQueueCount() { queueCountTimer += Time.deltaTime; if (queueCountTimer < queueCountInterval) { return; } queueCountTimer = 0f; string localSteamId = MatchTracker.LocalSteamId; string text = ((!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") ? ("?steam_id=" + Escape(localSteamId)) : ""); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/queue/count" + text, delegate(bool success, string response) { if (success) { int num = ExtractJsonInt(response, "searching"); int num2 = ExtractJsonInt(response, "total"); int num3 = ExtractJsonInt(response, "online"); if (num != CachedQueueSearching || num2 != CachedQueueTotal || num3 != CachedOnlineCount) { CachedQueueSearching = num; CachedQueueTotal = num2; CachedOnlineCount = num3; NativeUI.MarkDirty(); } } })); } public static void ResetQueueCountTimer() { queueCountTimer = queueCountInterval; } public static void FetchOnlinePlayers() { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/presence/online", delegate(bool ok, string resp) { if (!ok || string.IsNullOrEmpty(resp)) { return; } try { CachedOnlineListCount = ExtractJsonInt(resp, "online_count"); CachedOnlinePlayers = ParsePresenceList(resp, "\"online\""); CachedRecentPlayers = ParsePresenceList(resp, "\"recent\""); NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[HOME] presence parse failed: " + ex.Message)); } })); } private static int FindMatchingBracketStringAware(string s, int openPos) { if (openPos < 0 || openPos >= s.Length) { return -1; } int num = 0; bool flag = false; for (int i = openPos; i < s.Length; i++) { char c = s[i]; if (flag) { switch (c) { case '\\': i++; break; case '"': flag = false; break; } continue; } switch (c) { case '"': flag = true; break; case '[': num++; break; case ']': num--; if (num == 0) { return i; } break; } } return -1; } private static int FindMatchingBraceStringAware(string s, int openPos) { if (openPos < 0 || openPos >= s.Length) { return -1; } int num = 0; bool flag = false; for (int i = openPos; i < s.Length; i++) { char c = s[i]; if (flag) { switch (c) { case '\\': i++; break; case '"': flag = false; break; } continue; } switch (c) { case '"': flag = true; break; case '{': num++; break; case '}': num--; if (num == 0) { return i; } break; } } return -1; } private static List ParsePresenceList(string json, string key) { List list = new List(); int num = json.IndexOf(key); if (num < 0) { return list; } int num2 = json.IndexOf('[', num); if (num2 < 0) { return list; } int num3 = FindMatchingBracketStringAware(json, num2); if (num3 < 0) { return list; } foreach (string item in SliceTopLevelObjects(json.Substring(num2, num3 - num2 + 1))) { OnlinePlayerEntry onlinePlayerEntry = new OnlinePlayerEntry { name = ExtractJsonString(item, "display_name"), rating = ExtractJsonInt(item, "rating"), minutesAgo = ExtractJsonInt(item, "minutes_ago"), title = ExtractJsonString(item, "title"), titleColor = ExtractJsonString(item, "title_color") }; if (!string.IsNullOrEmpty(onlinePlayerEntry.name)) { list.Add(onlinePlayerEntry); } } return list; } public static void FetchNewestCosmetics() { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/shop/newest?limit=12&batches=2", delegate(bool ok, string resp) { if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = resp.IndexOf("\"items\""); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num3 < 0) { Plugin.Log.LogWarning((object)"[HOME] shop/newest: items array not found"); } else { foreach (string item in SliceTopLevelObjects(resp.Substring(num2, num3 - num2 + 1))) { NewestCosmeticEntry newestCosmeticEntry = new NewestCosmeticEntry { sku = ExtractJsonString(item, "sku"), kind = ExtractJsonString(item, "kind"), name = ExtractJsonString(item, "name"), rarity = ExtractJsonString(item, "rarity"), price = ExtractJsonInt(item, "price"), previewColor = ExtractJsonString(item, "preview_color"), artistName = ExtractJsonString(item, "artist_name"), added = ExtractJsonString(item, "added"), onSale = !item.Contains("\"on_sale\":false") }; if (!string.IsNullOrEmpty(newestCosmeticEntry.sku)) { list.Add(newestCosmeticEntry); } } CachedNewestCosmetics = list; NativeUI.MarkDirty(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[HOME] shop/newest parse failed: " + ex.Message)); } })); } public static void FetchReleaseNotes(bool force = false) { if (_releasesFetchInFlight || (!force && CachedReleaseNotes != null && CachedReleaseNotes.Count > 0)) { return; } _releasesFetchInFlight = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/releases/recent?limit=3", delegate(bool ok, string resp) { List list = (ok ? ParseReleasePosts(resp) : null); if (list != null && list.Count > 0) { _releasesFetchInFlight = false; CachedReleaseNotes = list; Plugin.Log.LogInfo((object)$"[HOME] release posts loaded: {list.Count} (channel mirror)"); NativeUI.MarkDirty(); } else { Plugin.Log.LogInfo((object)"[HOME] release mirror empty/unreachable - falling back to GitHub"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(DoFetchReleaseNotes()); } })); } private static List ParseReleasePosts(string resp) { try { List list = new List(); if (string.IsNullOrEmpty(resp)) { return list; } int num = resp.IndexOf("\"posts\""); if (num < 0) { return list; } int num2 = resp.IndexOf('[', num); if (num2 < 0) { return list; } int num3 = FindMatchingBracketStringAware(resp, num2); if (num3 < 0) { return list; } foreach (string item in SliceTopLevelObjects(resp.Substring(num2, num3 - num2 + 1))) { ReleaseNoteEntry releaseNoteEntry = new ReleaseNoteEntry { tag = ExtractJsonString(item, "author"), title = "", date = ExtractJsonString(item, "posted_at"), body = CleanReleaseBody(ExtractJsonString(item, "content")) }; if (!string.IsNullOrEmpty(releaseNoteEntry.date) && releaseNoteEntry.date.Length >= 10) { releaseNoteEntry.date = releaseNoteEntry.date.Substring(0, 10); } if (!string.IsNullOrEmpty(releaseNoteEntry.body)) { list.Add(releaseNoteEntry); } } return list; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[HOME] release posts parse failed: " + ex.Message)); return null; } } private static IEnumerator DoFetchReleaseNotes() { UnityWebRequest req = UnityWebRequest.Get("https://api.github.com/repos/SidNDeed/SidsCompetitiveRounds/releases?per_page=3"); req.SetRequestHeader("User-Agent", "CompetitiveRounds-HomeTab"); req.timeout = 15; yield return req.SendWebRequest(); _releasesFetchInFlight = false; if ((int)req.result != 1) { Plugin.Log.LogWarning((object)("[HOME] release notes fetch failed: " + req.error)); yield break; } try { List list = new List(); foreach (string obj in SliceTopLevelObjects(req.downloadHandler.text)) { ReleaseNoteEntry e = new ReleaseNoteEntry { tag = ExtractGhString(obj, "tag_name"), title = ExtractGhString(obj, "name"), date = ExtractGhString(obj, "published_at"), body = CleanReleaseBody(ExtractGhString(obj, "body")) }; if (!string.IsNullOrEmpty(e.date) && e.date.Length >= 10) { e.date = e.date.Substring(0, 10); } if (!string.IsNullOrEmpty(e.tag)) { list.Add(e); } if (list.Count >= 3) { break; } } CachedReleaseNotes = list; Plugin.Log.LogInfo((object)$"[HOME] release notes loaded: {list.Count}"); NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[HOME] release notes parse failed: " + ex.Message)); } } private static List SliceTopLevelObjects(string json) { List list = new List(); if (string.IsNullOrEmpty(json)) { return list; } int num = 0; int num2 = -1; bool flag = false; for (int i = 0; i < json.Length; i++) { char c = json[i]; if (flag) { switch (c) { case '\\': i++; break; case '"': flag = false; break; } continue; } switch (c) { case '"': flag = true; break; case '{': if (num == 0) { num2 = i; } num++; break; case '}': num--; if (num == 0 && num2 >= 0) { list.Add(json.Substring(num2, i - num2 + 1)); num2 = -1; } break; } } return list; } private static string ExtractGhString(string json, string key) { try { int num = json.IndexOf("\"" + key + "\""); if (num < 0) { return ""; } int num2 = json.IndexOf(':', num + key.Length + 2); if (num2 < 0) { return ""; } int i; for (i = num2 + 1; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } if (i >= json.Length || json[i] != '"') { return ""; } return ExtractJsonString("\"" + key + "\":" + json.Substring(i), key); } catch { return ""; } } private static string CleanReleaseBody(string body) { if (string.IsNullOrEmpty(body)) { return ""; } string text = body.Replace("\r\n", "\n").Replace("\r", "\n"); text = text.Replace("**", "").Replace("__", "").Replace("`", ""); text = text.Replace("<", "[").Replace(">", "]"); text = text.Replace("—", "-").Replace("–", "-").Replace("×", "x") .Replace("•", "-") .Replace("→", "->") .Replace("·", "-") .Replace("‘", "'") .Replace("’", "'") .Replace("“", "\"") .Replace("”", "\""); StringBuilder stringBuilder = new StringBuilder(text.Length); string[] array = text.Split('\n'); foreach (string text2 in array) { string text3 = text2.TrimEnd(); string text4 = text3.TrimStart(); if (text4.StartsWith("###")) { text3 = text4.TrimStart('#', ' '); } else if (text4.StartsWith("##")) { text3 = text4.TrimStart('#', ' '); } else if (text4.StartsWith("#")) { text3 = text4.TrimStart('#', ' '); } stringBuilder.Append(text3).Append('\n'); } text = stringBuilder.ToString(); StringBuilder stringBuilder2 = new StringBuilder(text.Length); string text5 = text; foreach (char c in text5) { if (c == '\n' || (c >= ' ' && c < '\u007f')) { stringBuilder2.Append(c); } } text = stringBuilder2.ToString(); while (text.Contains("\n\n\n")) { text = text.Replace("\n\n\n", "\n\n"); } text = text.Trim(); if (text.Length > 2500) { text = text.Substring(0, 2500).TrimEnd() + " ..."; } return text; } public static IEnumerator PresenceLoop() { yield return (object)new WaitForSeconds(15f); string lastInMatchSent = null; float lastPingAt = -999f; while (true) { try { SteamAuth.MaybeRefresh(); } catch { } try { GameStateWatcher.EnsureIdentityResolved(); string sid = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(sid) && sid != "unknown") { string inMatch = GetPresenceMatchGroupId(); bool due = Time.realtimeSinceStartup - lastPingAt >= 60f; bool edge = !string.IsNullOrEmpty(inMatch) && inMatch != lastInMatchSent; if (due || edge) { lastPingAt = Time.realtimeSinceStartup; string sentInMatch = inMatch; string matchQuery = (string.IsNullOrEmpty(inMatch) ? "" : ("&in_match=" + UnityWebRequest.EscapeURL(inMatch))); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/presence/ping?steam_id=" + UnityWebRequest.EscapeURL(sid) + matchQuery, delegate(bool success, string response) { if (success) { lastInMatchSent = sentInMatch; int num = ExtractJsonInt(response, "online"); if (num != CachedOnlineCount) { CachedOnlineCount = num; NativeUI.MarkDirty(); } } })); } } } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogWarning((object)("[PRESENCE] tick failed: " + ex2.Message)); } yield return (object)new WaitForSeconds(5f); } } private static string GetPresenceMatchGroupId() { try { if (!CompetitiveRoomDetect.IsCompetitiveRoom() || PhotonNetwork.CurrentRoom == null) { return null; } try { if ((Object)(object)GameManager.instance == (Object)null || !GameManager.instance.battleOngoing) { return null; } } catch { return null; } string text = PhotonNetwork.CurrentRoom.Name ?? ""; if (text.StartsWith("ffa_", StringComparison.Ordinal)) { return string.IsNullOrEmpty(ActiveFfaLobbyId) ? null : ActiveFfaLobbyId; } if (text.StartsWith("ovt_", StringComparison.Ordinal)) { return string.IsNullOrEmpty(ActiveOvt1v2SeriesId) ? null : ActiveOvt1v2SeriesId; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (text.StartsWith("team_", StringComparison.Ordinal) || (customProperties != null && ((Dictionary)(object)customProperties).ContainsKey((object)"cr_ff"))) { return string.IsNullOrEmpty(ActiveTeamSeriesId) ? null : ActiveTeamSeriesId; } } catch { } return null; } public static void JoinTeamQueue(string steamId, string displayName, string region, string queueType = "auto") { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (CurrentTeamQueueState == TeamQueueState.Leaving) { if (Time.realtimeSinceStartup - teamLeavingSince < 45f) { CompetitiveUI.ShowNotification("Still leaving the 2v2 queue — try again in a moment.", new Color(1f, 0.6f, 0.2f)); return; } CurrentTeamQueueState = TeamQueueState.Idle; } if (string.IsNullOrEmpty(region)) { try { region = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { region = ""; } } string qt = ((queueType == "manual") ? "manual" : "auto"); string text = Escape(displayName ?? steamId); string json = "{\"steam_id\":\"" + Escape(steamId) + "\",\"display_name\":\"" + text + "\",\"region\":\"" + Escape(region ?? "") + "\",\"queue_type\":\"" + qt + "\"}"; int gen = ++teamGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/team/queue/join", json, delegate(bool success, string response) { //IL_00eb: 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) if (gen != teamGen) { Plugin.Log.LogInfo((object)"[TEAM-QUEUE] stale join ack ignored (lifecycle moved on)"); } else if (success) { CurrentTeamQueueState = TeamQueueState.Searching; CurrentTeamQueueType = qt; IsTeamQueuePolling = true; teamQueuePollTimer = 0f; Plugin.Log.LogInfo((object)("[TEAM-QUEUE] Joined 2v2 " + qt + " queue")); string text2 = ((qt == "manual") ? "Searching for custom 2v2 lobby..." : "Searching for 2v2 match..."); CompetitiveUI.ShowNotification(text2, new Color(0.4f, 0.8f, 1f)); NativeUI.MarkDirty(); } else { Plugin.Log.LogWarning((object)("[TEAM-QUEUE] Join failed: " + response)); CompetitiveUI.ShowNotification("Failed to join 2v2 queue", new Color(1f, 0.4f, 0.4f)); } })); } public static void LeaveTeamQueue(string steamId) { if (CurrentTeamQueueState == TeamQueueState.Leaving || (CurrentTeamQueueState == TeamQueueState.Idle && !IsTeamQueuePolling)) { return; } int gen = ++teamGen; CurrentTeamQueueState = TeamQueueState.Leaving; teamLeavingSince = Time.realtimeSinceStartup; IsTeamQueuePolling = false; LastTeamPollData = null; ActiveTeamSeriesId = null; Plugin.ClearPending2v2Slot(); NativeUI.MarkDirty(); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/team/queue/leave?steam_id=" + Escape(steamId), "", delegate(bool success, string response) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (gen == teamGen) { if (success) { Plugin.Log.LogInfo((object)"[TEAM-QUEUE] Left 2v2 queue"); } else { Plugin.Log.LogWarning((object)("[TEAM-QUEUE] Leave failed after retries: " + response + " — server will prune the stale row")); CompetitiveUI.ShowNotification("Couldn't confirm 2v2 queue leave — the server will clear you shortly.", new Color(1f, 0.6f, 0.2f)); } if (CurrentTeamQueueState == TeamQueueState.Leaving) { CurrentTeamQueueState = TeamQueueState.Idle; } NativeUI.MarkDirty(); } })); } public static void ReadyUpTeam(string steamId) { if (CurrentTeamQueueState != TeamQueueState.Matched) { return; } CurrentTeamQueueState = TeamQueueState.ReadySent; NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)"[TEAM-QUEUE] Ready Up sent"); int gen = teamGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/team/queue/ready?steam_id=" + Escape(steamId), "", delegate(bool success, string response) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (gen == teamGen && CurrentTeamQueueState == TeamQueueState.ReadySent && !success) { Plugin.Log.LogWarning((object)("[TEAM-QUEUE] Ready failed after retries: " + response)); CompetitiveUI.ShowNotification("Ready-up failed — retrying search", new Color(1f, 0.6f, 0.2f)); CurrentTeamQueueState = TeamQueueState.Matched; NativeUI.MarkDirty(); } })); } public static void UpdateTeamQueuePoll(string steamId) { if (!IsTeamQueuePolling) { return; } teamQueuePollTimer += Time.deltaTime; if (teamQueuePollTimer < 3f) { return; } teamQueuePollTimer = 0f; int gen = teamGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/team/queue/poll/" + steamId, delegate(bool success, string response) { if (!success || !IsTeamQueuePolling || gen != teamGen) { return; } try { ParseTeamQueuePoll(response); } catch (Exception ex) { Plugin.Log.LogError((object)("[TEAM-QUEUE] poll parse: " + ex.Message)); } })); } public static void UpdateTeamQueueList(bool force = false) { teamQueueListTimer += Time.deltaTime; if (!force && teamQueueListTimer < 2f) { return; } teamQueueListTimer = 0f; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/team/queue/list", delegate(bool success, string response) { if (!success || string.IsNullOrEmpty(response)) { return; } try { ParseTeamQueueList(response); NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TEAM-QUEUE-LIST] parse: " + ex.Message)); } })); } private static void ParseTeamQueueList(string response) { List list = new List(); int num = response.IndexOf("\"queuers\""); if (num < 0) { CachedTeamQueueList = list; return; } int num2 = response.IndexOf('[', num); int num3 = FindMatchingBracket(response, num2); if (num2 < 0 || num3 < 0) { CachedTeamQueueList = list; return; } string text = response.Substring(num2 + 1, num3 - num2 - 1); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = 1; int i; for (i = num5 + 1; i < text.Length; i++) { if (num6 <= 0) { break; } if (text[i] == '{') { num6++; } else if (text[i] == '}') { num6--; } } if (num6 != 0) { break; } string json = text.Substring(num5, i - num5); string text2 = ExtractJsonString(json, "queue_type"); if (string.IsNullOrEmpty(text2)) { text2 = "auto"; } list.Add(new TeamQueueListEntry { steam_id = ExtractJsonString(json, "steam_id"), display_name = ExtractJsonString(json, "display_name"), rating = ExtractJsonInt(json, "rating"), balance_rating = ExtractJsonInt(json, "balance_rating"), using_fallback_rating = ExtractJsonBool(json, "using_fallback_rating"), completed_series = ExtractJsonInt(json, "completed_series"), region = ExtractJsonString(json, "region"), status = ExtractJsonString(json, "status"), team_assigned = ExtractJsonInt(json, "team_assigned"), series_id = ExtractJsonString(json, "series_id"), wait_seconds = ExtractJsonInt(json, "wait_seconds"), manual_pick_enabled = ExtractJsonBool(json, "manual_pick_enabled"), preferred_team = ExtractJsonInt(json, "preferred_team"), queue_type = text2 }); num4 = i; } CachedTeamQueueList = list; List list2 = new List(); List list3 = new List(); foreach (TeamQueueListEntry item in list) { if (item.queue_type == "manual") { list3.Add(item); } else { list2.Add(item); } } CachedTeamQueueAuto = list2; CachedTeamQueueManual = list3; } public static void ToggleTeamManualPick(string steamId, bool enabled) { if (string.IsNullOrEmpty(steamId)) { return; } string url = baseUrl + "/api/v1/team/queue/manual-pick-toggle?steam_id=" + UnityWebRequest.EscapeURL(steamId) + "&enabled=" + (enabled ? "true" : "false"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { if (ok) { Plugin.Log.LogInfo((object)$"[2v2-MANUAL] toggle={enabled} ok: {resp}"); } else { Plugin.Log.LogWarning((object)("[2v2-MANUAL] toggle failed: " + resp)); } UpdateTeamQueueList(force: true); })); } public static void SetTeamPreferredTeam(string steamId, int team) { if (string.IsNullOrEmpty(steamId)) { return; } string url = $"{baseUrl}/api/v1/team/queue/preferred-team?steam_id={UnityWebRequest.EscapeURL(steamId)}&team={team}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { if (ok) { Plugin.Log.LogInfo((object)$"[2v2-MANUAL] team={team} ok: {resp}"); } else { Plugin.Log.LogWarning((object)("[2v2-MANUAL] team set failed: " + resp)); } UpdateTeamQueueList(force: true); })); } private static void ParseTeamQueuePoll(string response) { //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) string text = ExtractJsonString(response, "status"); TeamQueuePollData teamQueuePollData = new TeamQueuePollData { status = text, queue_count = ExtractJsonInt(response, "queue_count"), elo_range = ExtractJsonInt(response, "elo_range"), series_id = ExtractJsonString(response, "series_id"), team_assigned = ExtractJsonInt(response, "team_assigned"), room_name = ExtractJsonString(response, "room_name"), room_region = ExtractJsonString(response, "room_region"), match_age_seconds = ExtractJsonInt(response, "match_age_seconds"), my_ready = ExtractJsonBool(response, "my_ready") }; teamQueuePollData.teammates = ExtractTeamMemberList(response, "teammates"); teamQueuePollData.opponents = ExtractTeamMemberList(response, "opponents"); LastTeamPollData = teamQueuePollData; switch (text) { case "ready_join": { if (string.IsNullOrEmpty(teamQueuePollData.room_name)) { break; } IsTeamQueuePolling = false; CurrentTeamQueueState = TeamQueueState.Idle; ActiveTeamSeriesId = teamQueuePollData.series_id; int num = ComputeMy2v2Slot(MatchTracker.LocalSteamId, teamQueuePollData.team_assigned, teamQueuePollData.teammates); Plugin.SetPending2v2Slot(num); try { Hashtable val = new Hashtable(); val[(object)"p_id"] = num; val[(object)"t_id"] = num / 2; string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { val[(object)"u_id"] = localSteamId; } if (PhotonNetwork.LocalPlayer != null) { PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2] pre-join SetCustomProperties: " + ex.Message)); } try { NametagStyler.PublishToPhoton(); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[2v2] pre-join nametag publish: " + ex2.Message)); } try { PlayerColorCosmetic.PublishLocalProps(); } catch (Exception ex3) { Plugin.Log.LogWarning((object)("[2v2] pre-join pcolor publish: " + ex3.Message)); } try { TrailCosmetic.PublishLocalProps(); } catch (Exception ex4) { Plugin.Log.LogWarning((object)("[2v2] pre-join trail publish: " + ex4.Message)); } Plugin.SetPendingRoom(teamQueuePollData.room_name, teamQueuePollData.room_region); Plugin.Log.LogInfo((object)string.Format("[TEAM-QUEUE] All ready! Room: {0} (region: {1}) series={2} my_slot={3}", teamQueuePollData.room_name, teamQueuePollData.room_region ?? "auto", teamQueuePollData.series_id, num)); CompetitiveUI.ShowNotification("4/4 ready! Joining 2v2...", Color.green); try { if (NativeUI.IsOpen) { NativeUI.Close(); } } catch { } NativeUI.MarkDirty(); break; } case "matched": if (CurrentTeamQueueState != TeamQueueState.ReadySent) { CurrentTeamQueueState = TeamQueueState.Matched; } ActiveTeamSeriesId = teamQueuePollData.series_id; NativeUI.MarkDirty(); break; case "searching": if (CurrentTeamQueueState != TeamQueueState.Searching) { CurrentTeamQueueState = TeamQueueState.Searching; ActiveTeamSeriesId = null; Plugin.ClearPending2v2Slot(); CompetitiveUI.ShowNotification("Match canceled — re-searching", new Color(1f, 0.6f, 0.2f)); } NativeUI.MarkDirty(); break; default: if (!(text == "not_in_queue")) { break; } goto case "expired"; case "expired": IsTeamQueuePolling = false; CurrentTeamQueueState = TeamQueueState.Idle; LastTeamPollData = null; ActiveTeamSeriesId = null; Plugin.ClearPending2v2Slot(); if (text == "expired") { CompetitiveUI.ShowNotification("Removed from 2v2 queue after 30 minutes of searching - rejoin if you're still here!", Color.yellow, 7f); } NativeUI.MarkDirty(); break; } } public static int ComputeMy2v2Slot(string mySteamId, int teamAssigned, List teammates) { int num = ((teamAssigned == 2) ? 2 : 0); string text = null; if (teammates != null) { foreach (TeamQueueMember teammate in teammates) { if (teammate == null || teammate.team_assigned != teamAssigned || !(teammate.steam_id != mySteamId)) { continue; } text = teammate.steam_id; break; } } if (string.IsNullOrEmpty(text)) { return num; } int num2 = ((string.Compare(mySteamId, text, StringComparison.Ordinal) > 0) ? 1 : 0); return num + num2; } private static List ExtractTeamMemberList(string json, string key) { List list = new List(); try { int num = json.IndexOf("\"" + key + "\""); int num2 = ((num >= 0) ? json.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(json, num2) : (-1)); if (num2 < 0 || num3 <= num2) { return list; } foreach (string item in SliceTopLevelObjects(json.Substring(num2 + 1, num3 - num2 - 1))) { list.Add(new TeamQueueMember { steam_id = ExtractJsonString(item, "steam_id"), display_name = ExtractJsonString(item, "display_name"), rating = ExtractJsonInt(item, "rating"), region = ExtractJsonString(item, "region"), team_assigned = ExtractJsonInt(item, "team_assigned"), using_fallback_rating = ExtractJsonBool(item, "using_fallback_rating"), balance_rating = ExtractJsonInt(item, "balance_rating"), completed_series = ExtractJsonInt(item, "completed_series"), ready = ExtractJsonBool(item, "ready") }); } } catch { } return list; } public static void UpdateTeamQueueCount() { teamQueueCountTimer += Time.deltaTime; if (teamQueueCountTimer < 10f) { return; } teamQueueCountTimer = 0f; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/team/queue/count", delegate(bool success, string response) { if (success) { int num = ExtractJsonInt(response, "searching"); if (num != CachedTeamQueueSearching) { CachedTeamQueueSearching = num; NativeUI.MarkDirty(); } } })); } public static void UpdateTeamSeriesStatePoll(bool force) { string activeTeamSeriesId = ActiveTeamSeriesId; if (!string.IsNullOrEmpty(activeTeamSeriesId)) { teamSeriesStateTimer += Time.deltaTime; if (force || !(teamSeriesStateTimer < 2f)) { teamSeriesStateTimer = 0f; PollTeamSeriesState(activeTeamSeriesId, delegate { }); } } } public static void RequestContinuationSeries(string reporterSteam, string roomId, string region, string t1a, string t1b, string t2a, string t2b, Action callback = null) { string message = "team-continuation:" + t1a + ":" + t1b + ":" + t2a + ":" + t2b + ":" + roomId + ":" + reporterSteam; string text = ComputeHmacHex(message); string json = "{\"reporter_steam_id\":\"" + Escape(reporterSteam) + "\",\"room_id\":\"" + Escape(roomId) + "\",\"region\":\"" + Escape(region ?? "") + "\",\"t1a_steam\":\"" + Escape(t1a) + "\",\"t1b_steam\":\"" + Escape(t1b) + "\",\"t2a_steam\":\"" + Escape(t2a) + "\",\"t2b_steam\":\"" + Escape(t2b) + "\",\"hmac_signature\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/team/series/continuation", json, delegate(bool ok, string resp) { if (ok && !string.IsNullOrEmpty(resp)) { string text2 = ExtractJsonString(resp, "series_id"); if (!string.IsNullOrEmpty(text2)) { ActiveTeamSeriesId = text2; Plugin.Log.LogInfo((object)("[2v2-CONTINUATION] active series set to " + text2 + " (" + ExtractJsonString(resp, "status") + ")")); } } else { Plugin.Log.LogWarning((object)("[2v2-CONTINUATION] request failed: " + resp)); } callback?.Invoke(ok); })); } public static void ReportTeamSeriesDc(string seriesId, string reporterSteamId, string dcPlayerSteamId, int t1PointsTotal, int t2PointsTotal) { if (string.IsNullOrEmpty(seriesId) || string.IsNullOrEmpty(reporterSteamId) || string.IsNullOrEmpty(dcPlayerSteamId)) { return; } string text = ComputeHmacHex(reporterSteamId + ":" + seriesId + ":" + dcPlayerSteamId + ":dc"); string url = baseUrl + "/api/v1/team/series/" + seriesId + "/report-dc?reporter_steam_id=" + UnityWebRequest.EscapeURL(reporterSteamId) + "&dc_player_steam_id=" + UnityWebRequest.EscapeURL(dcPlayerSteamId) + $"&t1_points_total={t1PointsTotal}" + $"&t2_points_total={t2PointsTotal}" + "&hmac_sig=" + UnityWebRequest.EscapeURL(text); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { if (ok) { Plugin.Log.LogInfo((object)("[2v2-DC] report accepted: " + resp)); } else { Plugin.Log.LogWarning((object)("[2v2-DC] report failed: " + resp)); } })); } public static void SendTeamSpawnConfirm(string seriesId, string steamId) { if (string.IsNullOrEmpty(seriesId) || string.IsNullOrEmpty(steamId)) { return; } string text = ComputeHmacHex(steamId + ":" + seriesId + ":spawn"); string url = baseUrl + "/api/v1/team/series/" + seriesId + "/spawn-confirm?steam_id=" + UnityWebRequest.EscapeURL(steamId) + "&hmac_sig=" + UnityWebRequest.EscapeURL(text); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { if (ok) { Plugin.Log.LogInfo((object)("[2v2] spawn-confirm OK: " + resp)); } else { Plugin.Log.LogWarning((object)("[2v2] spawn-confirm failed: " + resp)); } })); } public static void PollTeamSeriesState(string seriesId, Action onResponse) { if (string.IsNullOrEmpty(seriesId)) { return; } string url = baseUrl + "/api/v1/team/series/" + seriesId + "/state"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(url, delegate(bool ok, string resp) { if (ok && !string.IsNullOrEmpty(resp)) { string text = ExtractJsonString(resp, "status") ?? ""; string text2 = ExtractJsonString(resp, "reason") ?? ""; int num = ExtractJsonInt(resp, "confirmations"); LastSeriesStateStatus = text; LastSeriesStateReason = text2; LastSeriesStateConfirmations = num; LastSeriesDcGraceSeconds = ExtractJsonInt(resp, "dc_grace_seconds_remaining"); LastSeriesDcTeamRemaining = ExtractJsonInt(resp, "dc_team_remaining"); LastSeriesT1Wins = ExtractJsonInt(resp, "t1_series_wins"); LastSeriesT2Wins = ExtractJsonInt(resp, "t2_series_wins"); onResponse?.Invoke(text, text2, num); } })); } private static void AppendTeamTelemetry(StringBuilder sb, string slot, TeamTelemetry t) { if (t != null) { sb.Append("\"" + slot + "_telemetry\":{"); sb.Append("\"fps_timeline\":\"" + Escape(ClampTimeline(t.fpsTimeline)) + "\","); sb.Append("\"ping_timeline\":\"" + Escape(ClampTimeline(t.pingTimeline)) + "\","); sb.Append($"\"ping_avg\":{Math.Max(0, Math.Min(30000, t.pingAvg))},"); sb.Append("\"hit_timeline\":\"" + Escape(ClampTimeline(t.hitTimeline, 1024)) + "\","); sb.Append("\"block_timeline\":\"" + Escape(ClampTimeline(t.blockTimeline, 1024)) + "\","); sb.Append($"\"bullets_fired\":{Math.Max(0, t.bulletsFired)},"); sb.Append($"\"bullets_hit\":{Math.Max(0, t.bulletsHit)},"); sb.Append($"\"blocks_activated\":{Math.Max(0, t.blocksActivated)},"); sb.Append($"\"blocks_successful\":{Math.Max(0, t.blocksSuccessful)},"); sb.Append($"\"keys_pressed\":{Math.Max(0, t.keysPressed)},"); sb.Append("\"active_seconds\":" + Math.Max(0f, t.activeSeconds).ToString("F1", CultureInfo.InvariantCulture)); sb.Append("},"); } } public static void ReportTeamMatch(string seriesId, string t1aSteam, string t1aName, List t1aCards, string t1bSteam, string t1bName, List t1bCards, string t2aSteam, string t2aName, List t2aCards, string t2bSteam, string t2bName, List t2bCards, int t1Rounds, int t2Rounds, int t1Points, int t2Points, string photonRoomId, string region, int durationSeconds, DateTime startedAt, string reporterSteamId, bool isRanked, int winnerTeam, int t1aFps, int t1bFps, int t2aFps, int t2bFps, TeamTelemetry t1aTele = null, TeamTelemetry t1bTele = null, TeamTelemetry t2aTele = null, TeamTelemetry t2bTele = null) { StringBuilder sb = new StringBuilder(); sb.Append("{"); sb.Append("\"series_id\":\"" + Escape(seriesId) + "\","); appendPlayer("t1a", t1aSteam, t1aName, t1aCards); appendPlayer("t1b", t1bSteam, t1bName, t1bCards); appendPlayer("t2a", t2aSteam, t2aName, t2aCards); appendPlayer("t2b", t2bSteam, t2bName, t2bCards); sb.Append($"\"t1_rounds_won\":{t1Rounds},"); sb.Append($"\"t2_rounds_won\":{t2Rounds},"); sb.Append($"\"t1_points_total\":{t1Points},"); sb.Append($"\"t2_points_total\":{t2Points},"); sb.Append($"\"winner_team\":{winnerTeam},"); sb.Append("\"photon_room_id\":\"" + Escape(photonRoomId) + "\","); sb.Append("\"game_version\":\"v" + Application.version + "\","); sb.Append("\"region\":\"" + Escape(region) + "\","); sb.Append($"\"match_duration\":{durationSeconds},"); sb.Append("\"started_at\":\"" + startedAt.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture) + "\","); sb.Append("\"is_ranked\":" + (isRanked ? "true" : "false") + ","); sb.Append("\"reported_by_steam_id\":\"" + Escape(reporterSteamId) + "\","); sb.Append($"\"t1a_fps\":{t1aFps},\"t1b_fps\":{t1bFps},\"t2a_fps\":{t2aFps},\"t2b_fps\":{t2bFps},"); AppendTeamTelemetry(sb, "t1a", t1aTele); AppendTeamTelemetry(sb, "t1b", t1bTele); AppendTeamTelemetry(sb, "t2a", t2aTele); AppendTeamTelemetry(sb, "t2b", t2bTele); string message = t1aSteam + ":" + t1bSteam + ":" + t2aSteam + ":" + t2bSteam + ":" + $"{t1Rounds}:{t2Rounds}:" + (isRanked ? "true" : "false") + ":" + reporterSteamId + ":" + string.Format("{0}:{1}:{2}", photonRoomId ?? "", winnerTeam, seriesId); string text = ComputeHmacHex(message); sb.Append("\"hmac_signature\":\"" + text + "\""); sb.Append("}"); string json = sb.ToString(); Plugin.Log.LogInfo((object)$"Reporting 2v2 match (series={seriesId}, winner=T{winnerTeam}, {t1Rounds}-{t2Rounds})..."); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/team/matches", json, delegate(bool success, string response) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) if (success) { Plugin.Log.LogInfo((object)("2v2 match reported: " + response)); string text2 = ExtractJsonString(response, "series_status"); string text3 = ExtractJsonString(response, "series_score"); if (text2 == "completed") { CompetitiveUI.ShowNotification("Series complete: " + text3, Color.green, 6f); try { bool won = false; if (!string.IsNullOrEmpty(text3)) { string[] array = text3.Split('-'); if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2)) { won = result > result2; } } GameStateWatcher.RecordSessionTeamSeries(won); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2] session tally failed: " + ex.Message)); } ActiveTeamSeriesId = null; Plugin.ClearPending2v2Slot(); } else if (!string.IsNullOrEmpty(text3)) { CompetitiveUI.ShowNotification("Series: " + text3, new Color(0.6f, 0.8f, 1f), 4f); } try { int num = response.IndexOf("\"rebalance_assignments\":"); if (num >= 0) { int num2 = response.IndexOf('{', num); int num3 = ((num2 >= 0) ? FindMatchingBrace(response, num2) : (-1)); if (num2 > 0 && num3 > num2) { string text4 = response.Substring(num2 + 1, num3 - num2 - 1); if (!string.IsNullOrEmpty(text4.Trim())) { Plugin.Log.LogInfo((object)("[2v2-REBALANCE] server says swap teams next match: " + text4)); CompetitiveUI.ShowNotification("Teams will rebalance next match!", new Color(1f, 0.8f, 0.4f)); } } } return; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[2v2-REBALANCE] parse: " + ex2.Message)); return; } } Plugin.Log.LogWarning((object)("2v2 match report failed: " + response)); EnqueueFailedReport(baseUrl + "/api/v1/team/matches", json); })); void appendPlayer(string field, string sid, string name, List cards) { sb.Append("\"" + field + "\":{\"steam_id\":\"" + Escape(sid) + "\",\"display_name\":\"" + Escape(name) + "\",\"cards\":["); AppendCards(sb, cards); sb.Append("],\"card_offers\":[]},"); } } public static void ResetTeamQueue() { CurrentTeamQueueState = TeamQueueState.Idle; IsTeamQueuePolling = false; LastTeamPollData = null; } public static void FetchAllSeriesPaged(int page = 0, int pageSize = 3) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/team/all-series-paged?page={page}&page_size={pageSize}", delegate(bool success, string response) { if (!success || string.IsNullOrEmpty(response)) { return; } try { ParseAllSeriesPaged(response, page, pageSize); NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TEAM-SERIES-PAGED] parse: " + ex.Message)); } })); } private static void ParseAllSeriesPaged(string response, int reqPage, int reqPageSize) { List list = new List(); int num = response.IndexOf("\"series\""); if (num < 0) { CachedTeamSeriesPaged = list; return; } int num2 = response.IndexOf('[', num); int num3 = FindMatchingBracket(response, num2); if (num2 < 0 || num3 < 0) { CachedTeamSeriesPaged = list; return; } string text = response.Substring(num2 + 1, num3 - num2 - 1); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = FindMatchingBrace(text, num5); if (num6 < 0) { break; } string text2 = text.Substring(num5, num6 - num5 + 1); TeamSeriesPagedEntry item = new TeamSeriesPagedEntry { series_id = ExtractJsonString(text2, "series_id"), completed_at = ExtractJsonString(text2, "completed_at"), winner_team = ExtractJsonInt(text2, "winner_team"), t1_series_wins = ExtractJsonInt(text2, "t1_series_wins"), t2_series_wins = ExtractJsonInt(text2, "t2_series_wins"), t1a = ParseSeriesSlot(text2, "t1a"), t1b = ParseSeriesSlot(text2, "t1b"), t2a = ParseSeriesSlot(text2, "t2a"), t2b = ParseSeriesSlot(text2, "t2b"), matches = ParseSeriesMatches(text2) }; list.Add(item); num4 = num6 + 1; } CachedTeamSeriesPaged = list; CachedTeamSeriesTotal = ExtractJsonInt(response, "total"); CachedTeamSeriesPage = reqPage; CachedTeamSeriesPageSize = reqPageSize; CachedTeamSeriesTotalPages = ExtractJsonInt(response, "total_pages"); } private static TeamSeriesSlot ParseSeriesSlot(string seriesObj, string slotKey) { int num = seriesObj.IndexOf("\"" + slotKey + "\":"); if (num < 0) { return new TeamSeriesSlot(); } int num2 = seriesObj.IndexOf('{', num); int num3 = FindMatchingBrace(seriesObj, num2); if (num2 < 0 || num3 < 0) { return new TeamSeriesSlot(); } string json = seriesObj.Substring(num2, num3 - num2 + 1); return new TeamSeriesSlot { steam_id = ExtractJsonString(json, "steam_id"), name = ExtractJsonString(json, "name"), title = ExtractJsonString(json, "title"), title_color = ExtractJsonString(json, "title_color"), rating = (int)ExtractJsonFloat(json, "rating"), rating_change = ExtractJsonFloat(json, "rating_change"), gold_earned = ExtractJsonInt(json, "gold_earned"), xp_earned = ExtractJsonInt(json, "xp_earned") }; } private static List ParseSeriesMatches(string seriesObj) { List list = new List(); int num = seriesObj.IndexOf("\"matches\":"); if (num < 0) { return list; } int num2 = seriesObj.IndexOf('[', num); int num3 = FindMatchingBracket(seriesObj, num2); if (num2 < 0 || num3 < 0) { return list; } string text = seriesObj.Substring(num2 + 1, num3 - num2 - 1); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = FindMatchingBrace(text, num5); if (num6 < 0) { break; } string text2 = text.Substring(num5, num6 - num5 + 1); TeamSeriesMatch teamSeriesMatch = new TeamSeriesMatch { match_id = ExtractJsonString(text2, "match_id"), ended_at = ExtractJsonString(text2, "ended_at"), t1_rounds_won = ExtractJsonInt(text2, "t1_rounds_won"), t2_rounds_won = ExtractJsonInt(text2, "t2_rounds_won"), t1_points_total = ExtractJsonInt(text2, "t1_points_total"), t2_points_total = ExtractJsonInt(text2, "t2_points_total"), duration_seconds = ExtractJsonInt(text2, "duration_seconds") }; int num7 = text2.IndexOf("\"fps_by_player\":"); if (num7 >= 0) { int num8 = text2.IndexOf('{', num7); int num9 = ((num8 >= 0) ? FindMatchingBraceStringAware(text2, num8) : (-1)); if (num8 >= 0 && num9 > num8) { string text3 = text2.Substring(num8 + 1, num9 - num8 - 1); int num10 = 0; while (num10 < text3.Length) { int num11 = text3.IndexOf('"', num10); if (num11 < 0) { break; } int num12 = text3.IndexOf('"', num11 + 1); if (num12 < 0) { break; } string key = text3.Substring(num11 + 1, num12 - num11 - 1); int num13 = text3.IndexOf(':', num12); if (num13 < 0) { break; } int i; for (i = num13 + 1; i < text3.Length && (char.IsDigit(text3[i]) || text3[i] == ' '); i++) { } if (int.TryParse(text3.Substring(num13 + 1, i - num13 - 1).Trim(), out var result)) { teamSeriesMatch.fps_by_player[key] = result; } num10 = i + 1; } } } int num14 = text2.IndexOf("\"telemetry_by_player\":"); if (num14 >= 0) { int num15 = text2.IndexOf('{', num14); int num16 = ((num15 >= 0) ? FindMatchingBraceStringAware(text2, num15) : (-1)); if (num15 >= 0 && num16 > num15) { string text4 = text2.Substring(num15 + 1, num16 - num15 - 1); int num17 = 0; while (num17 < text4.Length) { int num18 = text4.IndexOf('"', num17); if (num18 < 0) { break; } int num19 = text4.IndexOf('"', num18 + 1); if (num19 < 0) { break; } string key2 = text4.Substring(num18 + 1, num19 - num18 - 1); int num20 = text4.IndexOf('{', num19); if (num20 < 0) { break; } int num21 = FindMatchingBraceStringAware(text4, num20); if (num21 < 0) { break; } string json = text4.Substring(num20, num21 - num20 + 1); teamSeriesMatch.telemetry_by_player[key2] = new TeamPlayerTele { fps_timeline = ExtractJsonString(json, "fps_timeline"), ping_timeline = ExtractJsonString(json, "ping_timeline"), hit_timeline = ExtractJsonString(json, "hit_timeline"), block_timeline = ExtractJsonString(json, "block_timeline"), ping_avg = ExtractJsonInt(json, "ping_avg"), bullets_fired = ExtractJsonInt(json, "bullets_fired"), bullets_hit = ExtractJsonInt(json, "bullets_hit"), blocks_activated = ExtractJsonInt(json, "blocks_activated"), blocks_successful = ExtractJsonInt(json, "blocks_successful") }; num17 = num21 + 1; } } } int num22 = text2.IndexOf("\"cards_by_player\":"); if (num22 >= 0) { int num23 = text2.IndexOf('{', num22); int num24 = FindMatchingBrace(text2, num23); if (num23 >= 0 && num24 > num23) { string text5 = text2.Substring(num23 + 1, num24 - num23 - 1); int num25 = 0; while (num25 < text5.Length) { int num26 = text5.IndexOf('"', num25); if (num26 < 0) { break; } int num27 = text5.IndexOf('"', num26 + 1); if (num27 < 0) { break; } string key3 = text5.Substring(num26 + 1, num27 - num26 - 1); int num28 = text5.IndexOf('[', num27); int num29 = FindMatchingBracket(text5, num28); if (num28 < 0 || num29 < 0) { break; } string text6 = text5.Substring(num28 + 1, num29 - num28 - 1); List list2 = new List(); int num30 = 0; while (num30 < text6.Length) { int num31 = text6.IndexOf('"', num30); if (num31 < 0) { break; } int num32 = text6.IndexOf('"', num31 + 1); if (num32 < 0) { break; } list2.Add(text6.Substring(num31 + 1, num32 - num31 - 1)); num30 = num32 + 1; } teamSeriesMatch.cards_by_player[key3] = list2; num25 = num29 + 1; } } } list.Add(teamSeriesMatch); num4 = num6 + 1; } return list; } public static void FetchTeamStats(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/team/players/" + steamId + "/team-stats", delegate(bool success, string response) { if (!success) { return; } try { TeamStatsData cachedTeamStats = new TeamStatsData { steam_id = ExtractJsonString(response, "steam_id"), display_name = ExtractJsonString(response, "display_name"), rating = ExtractJsonFloat(response, "rating"), rating_deviation = ExtractJsonFloat(response, "rating_deviation"), peak_rating = ExtractJsonFloat(response, "peak_rating"), completed_series = ExtractJsonInt(response, "completed_series"), series_wins = ExtractJsonInt(response, "series_wins"), series_losses = ExtractJsonInt(response, "series_losses"), series_win_rate = ExtractJsonFloat(response, "series_win_rate"), match_wins = ExtractJsonInt(response, "match_wins"), match_losses = ExtractJsonInt(response, "match_losses"), current_streak = ExtractJsonInt(response, "current_streak") }; CachedTeamStats = cachedTeamStats; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogError((object)("[TEAM-STATS] parse: " + ex.Message)); } })); } public static void FetchTeamMatchHistory(string steamId, int limit = 50) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/team/players/{steamId}/team-matches?limit={limit}", delegate(bool success, string response) { if (!success) { return; } try { List list = new List(); if (string.IsNullOrEmpty(response) || response.Trim() == "[]") { CachedTeamMatchHistory = list; NativeUI.MarkDirty(); } else { string[] array = response.Split(new string[1] { "\"match_id\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = array[i]; TeamMatchHistoryEntry teamMatchHistoryEntry = new TeamMatchHistoryEntry { match_id = ExtractJsonString(text, ""), series_id = ExtractJsonString(text, "series_id"), ended_at = ExtractJsonString(text, "ended_at"), won = text.Contains("\"won\":true"), my_team = ExtractJsonInt(text, "my_team"), t1a_steam_id = ExtractJsonString(text, "t1a_steam_id"), t1a_name = ExtractJsonString(text, "t1a_name"), t1b_steam_id = ExtractJsonString(text, "t1b_steam_id"), t1b_name = ExtractJsonString(text, "t1b_name"), t2a_steam_id = ExtractJsonString(text, "t2a_steam_id"), t2a_name = ExtractJsonString(text, "t2a_name"), t2b_steam_id = ExtractJsonString(text, "t2b_steam_id"), t2b_name = ExtractJsonString(text, "t2b_name"), t1_rounds_won = ExtractJsonInt(text, "t1_rounds_won"), t2_rounds_won = ExtractJsonInt(text, "t2_rounds_won"), t1_points_total = ExtractJsonInt(text, "t1_points_total"), t2_points_total = ExtractJsonInt(text, "t2_points_total"), series_score = ExtractJsonString(text, "series_score"), series_rating_change = ExtractJsonFloat(text, "series_rating_change") }; try { int num = text.IndexOf("\"cards_by_player\""); if (num >= 0) { int num2 = text.IndexOf('{', num); int num3 = FindMatchingBrace(text, num2); if (num2 >= 0 && num3 > num2) { string text2 = text.Substring(num2 + 1, num3 - num2 - 1); int num4 = 0; while (num4 < text2.Length) { int num5 = text2.IndexOf('"', num4); if (num5 < 0) { break; } int num6 = text2.IndexOf('"', num5 + 1); if (num6 < 0) { break; } string key = text2.Substring(num5 + 1, num6 - num5 - 1); int num7 = text2.IndexOf('[', num6); int num8 = FindMatchingBracket(text2, num7); if (num7 < 0 || num8 < 0) { break; } string text3 = text2.Substring(num7 + 1, num8 - num7 - 1); List list2 = new List(); int num9 = 0; while (num9 < text3.Length) { int num10 = text3.IndexOf('{', num9); if (num10 < 0) { break; } int num11 = 1; int j; for (j = num10 + 1; j < text3.Length; j++) { if (num11 <= 0) { break; } if (text3[j] == '{') { num11++; } else if (text3[j] == '}') { num11--; } } string json = text3.Substring(num10, j - num10); string text4 = ExtractJsonString(json, "card_name"); if (!string.IsNullOrEmpty(text4)) { list2.Add(text4); } num9 = j; } teamMatchHistoryEntry.cards_by_player[key] = list2; num4 = num8 + 1; } } } } catch { } list.Add(teamMatchHistoryEntry); } CachedTeamMatchHistory = list; Plugin.Log.LogInfo((object)$"[TEAM-HIST] loaded {list.Count} 2v2 matches"); NativeUI.MarkDirty(); } } catch (Exception ex) { Plugin.Log.LogError((object)("[TEAM-HIST] parse: " + ex.Message)); } })); } public static void FetchTeamLeaderboard(int limit = 200, string sortBy = "rating") { CachedTeamLeaderboardSort = sortBy; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/team/leaderboard?limit={limit}&sort_by={sortBy}", delegate(bool success, string response) { if (!success) { return; } try { List list = new List(); string[] array = response.Split(new string[1] { "\"rank\":" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = array[i]; int rank = 0; try { rank = int.Parse(text[..text.IndexOf(',')]); } catch { } list.Add(new TeamLeaderboardEntry { rank = rank, steam_id = ExtractJsonString(text, "steam_id"), display_name = ExtractJsonString(text, "display_name"), rating = ExtractJsonInt(text, "rating"), rd = ExtractJsonInt(text, "rd"), completed_series = ExtractJsonInt(text, "completed_series"), series_wins = ExtractJsonInt(text, "series_wins"), series_losses = ExtractJsonInt(text, "series_losses"), win_rate = ExtractJsonFloat(text, "win_rate"), level = ExtractJsonInt(text, "level"), title = ExtractJsonString(text, "title"), title_color = ExtractJsonString(text, "title_color"), avg_teammate_elo = ExtractJsonInt(text, "avg_teammate_elo"), team_gold_earned = ExtractJsonInt(text, "team_gold_earned"), team_xp_earned = ExtractJsonInt(text, "team_xp_earned") }); } CachedTeamLeaderboard = list; CachedTeamLeaderboardTotal = ExtractJsonInt(response, "total_players"); NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)$"[TEAM-LB] Loaded {list.Count} 2v2 ranked players"); } catch (Exception ex) { Plugin.Log.LogError((object)("[TEAM-LB] parse error: " + ex.Message)); } })); } public static void OvtJoinQueue(int preferredSide, bool soloExtraPick) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { return; } if (OvtQueueStatus == "leaving") { if (Time.realtimeSinceStartup - _ovtLeavingSince < 45f) { CompetitiveUI.ShowNotification("Still leaving the 1v2 queue — try again in a moment.", new Color(1f, 0.6f, 0.2f)); return; } OvtQueueStatus = ""; } bool flag = false; try { flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode; } catch { } if (flag) { CompetitiveUI.ShowNotification("Finish or leave your current game before joining the 1v2 queue.", new Color(1f, 0.7f, 0.3f)); return; } _ovtLastPreferredSide = preferredSide; _ovtLastSoloExtraPick = soloExtraPick; string text = Escape(MatchTracker.LocalDisplayName ?? "Player"); string text2 = ""; try { text2 = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { text2 = ""; } string json = "{\"steam_id\":\"" + localSteamId + "\",\"display_name\":\"" + text + "\",\"region\":\"" + Escape(text2) + "\"," + string.Format("\"preferred_side\":{0},\"solo_extra_pick\":{1}}}", preferredSide, soloExtraPick ? "true" : "false"); int gen = ++ovtGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/ovt/queue/join", json, delegate(bool ok, string resp) { if (gen != ovtGen) { Plugin.Log.LogInfo((object)"[1v2] stale join ack ignored (lifecycle moved on)"); } else if (ok) { IsOvtQueuePolling = true; OvtQueueStatus = "searching"; UpdateOvtQueueList(force: true); NativeUI.MarkDirty(); } else { Plugin.Log.LogWarning((object)("[1v2] join failed: " + resp)); } })); } public static void OvtLeaveQueue() { string localSteamId = MatchTracker.LocalSteamId; if (OvtQueueStatus == "leaving") { return; } IsOvtQueuePolling = false; OvtQueueCount = 0; OvtLockedSoloName = null; OvtLockedDuo = null; ActiveOvt1v2SeriesId = null; Plugin.ClearPendingOvtSlot(); if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { OvtQueueStatus = ""; return; } int gen = ++ovtGen; OvtQueueStatus = "leaving"; _ovtLeavingSince = Time.realtimeSinceStartup; NativeUI.MarkDirty(); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/ovt/queue/leave?steam_id=" + UnityWebRequest.EscapeURL(localSteamId), "", delegate(bool ok, string resp) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (gen == ovtGen) { if (ok) { Plugin.Log.LogInfo((object)"[1v2] Left 1v2 queue"); } else { Plugin.Log.LogWarning((object)("[1v2] Leave failed after retries: " + resp + " — server will prune the stale row")); CompetitiveUI.ShowNotification("Couldn't confirm 1v2 queue leave — the server will clear you shortly.", new Color(1f, 0.6f, 0.2f)); } if (OvtQueueStatus == "leaving") { OvtQueueStatus = ""; } UpdateOvtQueueList(force: true); NativeUI.MarkDirty(); } })); } public static void UpdateOvtQueuePoll(bool force) { if (!IsOvtQueuePolling) { return; } string sid = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(sid) || sid == "unknown" || (!force && Time.unscaledTime - _ovtLastPollAt < 2f)) { return; } _ovtLastPollAt = Time.unscaledTime; int gen = ovtGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/ovt/queue/poll/" + sid, delegate(bool ok, string resp) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Expected O, but got Unknown //IL_0525: Unknown result type (might be due to invalid IL or missing references) if (ok && !string.IsNullOrEmpty(resp) && IsOvtQueuePolling && gen == ovtGen) { string text = (OvtQueueStatus = ExtractJsonString(resp, "status") ?? ""); OvtQueueCount = ExtractJsonInt(resp, "queue_count"); if (text == "ready_join") { bool flag = false; try { flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode; } catch { } if (flag) { Plugin.Log.LogWarning((object)"[1v2] ready_join landed while in another room — declining (leaving 1v2 queue)"); OvtLeaveQueue(); CompetitiveUI.ShowNotification("1v2 match found, but you're in a game — removed from the 1v2 queue.", new Color(1f, 0.7f, 0.3f), 7f); NativeUI.MarkDirty(); return; } IsOvtQueuePolling = false; ActiveOvt1v2SeriesId = ExtractJsonString(resp, "series_id"); OvtMySide = ExtractJsonInt(resp, "side_assigned"); OvtSoloExtraPick = ExtractJsonBool(resp, "solo_extra_pick"); string text2 = ExtractJsonString(resp, "room_name"); string text3 = ExtractJsonString(resp, "room_region"); string ovtLockedSoloName = null; try { int num = resp.IndexOf("\"solo\":"); int num2 = ((num >= 0) ? resp.IndexOf('{', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBrace(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { ovtLockedSoloName = ExtractJsonString(resp.Substring(num2, num3 - num2 + 1), "display_name"); } } catch { } List list = ExtractTeamMemberList(resp, "duo"); OvtLockedSoloName = ovtLockedSoloName; OvtLockedDuo = list; if (!string.IsNullOrEmpty(text2)) { string text4 = ActiveOvt1v2SeriesId + "|" + text2; if (text4 == _ovtLastReadyFireKey) { _ovtReadyFireCount++; } else { _ovtLastReadyFireKey = text4; _ovtReadyFireCount = 1; } if (_ovtReadyFireCount > 3) { Plugin.Log.LogWarning((object)$"[1v2] ready_join re-fired {_ovtReadyFireCount}x for '{text2}' — giving up and leaving the 1v2 queue"); CompetitiveUI.ShowNotification("Couldn't join the 1v2 room - left the queue. Please requeue.", Color.yellow, 8f); OvtLeaveQueue(); NativeUI.MarkDirty(); return; } int num4 = 0; if (OvtMySide != 1) { if (list.Count >= 1 && list[0].steam_id == sid) { num4 = 1; } else if (list.Count >= 2 && list[1].steam_id == sid) { num4 = 2; } else { num4 = 1; Plugin.Log.LogWarning((object)$"[1v2] my steam id not found in duo payload — defaulting slot 1 (duo={list.Count})"); } } Plugin.SetPendingOvtSlot(num4); try { Hashtable val = new Hashtable(); val[(object)"p_id"] = num4; val[(object)"t_id"] = ((num4 != 0) ? 1 : 0); val[(object)"u_id"] = sid; if (PhotonNetwork.LocalPlayer != null) { PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[1v2] pre-join SetCustomProperties: " + ex.Message)); } try { NametagStyler.PublishToPhoton(); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[1v2] pre-join nametag publish: " + ex2.Message)); } try { PlayerColorCosmetic.PublishLocalProps(); } catch (Exception ex3) { Plugin.Log.LogWarning((object)("[1v2] pre-join pcolor publish: " + ex3.Message)); } try { TrailCosmetic.PublishLocalProps(); } catch (Exception ex4) { Plugin.Log.LogWarning((object)("[1v2] pre-join trail publish: " + ex4.Message)); } Plugin.SetPendingRoom(text2, text3); Plugin.Log.LogInfo((object)string.Format("[1v2] All ready! Room: {0} (region: {1}) series={2} side={3} slot={4}", text2, text3 ?? "auto", ActiveOvt1v2SeriesId, OvtMySide, num4)); CompetitiveUI.ShowNotification((OvtMySide == 1) ? "3/3 ready! Joining 1v2 — you are the SOLO..." : "3/3 ready! Joining 1v2 — you are on the DUO...", Color.green); try { if (NativeUI.IsOpen) { NativeUI.Close(); } } catch { } } } else if (text == "not_in_queue" || text == "expired") { IsOvtQueuePolling = false; OvtQueueStatus = ""; OvtLockedSoloName = null; OvtLockedDuo = null; Plugin.ClearPendingOvtSlot(); if (text == "expired") { CompetitiveUI.ShowNotification("Removed from 1v2 queue after 30 minutes of searching - rejoin if you're still here!", Color.yellow, 7f); } if (text == "not_in_queue" && (!PhotonNetwork.InRoom || PhotonNetwork.OfflineMode) && Time.unscaledTime - _ovtLastAutoRejoinAt > 60f) { _ovtLastAutoRejoinAt = Time.unscaledTime; Plugin.Log.LogWarning((object)"[1v2] queue row vanished server-side while searching — auto-rejoining"); OvtJoinQueue(_ovtLastPreferredSide, _ovtLastSoloExtraPick); } } NativeUI.MarkDirty(); } })); } public static void UpdateOvtQueueList(bool force = false) { if (!force && Time.unscaledTime - _ovtListLastAt < 2f) { return; } _ovtListLastAt = Time.unscaledTime; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/ovt/queue/list", delegate(bool ok, string resp) { if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = resp.IndexOf("\"queuers\""); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracket(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { string text = resp.Substring(num2 + 1, num3 - num2 - 1); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = FindMatchingBrace(text, num5); if (num6 < 0) { break; } string json = text.Substring(num5, num6 - num5 + 1); list.Add(new OvtQueueListEntry { steam_id = ExtractJsonString(json, "steam_id"), display_name = ExtractJsonString(json, "display_name"), rating_1v1 = ExtractJsonInt(json, "rating_1v1"), rating_2v2 = ExtractJsonInt(json, "rating_2v2"), preferred_side = ExtractJsonInt(json, "preferred_side"), solo_extra_pick = ExtractJsonBool(json, "solo_extra_pick"), status = ExtractJsonString(json, "status"), side_assigned = ExtractJsonInt(json, "side_assigned"), wait_seconds = ExtractJsonInt(json, "wait_seconds"), region = ExtractJsonString(json, "region") }); num4 = num6 + 1; } } CachedOvtQueueList = list; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[1v2-QUEUE-LIST] parse: " + ex.Message)); } })); } public static void RequestOvtContinuationSeries(string reporterSteam, string roomId, string region, string soloSteam, string duoASteam, string duoBSteam, Action callback = null) { string message = "ovt-continuation:" + soloSteam + ":" + duoASteam + ":" + duoBSteam + ":" + roomId + ":" + reporterSteam; string text = ComputeHmacHex(message); string json = "{\"reporter_steam_id\":\"" + Escape(reporterSteam) + "\",\"room_id\":\"" + Escape(roomId) + "\",\"region\":\"" + Escape(region ?? "") + "\",\"t1a_steam\":\"" + Escape(soloSteam) + "\",\"t1b_steam\":\"" + Escape(duoASteam) + "\",\"t2a_steam\":\"" + Escape(duoBSteam) + "\",\"t2b_steam\":\"" + Escape(duoBSteam) + "\",\"hmac_signature\":\"" + text + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/ovt/series/continuation", json, delegate(bool ok, string resp) { if (ok && !string.IsNullOrEmpty(resp)) { string text2 = ExtractJsonString(resp, "series_id"); if (!string.IsNullOrEmpty(text2)) { ActiveOvt1v2SeriesId = text2; Plugin.Log.LogInfo((object)("[1v2-CONTINUATION] active series set to " + text2 + " (" + ExtractJsonString(resp, "status") + ")")); } } else { Plugin.Log.LogWarning((object)("[1v2-CONTINUATION] request failed: " + resp)); } callback?.Invoke(ok); }, 2)); } public static void FetchOvtLeaderboard(int limit = 200, string role = "combined") { string roleQ = ((role == "solo" || role == "duo") ? role : "combined"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/ovt/leaderboard?limit={limit}&role={roleQ}", delegate(bool ok, string resp) { if (!ok) { return; } try { List list = new List(); int num = resp.IndexOf("\"entries\""); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { list.Add(new OvtLeaderboardEntry { rank = ExtractJsonInt(item, "rank"), steam_id = ExtractJsonString(item, "steam_id"), display_name = ExtractJsonString(item, "display_name"), games_played = ExtractJsonInt(item, "games_played"), wins = ExtractJsonInt(item, "wins"), losses = ExtractJsonInt(item, "losses"), win_rate = ExtractJsonFloat(item, "win_rate"), solo_games = ExtractJsonInt(item, "solo_games"), duo_games = ExtractJsonInt(item, "duo_games"), solo_wins = ExtractJsonInt(item, "solo_wins"), solo_losses = ExtractJsonInt(item, "solo_losses"), duo_wins = ExtractJsonInt(item, "duo_wins"), duo_losses = ExtractJsonInt(item, "duo_losses"), level = ExtractJsonInt(item, "level"), title = ExtractJsonString(item, "title"), title_color = ExtractJsonString(item, "title_color"), last_played = ExtractJsonString(item, "last_played") }); } } if (roleQ == "solo") { CachedOvtLeaderboardSolo = list; } else if (roleQ == "duo") { CachedOvtLeaderboardDuo = list; } else { CachedOvtLeaderboard = list; CachedOvtLeaderboardTotal = ExtractJsonInt(resp, "total_players"); } NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)$"[1v2-LB] loaded {list.Count} players (role={roleQ})"); } catch (Exception ex) { Plugin.Log.LogError((object)("[1v2-LB] parse: " + ex.Message)); } })); } public static void ReportOvtMatch(string seriesId, string room, string region, int durationSeconds, string soloSteam, string soloName, List soloCards, string duoASteam, string duoAName, List duoACards, string duoBSteam, string duoBName, List duoBCards, int soloRounds, int duoRounds, int soloPoints, int duoPoints, string reporterSteam, int soloFps, int duoAFps, int duoBFps) { int num = ((soloRounds > duoRounds) ? 1 : 2); bool flag = false; StringBuilder sb = new StringBuilder(); sb.Append("{"); sb.Append("\"series_id\":\"" + Escape(seriesId) + "\","); appendPlayer("solo", soloSteam, soloName, soloCards); appendPlayer("duo_a", duoASteam, duoAName, duoACards); appendPlayer("duo_b", duoBSteam, duoBName, duoBCards); sb.Append($"\"solo_rounds_won\":{soloRounds},\"duo_rounds_won\":{duoRounds},"); sb.Append($"\"solo_points_total\":{soloPoints},\"duo_points_total\":{duoPoints},"); sb.Append($"\"winner_side\":{num},"); sb.Append("\"photon_room_id\":\"" + Escape(room) + "\",\"game_version\":\"v" + Application.version + "\","); sb.Append($"\"region\":\"{Escape(region)}\",\"match_duration\":{durationSeconds},"); sb.Append("\"is_ranked\":" + (flag ? "true" : "false") + ","); sb.Append("\"reported_by_steam_id\":\"" + Escape(reporterSteam) + "\","); sb.Append($"\"solo_fps\":{soloFps},\"duo_a_fps\":{duoAFps},\"duo_b_fps\":{duoBFps},"); string message = $"{soloSteam}:{duoASteam}:{duoBSteam}:{soloRounds}:{duoRounds}:" + string.Format("{0}:{1}:{2}:{3}:{4}", flag ? "true" : "false", reporterSteam, room ?? "", num, seriesId); sb.Append("\"hmac_signature\":\"" + ComputeHmacHex(message) + "\""); sb.Append("}"); string json = sb.ToString(); Plugin.Log.LogInfo((object)$"[1v2-REPORT] submitting series={seriesId} winner=side{num} {soloRounds}-{duoRounds}"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/ovt/matches", json, delegate(bool ok, string resp) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if (ok) { Plugin.Log.LogInfo((object)("[1v2] match reported: " + resp)); string text = ExtractJsonString(resp, "series_status"); string text2 = ExtractJsonString(resp, "series_score"); if (text == "completed") { CompetitiveUI.ShowNotification("1v2 series complete: " + text2, Color.green, 6f); ActiveOvt1v2SeriesId = null; Plugin.ClearPendingOvtSlot(); } else if (!string.IsNullOrEmpty(text2)) { CompetitiveUI.ShowNotification("1v2 series: " + text2, new Color(0.6f, 0.8f, 1f), 4f); } int num2 = ExtractJsonInt(resp, "xp_gained"); int num3 = ExtractJsonInt(resp, "gold_gained"); if (num2 > 0 || num3 > 0) { string text3 = $"+{num2} XP" + ((num3 > 0) ? $" +{num3}g" : ""); string text4 = string.Join(", ", ExtractJsonStringArray(resp, "xp_bonuses").ToArray()); if (!string.IsNullOrEmpty(text4)) { text3 = text3 + " (" + text4 + ")"; } CompetitiveUI.QueueNotification(text3, new Color(0.75f, 0.9f, 0.6f)); } } else { Plugin.Log.LogWarning((object)("[1v2] report failed: " + resp)); EnqueueFailedReport(baseUrl + "/api/v1/ovt/matches", json); } })); void appendPlayer(string key, string steam, string nm, List cards) { sb.Append("\"" + key + "\":{\"steam_id\":\"" + Escape(steam) + "\",\"display_name\":\"" + Escape(nm) + "\",\"cards\":["); AppendCards(sb, cards ?? new List()); sb.Append("]},"); } } private static Dictionary ParseSteamIntMap(string json, string key) { Dictionary dictionary = new Dictionary(); int num = json.IndexOf("\"" + key + "\":"); if (num < 0) { return dictionary; } int num2 = json.IndexOf('{', num); if (num2 < 0) { return dictionary; } int num3 = FindMatchingBraceStringAware(json, num2); if (num3 < 0) { return dictionary; } int num4 = num2 + 1; while (num4 < num3) { int num5 = json.IndexOf('"', num4); if (num5 < 0 || num5 >= num3) { break; } int num6 = json.IndexOf('"', num5 + 1); if (num6 < 0 || num6 >= num3) { break; } string text = json.Substring(num5 + 1, num6 - num5 - 1); int num7 = json.IndexOf(':', num6); if (num7 < 0 || num7 >= num3) { break; } int i; for (i = num7 + 1; i < num3 && json[i] == ' '; i++) { } int num8 = i; for (; i < num3 && (char.IsDigit(json[i]) || json[i] == '-'); i++) { } int result = 0; if (i > num8) { int.TryParse(json.Substring(num8, i - num8), out result); } if (!string.IsNullOrEmpty(text)) { dictionary[text] = result; } num4 = i + 1; } return dictionary; } private static List ParseJsonStringArray(string s, int open, int close) { List list = new List(); StringBuilder stringBuilder = new StringBuilder(); bool flag = false; for (int i = open + 1; i < close; i++) { char c = s[i]; if (!flag) { if (c == '"') { flag = true; stringBuilder.Length = 0; } } else if (c == '\\' && i + 1 < close) { i++; char c2 = s[i]; stringBuilder.Append(c2 switch { 'r' => '\r', 't' => '\t', 'n' => '\n', _ => c2, }); } else if (c == '"') { flag = false; list.Add(stringBuilder.ToString()); } else { stringBuilder.Append(c); } } return list; } private static Dictionary> ParseSteamCardsMap(string json, string key) { Dictionary> dictionary = new Dictionary>(); int num = json.IndexOf("\"" + key + "\":"); if (num < 0) { return dictionary; } int num2 = json.IndexOf('{', num); if (num2 < 0) { return dictionary; } int num3 = FindMatchingBraceStringAware(json, num2); if (num3 < 0) { return dictionary; } int num4 = num2 + 1; while (num4 < num3) { int num5 = json.IndexOf('"', num4); if (num5 < 0 || num5 >= num3) { break; } int num6 = json.IndexOf('"', num5 + 1); if (num6 < 0 || num6 >= num3) { break; } string text = json.Substring(num5 + 1, num6 - num5 - 1); int num7 = json.IndexOf('[', num6); if (num7 < 0 || num7 >= num3) { break; } int num8 = FindMatchingBracketStringAware(json, num7); if (num8 < 0 || num8 > num3) { break; } if (!string.IsNullOrEmpty(text)) { dictionary[text] = ParseJsonStringArray(json, num7, num8); } num4 = num8 + 1; } return dictionary; } public static void FetchOvtRecent(int page = 0, int pageSize = 5) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/ovt/recent?page={page}&page_size={pageSize}", delegate(bool ok, string resp) { if (!ok) { return; } try { List list = new List(); int num = resp.IndexOf("\"series\""); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { int num4 = item.IndexOf("\"matches\":"); string text = ((num4 >= 0) ? item.Substring(0, num4) : item); OvtRecentSeries ovtRecentSeries = new OvtRecentSeries { series_id = ExtractJsonString(text, "series_id"), status = ExtractJsonString(text, "status"), winner_side = ExtractJsonInt(text, "winner_side"), created_at = ExtractJsonString(text, "created_at"), completed_at = ExtractJsonString(text, "completed_at"), solo_wins = ExtractJsonInt(text, "solo_wins"), duo_wins = ExtractJsonInt(text, "duo_wins"), solo_extra_pick = ExtractJsonBool(text, "solo_extra_pick"), gold_by_steam = ParseSteamIntMap(text, "gold_by_steam"), xp_by_steam = ParseSteamIntMap(text, "xp_by_steam") }; int num5 = text.IndexOf("\"solo\":"); int num6 = ((num5 >= 0) ? text.IndexOf('{', num5) : (-1)); int num7 = ((num6 >= 0) ? FindMatchingBraceStringAware(text, num6) : (-1)); if (num6 >= 0 && num7 > num6) { string json = text.Substring(num6, num7 - num6 + 1); ovtRecentSeries.solo_steam = ExtractJsonString(json, "steam_id"); ovtRecentSeries.solo_name = ExtractJsonString(json, "display_name"); } int num8 = text.IndexOf("\"duo\":"); int num9 = ((num8 >= 0) ? text.IndexOf('[', num8) : (-1)); int num10 = ((num9 >= 0) ? FindMatchingBracketStringAware(text, num9) : (-1)); if (num9 >= 0 && num10 > num9) { List list2 = SliceTopLevelObjects(text.Substring(num9 + 1, num10 - num9 - 1)); if (list2.Count > 0) { ovtRecentSeries.duo_a_steam = ExtractJsonString(list2[0], "steam_id"); ovtRecentSeries.duo_a_name = ExtractJsonString(list2[0], "display_name"); } if (list2.Count > 1) { ovtRecentSeries.duo_b_steam = ExtractJsonString(list2[1], "steam_id"); ovtRecentSeries.duo_b_name = ExtractJsonString(list2[1], "display_name"); } } int num11 = ((num4 >= 0) ? item.IndexOf('[', num4) : (-1)); int num12 = ((num11 >= 0) ? FindMatchingBracketStringAware(item, num11) : (-1)); if (num11 >= 0 && num12 > num11) { foreach (string item2 in SliceTopLevelObjects(item.Substring(num11 + 1, num12 - num11 - 1))) { ovtRecentSeries.matches.Add(new OvtRecentMatch { match_id = ExtractJsonString(item2, "match_id"), ended_at = ExtractJsonString(item2, "ended_at"), winner_side = ExtractJsonInt(item2, "winner_side"), solo_rounds = ExtractJsonInt(item2, "solo_rounds"), duo_rounds = ExtractJsonInt(item2, "duo_rounds"), solo_points = ExtractJsonInt(item2, "solo_points"), duo_points = ExtractJsonInt(item2, "duo_points"), duration_seconds = ExtractJsonInt(item2, "duration_seconds"), fps_by_steam = ParseSteamIntMap(item2, "fps_by_steam"), cards_by_steam = ParseSteamCardsMap(item2, "cards_by_steam") }); } } list.Add(ovtRecentSeries); } } CachedOvtRecent = list; CachedOvtRecentTotal = ExtractJsonInt(resp, "total"); CachedOvtRecentPages = ExtractJsonInt(resp, "total_pages"); NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)$"[1v2-RECENT] loaded {list.Count} series (page {page})"); } catch (Exception ex) { Plugin.Log.LogError((object)("[1v2-RECENT] parse: " + ex.Message)); } })); } private static void FfaLobbyActionBegin() { _ffaLobbyActionInFlight = true; _ffaLobbyActionAt = Time.realtimeSinceStartup; _ffaLobbyActionGen++; } private static void FfaLobbyActionEnd(int actionGen) { if (actionGen == _ffaLobbyActionGen) { _ffaLobbyActionInFlight = false; } } private static string DetailOr(string resp, string fallback) { string text = ExtractJsonString(resp ?? "", "detail"); return string.IsNullOrEmpty(text) ? fallback : text; } public static void FfaJoinQueue() { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { return; } if (FfaQueueStatus == "leaving") { if (Time.realtimeSinceStartup - _ffaLeavingSince < 45f) { CompetitiveUI.ShowNotification("Still leaving the FFA queue — try again in a moment.", new Color(1f, 0.6f, 0.2f)); return; } FfaQueueStatus = ""; } bool flag = false; try { flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode; } catch { } if (flag) { CompetitiveUI.ShowNotification("Finish or leave your current game before joining the FFA queue.", new Color(1f, 0.7f, 0.3f)); return; } string text = Escape(MatchTracker.LocalDisplayName ?? "Player"); string text2 = ""; try { text2 = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { text2 = ""; } string json = "{\"steam_id\":\"" + localSteamId + "\",\"display_name\":\"" + text + "\",\"region\":\"" + Escape(text2) + "\"}"; int gen = ++ffaGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/ffa/queue/join", json, delegate(bool ok, string resp) { if (gen != ffaGen) { Plugin.Log.LogInfo((object)"[FFA] stale join ack ignored (lifecycle moved on)"); } else if (ok) { IsFfaQueuePolling = true; FfaQueueStatus = "searching"; UpdateFfaQueueList(force: true); NativeUI.MarkDirty(); } else { Plugin.Log.LogWarning((object)("[FFA] join failed: " + resp)); } })); } private static bool FfaLobbyActionPreflight(out string sid) { //IL_011e: 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_00cc: Unknown result type (might be due to invalid IL or missing references) sid = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(sid) || sid == "unknown") { return false; } if (_ffaLobbyActionInFlight && Time.realtimeSinceStartup - _ffaLobbyActionAt > 30f) { _ffaLobbyActionInFlight = false; } if (_ffaLobbyActionInFlight) { return false; } if (FfaQueueStatus == "leaving") { CompetitiveUI.ShowNotification("Still leaving — try again in a moment.", new Color(1f, 0.6f, 0.2f)); return false; } if (!string.IsNullOrEmpty(ActiveFfaLobbyId)) { CompetitiveUI.ShowNotification("Your FFA is already starting — leave it first if you meant to switch.", new Color(1f, 0.7f, 0.3f)); return false; } bool flag = false; try { flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode && CompetitiveRoomDetect.IsCompetitiveRoom(); } catch { } if (flag) { CompetitiveUI.ShowNotification("Finish or leave your current game first.", new Color(1f, 0.7f, 0.3f)); return false; } return true; } private static string FfaLobbyBody(string sid, string lobbyId = null) { string text = Escape(MatchTracker.LocalDisplayName ?? "Player"); string text2 = ""; try { text2 = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { text2 = ""; } string text3 = ((lobbyId == null) ? "" : (",\"lobby_id\":\"" + Escape(lobbyId) + "\"")); return "{\"steam_id\":\"" + sid + "\",\"display_name\":\"" + text + "\",\"region\":\"" + Escape(text2) + "\"" + text3 + "}"; } private static void FfaEnrollResult(bool ok, string resp, string intendedLobbyId, bool wasRecovery) { //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) if (ok) { string text = ExtractJsonString(resp, "lobby_id"); OpenFfaLobbyId = (string.IsNullOrEmpty(text) ? intendedLobbyId : text); _ffaLeaveIntent = false; IsFfaQueuePolling = true; FfaQueueStatus = "lobby"; Plugin.Log.LogInfo((object)$"[FFA-LOBBY] enrolled in lobby {OpenFfaLobbyId} (recovery={wasRecovery})"); bool flag = false; try { flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode && CompetitiveRoomDetect.IsCompetitiveRoom(); } catch { } if (flag) { Plugin.Log.LogWarning((object)"[FFA-LOBBY] enrolled while inside a competitive room — leaving the lobby"); FfaLeaveQueue(); return; } } else { bool flag2 = resp?.StartsWith("HTTP 4", StringComparison.Ordinal) ?? false; Plugin.Log.LogWarning((object)$"[FFA-LOBBY] enroll failed (recovery={wasRecovery}, serverSpoke={flag2}): {resp}"); if (wasRecovery && flag2) { OpenFfaLobbyId = null; FfaLobbyIsHost = false; FfaLobbyCanStart = false; FfaLobbyMembers = null; FfaLobbyMemberCount = 0; IsFfaQueuePolling = false; if (FfaQueueStatus == "lobby") { FfaQueueStatus = ""; } CompetitiveUI.ShowNotification("Your FFA lobby closed.", new Color(1f, 0.75f, 0.4f), 6f); } else if (!flag2) { if (!string.IsNullOrEmpty(intendedLobbyId)) { OpenFfaLobbyId = intendedLobbyId; } _ffaAmbiguousPollUntil = Time.unscaledTime + 90f; IsFfaQueuePolling = true; UpdateFfaQueuePoll(force: true); } else { CompetitiveUI.ShowNotification(DetailOr(resp, "Couldn't join that lobby."), new Color(1f, 0.6f, 0.2f)); } } FetchFfaLobbies(force: true); NativeUI.MarkDirty(); } public static void FfaCreateLobby() { if (!FfaLobbyActionPreflight(out var sid)) { return; } _ffaLeaveIntent = false; int gen = ++ffaGen; FfaLobbyActionBegin(); int actionGen = _ffaLobbyActionGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/ffa/lobby/create", FfaLobbyBody(sid), delegate(bool ok, string resp) { FfaLobbyActionEnd(actionGen); if (gen == ffaGen) { if (ok) { FfaLobbyIsHost = true; } FfaEnrollResult(ok, resp, null, wasRecovery: false); } })); } public static void FfaJoinLobby(string lobbyId) { if (string.IsNullOrEmpty(lobbyId) || !FfaLobbyActionPreflight(out var sid)) { return; } bool wasRecovery = OpenFfaLobbyId == lobbyId; if (!wasRecovery) { _ffaLeaveIntent = false; } int gen = ++ffaGen; FfaLobbyActionBegin(); int actionGen = _ffaLobbyActionGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/ffa/lobby/join", FfaLobbyBody(sid, lobbyId), delegate(bool ok, string resp) { FfaLobbyActionEnd(actionGen); if (gen == ffaGen) { FfaEnrollResult(ok, resp, lobbyId, wasRecovery); } })); } public static void FfaStartLobby() { string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { return; } if (_ffaLobbyActionInFlight && Time.realtimeSinceStartup - _ffaLobbyActionAt > 30f) { _ffaLobbyActionInFlight = false; } if (_ffaLobbyActionInFlight) { return; } int gen = ffaGen; FfaLobbyActionBegin(); int actionGen = _ffaLobbyActionGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/ffa/lobby/start", "{\"steam_id\":\"" + localSteamId + "\"}", delegate(bool ok, string resp) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) FfaLobbyActionEnd(actionGen); if (gen == ffaGen) { if (!ok) { Plugin.Log.LogWarning((object)("[FFA-LOBBY] start failed: " + resp)); CompetitiveUI.ShowNotification(DetailOr(resp, "Couldn't start the game."), new Color(1f, 0.6f, 0.2f)); NativeUI.MarkDirty(); } else { Plugin.Log.LogInfo((object)"[FFA-LOBBY] start accepted — lock lands via the poll"); } } })); } public static void FetchFfaLobbies(bool force = false) { if (!force && Time.unscaledTime - _ffaLobbiesLastAt < 3f) { return; } _ffaLobbiesLastAt = Time.unscaledTime; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/ffa/lobbies", delegate(bool ok, string resp) { if (!ok || string.IsNullOrEmpty(resp)) { FfaLobbiesUnavailable = true; if (CachedFfaLobbies == null) { CachedFfaLobbies = new List(); } NativeUI.MarkDirty(); return; } FfaLobbiesUnavailable = false; try { List list = new List(); int num = resp.IndexOf("\"lobbies\""); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { FfaOpenLobbyEntry ffaOpenLobbyEntry = new FfaOpenLobbyEntry { lobby_id = ExtractJsonString(item, "lobby_id"), host_name = (ExtractJsonString(item, "host_name") ?? "?"), player_count = ExtractJsonInt(item, "player_count"), max_players = Math.Max(1, ExtractJsonInt(item, "max_players")), age_seconds = ExtractJsonInt(item, "age_seconds") }; if (!string.IsNullOrEmpty(ffaOpenLobbyEntry.lobby_id)) { list.Add(ffaOpenLobbyEntry); } } } CachedFfaLobbies = list; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-LOBBY] browser parse: " + ex.Message)); } })); } public static void FfaProbeServerState() { if (_ffaProbed || IsFfaQueuePolling) { _ffaProbed = true; return; } _ffaProbed = true; IsFfaQueuePolling = true; UpdateFfaQueuePoll(force: true); } public static void FfaLeaveQueue() { string localSteamId = MatchTracker.LocalSteamId; if (FfaQueueStatus == "leaving") { return; } string expectedLobby = ((!string.IsNullOrEmpty(OpenFfaLobbyId)) ? OpenFfaLobbyId : ActiveFfaLobbyId); _ffaLeaveIntent = true; if (!string.IsNullOrEmpty(expectedLobby)) { _ffaLeaveTargetLobby = expectedLobby; } _ffaJoinCountdownKey = null; _ffaJoinCountdownActiveToken = 0; CompetitiveUI.CancelFfaStartCountdown(); IsFfaQueuePolling = false; FfaQueueCount = 0; FfaGatherSecondsLeft = -1; FfaLockedRoster = null; ActiveFfaLobbyId = null; FfaMySlot = -1; FfaLobbyPlayerCount = 0; FfaLobbyIsHost = false; FfaLobbyCanStart = false; FfaLobbyMembers = null; FfaLobbyMemberCount = 0; Plugin.ClearPendingFfaSlot(); try { if ((Plugin.PendingRankedRoom ?? "").StartsWith("ffa_")) { Plugin.ClearPendingRoom(); } } catch { } if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { FfaQueueStatus = ""; OpenFfaLobbyId = null; _ffaLeaveIntent = false; return; } int gen = ++ffaGen; FfaQueueStatus = "leaving"; _ffaLeavingSince = Time.realtimeSinceStartup; NativeUI.MarkDirty(); string text = baseUrl + "/api/v1/ffa/queue/leave?steam_id=" + UnityWebRequest.EscapeURL(localSteamId); if (!string.IsNullOrEmpty(expectedLobby)) { text = text + "&expected_lobby_id=" + UnityWebRequest.EscapeURL(expectedLobby); } ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(text, "", delegate(bool ok, string resp) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (gen == ffaGen) { if (ok) { OpenFfaLobbyId = null; _ffaLeaveIntent = false; _ffaLeaveTargetLobby = null; Plugin.Log.LogInfo((object)"[FFA] Left FFA queue/lobby"); } else { Plugin.Log.LogWarning((object)("[FFA] Leave failed after retries: " + resp + " — re-arming the poll to recover")); OpenFfaLobbyId = OpenFfaLobbyId ?? expectedLobby; IsFfaQueuePolling = !string.IsNullOrEmpty(OpenFfaLobbyId); CompetitiveUI.ShowNotification("Couldn't confirm FFA leave — the server will clear you shortly.", new Color(1f, 0.6f, 0.2f)); } if (FfaQueueStatus == "leaving") { FfaQueueStatus = ""; } UpdateFfaQueueList(force: true); FetchFfaLobbies(force: true); NativeUI.MarkDirty(); } })); } public static void UpdateFfaQueuePoll(bool force) { if (!IsFfaQueuePolling) { return; } if (_ffaAmbiguousPollUntil > 0f && Time.unscaledTime > _ffaAmbiguousPollUntil && string.IsNullOrEmpty(OpenFfaLobbyId) && string.IsNullOrEmpty(ActiveFfaLobbyId) && !_ffaLeaveIntent) { _ffaAmbiguousPollUntil = -999f; IsFfaQueuePolling = false; if (FfaQueueStatus != "leaving") { FfaQueueStatus = ""; } Plugin.Log.LogInfo((object)"[FFA-LOBBY] ambiguity window lapsed with no resolution — stopping the probe poll"); NativeUI.MarkDirty(); return; } string sid = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(sid) || sid == "unknown" || (!force && Time.unscaledTime - _ffaLastPollAt < 2f)) { return; } _ffaLastPollAt = Time.unscaledTime; int gen = ffaGen; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/ffa/queue/poll/" + sid, delegate(bool ok, string resp) { //IL_0945: Unknown result type (might be due to invalid IL or missing references) //IL_0a5c: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_05da: Unknown result type (might be due to invalid IL or missing references) //IL_074a: Unknown result type (might be due to invalid IL or missing references) //IL_077c: Unknown result type (might be due to invalid IL or missing references) //IL_0783: Expected O, but got Unknown //IL_049a: Unknown result type (might be due to invalid IL or missing references) if (ok && !string.IsNullOrEmpty(resp) && IsFfaQueuePolling && gen == ffaGen) { string text = (FfaQueueStatus = ExtractJsonString(resp, "status") ?? ""); FfaQueueCount = ExtractJsonInt(resp, "queue_count"); switch (text) { case "searching": { int ffaGatherSecondsLeft = -1; try { ffaGatherSecondsLeft = (resp.Contains("\"gather_seconds_left\"") ? ExtractJsonInt(resp, "gather_seconds_left") : (-1)); } catch { } FfaGatherSecondsLeft = ffaGatherSecondsLeft; bool flag2 = !string.IsNullOrEmpty(OpenFfaLobbyId) || !string.IsNullOrEmpty(ActiveFfaLobbyId) || Plugin.PendingFfaSlot >= 0; OpenFfaLobbyId = null; ActiveFfaLobbyId = null; FfaLobbyIsHost = false; FfaLobbyCanStart = false; FfaLobbyMembers = null; FfaLobbyMemberCount = 0; FfaMySlot = -1; FfaLobbyPlayerCount = 0; FfaLockedRoster = null; Plugin.ClearPendingFfaSlot(); if (flag2) { CompetitiveUI.ShowNotification("Your FFA lobby was dissolved.", new Color(1f, 0.75f, 0.4f), 6f); } Plugin.Log.LogInfo((object)$"[FFA-LOBBY] legacy searching row detected (belief={flag2}) — leaving it"); FfaLeaveQueue(); NativeUI.MarkDirty(); return; } case "lobby": { if (!string.IsNullOrEmpty(ActiveFfaLobbyId)) { return; } if (_ffaLeaveIntent) { if (Time.unscaledTime - _ffaLeaveRetryAt > 10f) { _ffaLeaveRetryAt = Time.unscaledTime; Plugin.Log.LogWarning((object)"[FFA-LOBBY] leave intent pending but seat still exists — retrying leave"); FfaLeaveQueue(); } return; } bool flag = false; try { flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode && CompetitiveRoomDetect.IsCompetitiveRoom(); } catch { } if (flag) { Plugin.Log.LogWarning((object)"[FFA-LOBBY] in a competitive room while holding a lobby seat — leaving the lobby"); FfaLeaveQueue(); return; } _ffaAmbiguousPollUntil = -999f; OpenFfaLobbyId = ExtractJsonString(resp, "lobby_id") ?? OpenFfaLobbyId; FfaLobbyIsHost = ExtractJsonBool(resp, "is_host"); FfaLobbyCanStart = ExtractJsonBool(resp, "can_start"); FfaLobbyMemberCount = ExtractJsonInt(resp, "player_count"); int num = ExtractJsonInt(resp, "min_players"); if (num > 0) { FfaLobbyMinPlayers = num; } int num2 = ExtractJsonInt(resp, "max_players"); if (num2 > 0) { FfaLobbyMaxPlayers = num2; } try { List list = new List(); int num3 = resp.IndexOf("\"members\""); int num4 = ((num3 >= 0) ? resp.IndexOf('[', num3) : (-1)); int num5 = ((num4 >= 0) ? FindMatchingBracketStringAware(resp, num4) : (-1)); if (num4 >= 0 && num5 > num4) { foreach (string item in SliceTopLevelObjects(resp.Substring(num4 + 1, num5 - num4 - 1))) { list.Add(new FfaLobbyMemberEntry { steam_id = ExtractJsonString(item, "steam_id"), display_name = (ExtractJsonString(item, "display_name") ?? "?"), rating = ExtractJsonInt(item, "rating"), rating_1v1 = ExtractJsonInt(item, "rating_1v1"), wait_seconds = ExtractJsonInt(item, "wait_seconds"), is_host = ExtractJsonBool(item, "is_host") }); } } FfaLobbyMembers = list; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-LOBBY] member parse: " + ex.Message)); } break; } case "lobby_closed": Plugin.Log.LogInfo((object)("[FFA-LOBBY] lobby closed server-side (was " + OpenFfaLobbyId + ")")); _ffaJoinCountdownKey = null; _ffaJoinCountdownActiveToken = 0; CompetitiveUI.CancelFfaStartCountdown(); OpenFfaLobbyId = null; FfaLobbyIsHost = false; FfaLobbyCanStart = false; FfaLobbyMembers = null; FfaLobbyMemberCount = 0; IsFfaQueuePolling = false; FfaQueueStatus = ""; CompetitiveUI.ShowNotification("Your FFA lobby closed.", new Color(1f, 0.75f, 0.4f), 6f); FetchFfaLobbies(force: true); break; } if (text == "ready_join") { if (_ffaLeaveIntent) { Plugin.Log.LogWarning((object)"[FFA-LOBBY] ready_join landed after a leave request — leaving instead of joining"); FfaLeaveQueue(); NativeUI.MarkDirty(); return; } string text2 = ExtractJsonString(resp, "lobby_id") ?? ""; string text3 = ExtractJsonString(resp, "room_name") ?? ""; if (_ffaJoinCountdownKey != null && _ffaJoinCountdownKey == text2 + "|" + text3 && _ffaJoinCountdownActiveToken != 0 && Time.realtimeSinceStartup - _ffaJoinCountdownArmedAt < 12f) { return; } bool flag3 = false; bool flag4 = false; try { flag3 = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode; flag4 = flag3 && !CompetitiveRoomDetect.IsCompetitiveRoom(); } catch { } if (flag3 && !flag4) { Plugin.Log.LogWarning((object)"[FFA] ready_join landed while in a competitive room — declining (leaving FFA queue)"); FfaLeaveQueue(); CompetitiveUI.ShowNotification("FFA match found, but you're in a game — removed from the FFA queue.", new Color(1f, 0.7f, 0.3f), 7f); NativeUI.MarkDirty(); return; } if (flag4) { Plugin.Log.LogInfo((object)"[FFA] host started the FFA while we're in a casual game — leaving it now (#132)"); try { GameStateWatcher.LeavingForRanked = true; PhotonNetwork.LeaveRoom(true); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[FFA] casual-room leave: " + ex2.Message)); } } ActiveFfaLobbyId = ExtractJsonString(resp, "lobby_id"); OpenFfaLobbyId = null; FfaLobbyIsHost = false; FfaLobbyCanStart = false; FfaLobbyMembers = null; FfaLobbyMemberCount = 0; FfaMySlot = ExtractJsonInt(resp, "slot"); FfaLobbyPlayerCount = ExtractJsonInt(resp, "player_count"); string text4 = ExtractJsonString(resp, "room_name"); string text5 = ExtractJsonString(resp, "room_region"); List ffaLockedRoster = ExtractTeamMemberList(resp, "players"); FfaLockedRoster = ffaLockedRoster; if (!string.IsNullOrEmpty(text4)) { string text6 = ActiveFfaLobbyId + "|" + text4; if (text6 == _ffaLastReadyFireKey) { _ffaReadyFireCount++; } else { _ffaLastReadyFireKey = text6; _ffaReadyFireCount = 1; } if (_ffaReadyFireCount > 3) { Plugin.Log.LogWarning((object)$"[FFA] ready_join re-fired {_ffaReadyFireCount}x for '{text4}' — giving up and leaving the FFA queue"); CompetitiveUI.ShowNotification("Couldn't join the FFA room - left the queue. Please requeue.", Color.yellow, 8f); FfaLeaveQueue(); NativeUI.MarkDirty(); return; } Plugin.SetPendingFfaSlot(FfaMySlot, FfaLobbyPlayerCount); try { Hashtable val = new Hashtable(); val[(object)"p_id"] = FfaMySlot; val[(object)"t_id"] = FfaMySlot; val[(object)"u_id"] = sid; val[(object)"cr_msv2"] = 1; if (PhotonNetwork.LocalPlayer != null) { PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch (Exception ex3) { Plugin.Log.LogWarning((object)("[FFA] pre-join SetCustomProperties: " + ex3.Message)); } try { NametagStyler.PublishToPhoton(); } catch (Exception ex4) { Plugin.Log.LogWarning((object)("[FFA] pre-join nametag publish: " + ex4.Message)); } try { PlayerColorCosmetic.PublishLocalProps(); } catch (Exception ex5) { Plugin.Log.LogWarning((object)("[FFA] pre-join pcolor publish: " + ex5.Message)); } try { TrailCosmetic.PublishLocalProps(); } catch (Exception ex6) { Plugin.Log.LogWarning((object)("[FFA] pre-join trail publish: " + ex6.Message)); } _ffaJoinCountdownKey = ActiveFfaLobbyId + "|" + text4; int myToken = (_ffaJoinCountdownActiveToken = ++_ffaJoinCountdownToken); _ffaJoinCountdownArmedAt = Time.realtimeSinceStartup; CompetitiveUI.ShowFfaStartCountdown(5f); Plugin.Log.LogInfo((object)string.Format("[FFA] Lobby locked! Room: {0} (region: {1}) lobby={2} slot={3} players={4} — joining in 5s", text4, text5 ?? "auto", ActiveFfaLobbyId, FfaMySlot, FfaLobbyPlayerCount)); CompetitiveUI.ShowNotification($"{FfaLobbyPlayerCount}-player FFA starting in 5 seconds!", Color.green); try { if (NativeUI.IsOpen) { NativeUI.Close(); } } catch { } ((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedFfaRoomJoin(text4, text5, gen, ActiveFfaLobbyId, myToken, 5f)); } } else if (text == "not_in_queue" || text == "expired") { IsFfaQueuePolling = false; FfaQueueStatus = ""; FfaLockedRoster = null; _ffaJoinCountdownKey = null; _ffaJoinCountdownActiveToken = 0; CompetitiveUI.CancelFfaStartCountdown(); ActiveFfaLobbyId = null; FfaMySlot = -1; FfaLobbyPlayerCount = 0; FfaLobbyIsHost = false; FfaLobbyCanStart = false; FfaLobbyMembers = null; FfaLobbyMemberCount = 0; Plugin.ClearPendingFfaSlot(); try { if ((Plugin.PendingRankedRoom ?? "").StartsWith("ffa_")) { Plugin.ClearPendingRoom(); } } catch { } if (text == "expired") { CompetitiveUI.ShowNotification("Removed from FFA queue after 30 minutes of searching - rejoin if you're still here!", Color.yellow, 7f); } if (_ffaLeaveIntent) { _ffaLeaveIntent = false; _ffaLeaveTargetLobby = null; OpenFfaLobbyId = null; NativeUI.MarkDirty(); return; } if (text == "expired") { _ffaAmbiguousPollUntil = -999f; } if (text == "not_in_queue" && string.IsNullOrEmpty(OpenFfaLobbyId) && Time.unscaledTime < _ffaAmbiguousPollUntil) { IsFfaQueuePolling = true; NativeUI.MarkDirty(); return; } if (text == "not_in_queue" && !string.IsNullOrEmpty(OpenFfaLobbyId) && (!PhotonNetwork.InRoom || PhotonNetwork.OfflineMode || !CompetitiveRoomDetect.IsCompetitiveRoom()) && Time.unscaledTime - _ffaLobbyRejoinAt > 60f) { _ffaLobbyRejoinAt = Time.unscaledTime; Plugin.Log.LogWarning((object)"[FFA-LOBBY] membership row vanished server-side — attempting same-lobby rejoin"); FfaJoinLobby(OpenFfaLobbyId); } } NativeUI.MarkDirty(); } })); } private static IEnumerator DelayedFfaRoomJoin(string room, string region, int gen, string lobbyId, int myToken, float delay) { yield return (object)new WaitForSecondsRealtime(delay); if (_ffaJoinCountdownActiveToken == myToken) { _ffaJoinCountdownActiveToken = 0; _ffaJoinCountdownKey = null; string pendingNow = null; try { pendingNow = Plugin.PendingRankedRoom; } catch { } bool foreignPending = !string.IsNullOrEmpty(pendingNow) && pendingNow != room; bool inCompetitiveRoomNow = false; try { inCompetitiveRoomNow = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode && CompetitiveRoomDetect.IsCompetitiveRoom(); } catch { } if (gen != ffaGen || _ffaLeaveIntent || string.IsNullOrEmpty(ActiveFfaLobbyId) || ActiveFfaLobbyId != lobbyId || foreignPending || inCompetitiveRoomNow) { CompetitiveUI.CancelFfaStartCountdown(); Plugin.Log.LogInfo((object)("[FFA] start countdown aborted (" + (foreignPending ? ("another join owns the room slot: " + pendingNow) : (inCompetitiveRoomNow ? "already in a competitive room" : "leave requested, lobby gone, or queue lifecycle moved on")) + ")")); } else { IsFfaQueuePolling = false; Plugin.SetPendingRoom(room, region); } } } public static void UpdateFfaQueueList(bool force = false) { if (!force && Time.unscaledTime - _ffaListLastAt < 2f) { return; } _ffaListLastAt = Time.unscaledTime; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/ffa/queue/list", delegate(bool ok, string resp) { if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = resp.IndexOf("\"queuers\""); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { list.Add(new FfaQueueListEntry { steam_id = ExtractJsonString(item, "steam_id"), display_name = ExtractJsonString(item, "display_name"), rating = ExtractJsonInt(item, "rating"), rating_1v1 = ExtractJsonInt(item, "rating_1v1"), status = ExtractJsonString(item, "status"), slot = ExtractJsonInt(item, "slot"), wait_seconds = ExtractJsonInt(item, "wait_seconds"), region = ExtractJsonString(item, "region") }); } } CachedFfaQueueList = list; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-QUEUE-LIST] parse: " + ex.Message)); } })); } public static void FetchFfaLeaderboard(int limit = 200, string sortBy = "rating") { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/ffa/leaderboard?limit={limit}&sort_by={UnityWebRequest.EscapeURL(sortBy)}", delegate(bool ok, string resp) { if (!ok) { return; } try { List list = new List(); int num = resp.IndexOf("\"entries\""); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { list.Add(new FfaLeaderboardEntry { rank = ExtractJsonInt(item, "rank"), steam_id = ExtractJsonString(item, "steam_id"), display_name = ExtractJsonString(item, "display_name"), rating = ExtractJsonInt(item, "rating"), rd = ExtractJsonInt(item, "rd"), games_played = ExtractJsonInt(item, "games_played"), wins = ExtractJsonInt(item, "wins"), top3 = ExtractJsonInt(item, "top3"), avg_placement = ExtractJsonFloat(item, "avg_placement"), win_rate = ExtractJsonFloat(item, "win_rate"), level = ExtractJsonInt(item, "level"), title = ExtractJsonString(item, "title"), title_color = ExtractJsonString(item, "title_color"), ffa_gold_earned = ExtractJsonInt(item, "ffa_gold_earned"), ffa_xp_earned = ExtractJsonInt(item, "ffa_xp_earned") }); } } CachedFfaLeaderboard = list; CachedFfaLeaderboardTotal = ExtractJsonInt(resp, "total_players"); NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)$"[FFA-LB] loaded {list.Count} players"); } catch (Exception ex) { Plugin.Log.LogError((object)("[FFA-LB] parse: " + ex.Message)); } })); } public static void FetchFfaRecent(int page = 0, int pageSize = 5) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest($"{baseUrl}/api/v1/ffa/recent?page={page}&page_size={pageSize}", delegate(bool ok, string resp) { if (!ok) { return; } try { List list = new List(); int num = resp.IndexOf("\"matches\""); int num2 = ((num >= 0) ? resp.IndexOf('[', num) : (-1)); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(resp, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(resp.Substring(num2 + 1, num3 - num2 - 1))) { FfaRecentMatch ffaRecentMatch = new FfaRecentMatch { match_id = ExtractJsonString(item, "match_id"), photon_room_id = ExtractJsonString(item, "photon_room_id"), ended_at = ExtractJsonString(item, "ended_at"), winner_steam_id = ExtractJsonString(item, "winner_steam_id"), player_count = ExtractJsonInt(item, "player_count"), duration_seconds = ExtractJsonInt(item, "duration_seconds"), is_ranked = ExtractJsonBool(item, "is_ranked"), timeline = ExtractJsonString(item, "timeline") }; int num4 = item.IndexOf("\"players\""); int num5 = ((num4 >= 0) ? item.IndexOf('[', num4) : (-1)); int num6 = ((num5 >= 0) ? FindMatchingBracketStringAware(item, num5) : (-1)); if (num5 >= 0 && num6 > num5) { foreach (string item2 in SliceTopLevelObjects(item.Substring(num5 + 1, num6 - num5 - 1))) { FfaRecentPlayer ffaRecentPlayer = new FfaRecentPlayer { steam_id = ExtractJsonString(item2, "steam_id"), display_name = ExtractJsonString(item2, "display_name"), title = ExtractJsonString(item2, "title"), title_color = ExtractJsonString(item2, "title_color"), slot = ExtractJsonInt(item2, "slot"), placement = ExtractJsonInt(item2, "placement"), rounds_won = ExtractJsonInt(item2, "rounds_won"), points_total = ExtractJsonInt(item2, "points_total"), kills = ExtractJsonInt(item2, "kills"), fps_avg = ExtractJsonInt(item2, "fps_avg"), xp_gained = ExtractJsonInt(item2, "xp_gained"), gold_gained = ExtractJsonInt(item2, "gold_gained"), left_early = ExtractJsonBool(item2, "left_early") }; try { int num7 = item2.IndexOf("\"rating_change\"", StringComparison.Ordinal); int num8 = ((num7 >= 0) ? item2.IndexOf(':', num7 + 15) : (-1)); int i; for (i = num8 + 1; i > 0 && i < item2.Length && (item2[i] == ' ' || item2[i] == '\t'); i++) { } if (num8 >= 0 && i < item2.Length && item2[i] != 'n') { ffaRecentPlayer.rating_change = ExtractJsonFloat(item2, "rating_change"); ffaRecentPlayer.has_rating_change = true; } } catch { } int num9 = item2.IndexOf("\"cards\""); int num10 = ((num9 >= 0) ? item2.IndexOf('[', num9) : (-1)); int num11 = ((num10 >= 0) ? FindMatchingBracketStringAware(item2, num10) : (-1)); if (num10 >= 0 && num11 > num10) { foreach (string item3 in SliceTopLevelObjects(item2.Substring(num10 + 1, num11 - num10 - 1))) { ffaRecentPlayer.cards.Add(new FfaRecentCard { name = ExtractJsonString(item3, "n"), rolled = ExtractJsonBool(item3, "r") }); } } ffaRecentMatch.players.Add(ffaRecentPlayer); } } list.Add(ffaRecentMatch); } } CachedFfaRecent = list; CachedFfaRecentTotal = ExtractJsonInt(resp, "total"); CachedFfaRecentPages = ExtractJsonInt(resp, "total_pages"); NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)$"[FFA-RECENT] loaded {list.Count} matches (page {page})"); } catch (Exception ex) { Plugin.Log.LogError((object)("[FFA-RECENT] parse: " + ex.Message)); } })); } private static bool TryExtractNullableJsonFloat(string json, string key, out float value) { value = 0f; if (string.IsNullOrEmpty(json) || string.IsNullOrEmpty(key)) { return false; } int num = json.IndexOf("\"" + key + "\"", StringComparison.Ordinal); int num2 = ((num >= 0) ? json.IndexOf(':', num + key.Length + 2) : (-1)); int i; for (i = num2 + 1; i > 0 && i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } if (num2 < 0 || i >= json.Length || json[i] == 'n') { return false; } value = ExtractJsonFloat(json, key); return true; } private static int FindJsonArrayStartStringAware(string json, string key) { if (string.IsNullOrEmpty(json) || string.IsNullOrEmpty(key)) { return -1; } for (int i = 0; i < json.Length; i++) { if (json[i] != '"') { continue; } int num = i + 1; int num2 = num; while (num2 < json.Length) { if (json[num2] == '\\') { num2 += 2; continue; } if (json[num2] == '"') { break; } num2++; } if (num2 >= json.Length) { return -1; } bool flag = num2 - num == key.Length && string.CompareOrdinal(json, num, key, 0, key.Length) == 0; int j; for (j = num2 + 1; j < json.Length && char.IsWhiteSpace(json[j]); j++) { } if (flag && j < json.Length && json[j] == ':') { for (j++; j < json.Length && char.IsWhiteSpace(json[j]); j++) { } if (j < json.Length && json[j] == '[') { return j; } } i = num2; } return -1; } private static List ExtractStringListStringAware(string json, string key) { List list = new List(); if (string.IsNullOrEmpty(json) || string.IsNullOrEmpty(key)) { return list; } int num = FindJsonArrayStartStringAware(json, key); int num2 = ((num >= 0) ? FindMatchingBracketStringAware(json, num) : (-1)); if (num < 0 || num2 <= num) { return list; } for (int i = num + 1; i < num2; i++) { for (; i < num2 && json[i] != '"'; i++) { } if (i >= num2) { break; } int num3 = i++; bool flag = false; for (; i < num2; i++) { char c = json[i]; if (flag) { flag = false; continue; } switch (c) { case '\\': flag = true; continue; default: continue; case '"': break; } break; } if (i >= num2) { break; } string text = json.Substring(num3, i - num3 + 1); list.Add(ExtractJsonString(":" + text, "")); } return list; } public static void FetchPlayerModeHistories(string steamId) { if (!string.IsNullOrEmpty(steamId) && !(steamId == "unknown")) { FetchPlayerTeamHistory(steamId); FetchPlayerOvtHistory(steamId); FetchPlayerFfaHistory(steamId); } } private static void FetchPlayerTeamHistory(string steamId) { if (CachedPlayerTeamHistory.ContainsKey(steamId) || !_playerTeamHistoryInFlight.Add(steamId)) { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + Escape(steamId) + "/team-history?limit=10", delegate(bool ok, string resp) { _playerTeamHistoryInFlight.Remove(steamId); if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = FindJsonArrayStartStringAware(resp, "series"); int num2 = ((num >= 0) ? FindMatchingBracketStringAware(resp, num) : (-1)); if (num >= 0 && num2 > num) { foreach (string item in SliceTopLevelObjects(resp.Substring(num + 1, num2 - num - 1))) { PlayerTeamHistoryEntry playerTeamHistoryEntry = new PlayerTeamHistoryEntry { series_id = ExtractJsonString(item, "series_id"), won = ExtractJsonBool(item, "won"), score = ExtractJsonString(item, "score"), mate = ExtractJsonString(item, "mate"), completed_at = ExtractJsonString(item, "completed_at"), opponents = ExtractStringListStringAware(item, "opponents") }; playerTeamHistoryEntry.has_rating_change = TryExtractNullableJsonFloat(item, "rating_change", out playerTeamHistoryEntry.rating_change); list.Add(playerTeamHistoryEntry); } } CachedPlayerTeamHistory[steamId] = list; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[LB-MODE-HIST] 2v2 parse: " + ex.Message)); } })); } private static void FetchPlayerOvtHistory(string steamId) { if (CachedPlayerOvtHistory.ContainsKey(steamId) || !_playerOvtHistoryInFlight.Add(steamId)) { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + Escape(steamId) + "/ovt-history?limit=10", delegate(bool ok, string resp) { _playerOvtHistoryInFlight.Remove(steamId); if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = FindJsonArrayStartStringAware(resp, "games"); int num2 = ((num >= 0) ? FindMatchingBracketStringAware(resp, num) : (-1)); if (num >= 0 && num2 > num) { foreach (string item in SliceTopLevelObjects(resp.Substring(num + 1, num2 - num - 1))) { list.Add(new PlayerOvtHistoryEntry { match_id = ExtractJsonString(item, "match_id"), role = ExtractJsonString(item, "role"), won = ExtractJsonBool(item, "won"), score = ExtractJsonString(item, "score"), solo = ExtractJsonString(item, "solo"), duo = ExtractStringListStringAware(item, "duo"), ended_at = ExtractJsonString(item, "ended_at"), gold_gained = ExtractJsonInt(item, "gold_gained"), series_gold_gained = ExtractJsonInt(item, "series_gold_gained") }); } } CachedPlayerOvtHistory[steamId] = list; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[LB-MODE-HIST] 1v2 parse: " + ex.Message)); } })); } private static void FetchPlayerFfaHistory(string steamId) { if (CachedPlayerFfaHistory.ContainsKey(steamId) || !_playerFfaHistoryInFlight.Add(steamId)) { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/" + Escape(steamId) + "/ffa-history?limit=15", delegate(bool ok, string resp) { _playerFfaHistoryInFlight.Remove(steamId); if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = FindJsonArrayStartStringAware(resp, "games"); int num2 = ((num >= 0) ? FindMatchingBracketStringAware(resp, num) : (-1)); if (num >= 0 && num2 > num) { foreach (string item in SliceTopLevelObjects(resp.Substring(num + 1, num2 - num - 1))) { PlayerFfaHistoryEntry playerFfaHistoryEntry = new PlayerFfaHistoryEntry { match_id = ExtractJsonString(item, "match_id"), player_count = ExtractJsonInt(item, "player_count"), placement = ExtractJsonInt(item, "placement"), kills = ExtractJsonInt(item, "kills"), rounds_won = ExtractJsonInt(item, "rounds_won"), points_total = ExtractJsonInt(item, "points_total"), ended_at = ExtractJsonString(item, "ended_at"), participants = ExtractStringListStringAware(item, "participants") }; playerFfaHistoryEntry.has_rating_change = TryExtractNullableJsonFloat(item, "rating_change", out playerFfaHistoryEntry.rating_change); list.Add(playerFfaHistoryEntry); } } CachedPlayerFfaHistory[steamId] = list; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[LB-MODE-HIST] FFA parse: " + ex.Message)); } })); } public static void FetchFfaBettable(string steamId) { if (_ffaBettableInFlight || string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } _ffaBettableInFlight = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/ffa/bettable?steam_id=" + Escape(steamId), delegate(bool ok, string resp) { _ffaBettableInFlight = false; if (!ok || string.IsNullOrEmpty(resp)) { return; } try { List list = new List(); int num = FindJsonArrayStartStringAware(resp, "lobbies"); int num2 = ((num >= 0) ? FindMatchingBracketStringAware(resp, num) : (-1)); if (num >= 0 && num2 > num) { foreach (string item in SliceTopLevelObjects(resp.Substring(num + 1, num2 - num - 1))) { FfaBettableLobby ffaBettableLobby = new FfaBettableLobby { lobby_id = ExtractJsonString(item, "lobby_id"), player_count = ExtractJsonInt(item, "player_count"), game_number = ExtractJsonInt(item, "game_number"), is_member = ExtractJsonBool(item, "is_member"), already_bet = ExtractJsonBool(item, "already_bet"), bets_open = ExtractJsonBool(item, "bets_open") }; int num3 = FindJsonArrayStartStringAware(item, "players"); int num4 = ((num3 >= 0) ? FindMatchingBracketStringAware(item, num3) : (-1)); if (num3 >= 0 && num4 > num3) { foreach (string item2 in SliceTopLevelObjects(item.Substring(num3 + 1, num4 - num3 - 1))) { ffaBettableLobby.players.Add(new FfaBettablePlayer { steam_id = ExtractJsonString(item2, "steam_id"), display_name = ExtractJsonString(item2, "display_name"), rating = ExtractJsonInt(item2, "rating"), odds_multiplier = ExtractJsonFloat(item2, "odds_multiplier"), bettable = ExtractJsonBool(item2, "bettable") }); } } list.Add(ffaBettableLobby); } } CachedFfaBettable = list; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-BET] bettable parse: " + ex.Message)); } })); } public static void PlaceFfaBet(string bettorSteamId, string lobbyId, string betOnSteamId, int amount, int gameNumber, Action callback) { string arg = ComputeHmacHex($"ffa-bet:{bettorSteamId}:{lobbyId}:{betOnSteamId}:{amount}:{gameNumber}"); string url = baseUrl + "/api/v1/ffa/bets?steam_id=" + Escape(bettorSteamId) + "&lobby_id=" + Escape(lobbyId) + "&bet_on_steam_id=" + Escape(betOnSteamId) + $"&amount={amount}&game_number={gameNumber}&sig={arg}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(url, "", delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[FFA-BET] place {amount} on {betOnSteamId}: ok={ok} resp={resp}"); callback?.Invoke(ok, resp); if (ok) { FetchPlayerStats(bettorSteamId); FetchFfaBettable(bettorSteamId); } })); } public static int FfaCompareSteamIds(string a, string b) { int length = (a ?? "").Length; int length2 = (b ?? "").Length; if (length != length2) { return length.CompareTo(length2); } return string.CompareOrdinal(a ?? "", b ?? ""); } public static void ReportFfaMatch(string lobbyId, string room, string region, int durationSeconds, List players, string winnerSteam, string reporterSteam, string timeline = null) { if (players == null || players.Count < 2) { Plugin.Log.LogWarning((object)"[FFA-REPORT] not enough players to report"); return; } bool flag = true; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); stringBuilder.Append("\"lobby_id\":\"" + Escape(lobbyId) + "\","); stringBuilder.Append("\"players\":["); for (int i = 0; i < players.Count; i++) { FfaReportPlayer ffaReportPlayer = players[i]; if (i > 0) { stringBuilder.Append(","); } stringBuilder.Append("{"); stringBuilder.Append("\"steam_id\":\"" + Escape(ffaReportPlayer.steamId) + "\",\"display_name\":\"" + Escape(ffaReportPlayer.displayName ?? "Player") + "\","); stringBuilder.Append($"\"slot\":{ffaReportPlayer.slot},\"rounds_won\":{ffaReportPlayer.rounds}," + $"\"points_total\":{ffaReportPlayer.points},\"kills\":{Math.Max(0, ffaReportPlayer.kills)}," + "\"left_early\":" + (ffaReportPlayer.leftEarly ? "true" : "false") + ",\"absent\":" + (ffaReportPlayer.absent ? "true" : "false") + ","); stringBuilder.Append($"\"fps\":{Math.Max(0, ffaReportPlayer.fps)},"); stringBuilder.Append($"\"damage_dealt\":{Math.Max(0, ffaReportPlayer.damageDealt)},"); if (!string.IsNullOrEmpty(ffaReportPlayer.killTimeline)) { stringBuilder.Append("\"kill_timeline\":\"" + Escape(ClampTimeline(ffaReportPlayer.killTimeline)) + "\","); } if (!string.IsNullOrEmpty(ffaReportPlayer.damageTimeline)) { stringBuilder.Append("\"damage_dealt_timeline\":\"" + Escape(ClampTimeline(ffaReportPlayer.damageTimeline, 1024)) + "\","); } stringBuilder.Append("\"cards\":["); AppendCards(stringBuilder, ffaReportPlayer.cards ?? new List()); stringBuilder.Append("]"); if (ffaReportPlayer.telemetry != null) { TeamTelemetry telemetry = ffaReportPlayer.telemetry; stringBuilder.Append(",\"telemetry\":{"); stringBuilder.Append("\"fps_timeline\":\"" + Escape(ClampTimeline(telemetry.fpsTimeline)) + "\","); stringBuilder.Append("\"ping_timeline\":\"" + Escape(ClampTimeline(telemetry.pingTimeline)) + "\","); stringBuilder.Append($"\"ping_avg\":{Math.Max(0, Math.Min(30000, telemetry.pingAvg))},"); stringBuilder.Append("\"hit_timeline\":\"" + Escape(ClampTimeline(telemetry.hitTimeline, 1024)) + "\","); stringBuilder.Append("\"block_timeline\":\"" + Escape(ClampTimeline(telemetry.blockTimeline, 1024)) + "\","); stringBuilder.Append($"\"bullets_fired\":{Math.Max(0, telemetry.bulletsFired)},"); stringBuilder.Append($"\"bullets_hit\":{Math.Max(0, telemetry.bulletsHit)},"); stringBuilder.Append($"\"blocks_activated\":{Math.Max(0, telemetry.blocksActivated)},"); stringBuilder.Append($"\"blocks_successful\":{Math.Max(0, telemetry.blocksSuccessful)},"); stringBuilder.Append($"\"keys_pressed\":{Math.Max(0, telemetry.keysPressed)},"); stringBuilder.Append("\"active_seconds\":" + Math.Max(0f, telemetry.activeSeconds).ToString("F1", CultureInfo.InvariantCulture)); stringBuilder.Append("}"); } stringBuilder.Append("}"); } stringBuilder.Append("],"); stringBuilder.Append("\"winner_steam_id\":\"" + Escape(winnerSteam) + "\","); stringBuilder.Append("\"photon_room_id\":\"" + Escape(room) + "\",\"game_version\":\"v" + Application.version + "\","); stringBuilder.Append($"\"region\":\"{Escape(region)}\",\"match_duration\":{durationSeconds},"); stringBuilder.Append("\"is_ranked\":" + (flag ? "true" : "false") + ","); stringBuilder.Append("\"reported_by_steam_id\":\"" + Escape(reporterSteam) + "\","); if (!string.IsNullOrEmpty(timeline)) { stringBuilder.Append("\"timeline\":\"" + Escape((timeline.Length > 1900) ? timeline.Substring(0, 1900) : timeline) + "\","); } List list = new List(players); list.Sort((FfaReportPlayer a, FfaReportPlayer b) => FfaCompareSteamIds(a.steamId, b.steamId)); StringBuilder stringBuilder2 = new StringBuilder(); stringBuilder2.Append(string.Format("ffa:{0}:{1}:{2}:{3}:{4}:{5}", lobbyId, room ?? "", reporterSteam, flag ? "true" : "false", winnerSteam, players.Count)); foreach (FfaReportPlayer item in list) { stringBuilder2.Append($":{item.steamId}:{item.rounds}:{item.points}"); } stringBuilder.Append("\"hmac_signature\":\"" + ComputeHmacHex(stringBuilder2.ToString()) + "\""); stringBuilder.Append("}"); string json = stringBuilder.ToString(); Plugin.Log.LogInfo((object)$"[FFA-REPORT] submitting lobby={lobbyId} n={players.Count} winner={winnerSteam}"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/ffa/matches", json, delegate(bool ok, string resp) { //IL_0086: 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) if (ok) { Plugin.Log.LogInfo((object)("[FFA] match reported: " + resp)); int num = ExtractJsonInt(resp, "placement"); int num2 = ExtractJsonInt(resp, "xp_gained"); if (num > 0) { CompetitiveUI.ShowNotification((num == 1) ? $"FFA VICTORY! +{num2}xp" : $"FFA: placed #{num} (+{num2}xp)", (Color)((num == 1) ? Color.green : new Color(0.6f, 0.8f, 1f)), 6f); } } else { Plugin.Log.LogWarning((object)("[FFA] report failed: " + resp)); EnqueueFailedReport(baseUrl + "/api/v1/ffa/matches", json); } })); } public static void FetchBlockedPlayers(string steamId) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/players/blocks/" + steamId, delegate(bool success, string response) { if (success) { BlockedSteamIds.Clear(); int num = response.IndexOf("["); int num2 = response.IndexOf("]"); if (num >= 0 && num2 > num) { string text = response.Substring(num + 1, num2 - num - 1); if (!string.IsNullOrEmpty(text)) { string[] array = text.Split(','); foreach (string text2 in array) { string text3 = text2.Trim().Trim('"'); if (!string.IsNullOrEmpty(text3)) { BlockedSteamIds.Add(text3); } } } } blocksLoaded = true; NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)$"[BLOCKS] Loaded {BlockedSteamIds.Count} blocked players"); } })); } public static bool IsPlayerBlocked(string steamId) { return BlockedSteamIds.Contains(steamId); } public static void ReportDisconnect(string reporterSteamId, string disconnectedSteamId) { if (string.IsNullOrEmpty(reporterSteamId) || string.IsNullOrEmpty(disconnectedSteamId)) { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/report-disconnect?reporter_steam_id=" + Escape(reporterSteamId) + "&disconnected_steam_id=" + Escape(disconnectedSteamId), "", delegate(bool success, string response) { if (success) { Plugin.Log.LogInfo((object)("[DC] Reported disconnect by " + disconnectedSteamId + ": " + response)); } else { Plugin.Log.LogWarning((object)("[DC] Failed to report disconnect: " + response)); } })); } public static void BlockPlayer(string mySteamId, string targetSteamId, Action callback = null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/players/block?steam_id=" + Escape(mySteamId) + "&target_steam_id=" + Escape(targetSteamId) + "&sig=" + ComputeHmacHex("block:" + mySteamId + ":" + targetSteamId), "", delegate(bool success, string response) { if (success) { BlockedSteamIds.Add(targetSteamId); Plugin.Log.LogInfo((object)("[BLOCKS] Blocked " + targetSteamId)); NativeUI.MarkDirty(); } callback?.Invoke(success); })); } public static void UnblockPlayer(string mySteamId, string targetSteamId, Action callback = null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/players/unblock?steam_id=" + Escape(mySteamId) + "&target_steam_id=" + Escape(targetSteamId) + "&sig=" + ComputeHmacHex("unblock:" + mySteamId + ":" + targetSteamId), "", delegate(bool success, string response) { if (success) { BlockedSteamIds.Remove(targetSteamId); Plugin.Log.LogInfo((object)("[BLOCKS] Unblocked " + targetSteamId)); NativeUI.MarkDirty(); } callback?.Invoke(success); })); } private static string ClampTimeline(string t, int max = 512) { t = t ?? ""; if (t.Length <= max) { return t; } int num = t.LastIndexOf(',', max - 1); return (num > 0) ? t.Substring(0, num) : t.Substring(0, max); } private static void HandleSessionReject(UnityWebRequest req, string sentToken) { try { if (req.responseCode == 401) { string text = null; try { DownloadHandler downloadHandler = req.downloadHandler; text = ((downloadHandler != null) ? downloadHandler.text : null); } catch { } if (text != null && text.Contains("session_required")) { SteamAuth.InvalidateSessionIf(sentToken); Plugin.Log.LogWarning((object)"[STEAM-AUTH] server rejected session (401) — re-minting on next heartbeat"); } } } catch { } } private static void StampVersionHeader(UnityWebRequest req) { try { req.SetRequestHeader("X-Mod-Version", "1.35.5"); } catch { } try { if (!string.IsNullOrEmpty(SteamAuth.SessionToken)) { req.SetRequestHeader("X-Session-Token", SteamAuth.SessionToken); } } catch { } } public static void PostSteamAuth(string ticketHex) { string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown" || (Object)(object)Plugin.Instance == (Object)null) { return; } string json = "{\"steam_id\":\"" + Escape(localSteamId) + "\",\"ticket_hex\":\"" + Escape(ticketHex) + "\",\"mod_version\":\"" + Escape("1.35.5") + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/auth/steam", json, delegate(bool success, string response) { if (!success) { Plugin.Log.LogWarning((object)("[STEAM-AUTH] session exchange failed: " + response)); } else { string text = ExtractJsonString(response, "session_token"); int num = ExtractJsonInt(response, "expires_in"); if (!string.IsNullOrEmpty(text)) { SteamAuth.SetSession(text, (num > 0) ? num : 86400); } else { Plugin.Log.LogWarning((object)"[STEAM-AUTH] session response had no token"); } } })); } private static bool IsConsentBypassed(string url) { if (string.IsNullOrEmpty(url)) { return false; } return url.Contains("/api/v1/mod-version"); } private static bool ConsentBlocksRequest(string url) { if (Plugin.DataConsentGranted) { return false; } if (IsConsentBypassed(url)) { return false; } return true; } public static void OnConsentChanged() { if (Plugin.DataConsentGranted) { if (Plugin.RankedDisabledByConsent != null && Plugin.RankedDisabledByConsent.Value) { Plugin.RankedDisabledByConsent.Value = false; if (Plugin.RankedEnabled != null && !Plugin.RankedEnabled.Value) { Plugin.RankedEnabled.Value = true; Plugin.Log.LogInfo((object)"[CONSENT] Ranked mode restored on consent grant (was auto-disabled by revoke)"); } } string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ToggleRanked(localSteamId, Plugin.RankedEnabled != null && Plugin.RankedEnabled.Value); FetchPlayerStats(localSteamId); FetchMatchHistory(localSteamId); FetchAchievements(localSteamId); } FetchLeaderboard(); FetchRecentSeries(); ChatClient.Connect(); } else { CachedLeaderboard = null; CachedPlayerStats = null; CachedCardStats = null; CachedMatchHistory = null; CachedRecentSeries = null; CachedRecentMultimode = null; CachedAchievements = null; CachedShopItems = null; CachedInventory = null; CachedActiveSeries = null; ChatClient.Disconnect(); if (Plugin.RankedEnabled != null && Plugin.RankedEnabled.Value) { Plugin.RankedEnabled.Value = false; if (Plugin.RankedDisabledByConsent != null) { Plugin.RankedDisabledByConsent.Value = true; } Plugin.Log.LogInfo((object)"[CONSENT] Ranked mode disabled due to revoke"); } } NativeUI.MarkDirty(); } private static bool HandleVersionGate(UnityWebRequest req) { if (req.responseCode == 426) { if (!ForceUpdateRequired) { Plugin.Log.LogWarning((object)"[VERSION] Server returned 426 — mod is below required version, gating UI"); } ForceUpdateRequired = true; return true; } return false; } private static void NoteAttempt() { LastApiAttemptAt = Time.unscaledTime; } private static void NoteResult(bool success, long httpCode) { if (success) { LastApiSuccessAt = Time.unscaledTime; LastResponseWasMaintenance = false; } else if (httpCode == 503) { LastResponseWasMaintenance = true; } } private static IEnumerator GetRequest(string url, Action callback) { if (ConsentBlocksRequest(url)) { callback(arg1: false, "no-consent"); yield break; } NoteAttempt(); UnityWebRequest request = UnityWebRequest.Get(url); try { StampVersionHeader(request); request.timeout = 20; yield return request.SendWebRequest(); if (HandleVersionGate(request)) { callback(arg1: false, "outdated"); yield break; } bool success = (int)request.result == 1; NoteResult(success, request.responseCode); callback(success, success ? request.downloadHandler.text : request.error); } finally { ((IDisposable)request)?.Dispose(); } } private static IEnumerator PostRequest(string url, string json, Action callback) { if (ConsentBlocksRequest(url)) { callback(arg1: false, "no-consent"); yield break; } NoteAttempt(); UnityWebRequest request = new UnityWebRequest(url, "POST"); try { if (!string.IsNullOrEmpty(json)) { byte[] bodyRaw = Encoding.UTF8.GetBytes(json); request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); } request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); StampVersionHeader(request); string _sentTok = SteamAuth.SessionToken; request.timeout = 20; yield return request.SendWebRequest(); if (HandleVersionGate(request)) { callback(arg1: false, "outdated"); yield break; } HandleSessionReject(request, _sentTok); bool success = (int)request.result == 1; NoteResult(success, request.responseCode); callback(success, success ? request.downloadHandler.text : FormatRequestError(request)); } finally { ((IDisposable)request)?.Dispose(); } } private static string FormatRequestError(UnityWebRequest request) { if (request == null) { return "request failed"; } string text = ""; try { DownloadHandler downloadHandler = request.downloadHandler; text = ((downloadHandler != null) ? downloadHandler.text : null) ?? ""; } catch { } if (text.Length > 300) { text = text.Substring(0, 300); } return (request.responseCode > 0) ? $"HTTP {request.responseCode}: {(string.IsNullOrEmpty(text) ? request.error : text)}" : request.error; } private static IEnumerator PostRequestWithRetry(string url, string json, Action callback, int maxRetries = 3, float retryDelay = 2f) { if (ConsentBlocksRequest(url)) { callback(arg1: false, "no-consent"); yield break; } for (int attempt = 1; attempt <= maxRetries; attempt++) { NoteAttempt(); UnityWebRequest request = new UnityWebRequest(url, "POST"); try { if (!string.IsNullOrEmpty(json)) { byte[] bodyRaw = Encoding.UTF8.GetBytes(json); request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); } request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); StampVersionHeader(request); string _sentTok = SteamAuth.SessionToken; request.timeout = 10; yield return request.SendWebRequest(); if (HandleVersionGate(request)) { callback(arg1: false, "outdated"); break; } HandleSessionReject(request, _sentTok); bool success = (int)request.result == 1; NoteResult(success, request.responseCode); if (success) { callback(arg1: true, request.downloadHandler.text); break; } Plugin.Log.LogWarning((object)$"[HTTP] POST attempt {attempt}/{maxRetries} failed: {request.error}"); if (attempt < maxRetries) { yield return (object)new WaitForSecondsRealtime(retryDelay); } else { callback(arg1: false, FormatRequestError(request)); } } finally { ((IDisposable)request)?.Dispose(); } } } public static void GenerateLinkCode(string steamId) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/players/link-code?steam_id=" + Escape(steamId), "", delegate(bool success, string response) { //IL_0088: 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) if (success) { string text = ExtractJsonString(response, "code"); if (!string.IsNullOrEmpty(text)) { Plugin.Log.LogInfo((object)("[LINK] Generated link code: " + text)); CompetitiveUI.ShowNotification("Link code: " + text, Color.cyan, 15f); NativeUI.SetLinkCode(text); } } else { Plugin.Log.LogWarning((object)("[LINK] Failed to generate code: " + response)); CompetitiveUI.ShowNotification("Failed to get link code", new Color(1f, 0.4f, 0.4f)); } })); } public static void SendLfpPing(string steamId, string message, int expiresMinutes) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } string json = string.Format("{{\"steam_id\":\"{0}\",\"message\":\"{1}\",\"expires_minutes\":{2}}}", Escape(steamId), JsonEscapeFull(message ?? ""), expiresMinutes); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/lfp-ping", json, delegate(bool success, string response) { //IL_001e: 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_00fc: 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_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) if (!success) { CompetitiveUI.ShowNotification("RLFP ping failed - server unreachable. Try again shortly.", new Color(1f, 0.5f, 0.4f), 6f); } else { string text = ExtractJsonString(response, "status"); switch (text) { case "queued": NativeUI.LfpArmCooldown(ExtractJsonInt(response, "cooldown_seconds")); CompetitiveUI.ShowNotification("Posted to Discord - good luck!", new Color(0.5f, 1f, 0.6f), 6f); break; case "cooldown": { int num = ExtractJsonInt(response, "seconds_left"); NativeUI.LfpArmCooldown(num); CompetitiveUI.ShowNotification($"RLFP ping available in {num / 60}m {num % 60}s (1 per hour).", new Color(1f, 0.8f, 0.3f), 6f); break; } case "not_linked": CompetitiveUI.ShowNotification("Link your Discord account first (Home tab) to use RLFP pings.", new Color(1f, 0.8f, 0.3f), 7f); break; case "ranked_disabled": CompetitiveUI.ShowNotification("Enable Ranked first - the RLFP ping is for ranked matches.", new Color(1f, 0.8f, 0.3f), 6f); break; default: CompetitiveUI.ShowNotification("RLFP ping failed: " + text, new Color(1f, 0.5f, 0.4f), 6f); break; } } })); } public static void FetchAchievementEarners(string achievementKey) { if (string.IsNullOrEmpty(achievementKey)) { return; } _earnersWantedKey = achievementKey; if (_earnersInFlight) { return; } _earnersInFlight = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/achievements/" + achievementKey + "/earners", delegate(bool success, string response) { _earnersInFlight = false; if (!success) { Plugin.Log.LogWarning((object)("[ACH] earners fetch failed: " + response)); if (_earnersWantedKey != null && _earnersWantedKey != achievementKey) { FetchAchievementEarners(_earnersWantedKey); } return; } try { List list = new List(); int num = response.IndexOf("\"earners\":"); if (num >= 0) { int num2 = response.IndexOf('[', num); int num3 = ((num2 >= 0) ? FindMatchingBracketStringAware(response, num2) : (-1)); if (num2 >= 0 && num3 > num2) { foreach (string item in SliceTopLevelObjects(response.Substring(num2 + 1, num3 - num2 - 1))) { AchEarnerData achEarnerData = new AchEarnerData { display_name = ExtractJsonString(item, "display_name"), unlocked_at = ExtractJsonString(item, "unlocked_at"), rating = (item.Contains("\"rating\":null") ? (-1) : ExtractJsonInt(item, "rating")), title = ExtractJsonString(item, "title"), title_color = ExtractJsonString(item, "title_color") }; if (!string.IsNullOrEmpty(achEarnerData.display_name)) { list.Add(achEarnerData); } } } } EarnersKey = achievementKey; CachedEarners = list; CachedEarnersTotal = ExtractJsonInt(response, "total"); NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)$"[ACH] earners loaded for {achievementKey}: {list.Count} (total={CachedEarnersTotal})"); if (_earnersWantedKey != null && _earnersWantedKey != achievementKey) { FetchAchievementEarners(_earnersWantedKey); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ACH] earners parse error: " + ex.Message)); } })); } public static void FetchAchievements(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/achievements/" + steamId, delegate(bool success, string response) { if (success) { try { Dictionary dictionary = new Dictionary(); string[] array = response.Split(new string[1] { "\"achievement_key\"" }, StringSplitOptions.None); for (int i = 1; i < array.Length; i++) { string text = ExtractJsonString(array[i], ""); if (!string.IsNullOrEmpty(text)) { bool unlocked = array[i].Contains("\"unlocked\":true") || array[i].Contains("\"unlocked\": true"); string unlocked_at = ExtractJsonString(array[i], "unlocked_at"); dictionary[text] = new AchievementData { achievement_key = text, unlocked = unlocked, unlocked_at = unlocked_at, global_pct = ExtractJsonFloat(array[i], "global_pct"), gold = ExtractJsonInt(array[i], "gold") }; } } CachedAchievements = dictionary; NativeUI.MarkDirty(); Plugin.Log.LogInfo((object)$"[ACH] Loaded {dictionary.Count} achievements"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ACH] Parse error: " + ex.Message)); } } })); } public static void UnlockAchievement(string steamId, string achievementKey, string matchId = null) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } string s = ComputeHmacHex("achievement:" + steamId + ":" + achievementKey); string text = "{\"steam_id\":\"" + Escape(steamId) + "\",\"achievement_key\":\"" + Escape(achievementKey) + "\",\"hmac_signature\":\"" + Escape(s) + "\""; if (!string.IsNullOrEmpty(matchId)) { text = text + ",\"match_id\":\"" + Escape(matchId) + "\""; } text += "}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequestWithRetry(baseUrl + "/api/v1/achievements/unlock", text, delegate(bool success, string response) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (success) { string text2 = ExtractJsonString(response, "status"); string text3 = ExtractJsonString(response, "name"); if (text2 == "unlocked" && !string.IsNullOrEmpty(text3)) { string[] value; string text4 = (AchievementDefs.TryGetValue(achievementKey, out value) ? value[1] : null); string text5 = "Achievement Unlocked: " + text3 + "!" + (string.IsNullOrEmpty(text4) ? "" : ("\n" + text4)); CompetitiveUI.ShowNotification(text5, new Color(1f, 0.85f, 0.3f), 8f); Plugin.Log.LogInfo((object)("[ACH] Unlocked: " + achievementKey + " (" + text3 + ")")); } else { Plugin.Log.LogInfo((object)("[ACH] " + achievementKey + ": " + text2)); } FetchAchievements(steamId); } else { Plugin.Log.LogWarning((object)("[ACH] Unlock failed for " + achievementKey + ": " + response)); } })); } private static string Escape(string s) { if (string.IsNullOrEmpty(s)) { return ""; } return s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") .Replace("\r", "\\r"); } private static string JsonEscapeFull(string s) { if (string.IsNullOrEmpty(s)) { return ""; } StringBuilder stringBuilder = new StringBuilder(s.Length + 64); foreach (char c in s) { switch (c) { case '\\': stringBuilder.Append("\\\\"); continue; case '"': stringBuilder.Append("\\\""); continue; case '\n': stringBuilder.Append("\\n"); continue; case '\r': stringBuilder.Append("\\r"); continue; case '\t': stringBuilder.Append("\\t"); continue; } if (c < ' ' || c == '\u007f') { stringBuilder.Append($"\\u{(int)c:x4}"); } else { stringBuilder.Append(c); } } return stringBuilder.ToString(); } public static void SubmitBugReport(string steamId, string displayName, string description, string reproSteps, string severity, string category, string logText, Action done) { if (string.IsNullOrEmpty(steamId)) { done?.Invoke(arg1: false, "steam_id missing"); return; } if (logText != null && logText.Length > 3500000) { logText = logText.Substring(logText.Length - 3500000); } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); stringBuilder.Append("\"steam_id\":\"" + JsonEscapeFull(steamId) + "\""); stringBuilder.Append(",\"display_name\":\"" + JsonEscapeFull(displayName ?? "") + "\""); stringBuilder.Append(",\"mod_version\":\"" + JsonEscapeFull("1.35.5") + "\""); stringBuilder.Append(",\"game_version\":\"" + JsonEscapeFull(Application.version ?? "") + "\""); stringBuilder.Append(",\"severity\":\"" + JsonEscapeFull(severity ?? "medium") + "\""); stringBuilder.Append(",\"category\":\"" + JsonEscapeFull(category ?? "other") + "\""); stringBuilder.Append(",\"description\":\"" + JsonEscapeFull(description ?? "") + "\""); if (!string.IsNullOrEmpty(reproSteps)) { stringBuilder.Append(",\"repro_steps\":\"" + JsonEscapeFull(reproSteps) + "\""); } if (!string.IsNullOrEmpty(logText)) { stringBuilder.Append(",\"log_text\":\"" + JsonEscapeFull(logText) + "\""); } stringBuilder.Append("}"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/bug-reports", stringBuilder.ToString(), delegate(bool ok, string response) { if (ok) { Plugin.Log.LogInfo((object)("[BUG-REPORT] submitted ok: " + response)); } else { Plugin.Log.LogWarning((object)("[BUG-REPORT] submit failed: " + response)); } done?.Invoke(ok, response); })); } public static string ReadLogTail(string path, int maxChars = 3500000) { try { if (string.IsNullOrEmpty(path) || !File.Exists(path)) { return ""; } using FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using StreamReader streamReader = new StreamReader(stream); string text = streamReader.ReadToEnd(); if (text.Length <= maxChars) { return text; } return text.Substring(text.Length - maxChars); } catch (Exception ex) { return "[log read error: " + ex.Message + "]"; } } public static void FetchTournamentCurrent(string steamId, bool force = false) { if (!force && Time.unscaledTime < _tournamentRefreshAt) { return; } _tournamentRefreshAt = Time.unscaledTime + 5f; string text = (string.IsNullOrEmpty(TournamentKind) ? "sync" : TournamentKind); string text2 = ((string.IsNullOrEmpty(steamId) || steamId == "unknown") ? ("?kind=" + text) : ("?steam_id=" + Escape(steamId) + "&kind=" + text)); ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/tournaments/current" + text2, delegate(bool success, string response) { if (!success || string.IsNullOrEmpty(response)) { return; } try { CachedTournamentJson = response; CachedTournament = ParseTournament(response); NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TOURNAMENT] parse failed: " + ex.Message)); } })); } private static TournamentSnapshot ParseTournament(string json) { TournamentSnapshot tournamentSnapshot = new TournamentSnapshot(); tournamentSnapshot.tournament_id = ExtractString(json, "tournament_id"); tournamentSnapshot.status = ExtractString(json, "status"); tournamentSnapshot.kind = ExtractString(json, "kind"); tournamentSnapshot.default_start_ts = ExtractString(json, "default_start_ts"); tournamentSnapshot.scheduled_start_ts = ExtractString(json, "scheduled_start_ts"); tournamentSnapshot.lock_at = ExtractString(json, "lock_at"); tournamentSnapshot.started_at = ExtractString(json, "started_at"); tournamentSnapshot.ended_at = ExtractString(json, "ended_at"); tournamentSnapshot.min_players = ExtractInt(json, "min_players", 8); tournamentSnapshot.max_players = ExtractInt(json, "max_players", 16); tournamentSnapshot.prize_players = ExtractInt(json, "prize_players", 0); tournamentSnapshot.prize_gold_1 = ExtractInt(json, "prize_gold_1", 0); tournamentSnapshot.prize_gold_2 = ExtractInt(json, "prize_gold_2", 0); tournamentSnapshot.prize_gold_3 = ExtractInt(json, "prize_gold_3", 0); tournamentSnapshot.prize_xp_1 = ExtractInt(json, "prize_xp_1", 0); tournamentSnapshot.prize_xp_2 = ExtractInt(json, "prize_xp_2", 0); tournamentSnapshot.prize_xp_3 = ExtractInt(json, "prize_xp_3", 0); tournamentSnapshot.my_signup_id = ExtractString(json, "my_signup_id"); tournamentSnapshot.my_ready = ExtractBool(json, "my_ready"); tournamentSnapshot.my_penalty_pct = ExtractFloat(json, "my_penalty_pct"); tournamentSnapshot.my_discord_linked = ExtractBool(json, "my_discord_linked"); tournamentSnapshot.force_vote_count = ExtractInt(json, "force_vote_count", 0); tournamentSnapshot.photon_region = ExtractString(json, "photon_region"); tournamentSnapshot.my_votes = ExtractStringArray(json, "my_votes"); tournamentSnapshot.time_slot_options = ExtractStringArray(json, "time_slot_options"); tournamentSnapshot.time_slot_tallies = ExtractObjectArray(json, "time_slot_tallies", (string raw) => new TimeVoteTally { slot_ts = ExtractString(raw, "slot_ts"), votes = ExtractInt(raw, "votes", 0) }); tournamentSnapshot.signups = ExtractObjectArray(json, "signups", (string raw) => new TournamentSignupRow { signup_id = ExtractString(raw, "signup_id"), steam_id = ExtractString(raw, "steam_id"), display_name = ExtractString(raw, "display_name"), is_speculative = ExtractBool(raw, "is_speculative"), seed = ExtractInt(raw, "seed", 0), penalty_at_signup = ExtractFloat(raw, "penalty_at_signup"), ready = ExtractBool(raw, "ready"), forfeited = ExtractBool(raw, "forfeited"), placed_rank = ExtractInt(raw, "placed_rank", 0), progress_label = ExtractString(raw, "progress_label") }); tournamentSnapshot.matches = ExtractObjectArray(json, "matches", (string raw) => new TournamentMatchRow { match_id = ExtractString(raw, "match_id"), round = ExtractInt(raw, "round", 0), bracket_side = ExtractString(raw, "bracket_side"), slot_idx = ExtractInt(raw, "slot_idx", 0), p1_signup_id = ExtractString(raw, "p1_signup_id"), p2_signup_id = ExtractString(raw, "p2_signup_id"), p1_display_name = ExtractString(raw, "p1_display_name"), p2_display_name = ExtractString(raw, "p2_display_name"), is_bye = ExtractBool(raw, "is_bye"), status = ExtractString(raw, "status"), series_id = ExtractString(raw, "series_id"), winner_signup_id = ExtractString(raw, "winner_signup_id"), p1_series_wins = ExtractInt(raw, "p1_series_wins", 0), p2_series_wins = ExtractInt(raw, "p2_series_wins", 0), deadline_at = ExtractString(raw, "deadline_at"), prereq_match_ids = ExtractStringArray(raw, "prereq_match_ids"), photon_room_name = ExtractString(raw, "photon_room_name") }); return tournamentSnapshot; } private static string ExtractString(string json, string key) { if (string.IsNullOrEmpty(json)) { return null; } int num = json.IndexOf("\"" + key + "\""); if (num < 0) { return null; } int num2 = json.IndexOf(':', num); if (num2 < 0) { return null; } int i; for (i = num2 + 1; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } if (i >= json.Length) { return null; } if (json[i] == 'n' && json.Length >= i + 4 && json.Substring(i, 4) == "null") { return null; } if (json[i] != '"') { return null; } int num3 = i + 1; StringBuilder stringBuilder = new StringBuilder(); for (int j = num3; j < json.Length; j++) { char c = json[j]; if (c == '\\' && j + 1 < json.Length) { stringBuilder.Append(json[j + 1]); j++; continue; } if (c == '"') { break; } stringBuilder.Append(c); } return stringBuilder.ToString(); } private static int ExtractInt(string json, string key, int def) { if (string.IsNullOrEmpty(json)) { return def; } int num = json.IndexOf("\"" + key + "\""); if (num < 0) { return def; } int num2 = json.IndexOf(':', num); if (num2 < 0) { return def; } int i; for (i = num2 + 1; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } if (i >= json.Length) { return def; } int j; for (j = i; j < json.Length && (char.IsDigit(json[j]) || json[j] == '-'); j++) { } if (j == i) { return def; } int result; return int.TryParse(json.Substring(i, j - i), out result) ? result : def; } private static float ExtractFloat(string json, string key) { if (string.IsNullOrEmpty(json)) { return 0f; } int num = json.IndexOf("\"" + key + "\""); if (num < 0) { return 0f; } int num2 = json.IndexOf(':', num); if (num2 < 0) { return 0f; } int i; for (i = num2 + 1; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } if (i >= json.Length) { return 0f; } int j; for (j = i; j < json.Length && (char.IsDigit(json[j]) || json[j] == '-' || json[j] == '.' || json[j] == 'e' || json[j] == 'E' || json[j] == '+'); j++) { } if (j == i) { return 0f; } float result; return float.TryParse(json.Substring(i, j - i), NumberStyles.Float, CultureInfo.InvariantCulture, out result) ? result : 0f; } private static bool ExtractBool(string json, string key) { if (string.IsNullOrEmpty(json)) { return false; } int num = json.IndexOf("\"" + key + "\""); if (num < 0) { return false; } int num2 = json.IndexOf(':', num); if (num2 < 0) { return false; } int i; for (i = num2 + 1; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } return i + 4 <= json.Length && json.Substring(i, 4) == "true"; } private static string[] ExtractStringArray(string json, string key) { if (string.IsNullOrEmpty(json)) { return Array.Empty(); } int num = json.IndexOf("\"" + key + "\""); if (num < 0) { return Array.Empty(); } int num2 = json.IndexOf('[', num); if (num2 < 0) { return Array.Empty(); } int num3 = json.IndexOf(']', num2); if (num3 < 0) { return Array.Empty(); } string text = json.Substring(num2 + 1, num3 - num2 - 1); List list = new List(); int num4 = 0; while (num4 < text.Length) { int num5 = text.IndexOf('"', num4); if (num5 < 0) { break; } int num6 = text.IndexOf('"', num5 + 1); if (num6 < 0) { break; } list.Add(text.Substring(num5 + 1, num6 - num5 - 1)); num4 = num6 + 1; } return list.ToArray(); } private static T[] ExtractObjectArray(string json, string key, Func parse) { if (string.IsNullOrEmpty(json)) { return Array.Empty(); } int num = json.IndexOf("\"" + key + "\""); if (num < 0) { return Array.Empty(); } int num2 = json.IndexOf('[', num); if (num2 < 0) { return Array.Empty(); } List list = new List(); int num3 = 0; int num4 = -1; for (int i = num2; i < json.Length; i++) { switch (json[i]) { case '[': num3++; continue; case ']': num3--; if (num3 == 0) { break; } continue; case '{': if (num4 < 0) { num4 = i; } num3++; continue; case '}': num3--; if (num3 == 1 && num4 >= 0) { list.Add(parse(json.Substring(num4, i - num4 + 1))); num4 = -1; } continue; default: continue; } break; } return list.ToArray(); } public static void TournamentSignup(string tournamentId, string steamId, string displayName, string[] slotIsos = null) { string text = ""; try { text = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { text = ""; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{\"steam_id\":\"").Append(Escape(steamId)).Append("\",\"display_name\":\"") .Append(Escape(displayName ?? steamId)) .Append("\",\"region\":\"") .Append(Escape(text)) .Append("\",\"slot_ts\":["); if (slotIsos != null) { for (int i = 0; i < slotIsos.Length; i++) { if (i > 0) { stringBuilder.Append(','); } stringBuilder.Append('"').Append(Escape(slotIsos[i])).Append('"'); } } stringBuilder.Append("]}"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/tournaments/" + tournamentId + "/signup", stringBuilder.ToString(), delegate(bool s, string r) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (s) { FetchTournamentCurrent(steamId, force: true); CompetitiveUI.ShowNotification("Signed up for tournament", new Color(0.4f, 1f, 0.5f)); } else { CompetitiveUI.ShowNotification(ExtractErrorDetail(r) ?? "Signup failed", new Color(1f, 0.4f, 0.4f)); } })); } public static void TournamentUnsignup(string tournamentId, string steamId) { string json = "{\"steam_id\":\"" + Escape(steamId) + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/tournaments/" + tournamentId + "/unsignup", json, delegate(bool s, string r) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (s) { FetchTournamentCurrent(steamId, force: true); CompetitiveUI.ShowNotification("Left tournament signup", new Color(0.9f, 0.9f, 0.4f)); } else { CompetitiveUI.ShowNotification(ExtractErrorDetail(r) ?? "Failed", new Color(1f, 0.4f, 0.4f)); } })); } public static void TournamentTimeVote(string tournamentId, string steamId, string[] slotIsos) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{\"steam_id\":\"").Append(Escape(steamId)).Append("\",\"slot_ts\":["); for (int i = 0; i < slotIsos.Length; i++) { if (i > 0) { stringBuilder.Append(','); } stringBuilder.Append('"').Append(Escape(slotIsos[i])).Append('"'); } stringBuilder.Append("]}"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/tournaments/" + tournamentId + "/time-vote", stringBuilder.ToString(), delegate(bool s, string r) { if (s) { FetchTournamentCurrent(steamId, force: true); } })); } public static void TournamentForceStartVote(string tournamentId, string steamId) { string json = "{\"steam_id\":\"" + Escape(steamId) + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/tournaments/" + tournamentId + "/force-start-vote", json, delegate(bool s, string r) { if (s) { FetchTournamentCurrent(steamId, force: true); } })); } public static void TournamentReady(string tournamentId, string steamId) { string json = "{\"steam_id\":\"" + Escape(steamId) + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/tournaments/" + tournamentId + "/ready", json, delegate(bool s, string r) { if (s) { FetchTournamentCurrent(steamId, force: true); } })); } public static void TournamentPlayNow(string tournamentId, string matchId, string steamId) { string json = "{\"steam_id\":\"" + Escape(steamId) + "\"}"; ((MonoBehaviour)Plugin.Instance).StartCoroutine(PostRequest(baseUrl + "/api/v1/tournaments/" + tournamentId + "/matches/" + matchId + "/play-now", json, delegate(bool s, string r) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (s) { CompetitiveUI.ShowNotification("Play Now sent - starts when your opponent presses it too", new Color(0.5f, 0.9f, 1f)); _myActiveMatchesRefreshAt = 0f; FetchMyActiveTournamentMatches(steamId); FetchTournamentCurrent(steamId, force: true); } else { CompetitiveUI.ShowNotification(ExtractErrorDetail(r) ?? "Play Now failed", new Color(1f, 0.5f, 0.4f)); } })); } private static string ExtractErrorDetail(string response) { if (string.IsNullOrEmpty(response)) { return null; } try { return ExtractString(response, "detail"); } catch { return null; } } public static void FetchPlayerTournaments(string steamId, Action onDone = null) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown") { return; } ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/tournaments/players/" + Escape(steamId) + "/tournaments?limit=8", delegate(bool success, string response) { if (!success || string.IsNullOrEmpty(response)) { return; } try { PlayerTournamentHistory value = new PlayerTournamentHistory { steam_id = (ExtractString(response, "steam_id") ?? steamId), winner_count = ExtractInt(response, "winner_count", 0), runner_up_count = ExtractInt(response, "runner_up_count", 0), third_place_count = ExtractInt(response, "third_place_count", 0), participant_count = ExtractInt(response, "participant_count", 0), recent = ExtractObjectArray(response, "recent", (string raw) => new PlayerTournamentEntry { tournament_id = ExtractString(raw, "tournament_id"), ended_at = ExtractString(raw, "ended_at"), placed_rank = ExtractInt(raw, "placed_rank", 0), kind = ExtractString(raw, "kind"), signup_count = ExtractInt(raw, "signup_count", 0), winner_display_name = ExtractString(raw, "winner_display_name") }) }; CachedPlayerTournaments[steamId] = value; NativeUI.MarkDirty(); onDone?.Invoke(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TOURNAMENT-HIST] parse: " + ex.Message)); } })); } public static void FetchMyActiveTournamentMatches(string steamId) { if (string.IsNullOrEmpty(steamId) || steamId == "unknown" || Time.unscaledTime < _myActiveMatchesRefreshAt) { return; } _myActiveMatchesRefreshAt = Time.unscaledTime + 20f; ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/tournaments/my-active-matches?steam_id=" + Escape(steamId), delegate(bool success, string response) { if (!success || string.IsNullOrEmpty(response)) { return; } try { List list = new List(); string[] array = ExtractObjectArray(response, "matches", (string r) => r); foreach (string json in array) { list.Add(new ActiveTournamentMatch { tournament_id = ExtractString(json, "tournament_id"), kind = ExtractString(json, "kind"), match_id = ExtractString(json, "match_id"), status = ExtractString(json, "status"), bracket_side = ExtractString(json, "bracket_side"), round = ExtractInt(json, "round", 0), opponent_steam_id = ExtractString(json, "opponent_steam_id"), opponent_display_name = ExtractString(json, "opponent_display_name"), photon_room_name = ExtractString(json, "photon_room_name"), photon_region = ExtractString(json, "photon_region"), my_ready = ExtractBool(json, "my_ready"), opp_ready = ExtractBool(json, "opp_ready"), ready_seconds_left = ExtractInt(json, "ready_seconds_left", -1), scheduled_seconds_left = ExtractInt(json, "scheduled_seconds_left", -1), my_early_ok = ExtractBool(json, "my_early_ok"), opp_early_ok = ExtractBool(json, "opp_early_ok"), fetched_at_realtime = Time.realtimeSinceStartup }); } CachedMyActiveTournamentMatches = list; NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TOURNAMENT-ACTIVE] parse: " + ex.Message)); } })); } public static void FetchSiteTournamentHistory() { ((MonoBehaviour)Plugin.Instance).StartCoroutine(GetRequest(baseUrl + "/api/v1/tournaments/history?limit=12", delegate(bool success, string response) { if (!success || string.IsNullOrEmpty(response)) { return; } try { string json = "{\"_hist\":" + response + "}"; CachedSiteTournamentHistory = ExtractObjectArray(json, "_hist", (string raw) => new PlayerTournamentEntry { tournament_id = ExtractString(raw, "tournament_id"), ended_at = ExtractString(raw, "ended_at"), placed_rank = 0, kind = ExtractString(raw, "kind"), signup_count = ExtractInt(raw, "signup_count", 0), winner_display_name = ExtractString(raw, "winner_display_name") }); NativeUI.MarkDirty(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TOURNAMENT-SITEHIST] parse: " + ex.Message)); } })); } } public static class CardImageLoader { private const int EXPECTED_CARD_COUNT = 67; private static volatile Dictionary _filesByKey; private static readonly Dictionary _spriteCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool _scanAttempted; private static string _cardsDir; public static bool IsAvailable => _filesByKey != null && _filesByKey.Count > 0; public static int Count => _filesByKey?.Count ?? 0; public static void Initialize() { if (_scanAttempted) { return; } _scanAttempted = true; try { string location = Assembly.GetExecutingAssembly().Location; string directoryName = Path.GetDirectoryName(location); _cardsDir = Path.Combine(directoryName, "cards"); _filesByKey = ScanCardsDir(); int count = _filesByKey.Count; if (count >= 67) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[CARD-ART] indexed {count} card images from {_cardsDir}"); } } else { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)$"[CARD-ART] only {count}/{67} card images present at {_cardsDir}. Reinstall via the mod manager if popups / tier list export look broken."); } } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[CARD-ART] init failed: " + ex.Message)); } _filesByKey = _filesByKey ?? new Dictionary(); } } private static Dictionary ScanCardsDir() { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrEmpty(_cardsDir) || !Directory.Exists(_cardsDir)) { return dictionary; } string[] array = new string[3] { "*.jpg", "*.jpeg", "*.png" }; foreach (string searchPattern in array) { string[] files = Directory.GetFiles(_cardsDir, searchPattern); foreach (string text in files) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); string key = NormalizeKey(fileNameWithoutExtension); if (!dictionary.ContainsKey(key)) { dictionary[key] = text; } } } return dictionary; } public static Sprite GetSprite(string cardName) { //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(cardName)) { return null; } if (!_scanAttempted) { Initialize(); } Dictionary filesByKey = _filesByKey; if (filesByKey == null) { return null; } string text = null; try { text = CardRarityLookup.GetCanonicalName(cardName); } catch { } string text2 = NormalizeKey(text ?? cardName); string text3 = NormalizeKey(cardName); if (_spriteCache.TryGetValue(text2, out var value) && (Object)(object)value != (Object)null) { return value; } if (text2 != text3 && _spriteCache.TryGetValue(text3, out var value2) && (Object)(object)value2 != (Object)null) { return value2; } string value3 = null; string text4 = null; if (filesByKey.TryGetValue(text2, out value3)) { text4 = text2; } else if (filesByKey.TryGetValue(text3, out value3)) { text4 = text3; } if (value3 == null) { return null; } try { byte[] array = File.ReadAllBytes(value3); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ((Object)val).hideFlags = (HideFlags)61; if (!ImageConversion.LoadImage(val, array)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[CARD-ART] LoadImage failed for " + value3)); } return null; } ((Texture)val).filterMode = (FilterMode)1; Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)val2).name = "CardArt_" + text4; ((Object)val2).hideFlags = (HideFlags)61; _spriteCache[text4] = val2; return val2; } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[CARD-ART] failed to load " + value3 + ": " + ex.Message)); } return null; } } private static string NormalizeKey(string s) { if (string.IsNullOrEmpty(s)) { return ""; } StringBuilder stringBuilder = new StringBuilder(s.Length); foreach (char c in s) { if (c != ' ' && c != '-' && c != '\'' && c != '.' && c != '_') { stringBuilder.Append(char.ToLowerInvariant(c)); } } return stringBuilder.ToString(); } } public static class ChatClient { private static ClientWebSocket socket; private static CancellationTokenSource cts; private static Task loopTask; private static volatile bool running; private static readonly ConcurrentQueue sendQueue = new ConcurrentQueue(); private static SemaphoreSlim sendSignal; public static Action OnMessage; private static volatile string overrideBase; public static bool IsConnected => socket != null && socket.State == WebSocketState.Open; public static bool UsingWsFallback { get; private set; } public static void Connect() { if (running) { return; } if (!Plugin.DataConsentGranted) { Plugin.Log.LogInfo((object)"[CHAT] Connect skipped — no data consent"); return; } running = true; cts = new CancellationTokenSource(); sendSignal = new SemaphoreSlim(0); loopTask = Task.Run(() => RunLoop(cts.Token)); } public static void Disconnect() { running = false; try { cts?.Cancel(); } catch { } try { sendSignal?.Release(); } catch { } try { if (socket != null && socket.State == WebSocketState.Open) { socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "bye", CancellationToken.None).Wait(1000); } } catch { } socket = null; } public static void Send(string steamId, string displayName, string message) { if (string.IsNullOrEmpty(message)) { return; } string text = Guid.NewGuid().ToString("N"); string item = "{\"steam_id\":\"" + JsonEscape(steamId ?? "") + "\",\"display_name\":\"" + JsonEscape(displayName ?? "") + "\",\"client_msg_id\":\"" + text + "\",\"message\":\"" + JsonEscape(message) + "\"}"; sendQueue.Enqueue(item); try { sendSignal?.Release(); } catch { } Plugin.Log.LogInfo((object)("[CHAT] queued: " + message)); ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; int num = ((cachedPlayerStats != null) ? ((int)Math.Round(cachedPlayerStats.rating)) : 0); string s = cachedPlayerStats?.active_title ?? ""; string s2 = cachedPlayerStats?.active_title_color ?? ""; string obj2 = "{\"source\":\"ingame\",\"steam_id\":\"" + JsonEscape(steamId ?? "") + "\",\"display_name\":\"" + JsonEscape(displayName ?? "") + "\",\"rating\":" + num + ",\"title\":\"" + JsonEscape(s) + "\",\"title_color\":\"" + JsonEscape(s2) + "\",\"message\":\"" + JsonEscape(message) + "\"}"; try { OnMessage?.Invoke(obj2); } catch { } } public static void Retarget(string newBaseHttp) { if (string.IsNullOrWhiteSpace(newBaseHttp)) { return; } overrideBase = newBaseHttp; Plugin.Log.LogInfo((object)("[CHAT] retargeting to " + newBaseHttp)); try { socket?.Abort(); } catch { } } private static string ResolveBaseHttp() { if (!string.IsNullOrWhiteSpace(overrideBase)) { return overrideBase; } string text = Plugin.ApiBaseUrl?.Value; return string.IsNullOrWhiteSpace(text) ? "https://competitive-rounds.duckdns.org:8444" : text; } private static async Task RunLoop(CancellationToken token) { int backoffSec = 2; int wssConnectFailures = 0; while (running && !token.IsCancellationRequested) { string baseHttp = ResolveBaseHttp().TrimEnd('/'); string wsUrl = baseHttp.Replace("https://", "wss://").Replace("http://", "ws://") + "/api/v1/ws/chat"; Task senderTask = null; bool connected = false; try { socket = new ClientWebSocket(); socket.Options.SetRequestHeader("X-Mod-Version", "1.35.5"); await socket.ConnectAsync(new Uri(wsUrl), token); connected = true; wssConnectFailures = 0; Plugin.Log.LogInfo((object)("[CHAT] WS connected: " + wsUrl)); backoffSec = 2; try { ApiClient.FetchRecentChat(); } catch { } senderTask = Task.Run(() => SendLoop(socket, token)); Task.Run(() => KeepAliveLoop(socket, token)); byte[] buffer = new byte[8192]; StringBuilder msg = new StringBuilder(); while (socket.State == WebSocketState.Open && !token.IsCancellationRequested) { ArraySegment seg = new ArraySegment(buffer); WebSocketReceiveResult result; try { result = await socket.ReceiveAsync(seg, token); } catch (WebSocketException ex) { Plugin.Log.LogWarning((object)("[CHAT] recv error: " + ex.Message)); break; } if (result.MessageType == WebSocketMessageType.Close) { Plugin.Log.LogWarning((object)$"[CHAT] WS close from server: {result.CloseStatus} {result.CloseStatusDescription}"); try { await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "closing", CancellationToken.None); } catch { } break; } msg.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); if (result.EndOfMessage) { string text = msg.ToString(); msg.Clear(); try { OnMessage?.Invoke(text); } catch { } Plugin.Log.LogInfo((object)("[CHAT] <- " + text)); } } } catch (Exception ex2) when (!token.IsCancellationRequested) { Plugin.Log.LogWarning((object)$"[CHAT] WS error: {ex2.Message} (reconnect in {backoffSec}s)"); int num2; if (!connected && overrideBase == null && wsUrl.StartsWith("wss://") && string.Equals(baseHttp, "https://competitive-rounds.duckdns.org:8444".TrimEnd('/'), StringComparison.OrdinalIgnoreCase)) { int num = wssConnectFailures + 1; wssConnectFailures = num; num2 = ((num >= 3) ? 1 : 0); } else { num2 = 0; } if (num2 != 0) { overrideBase = "http://competitive-rounds.duckdns.org:8443"; UsingWsFallback = true; Plugin.Log.LogWarning((object)(string.Format("[CHAT] wss unreachable after {0} attempts — session fallback to plaintext ws ({1}). ", wssConnectFailures, "http://competitive-rounds.duckdns.org:8443") + "Config untouched; TLS is retried next launch.")); } } finally { try { sendSignal?.Release(); } catch { } if (senderTask != null) { try { await senderTask; } catch { } } try { socket?.Dispose(); } catch { } socket = null; } if (!running || token.IsCancellationRequested) { break; } try { await Task.Delay(backoffSec * 1000, token); } catch { } backoffSec = Math.Min(backoffSec * 2, 60); } Plugin.Log.LogInfo((object)"[CHAT] WS loop exited"); } private static async Task SendLoop(ClientWebSocket ws, CancellationToken token) { while (!token.IsCancellationRequested && ws.State == WebSocketState.Open) { try { await sendSignal.WaitAsync(token); } catch { break; } string json; while (sendQueue.TryDequeue(out json)) { if (ws.State != WebSocketState.Open) { sendQueue.Enqueue(json); return; } byte[] bytes = Encoding.UTF8.GetBytes(json); try { await ws.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Text, endOfMessage: true, token); Plugin.Log.LogInfo((object)$"[CHAT] -> sent ({bytes.Length}B)"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CHAT] send failed: " + ex.Message + " — requeueing")); sendQueue.Enqueue(json); return; } } } } private static async Task KeepAliveLoop(ClientWebSocket ws, CancellationToken token) { while (!token.IsCancellationRequested && ws.State == WebSocketState.Open) { try { await Task.Delay(25000, token); } catch { break; } if (ws.State != WebSocketState.Open) { break; } sendQueue.Enqueue("{\"type\":\"ping\"}"); try { sendSignal?.Release(); } catch { } } } private static string JsonEscape(string s) { if (string.IsNullOrEmpty(s)) { return ""; } StringBuilder stringBuilder = new StringBuilder(s.Length); foreach (char c in s) { switch (c) { case '\\': stringBuilder.Append("\\\\"); continue; case '"': stringBuilder.Append("\\\""); continue; case '\n': stringBuilder.Append("\\n"); continue; case '\r': stringBuilder.Append("\\r"); continue; case '\t': stringBuilder.Append("\\t"); continue; } if (c < ' ') { stringBuilder.Append($"\\u{(int)c:x4}"); } else { stringBuilder.Append(c); } } return stringBuilder.ToString(); } } public static class CompetitiveUI { private struct QueuedNotif { public string text; public Color color; public float dur; } private struct FfaHudRow { public bool active; public bool dead; public bool halfDot; public string name; public Color nameColor; public Color dotColor; public int fullDots; public Rect nameRect; public float dotX; public float dotY; } public struct CardHoverRegion { public Rect screenRect; public string fullCardLine; public bool isOpponent; public string titleOverride; public string bodyOverride; public RectTransform sourceRT; public Camera sourceCam; public float widthFrac; public RectTransform clipRT; public object sourceTxt; } public struct ScoreGraphRegion { public Rect screenRect; public string timeline; public bool won; public RectTransform sourceRT; public Camera sourceCam; public float widthFrac; public RectTransform clipRT; public object sourceTxt; } public struct FpsGraphRegion { public Rect screenRect; public string mySeries; public string oppSeries; public int kind; public float myStep; public bool subjectIsOpp; public string pairHit; public string pairBlock; public string subjectLabel; public string pointTimes; public string pointTimeline; public RectTransform sourceRT; public Camera sourceCam; public float widthFrac; public RectTransform clipRT; public object sourceTxt; } private struct ChatLineLayout { public string Disp; public float H; } public static int LastKnownLevel = -1; private static float fpsTimer = 0f; private static int fpsCnt = 0; private static float fpsVal = 0f; private static GUIStyle fpsStyle; private static string fpsLabel = ""; private static float fpsLabelWidth = 60f; private static bool fpsLabelShowFps; private static bool fpsLabelShowRegion; private static string notifText = ""; private static Color notifColor = Color.white; private static float notifTimer = 0f; private static List notifQueue = new List(); private static GUIStyle notifStyle; private static GUIStyle statusStyle; private static AudioClip matchFoundClip; private static GameObject soundObj; private const int FfaHudMaxRows = 10; private const int FfaHudNameChars = 12; private static readonly FfaHudRow[] ffaHudRows = new FfaHudRow[10]; private static readonly char[] ffaHudNameBuffer = new char[12]; private static readonly string[] ffaHudFallbackNames = new string[10] { "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9", "P10" }; private static int ffaHudRowExtent; private static int ffaHudLayoutExtent = -1; private static int ffaHudScreenWidth = -1; private static int ffaHudScreenHeight = -1; private static float ffaHudRowsCachedAt = -999f; private static float ffaVanillaCounterCheckedAt = -999f; private static float ffaHudScale = 1f; private static float ffaHudDotSize; private static float ffaHudDotPitch; private static Rect ffaHudBackingRect; private static Rect ffaPickBannerRect; private static GUIStyle ffaHudNameStyle; private static GUIStyle ffaPickBannerStyle; private static Texture2D ffaFullDotTexture; private static Texture2D ffaHalfDotTexture; private static string ffaPickBannerText = ""; private static float ffaPickBannerCachedAt = -999f; private static int ffaPickBannerSeconds = -1; private static bool ffaPickBannerLocal; private static float ffaStartCountdownUntil = -999f; private static readonly HashSet _tourneyBannerAnnounced = new HashSet(); private static GUIStyle tourneyBannerStyle; private static string _leaverText; private static float _leaverUntil; private static bool _leaverRed; private static GUIStyle _leaverStyle; private static GUIStyle mapToastStyle; private static GUIStyle betPromptStyle; private static GUIStyle betPromptTitleStyle; private const string BET_AMOUNT_CTRL = "CustomBetAmount"; private static GUIStyle lfpFieldStyle; private static GUIStyle lfpTitleStyle; private const string LFP_MSG_CTRL = "LfpMsgField"; private static GUIStyle compareSearchStyle; private static GUIStyle compareSearchHintStyle; private static bool compareSearchFocused = false; private const string CMP_SEARCH_CTRL = "CmpSearchField"; private static bool lbSearchFocused = false; private const string LB_SEARCH_CTRL = "LbSearchField"; private static readonly List _cardHoverRegions = new List(40); private static readonly Vector3[] _liveCornerBuf = (Vector3[])(object)new Vector3[4]; private static readonly Rect _offscreenRect = new Rect(-99999f, -99999f, 1f, 1f); private static PropertyInfo _pPrefWidth; private static readonly List _scoreGraphRegions = new List(40); private static GUIStyle _scoreGraphLbl; private static readonly List _fpsGraphRegions = new List(60); private static GUIStyle _cardTipTitleStyle; private static GUIStyle _cardTipBodyStyle; private static GUIStyle stuckTitleStyle; private static GUIStyle stuckTextStyle; private static GUIStyle stuckButtonStyle; private static readonly string[] BUG_STATUSES = new string[5] { "open", "triaged", "resolved", "wontfix", "dupe" }; private static bool bugAdminOpen = false; private static string bugAdminSelectedId = null; private static Vector2 bugAdminListScroll; private static Vector2 bugAdminDetailScroll; private static bool bugAdminLoading = false; private static GUIStyle bugAdminRowStyle; private static GUIStyle bugAdminDetailStyle; private static GUIStyle bugAdminTabStyle; private static GUIStyle bugAdminTabActiveStyle; private static GUIStyle bugAdminLogStyle; private static List bugAdminLogChunks; private static List bugAdminLogHeights; private static float bugAdminLogTotalH; private static float bugAdminMetaH; private static float bugAdminLayoutW = -1f; private static string bugAdminLayoutKey = null; private static string bugAdminCommentDraft = ""; private static int bugAdminStatusIdx = 0; private static string bugAdminActionStatus = ""; private static string bugAdminLookup = ""; private static GUIStyle inputKeyStyle; private static GUIStyle inputKeySmallStyle; private static GUIStyle blockDbgStyle; private static GUIStyle blockDbgSmallStyle; private static GUIStyle ingameChatStyle; private const int CHAT_MAX_WRAP_LINES = 3; private const string CHAT_CUT_SUFFIX = " ... [see F5]"; private static readonly Dictionary chatLayoutCache = new Dictionary(); private static readonly List _chatEntryScratch = new List(8); private static ChatLineLayout[] _chatLayoutScratch = new ChatLineLayout[8]; private static float[] _chatAlphaScratch = new float[8]; private static bool adminPromptOpen = false; private static string adminPromptMode = ""; private static string adminInputA = ""; private static string adminInputB = ""; private static GUIStyle adminFieldStyle; private static GUIStyle adminLabelStyle; private static readonly string[] ADMIN_ACHIEVEMENT_KEYS = new string[41] { "untouchable", "silent_assassin", "total_mayhem", "fragile_perfection", "no_escape", "rise_from_the_ashes", "the_comeback_kid", "stacked_deck", "regicide", "stan_slayer", "pacifist", "immovable_object", "master_rank", "team_sweep", "grand_master", "flawless", "bullet_hell", "spray_and_pray", "demolitionist", "controlled_burst", "field_medic", "god_build", "double_nova", "lumberjack", "pristine_perfection", "silent_drill", "double_glass", "sustained_power", "deep_end", "clutch", "collector", "grounded", "instinct", "rising_star", "on_fire", "unstoppable", "immortal", "casual_century", "casual_conqueror", "touch_grass", "twins" }; private static bool confirmOpen = false; private static string confirmMessage = ""; private static Action confirmOnYes = null; private static bool artistPromptOpen = false; private static string artistPromptTitle = ""; private static string artistPromptLabel = ""; private static string artistPromptValue = ""; private static Action artistPromptOnSubmit = null; private static bool artistPickerOpen = false; private static string artistPickerTitle = ""; private static string[] artistPickerNames = null; private static string[] artistPickerIds = null; private static int artistPickerIdx = 0; private static Action artistPickerOnPick = null; private static string artistPickerAction = "Assign"; private static bool artistPickerShowClear = true; private static Vector2 artistPickerScroll = Vector2.zero; private static GUIStyle pickerRowStyle; private static bool playerSearchOpen = false; private static string playerSearchTitle = ""; private static string playerSearchQuery = ""; private static string playerSearchPrevQuery = ""; private static string playerSearchLastFetched = null; private static float playerSearchTypedAt = 0f; private static bool playerSearchBusy = false; private static string playerSearchStatus = ""; private static List playerSearchResults = new List(); private static Action playerSearchOnPick = null; private static bool cosTestOpen = false; private static Texture2D cosTestTex = null; private static string cosTestName = ""; private static string cosTestSlot = ""; private static float cosTestScale = 1.3f; private static Vector2 cosTestOffset = Vector2.zero; private static Vector2 cosTestInitialOffset = Vector2.zero; private static bool cosTestDragging = false; private static Vector2 cosTestLastMouse = Vector2.zero; private static string cosTestSubmitLabel = "Submit"; private static bool cosTestIsRevision = false; private static Action cosTestOnSubmit = null; private const float COS_BODY_SOURCE_PX = 662.5f; private const float COS_BODY_LOCAL_DIAMETER = 6.625f; private static readonly Color COS_BODY_ORANGE = new Color(0.96f, 0.55f, 0.23f, 0.82f); private static bool cosReviewOpen = false; private static List cosReviewSubs = null; private static int cosReviewIdx = 0; private static bool cosReviewBusy = false; private static string cosReviewStatus = ""; private static string cosReviewDenialReason = ""; private static bool cosReviewDragging = false; private static Vector2 cosReviewPreviewOffset = Vector2.zero; private static int cosReviewPreviewSubId = -1; private static Vector2 cosReviewLastMouse = Vector2.zero; private static GUIStyle cosReviewReasonStyle; private static readonly Dictionary cosReviewTex = new Dictionary(); private static bool cosReleaseOpen = false; private static bool cosReleaseBusy = false; private static string cosReleaseStatus = ""; private static Vector2 cosReleaseScroll = Vector2.zero; private static List cosReleaseCandidates = new List(); private static bool flagEvidenceOpen = false; private static bool flagEvidenceBusy = false; private static bool flagRepairConfirm = false; private static ApiClient.FlaggedMatchEntry flagEvidenceEntry; private static Vector2 flagEvidenceScroll = Vector2.zero; private static readonly string[] BUG_SEVERITIES = new string[4] { "low", "medium", "high", "crash" }; private static readonly string[] BUG_CATEGORIES = new string[4] { "ui", "gameplay", "network", "other" }; private static bool bugModalOpen = false; private static string bugDescription = ""; private static string bugRepro = ""; private static int bugSeverityIdx = 1; private static int bugCategoryIdx = 3; private static bool bugSendLogs = true; private static string bugSubmitStatus = ""; private static bool bugSubmitting = false; private static Vector2 bugDescScroll; private static Vector2 bugReproScroll; private static GUIStyle bugTitleStyle; private static GUIStyle bugLabelStyle; private static GUIStyle bugFieldStyle; private static GUIStyle bugAreaStyle; private static GUIStyle bugButtonStyle; private static GUIStyle bugBtnPickedStyle; private const int BUNDLE_CAP_BEP_CURRENT = 1500000; private const int BUNDLE_CAP_BEP_PREV = 1000000; private const int BUNDLE_CAP_UNITY = 1000000; private static bool logViewerOpen = false; private static int logViewerTab = 0; private static Vector2 logViewerScroll; private static string logViewerBepCache; private static string logViewerBepPrevCache; private static string logViewerUniCache; private static GUIStyle logViewerStyle; private static GUIStyle logViewerTabStyle; private static GUIStyle logViewerTabActiveStyle; private static Type s_eventSystemType; private static PropertyInfo s_eventSystemCurrentProp; private static PropertyInfo s_eventSystemSelectedProp; private static FieldInfo s_devConsoleIsTyping; private static bool s_devConsoleLookedUp; private static object s_devConsoleInstance; private static FieldInfo s_devConsoleField; private static bool gameplayInputLockHeld; private static bool weHoldTypingFlag; private static float chatDrawStampedAt = -999f; private static bool chatInputOpen = false; private static bool chatJustOpened = false; private static string chatInputText = ""; private static GUIStyle chatStyle; private static GUIStyle consentTitleStyle; private static GUIStyle consentBodyStyle; private static GameObject consentBlockerGO; private static float matchStatusCacheUntil = 0f; private static bool matchStatusCachedRanked = false; private static bool matchStatusIsOvt = false; private static string matchStatusSeries = ""; private static string matchStatusH2H = ""; private static Color matchStatusH2HTint = new Color(0.7f, 0.7f, 0.7f); private static GUIStyle scoreStyle; public static bool FfaStartCountdownActive => Time.realtimeSinceStartup < ffaStartCountdownUntil; public static bool IsCompareSearchFocused => compareSearchFocused; public static bool IsLbSearchFocused => lbSearchFocused; public static bool ArtistPromptOpen => artistPromptOpen || artistPickerOpen || playerSearchOpen || cosTestOpen || cosReviewOpen; public static bool CosmeticReviewOpen => cosReviewOpen; public static bool AnyChatTyping => chatInputOpen || IsVanillaChatTypingRaw(); internal static bool VanillaChatBoxOnScreen => VanillaChatBoxActive(); public static bool IsChatInputOpen => chatInputOpen; public static void ToggleOverlay() { NativeUI.Toggle(); } public static void ShowNotification(string text, Color color, float duration = 5f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ShowNotifications.Value) { notifText = text; notifColor = color; notifTimer = duration; } } public static void QueueNotification(string text, Color color, float duration = 5f) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ShowNotifications.Value) { notifQueue.Add(new QueuedNotif { text = text, color = color, dur = duration }); } } public static void PlayMatchFoundSound() { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown try { if ((Object)(object)matchFoundClip == (Object)null) { int num = 44100; float num2 = 0.45f; int num3 = (int)((float)num * num2); matchFoundClip = AudioClip.Create("MatchFound", num3, 1, num, false); float[] array = new float[num3]; int num4 = num3 / 2; for (int i = 0; i < num3; i++) { float num5 = (float)i / (float)num; float num6 = ((i < num4) ? 660f : 880f); array[i] = Mathf.Sin(MathF.PI * 2f * num6 * num5) * 0.35f; float num7 = ((i < num4) ? ((float)i / (float)num4) : ((float)(i - num4) / (float)(num3 - num4))); float num8 = Mathf.Clamp01(num7 * 10f) * Mathf.Clamp01((1f - num7) * 5f); array[i] *= num8; } matchFoundClip.SetData(array, 0); } if ((Object)(object)soundObj == (Object)null) { soundObj = new GameObject("CR_Sound"); ((Object)soundObj).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)soundObj); } AudioSource val = soundObj.GetComponent(); if ((Object)(object)val == (Object)null) { val = soundObj.AddComponent(); } val.clip = matchFoundClip; val.volume = 0.7f; val.Play(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SOUND] Match found sound failed: " + ex.Message)); } } public static void ResetStyles() { } public static void CacheRaycasters() { } public static void MarkDirty() { NativeUI.MarkDirty(); } public static void Tick() { TickChatLockWatchdog(); NativeUI.Tick(); } public static void DrawUI() { TickChatLockWatchdog(); DrawFPS(); TabStatsOverlay.Draw(); PlayerEffectCosmetic.DrawPreview(); DrawNotification(); DrawFfaScoreStrip(); DrawMatchStatus(); DrawInGameChat(); DrawChatInput(); DrawAdminPrompt(); DrawConfirm(); DrawBugReportModal(); DrawBugReportAdminViewer(); DrawLogViewerModal(); DrawBlockDebug(); DrawInputOverlay(); DrawCardHoverTooltip(); DrawScoreHoverGraph(); DrawFpsHoverGraph(); DrawCompareSearch(); DrawLeaderboardSearch(); DrawMapColorToast(); DrawCustomBetPrompt(); DrawLfpPrompt(); DrawArtistInput(); DrawArtistPicker(); DrawPlayerSearch(); DrawCosmeticTestPreview(); DrawCosmeticReview(); DrawCosmeticReleaseQueue(); DrawFlagEvidence(); DrawLeaverBanner(); DrawTournamentBanner(); bool flag = bugModalOpen || logViewerOpen || bugAdminOpen || NativeUI.CustomBetPromptOpen || artistPromptOpen || artistPickerOpen || playerSearchOpen || cosTestOpen || cosReviewOpen || cosReleaseOpen || flagEvidenceOpen || adminPromptOpen || NativeUI.LfpPromptOpen; NativeUI.SetClickBlocker(flag); ClickHandler.ModalBlockInput = flag || NativeUI.InfoPopupOpen || !Plugin.DataConsentAsked; DrawConsentModal(); } public static void ShowFfaStartCountdown(float seconds) { ffaStartCountdownUntil = Time.realtimeSinceStartup + seconds; } public static void CancelFfaStartCountdown() { ffaStartCountdownUntil = -999f; } private static void DrawFfaScoreStrip() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Invalid comparison between Unknown and I4 //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Invalid comparison between Unknown and I4 if (Event.current == null) { return; } try { bool inFfaMatch = FfaMode.InFfaMatch; bool pickPhaseActive = FfaMode.PickPhaseActive; bool flag = Time.realtimeSinceStartup < ffaStartCountdownUntil; if (!inFfaMatch && !pickPhaseActive && !flag) { ffaHudRowsCachedAt = -999f; ffaHudRowExtent = 0; ffaPickBannerText = ""; ffaPickBannerSeconds = -1; return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if ((int)Event.current.type == 8) { if (inFfaMatch) { SuppressFfaVanillaCounter(realtimeSinceStartup); if (realtimeSinceStartup - ffaHudRowsCachedAt >= 0.5f) { ffaHudRowsCachedAt = realtimeSinceStartup; RefreshFfaHudRows(); } } else { ffaHudRowExtent = 0; } RefreshFfaPickBanner(realtimeSinceStartup, pickPhaseActive); } else if ((int)Event.current.type == 7) { EnsureFfaHudResources(); RefreshFfaHudLayout(); if (inFfaMatch) { DrawFfaScoreRows(); } DrawFfaPickBanner(realtimeSinceStartup); } } catch { } } private static void EnsureFfaHudResources() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (ffaHudNameStyle == null) { ffaHudNameStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, fontStyle = (FontStyle)1, richText = false, clipping = (TextClipping)1 }; ffaHudNameStyle.normal.textColor = Color.white; } if (ffaPickBannerStyle == null) { ffaPickBannerStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontStyle = (FontStyle)1, richText = false, clipping = (TextClipping)1 }; ffaPickBannerStyle.normal.textColor = Color.white; } if ((Object)(object)ffaFullDotTexture == (Object)null) { ffaFullDotTexture = BuildFfaDotTexture(half: false, "CR_FFA_FullDot"); } if ((Object)(object)ffaHalfDotTexture == (Object)null) { ffaHalfDotTexture = BuildFfaDotTexture(half: true, "CR_FFA_HalfDot"); } } private static Texture2D BuildFfaDotTexture(bool half, string textureName) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); ((Object)val).name = textureName; ((Object)val).hideFlags = (HideFlags)61; ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; Color32[] array = (Color32[])(object)new Color32[1024]; float num = 16f; float num2 = num - 1f; for (int i = 0; i < 32; i++) { float num3 = (float)i + 0.5f - num; for (int j = 0; j < 32; j++) { float num4 = (float)j + 0.5f - num; float num5 = Mathf.Clamp01(num2 + 0.5f - Mathf.Sqrt(num4 * num4 + num3 * num3)); if (half && num4 > 0f) { num5 = 0f; } array[i * 32 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num5 * 255f)); } } val.SetPixels32(array); val.Apply(false, true); return val; } private static void RefreshFfaHudRows() { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 10; i++) { FfaHudRow ffaHudRow = ffaHudRows[i]; ffaHudRow.active = false; ffaHudRow.name = null; ffaHudRows[i] = ffaHudRow; } ffaHudRowExtent = 0; PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null) { return; } foreach (Player player in instance.players) { if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null || (Object)(object)player.data == (Object)null) { continue; } int teamID = player.TeamID; if (teamID < 0 || teamID >= 10) { continue; } string input = null; try { PhotonView view = player.data.view; object obj; if (view == null) { obj = null; } else { Player owner = view.Owner; obj = ((owner != null) ? owner.NickName : null); } input = (string)obj; } catch { } Color val = Color.white; try { PlayerSkin playerSkinColors = PlayerSkinBank.GetPlayerSkinColors(teamID); if ((Object)(object)playerSkinColors != (Object)null) { val = playerSkinColors.color; } } catch { } FfaHudRow ffaHudRow2 = ffaHudRows[teamID]; ffaHudRow2.active = true; ffaHudRow2.dead = player.data.dead; ffaHudRow2.name = StripFfaHudName(input, teamID); ffaHudRow2.nameColor = FfaHudReadableNameColor(val); ffaHudRow2.dotColor = val; ffaHudRow2.fullDots = Mathf.Clamp(FfaMode.RoundsFor(teamID), 0, 5); ffaHudRow2.halfDot = ffaHudRow2.fullDots < 5 && FfaMode.PointsFor(teamID) >= 1; ffaHudRows[teamID] = ffaHudRow2; if (teamID + 1 > ffaHudRowExtent) { ffaHudRowExtent = teamID + 1; } } } private static string StripFfaHudName(string input, int slot) { if (string.IsNullOrEmpty(input)) { return ffaHudFallbackNames[slot]; } int num = 0; bool flag = false; for (int i = 0; i < input.Length; i++) { if (num >= 12) { break; } char c = input[i]; if (c == '<') { flag = true; } else if (flag) { if (c == '>') { flag = false; } } else { ffaHudNameBuffer[num++] = ((c < ' ') ? ' ' : c); } } while (num > 0 && ffaHudNameBuffer[num - 1] == ' ') { num--; } int j; for (j = 0; j < num && ffaHudNameBuffer[j] == ' '; j++) { } return (j >= num) ? ffaHudFallbackNames[slot] : new string(ffaHudNameBuffer, j, num - j); } private static Color FfaHudReadableNameColor(Color raw) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(raw.r, Mathf.Max(raw.g, raw.b)); float num2 = Mathf.Min(raw.r, Mathf.Min(raw.g, raw.b)); if (num <= 0.2f || num2 >= 0.82f) { return Color.white; } return new Color(raw.r, raw.g, raw.b, 1f); } private static void RefreshFfaHudLayout() { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) int width = Screen.width; int height = Screen.height; if (width != ffaHudScreenWidth || height != ffaHudScreenHeight || ffaHudLayoutExtent != ffaHudRowExtent) { ffaHudScreenWidth = width; ffaHudScreenHeight = height; ffaHudLayoutExtent = ffaHudRowExtent; ffaHudScale = (float)height / 1080f; float num = 6f * ffaHudScale; float num2 = 4f * ffaHudScale; float num3 = 100f * ffaHudScale; float num4 = 8f * ffaHudScale; float num5 = 18f * ffaHudScale; ffaHudDotSize = 12f * ffaHudScale; ffaHudDotPitch = 16f * ffaHudScale; float num6 = 16f * ffaHudScale; float num7 = 46f * ffaHudScale; float num8 = 5f * ffaHudDotSize + 16f * ffaHudScale; ffaHudBackingRect = new Rect(num6, num7, num + num3 + num4 + num8 + num, num2 * 2f + (float)ffaHudRowExtent * num5); for (int i = 0; i < 10; i++) { FfaHudRow ffaHudRow = ffaHudRows[i]; float num9 = num7 + num2 + (float)i * num5; ffaHudRow.nameRect = new Rect(num6 + num, num9, num3, num5); ffaHudRow.dotX = num6 + num + num3 + num4; ffaHudRow.dotY = num9 + (num5 - ffaHudDotSize) * 0.5f; ffaHudRows[i] = ffaHudRow; } float num10 = 260f * ffaHudScale; ffaPickBannerRect = new Rect(((float)width - num10) * 0.5f, 6f * ffaHudScale, num10, 28f * ffaHudScale); ffaHudNameStyle.fontSize = Mathf.Max(1, Mathf.RoundToInt(12f * ffaHudScale)); ffaPickBannerStyle.fontSize = Mathf.Max(1, Mathf.RoundToInt(14f * ffaHudScale)); } } private static void DrawFfaScoreRows() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0257: 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_00b7: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) if (ffaHudRowExtent <= 0) { return; } Color color = GUI.color; for (int i = 0; i < ffaHudRowExtent; i++) { FfaHudRow ffaHudRow = ffaHudRows[i]; if (ffaHudRow.active) { float num = (ffaHudRow.dead ? 0.5f : 1f); GUI.color = new Color(0f, 0f, 0f, 0.75f * num); GUI.Label(new Rect(((Rect)(ref ffaHudRow.nameRect)).x + ffaHudScale, ((Rect)(ref ffaHudRow.nameRect)).y + ffaHudScale, ((Rect)(ref ffaHudRow.nameRect)).width, ((Rect)(ref ffaHudRow.nameRect)).height), ffaHudRow.name, ffaHudNameStyle); GUI.color = new Color(ffaHudRow.nameColor.r, ffaHudRow.nameColor.g, ffaHudRow.nameColor.b, num); GUI.Label(ffaHudRow.nameRect, ffaHudRow.name, ffaHudNameStyle); int num2 = ffaHudRow.fullDots + (ffaHudRow.halfDot ? 1 : 0); GUI.color = new Color(0.62f, 0.62f, 0.62f, 0.55f); float num3 = ffaHudDotSize * 0.45f; float num4 = (ffaHudDotSize - num3) * 0.5f; for (int j = num2; j < 5; j++) { GUI.DrawTexture(new Rect(ffaHudRow.dotX + (float)j * ffaHudDotPitch + num4, ffaHudRow.dotY + num4, num3, num3), (Texture)(object)ffaFullDotTexture); } GUI.color = ffaHudRow.dotColor; for (int k = 0; k < ffaHudRow.fullDots; k++) { GUI.DrawTexture(new Rect(ffaHudRow.dotX + (float)k * ffaHudDotPitch, ffaHudRow.dotY, ffaHudDotSize, ffaHudDotSize), (Texture)(object)ffaFullDotTexture); } if (ffaHudRow.halfDot) { GUI.DrawTexture(new Rect(ffaHudRow.dotX + (float)ffaHudRow.fullDots * ffaHudDotPitch, ffaHudRow.dotY, ffaHudDotSize, ffaHudDotSize), (Texture)(object)ffaHalfDotTexture); } } } GUI.color = color; } private static void RefreshFfaPickBanner(float now, bool active) { if (!active) { float num = ffaStartCountdownUntil - now; if (num > 0f) { int num2 = Mathf.CeilToInt(num); if (num2 != ffaPickBannerSeconds || !ffaPickBannerLocal || string.IsNullOrEmpty(ffaPickBannerText)) { ffaPickBannerLocal = true; ffaPickBannerSeconds = num2; ffaPickBannerText = $"FFA STARTING IN {num2}..."; } } else if (FfaMode.SpawnGraceActive) { ffaPickBannerLocal = false; ffaPickBannerSeconds = -1; ffaPickBannerText = "GET READY - fire and block unlock in a moment"; } else { ffaPickBannerText = ""; ffaPickBannerSeconds = -1; } } else { bool localPickOpen = FfaMode.LocalPickOpen; if (string.IsNullOrEmpty(ffaPickBannerText) || now - ffaPickBannerCachedAt >= 0.25f || localPickOpen != ffaPickBannerLocal) { ffaPickBannerCachedAt = now; ffaPickBannerLocal = localPickOpen; ffaPickBannerSeconds = Mathf.CeilToInt(localPickOpen ? FfaMode.PickSecondsLeft : FfaMode.PickWindowSecondsLeft); ffaPickBannerText = (localPickOpen ? $"PICK YOUR CARD - {ffaPickBannerSeconds}s" : $"Card picks close in {ffaPickBannerSeconds}s"); } } } private static void DrawFfaPickBanner(float now) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(ffaPickBannerText)) { Color color = default(Color); Color color2 = default(Color); if (!ffaPickBannerLocal) { ((Color)(ref color))..ctor(0.08f, 0.08f, 0.09f, 0.66f); ((Color)(ref color2))..ctor(0.62f, 0.62f, 0.64f, 0.9f); } else if (ffaPickBannerSeconds <= 5) { float num = 0.5f + 0.5f * Mathf.Sin(now * 7f); color = Color.Lerp(new Color(0.78f, 0.08f, 0.04f, 0.92f), new Color(0.92f, 0.55f, 0.04f, 0.94f), num); color2 = Color.Lerp(new Color(1f, 0.78f, 0.16f, 1f), Color.white, num); } else { ((Color)(ref color))..ctor(0.12f, 0.2f, 0.31f, 0.88f); ((Color)(ref color2))..ctor(1f, 0.86f, 0.3f, 1f); } Color color3 = GUI.color; GUI.color = color; GUI.DrawTexture(ffaPickBannerRect, (Texture)(object)Texture2D.whiteTexture); GUI.color = color2; GUI.Label(ffaPickBannerRect, ffaPickBannerText, ffaPickBannerStyle); GUI.color = color3; } } private static void SuppressFfaVanillaCounter(float now) { if (now - ffaVanillaCounterCheckedAt < 1f) { return; } ffaVanillaCounterCheckedAt = now; try { UIHandler instance = UIHandler.instance; RoundCounter val = (((Object)(object)instance != (Object)null) ? instance.roundCounterSmall : null); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); } } catch { } } public static void ShowLeaverBanner(string text, bool red) { if (string.IsNullOrEmpty(text)) { return; } bool flag = Time.unscaledTime < _leaverUntil && !string.IsNullOrEmpty(_leaverText); if (flag && _leaverText != text && _leaverText.Length < 160) { _leaverText = _leaverText + " + " + text; } else { _leaverText = text; } _leaverRed = red || (flag && _leaverRed); _leaverUntil = Time.unscaledTime + 9f; try { TaskbarFlash.Flash(); } catch { } } public static void ClearLeaverBanner() { _leaverUntil = 0f; _leaverText = null; _leaverRed = false; } private static void DrawLeaverBanner() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_008b: 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_0090: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown if (Event.current != null && (int)Event.current.type == 7 && !string.IsNullOrEmpty(_leaverText) && !(Time.unscaledTime >= _leaverUntil)) { float num = 34f; Color val = (_leaverRed ? new Color(0.72f, 0.1f, 0.1f, 0f) : new Color(0.82f, 0.52f, 0.08f, 0f)); float num2 = 0.78f + 0.14f * Mathf.Sin(Time.unscaledTime * 5f); float num3 = Mathf.Clamp01(_leaverUntil - Time.unscaledTime); val.a = 0.92f * num2 * num3; GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, num), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val, 0f, 0f); if (_leaverStyle == null) { _leaverStyle = new GUIStyle(GUI.skin.label) { fontSize = 16, fontStyle = (FontStyle)1, richText = true, alignment = (TextAnchor)4, clipping = (TextClipping)0 }; } Color color = GUI.color; GUI.color = new Color(1f, 1f, 1f, Mathf.Clamp01(num3 * 1.5f)); GUI.Label(new Rect(0f, 0f, (float)Screen.width, num), _leaverText, _leaverStyle); GUI.color = color; } } private static void DrawTournamentBanner() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_05d3: Unknown result type (might be due to invalid IL or missing references) //IL_05d8: Unknown result type (might be due to invalid IL or missing references) //IL_05e1: Unknown result type (might be due to invalid IL or missing references) //IL_05e9: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Unknown result type (might be due to invalid IL or missing references) //IL_05fe: Expected O, but got Unknown //IL_064b: Unknown result type (might be due to invalid IL or missing references) //IL_0650: Unknown result type (might be due to invalid IL or missing references) //IL_0652: Unknown result type (might be due to invalid IL or missing references) //IL_0659: Unknown result type (might be due to invalid IL or missing references) //IL_0660: Unknown result type (might be due to invalid IL or missing references) //IL_0667: Unknown result type (might be due to invalid IL or missing references) //IL_0671: Unknown result type (might be due to invalid IL or missing references) //IL_068e: Unknown result type (might be due to invalid IL or missing references) //IL_069f: Unknown result type (might be due to invalid IL or missing references) //IL_06bc: Unknown result type (might be due to invalid IL or missing references) //IL_06ce: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7) { return; } try { ApiClient.ActiveTournamentMatch activeTournamentMatch = null; ApiClient.ActiveTournamentMatch activeTournamentMatch2 = null; List cachedMyActiveTournamentMatches = ApiClient.CachedMyActiveTournamentMatches; if (cachedMyActiveTournamentMatches != null) { foreach (ApiClient.ActiveTournamentMatch item in cachedMyActiveTournamentMatches) { if (item != null && !(item.kind != "sync")) { if (item.status == "ready") { activeTournamentMatch = item; break; } if (item.status == "scheduled" && activeTournamentMatch2 == null) { activeTournamentMatch2 = item; } } } } string text = null; Color black = Color.black; float num = 44f; if (activeTournamentMatch == null && activeTournamentMatch2 != null) { int num2 = -1; if (activeTournamentMatch2.scheduled_seconds_left >= 0) { num2 = Mathf.Max(0, activeTournamentMatch2.scheduled_seconds_left - (int)(Time.realtimeSinceStartup - activeTournamentMatch2.fetched_at_realtime)); } string text2 = ((num2 >= 0) ? $" in {num2 / 60}:{num2 % 60:00}" : " soon"); string text3 = activeTournamentMatch2.opponent_display_name ?? "opponent"; string text4 = (activeTournamentMatch2.my_early_ok ? " (Play Now sent - waiting on them)" : " (both press Play Now in F5 to start early)"); text = "Next tournament match vs " + text3 + text2 + text4; ((Color)(ref black))..ctor(0.12f, 0.25f, 0.45f, 0.85f); num = 26f; } else if (activeTournamentMatch != null) { bool flag = false; bool flag2 = false; try { flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode; Room currentRoom = PhotonNetwork.CurrentRoom; flag2 = flag && currentRoom != null && currentRoom.Name == activeTournamentMatch.photon_room_name; } catch { } if (flag2) { return; } if (!_tourneyBannerAnnounced.Contains(activeTournamentMatch.match_id)) { _tourneyBannerAnnounced.Add(activeTournamentMatch.match_id); try { PlayMatchFoundSound(); } catch { } try { TaskbarFlash.Flash(); } catch { } } int num3 = -1; if (activeTournamentMatch.ready_seconds_left >= 0) { num3 = Mathf.Max(0, activeTournamentMatch.ready_seconds_left - (int)(Time.realtimeSinceStartup - activeTournamentMatch.fetched_at_realtime)); } string text5 = ((num3 >= 0) ? $" {num3 / 60}:{num3 % 60:00}" : ""); string text6 = activeTournamentMatch.opponent_display_name ?? "opponent"; if (flag) { text = "TOURNAMENT MATCH vs " + text6 + " IS WAITING - LEAVE THIS GAME NOW!" + text5; ((Color)(ref black))..ctor(0.72f, 0.1f, 0.1f, 0.93f); } else { text = "TOURNAMENT MATCH vs " + text6 + " - connecting automatically, hold tight..." + text5; ((Color)(ref black))..ctor(0.08f, 0.48f, 0.2f, 0.93f); } } else { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament == null || cachedTournament.kind != "sync" || string.IsNullOrEmpty(cachedTournament.my_signup_id)) { return; } if (cachedTournament.status == "locked" && !string.IsNullOrEmpty(cachedTournament.scheduled_start_ts)) { if (DateTime.TryParse(cachedTournament.scheduled_start_ts, null, DateTimeStyles.RoundtripKind, out var result)) { double totalMinutes = (result.ToUniversalTime() - DateTime.UtcNow).TotalMinutes; if (totalMinutes > 0.0 && totalMinutes <= 15.0) { int num4 = (int)(result.ToUniversalTime() - DateTime.UtcNow).TotalSeconds; text = $"TOURNAMENT STARTS IN {num4 / 60}:{num4 % 60:00} - stay in ROUNDS at the main menu!"; ((Color)(ref black))..ctor(0.75f, 0.6f, 0.05f, 0.93f); } else if (totalMinutes <= 0.0 && totalMinutes > -10.0) { text = "TOURNAMENT STARTING - matches are being created, hold tight..."; ((Color)(ref black))..ctor(0.75f, 0.6f, 0.05f, 0.93f); } } } else if (cachedTournament.status == "running") { bool flag3 = false; try { flag3 = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode; } catch { } if (flag3) { return; } bool flag4 = false; if (cachedTournament.signups != null) { ApiClient.TournamentSignupRow[] signups = cachedTournament.signups; foreach (ApiClient.TournamentSignupRow tournamentSignupRow in signups) { if (tournamentSignupRow != null && tournamentSignupRow.signup_id == cachedTournament.my_signup_id) { flag4 = !tournamentSignupRow.forfeited && tournamentSignupRow.placed_rank <= 0; break; } } } if (!flag4) { return; } text = "Tournament in progress - your next match will connect automatically. Keep ROUNDS open."; ((Color)(ref black))..ctor(0.12f, 0.25f, 0.45f, 0.85f); num = 26f; } } if (text != null) { if (tourneyBannerStyle == null) { tourneyBannerStyle = new GUIStyle(GUI.skin.label) { fontSize = 17, alignment = (TextAnchor)4, fontStyle = (FontStyle)1, richText = false }; } tourneyBannerStyle.fontSize = ((num > 30f) ? 17 : 13); float num5 = ((num > 30f) ? (0.85f + 0.15f * Mathf.PingPong(Time.unscaledTime * 1.6f, 1f)) : 1f); Color color = GUI.color; GUI.color = new Color(black.r, black.g, black.b, black.a * num5); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, num), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0); GUI.color = Color.white; GUI.Label(new Rect(0f, 0f, (float)Screen.width, num), text, tourneyBannerStyle); GUI.color = color; } } catch { } } private static void DrawMapColorToast() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_0161: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown if (Event.current == null || (int)Event.current.type != 7) { return; } try { if (Time.unscaledTime >= MapColorState.ToastUntil) { return; } string toastText = MapColorState.ToastText; if (!string.IsNullOrEmpty(toastText)) { if (mapToastStyle == null) { mapToastStyle = new GUIStyle(GUI.skin.label) { fontSize = 22, alignment = (TextAnchor)4, fontStyle = (FontStyle)1, richText = true }; } float num = 460f; float num2 = 40f; float num3 = ((float)Screen.width - num) / 2f; float num4 = (float)Screen.height - 120f; float num5 = MapColorState.ToastUntil - Time.unscaledTime; float num6 = Mathf.Clamp01(num5 / 0.6f); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.55f * num6); GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)Texture2D.whiteTexture); GUI.color = new Color(1f, 1f, 1f, num6); GUI.Label(new Rect(num3, num4, num, num2), "Map skin: " + toastText + "", mapToastStyle); GUI.color = color; } } catch { } } private static void DrawCustomBetPrompt() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_0209: 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_00d7: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) if (!NativeUI.CustomBetPromptOpen) { return; } try { Event current = Event.current; if (current != null && (int)current.type == 4) { if ((int)current.keyCode == 13 || (int)current.keyCode == 271) { current.Use(); NativeUI.SubmitCustomBet(); return; } if ((int)current.keyCode == 27) { current.Use(); NativeUI.CancelCustomBet(); return; } } if (betPromptStyle == null) { betPromptStyle = new GUIStyle(GUI.skin.textField) { fontSize = 18, alignment = (TextAnchor)4 }; } if (betPromptTitleStyle == null) { betPromptTitleStyle = new GUIStyle(GUI.skin.label) { fontSize = 14, alignment = (TextAnchor)4, richText = true, fontStyle = (FontStyle)1 }; } float num = 340f; float num2 = 128f; float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.color = new Color(0f, 0f, 0f, 0.55f); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture); GUI.color = new Color(0.1f, 0.11f, 0.14f, 0.98f); GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(new Rect(num3, num4 + 6f, num, 22f), "Custom bet on " + NativeUI.CustomBetTargetLabel + "", betPromptTitleStyle); GUI.SetNextControlName("CustomBetAmount"); string text = GUI.TextField(new Rect(num3 + 40f, num4 + 34f, num - 80f, 30f), NativeUI.CustomBetAmountText ?? "", 5, betPromptStyle); StringBuilder stringBuilder = new StringBuilder(text.Length); string text2 = text; foreach (char c in text2) { if (char.IsDigit(c) || c == ',') { stringBuilder.Append(c); } } NativeUI.CustomBetAmountText = stringBuilder.ToString(); GUI.FocusControl("CustomBetAmount"); GUI.Label(new Rect(num3, num4 + 64f, num, 16f), "1 - 2,000 gold", betPromptTitleStyle); if (GUI.Button(new Rect(num3 + 34f, num4 + 86f, 130f, 30f), "Place bet")) { NativeUI.SubmitCustomBet(); } if (GUI.Button(new Rect(num3 + num - 164f, num4 + 86f, 130f, 30f), "Cancel")) { NativeUI.CancelCustomBet(); } } catch { } } private static void DrawLfpPrompt() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_0145: 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_018a: 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_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0227: 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_00d7: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) if (!NativeUI.LfpPromptOpen) { return; } try { Event current = Event.current; if (current != null && (int)current.type == 4) { if ((int)current.keyCode == 13 || (int)current.keyCode == 271) { current.Use(); NativeUI.SubmitLfpPing(); return; } if ((int)current.keyCode == 27) { current.Use(); NativeUI.CancelLfpPing(); return; } } if (lfpFieldStyle == null) { lfpFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 15, alignment = (TextAnchor)3 }; } if (lfpTitleStyle == null) { lfpTitleStyle = new GUIStyle(GUI.skin.label) { fontSize = 14, alignment = (TextAnchor)4, richText = true, fontStyle = (FontStyle)1, clipping = (TextClipping)0 }; } float num = 520f; float num2 = 208f; float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.color = new Color(0f, 0f, 0f, 0.55f); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture); GUI.color = new Color(0.1f, 0.11f, 0.14f, 0.98f); GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(new Rect(num3, num4 + 6f, num, 22f), "Ranked Looking For Player - Discord ping", lfpTitleStyle); GUI.Label(new Rect(num3, num4 + 28f, num, 18f), "Pings the Ranked Looking For Player role (max 1 per hour). Optional message:", lfpTitleStyle); GUI.SetNextControlName("LfpMsgField"); string lfpMessageText = GUI.TextField(new Rect(num3 + 20f, num4 + 52f, num - 40f, 30f), NativeUI.LfpMessageText ?? "", 200, lfpFieldStyle); NativeUI.LfpMessageText = lfpMessageText; GUI.FocusControl("LfpMsgField"); GUI.Label(new Rect(num3, num4 + 90f, num, 18f), "How long are you searching? (shown to players as an expiry)", lfpTitleStyle); float num5 = 70f; float num6 = num3 + (num - (num5 * 4f + 24f)) / 2f; for (int i = 0; i < 4; i++) { GUI.color = ((NativeUI.LfpExpiryIdx == i) ? new Color(0.35f, 0.55f, 0.85f, 1f) : new Color(0.22f, 0.24f, 0.3f, 1f)); GUI.DrawTexture(new Rect(num6 + (float)i * (num5 + 8f), num4 + 112f, num5, 26f), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; if (GUI.Button(new Rect(num6 + (float)i * (num5 + 8f), num4 + 112f, num5, 26f), NativeUI.LfpExpiryLabels[i], lfpTitleStyle)) { NativeUI.LfpExpiryIdx = i; } } if (GUI.Button(new Rect(num3 + 60f, num4 + 156f, 180f, 32f), "Send ping")) { NativeUI.SubmitLfpPing(); } if (GUI.Button(new Rect(num3 + num - 240f, num4 + 156f, 180f, 32f), "Cancel")) { NativeUI.CancelLfpPing(); } } catch { } } private static void DrawCompareSearch() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00a4: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_011a: 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) compareSearchFocused = false; try { if (!NativeUI.IsOpen || NativeUI.CurrentTab != 9) { return; } Rect compareSearchScreenRect = NativeUI.GetCompareSearchScreenRect(); if (!(((Rect)(ref compareSearchScreenRect)).width < 1f) && !(((Rect)(ref compareSearchScreenRect)).height < 1f)) { if (compareSearchStyle == null) { compareSearchStyle = new GUIStyle(GUI.skin.textField) { fontSize = 13, alignment = (TextAnchor)3 }; } if (compareSearchHintStyle == null) { compareSearchHintStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, alignment = (TextAnchor)3, richText = true }; } float num = Mathf.Max(((Rect)(ref compareSearchScreenRect)).height, 22f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref compareSearchScreenRect)).x, ((Rect)(ref compareSearchScreenRect)).y, Mathf.Max(((Rect)(ref compareSearchScreenRect)).width, 200f), num); string text = NativeUI.CompareSearch ?? ""; GUI.SetNextControlName("CmpSearchField"); string text2 = GUI.TextField(val, text, compareSearchStyle); compareSearchFocused = GUI.GetNameOfFocusedControl() == "CmpSearchField"; if (string.IsNullOrEmpty(text2)) { GUI.Label(new Rect(((Rect)(ref val)).x + 6f, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 8f, num), "search players...", compareSearchHintStyle); } if (text2 != text) { NativeUI.CompareSearch = text2; NativeUI.MarkDirty(); } } } catch { } } private static void DrawLeaderboardSearch() { //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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) lbSearchFocused = false; try { if (!NativeUI.IsOpen || NativeUI.CurrentTab != 1) { return; } Rect lbSearchScreenRect = NativeUI.GetLbSearchScreenRect(); if (!(((Rect)(ref lbSearchScreenRect)).width < 1f) && !(((Rect)(ref lbSearchScreenRect)).height < 1f)) { if (compareSearchStyle == null) { compareSearchStyle = new GUIStyle(GUI.skin.textField) { fontSize = 13, alignment = (TextAnchor)3 }; } if (compareSearchHintStyle == null) { compareSearchHintStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, alignment = (TextAnchor)3, richText = true }; } float num = Mathf.Max(((Rect)(ref lbSearchScreenRect)).height, 22f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref lbSearchScreenRect)).x, ((Rect)(ref lbSearchScreenRect)).y, Mathf.Max(((Rect)(ref lbSearchScreenRect)).width, 200f), num); string text = NativeUI.LeaderboardSearch ?? ""; GUI.SetNextControlName("LbSearchField"); string text2 = GUI.TextField(val, text, compareSearchStyle); lbSearchFocused = GUI.GetNameOfFocusedControl() == "LbSearchField"; if (string.IsNullOrEmpty(text2)) { GUI.Label(new Rect(((Rect)(ref val)).x + 6f, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 8f, num), "search players...", compareSearchHintStyle); } if (text2 != text) { NativeUI.LeaderboardSearch = text2; NativeUI.MarkDirty(); } } } catch { } } public static void ClearCardHoverRegions() { _cardHoverRegions.Clear(); _scoreGraphRegions.Clear(); _fpsGraphRegions.Clear(); } internal static float LiveWidthFrac(object txt, RectTransform rt, float fallback) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) try { if (txt == null || (Object)(object)rt == (Object)null) { return fallback; } if (_pPrefWidth == null) { _pPrefWidth = txt.GetType().GetProperty("preferredWidth", BindingFlags.Instance | BindingFlags.Public); } if (_pPrefWidth == null) { return fallback; } Rect rect = rt.rect; float width = ((Rect)(ref rect)).width; if (width <= 0f) { return fallback; } float num = (float)_pPrefWidth.GetValue(txt); if (num <= 0f) { return fallback; } return Mathf.Clamp01(num / width); } catch { return fallback; } } internal static Rect LiveRegionRect(RectTransform rt, Camera cam, float frac, RectTransform clip, Rect fallback) { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)rt == (Object)null) { return fallback; } if (!((Component)rt).gameObject.activeInHierarchy) { return _offscreenRect; } Rect result = ScreenRectOf(rt, cam); if (frac > 0f && frac <= 1f) { ((Rect)(ref result)).width = Mathf.Min(((Rect)(ref result)).width, ((Rect)(ref result)).width * frac + 12f); } if ((Object)(object)clip != (Object)null) { Rect val = ScreenRectOf(clip, cam); float num = Mathf.Max(((Rect)(ref result)).xMin, ((Rect)(ref val)).xMin); float num2 = Mathf.Min(((Rect)(ref result)).xMax, ((Rect)(ref val)).xMax); float num3 = Mathf.Max(((Rect)(ref result)).yMin, ((Rect)(ref val)).yMin); float num4 = Mathf.Min(((Rect)(ref result)).yMax, ((Rect)(ref val)).yMax); if (num2 - num < 1f || num4 - num3 < 1f) { return _offscreenRect; } ((Rect)(ref result))..ctor(num, num3, num2 - num, num4 - num3); } return result; } catch { return fallback; } } private static Rect ScreenRectOf(RectTransform rt, Camera cam) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) rt.GetWorldCorners(_liveCornerBuf); Vector2 val = default(Vector2); Vector2 val2 = default(Vector2); if ((Object)(object)cam == (Object)null) { ((Vector2)(ref val))..ctor(_liveCornerBuf[0].x, _liveCornerBuf[0].y); ((Vector2)(ref val2))..ctor(_liveCornerBuf[2].x, _liveCornerBuf[2].y); } else { Vector3 val3 = cam.WorldToScreenPoint(_liveCornerBuf[0]); Vector3 val4 = cam.WorldToScreenPoint(_liveCornerBuf[2]); ((Vector2)(ref val))..ctor(val3.x, val3.y); ((Vector2)(ref val2))..ctor(val4.x, val4.y); } return new Rect(val.x, val.y, Mathf.Max(1f, val2.x - val.x), Mathf.Max(1f, val2.y - val.y)); } public static void RegisterScoreGraphRegion(Rect screenRect, string timeline, bool won) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) RegisterScoreGraphRegion(screenRect, timeline, won, null, null, -1f, null); } public static void RegisterScoreGraphRegion(Rect screenRect, string timeline, bool won, RectTransform sourceRT, Camera sourceCam, float widthFrac, RectTransform clipRT, object sourceTxt = null) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(timeline)) { _scoreGraphRegions.Add(new ScoreGraphRegion { screenRect = screenRect, timeline = timeline, won = won, sourceRT = sourceRT, sourceCam = sourceCam, widthFrac = widthFrac, clipRT = clipRT, sourceTxt = sourceTxt }); } } private static void GuiLine(Vector2 a, Vector2 b, Color color, float width) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0059: 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_0062: 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_0078: 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_008f: 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) Color color2 = GUI.color; GUI.color = color; float num = Vector2.Distance(a, b); if (num < 0.5f) { GUI.color = color2; return; } float num2 = Mathf.Atan2(b.y - a.y, b.x - a.x) * 57.29578f; Matrix4x4 matrix = GUI.matrix; GUIUtility.RotateAroundPivot(num2, a); GUI.DrawTexture(new Rect(a.x, a.y - width / 2f, num, width), (Texture)(object)Texture2D.whiteTexture); GUI.matrix = matrix; GUI.color = color2; } private static void DrawScoreHoverGraph() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Expected O, but got Unknown //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_0512: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_0534: Unknown result type (might be due to invalid IL or missing references) //IL_0579: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7 || !NativeUI.IsOpen || (NativeUI.CurrentTab != 0 && NativeUI.CurrentTab != 8) || _scoreGraphRegions.Count == 0) { return; } Vector2 val = Vector2.op_Implicit(Input.mousePosition); ScoreGraphRegion? scoreGraphRegion = null; for (int num = _scoreGraphRegions.Count - 1; num >= 0; num--) { ScoreGraphRegion value = _scoreGraphRegions[num]; float frac = LiveWidthFrac(value.sourceTxt, value.sourceRT, value.widthFrac); Rect val2 = LiveRegionRect(value.sourceRT, value.sourceCam, frac, value.clipRT, value.screenRect); if (((Rect)(ref val2)).Contains(val)) { scoreGraphRegion = value; break; } } if (!scoreGraphRegion.HasValue) { return; } string[] array = scoreGraphRegion.Value.timeline.Split(','); int num2 = array.Length + 1; if (num2 < 3) { return; } int[] array2 = new int[num2]; int[] array3 = new int[num2]; int num3 = 1; for (int i = 1; i < num2; i++) { string[] array4 = array[i - 1].Split(':'); if (array4.Length != 2 || !int.TryParse(array4[0], out var result) || !int.TryParse(array4[1], out var result2)) { return; } array2[i] = result; array3[i] = result2; if (result > num3) { num3 = result; } if (result2 > num3) { num3 = result2; } } if (_scoreGraphLbl == null) { _scoreGraphLbl = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, clipping = (TextClipping)0, wordWrap = false }; } float num4 = 280f; float num5 = 178f; float num6 = 30f; float num7 = Mathf.Min(val.x + 18f, (float)Screen.width - num4 - 8f); float num8 = Mathf.Clamp((float)Screen.height - val.y - num5 / 2f, 8f, (float)Screen.height - num5 - 8f); GUI.DrawTexture(new Rect(num7 - 4f, num8 - 4f, num4 + 8f, num5 + 8f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.93f), 0f, 0f); GUI.Label(new Rect(num7 + 8f, num8 + 2f, num4 - 16f, 24f), "Scoring history you vs opponent", _scoreGraphLbl); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(num7 + num6, num8 + 30f, num4 - num6 - 10f, num5 - 30f - 26f); for (int j = 0; j <= num3; j += 2) { float num9 = ((Rect)(ref val3)).yMax - ((Rect)(ref val3)).height * (float)j / (float)num3; GuiLine(new Vector2(((Rect)(ref val3)).xMin, num9), new Vector2(((Rect)(ref val3)).xMax, num9), new Color(1f, 1f, 1f, 0.08f), 1f); GUI.Label(new Rect(num7 + 4f, num9 - 11f, num6 - 6f, 22f), $"{j / 2}", _scoreGraphLbl); } for (int k = 1; k < num2; k++) { float num10 = ((Rect)(ref val3)).xMin + ((Rect)(ref val3)).width * (float)(k - 1) / (float)(num2 - 1); float num11 = ((Rect)(ref val3)).xMin + ((Rect)(ref val3)).width * (float)k / (float)(num2 - 1); float num12 = ((Rect)(ref val3)).yMax - ((Rect)(ref val3)).height * (float)array2[k - 1] / (float)num3; float num13 = ((Rect)(ref val3)).yMax - ((Rect)(ref val3)).height * (float)array2[k] / (float)num3; float num14 = ((Rect)(ref val3)).yMax - ((Rect)(ref val3)).height * (float)array3[k - 1] / (float)num3; float num15 = ((Rect)(ref val3)).yMax - ((Rect)(ref val3)).height * (float)array3[k] / (float)num3; GuiLine(new Vector2(num10, num14), new Vector2(num11, num15), new Color(0.87f, 0.47f, 0.47f, 0.95f), 2f); GuiLine(new Vector2(num10, num12), new Vector2(num11, num13), new Color(0.4f, 0.87f, 0.4f, 0.95f), 2f); } GUI.Label(new Rect(num7 + 8f, num8 + num5 - 24f, num4 - 16f, 22f), "rounds on the left - each step is one point scored", _scoreGraphLbl); } public static void RegisterFpsGraphRegion(Rect screenRect, string mySeries, string oppSeries, bool isPing, RectTransform sourceRT, Camera sourceCam, float widthFrac, RectTransform clipRT, object sourceTxt = null, string pointTimes = null, string pointTimeline = null, float myStep = 0f) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(mySeries) || !string.IsNullOrEmpty(oppSeries)) { _fpsGraphRegions.Add(new FpsGraphRegion { screenRect = screenRect, mySeries = (mySeries ?? ""), oppSeries = (oppSeries ?? ""), kind = (isPing ? 1 : 0), myStep = ((myStep > 0f) ? myStep : (isPing ? 3f : 5f)), pointTimes = pointTimes, pointTimeline = pointTimeline, sourceRT = sourceRT, sourceCam = sourceCam, widthFrac = widthFrac, clipRT = clipRT, sourceTxt = sourceTxt }); } } public static void RegisterPairGraphRegion(Rect screenRect, string pairSeries, bool isBlock, bool subjectIsOpp, RectTransform sourceRT, Camera sourceCam, float widthFrac, RectTransform clipRT, object sourceTxt, string pointTimes, string pointTimeline) { //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) if (!string.IsNullOrEmpty(pairSeries) && pairSeries.IndexOf(':') >= 0) { _fpsGraphRegions.Add(new FpsGraphRegion { screenRect = screenRect, mySeries = pairSeries, oppSeries = "", kind = (isBlock ? 3 : 2), myStep = 3f, subjectIsOpp = subjectIsOpp, pointTimes = pointTimes, pointTimeline = pointTimeline, sourceRT = sourceRT, sourceCam = sourceCam, widthFrac = widthFrac, clipRT = clipRT, sourceTxt = sourceTxt }); } } public static void RegisterPlayerComboRegion(Rect screenRect, string fpsSeries, string pingSeries, string hitPairs, string blockPairs, string playerName, bool isRightTeam, RectTransform sourceRT, Camera sourceCam, float widthFrac, RectTransform clipRT, object sourceTxt) { //IL_003b: 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) if (!string.IsNullOrEmpty(fpsSeries) || !string.IsNullOrEmpty(pingSeries) || !string.IsNullOrEmpty(hitPairs) || !string.IsNullOrEmpty(blockPairs)) { _fpsGraphRegions.Add(new FpsGraphRegion { screenRect = screenRect, mySeries = (fpsSeries ?? ""), oppSeries = (pingSeries ?? ""), kind = 4, myStep = 3f, subjectIsOpp = isRightTeam, pairHit = hitPairs, pairBlock = blockPairs, subjectLabel = playerName, sourceRT = sourceRT, sourceCam = sourceCam, widthFrac = widthFrac, clipRT = clipRT, sourceTxt = sourceTxt }); } } private static int[] ParseFpsSeries(string csv) { if (string.IsNullOrEmpty(csv)) { return null; } string[] array = csv.Split(','); List list = new List(array.Length); string[] array2 = array; foreach (string s in array2) { if (int.TryParse(s, out var result) && result > 0) { list.Add(result); } } return (list.Count >= 2) ? list.ToArray() : null; } private static bool ParsePairSeries(string csv, out int[] first, out int[] second) { first = null; second = null; if (string.IsNullOrEmpty(csv)) { return false; } string[] array = csv.Split(','); List list = new List(array.Length + 1) { 0 }; List list2 = new List(array.Length + 1) { 0 }; string[] array2 = array; foreach (string text in array2) { int num = text.IndexOf(':'); if (num > 0 && int.TryParse(text.Substring(0, num), out var result) && int.TryParse(text.Substring(num + 1), out var result2)) { list.Add(result); list2.Add(result2); } } if (list.Count < 3) { return false; } first = list.ToArray(); second = list2.ToArray(); return true; } private static float DrawPointMarkers(Rect plot, float maxT, string pointTimes, string pointTimeline, bool drawNow) { //IL_0147: 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) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(pointTimes) || string.IsNullOrEmpty(pointTimeline)) { return 0f; } string[] array = pointTimes.Split(','); string[] array2 = pointTimeline.Split(','); int num = Mathf.Min(array.Length, array2.Length); float num2 = 0f; int num3 = 0; int num4 = 0; for (int i = 0; i < num; i++) { if (!int.TryParse(array[i], out var result)) { continue; } if ((float)result > num2) { num2 = result; } if (!drawNow) { } int num5 = array2[i].IndexOf(':'); if (num5 <= 0 || !int.TryParse(array2[i].Substring(0, num5), out var result2) || !int.TryParse(array2[i].Substring(num5 + 1), out var result3)) { continue; } bool flag = result2 > num3; bool flag2 = result3 > num4; num3 = result2; num4 = result3; if (drawNow && maxT > 0f) { float num6 = ((Rect)(ref plot)).xMin + ((Rect)(ref plot)).width * Mathf.Clamp01((float)result / maxT); if (flag) { GuiLine(new Vector2(num6, ((Rect)(ref plot)).yMin), new Vector2(num6, ((Rect)(ref plot)).yMax), new Color(0.3f, 0.85f, 0.3f, 0.35f), 2f); } if (flag2) { GuiLine(new Vector2(num6 + (flag ? 2f : 0f), ((Rect)(ref plot)).yMin), new Vector2(num6 + (flag ? 2f : 0f), ((Rect)(ref plot)).yMax), new Color(0.9f, 0.3f, 0.3f, 0.35f), 2f); } } } return num2; } private static void DrawFpsHoverGraph() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_00e3: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_053d: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Unknown result type (might be due to invalid IL or missing references) //IL_0595: Unknown result type (might be due to invalid IL or missing references) //IL_05d5: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Unknown result type (might be due to invalid IL or missing references) //IL_064f: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7 || !NativeUI.IsOpen || (NativeUI.CurrentTab != 0 && NativeUI.CurrentTab != 8) || _fpsGraphRegions.Count == 0) { return; } Vector2 val = Vector2.op_Implicit(Input.mousePosition); FpsGraphRegion? fpsGraphRegion = null; for (int num = _fpsGraphRegions.Count - 1; num >= 0; num--) { FpsGraphRegion value = _fpsGraphRegions[num]; float frac = LiveWidthFrac(value.sourceTxt, value.sourceRT, value.widthFrac); Rect val2 = LiveRegionRect(value.sourceRT, value.sourceCam, frac, value.clipRT, value.screenRect); if (((Rect)(ref val2)).Contains(val)) { fpsGraphRegion = value; break; } } if (!fpsGraphRegion.HasValue) { return; } if (_scoreGraphLbl == null) { _scoreGraphLbl = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, clipping = (TextClipping)0, wordWrap = false }; } int kind = fpsGraphRegion.Value.kind; if (kind == 4) { DrawPlayerComboGraph(fpsGraphRegion.Value, val); return; } if (kind >= 2) { DrawPairHoverGraph(fpsGraphRegion.Value, val); return; } bool flag = kind == 1; float myStep = fpsGraphRegion.Value.myStep; int[] array = ParseFpsSeries(fpsGraphRegion.Value.mySeries); int[] array2 = ParseFpsSeries(fpsGraphRegion.Value.oppSeries); if (array == null && array2 == null) { return; } float num2 = 360f; float num3 = 230f; float num4 = 44f; float num5 = Mathf.Min(val.x + 18f, (float)Screen.width - num2 - 8f); float num6 = Mathf.Clamp((float)Screen.height - val.y - num3 / 2f, 8f, (float)Screen.height - num3 - 8f); GUI.DrawTexture(new Rect(num5 - 4f, num6 - 4f, num2 + 8f, num3 + 8f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.93f), 0f, 0f); string text = (flag ? "Latency (ms)" : "FPS"); GUI.Label(new Rect(num5 + 8f, num6 + 2f, num2 - 16f, 24f), "" + text + " over the match you vs opponent", _scoreGraphLbl); float maxT = 1f; if (array != null) { maxT = Mathf.Max(maxT, (float)(array.Length - 1) * myStep); } if (array2 != null) { maxT = Mathf.Max(maxT, (float)(array2.Length - 1) * 3f); } float num7 = DrawPointMarkers(default(Rect), 0f, fpsGraphRegion.Value.pointTimes, fpsGraphRegion.Value.pointTimeline, drawNow: false); if (num7 > maxT) { maxT = num7; } int maxV = (flag ? 60 : 90); if (array != null) { int[] array3 = array; foreach (int num8 in array3) { if (num8 > maxV) { maxV = num8; } } } if (array2 != null) { int[] array4 = array2; foreach (int num9 in array4) { if (num9 > maxV) { maxV = num9; } } } maxV = Mathf.CeilToInt((float)maxV * 1.08f); Rect plot = new Rect(num5 + num4, num6 + 34f, num2 - num4 - 12f, num3 - 34f - 14f); int[] array5 = new int[15] { 10, 20, 25, 30, 50, 60, 100, 120, 150, 200, 250, 300, 500, 600, 1000 }; int num10 = array5[^1]; int[] array6 = array5; foreach (int num11 in array6) { if (maxV / num11 <= 6) { num10 = num11; break; } } for (int l = num10; l <= maxV; l += num10) { float num12 = ((Rect)(ref plot)).yMax - ((Rect)(ref plot)).height * (float)l / (float)maxV; GuiLine(new Vector2(((Rect)(ref plot)).xMin, num12), new Vector2(((Rect)(ref plot)).xMax, num12), new Color(1f, 1f, 1f, 0.08f), 1f); GUI.Label(new Rect(num5 + 2f, num12 - 11f, num4 - 6f, 22f), $"{l}", _scoreGraphLbl); } DrawPointMarkers(plot, maxT, fpsGraphRegion.Value.pointTimes, fpsGraphRegion.Value.pointTimeline, drawNow: true); Action action = delegate(int[] vals, float step, Color col) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) if (vals != null) { for (int m = 1; m < vals.Length; m++) { float num13 = ((Rect)(ref plot)).xMin + ((Rect)(ref plot)).width * ((float)(m - 1) * step / maxT); float num14 = ((Rect)(ref plot)).xMin + ((Rect)(ref plot)).width * ((float)m * step / maxT); float num15 = ((Rect)(ref plot)).yMax - ((Rect)(ref plot)).height * (float)Mathf.Min(vals[m - 1], maxV) / (float)maxV; float num16 = ((Rect)(ref plot)).yMax - ((Rect)(ref plot)).height * (float)Mathf.Min(vals[m], maxV) / (float)maxV; GuiLine(new Vector2(num13, num15), new Vector2(num14, num16), col, 2f); } } }; action(array2, 3f, new Color(0.9f, 0.6f, 0.53f, 0.95f)); action(array, myStep, new Color(0.6f, 0.7f, 0.9f, 0.95f)); } private static void DrawPairHoverGraph(FpsGraphRegion reg, Vector2 mp) { //IL_0069: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_0133: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_048b: Unknown result type (might be due to invalid IL or missing references) //IL_04b8: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Unknown result type (might be due to invalid IL or missing references) //IL_05d3: Unknown result type (might be due to invalid IL or missing references) //IL_05e0: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_057f: Unknown result type (might be due to invalid IL or missing references) //IL_0685: Unknown result type (might be due to invalid IL or missing references) if (!ParsePairSeries(reg.mySeries, out var first, out var second)) { return; } bool flag = reg.kind == 3; bool subjectIsOpp = reg.subjectIsOpp; Color arg = (subjectIsOpp ? new Color(0.95f, 0.55f, 0.45f, 0.95f) : new Color(0.55f, 0.75f, 0.98f, 0.95f)); Color arg2 = (subjectIsOpp ? new Color(0.7f, 0.42f, 0.38f, 0.8f) : new Color(0.42f, 0.52f, 0.7f, 0.8f)); string text = (subjectIsOpp ? "opponent" : "you"); string text2 = (subjectIsOpp ? "#F28C73" : "#8CBFFA"); string text3 = (subjectIsOpp ? "#B36B61" : "#6B85B3"); if (_scoreGraphLbl == null) { _scoreGraphLbl = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, clipping = (TextClipping)0, wordWrap = false }; } float num = 360f; float num2 = 230f; float num3 = 44f; float num4 = (flag ? 34f : 12f); float num5 = Mathf.Min(mp.x + 18f, (float)Screen.width - num - 8f); float num6 = Mathf.Clamp((float)Screen.height - mp.y - num2 / 2f, 8f, (float)Screen.height - num2 - 8f); GUI.DrawTexture(new Rect(num5 - 4f, num6 - 4f, num + 8f, num2 + 8f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.93f), 0f, 0f); string text4 = (flag ? ("Block — " + text + " dmg taken · blocks") : ("Hit — " + text + " shots fired · hits")); GUI.Label(new Rect(num5 + 8f, num6 + 2f, num - 16f, 24f), text4, _scoreGraphLbl); int num7 = first.Length; float maxT = Mathf.Max(1f, (float)(num7 - 1) * 3f); float num8 = DrawPointMarkers(default(Rect), 0f, reg.pointTimes, reg.pointTimeline, drawNow: false); if (num8 > maxT) { maxT = num8; } int num9 = 1; int num10 = 1; int[] array = first; foreach (int num11 in array) { if (num11 > num9) { num9 = num11; } } int[] array2 = second; foreach (int num12 in array2) { if (num12 > num10) { num10 = num12; } } num9 = Mathf.CeilToInt((float)num9 * 1.08f); int num13 = (flag ? Mathf.CeilToInt((float)num10 * 1.08f) : num9); if (num13 < 1) { num13 = 1; } Rect plot = new Rect(num5 + num3, num6 + 34f, num - num3 - num4, num2 - 34f - 26f); int[] array3 = new int[14] { 1, 2, 5, 10, 20, 25, 50, 100, 150, 200, 300, 500, 1000, 2000 }; int num14 = array3[^1]; int[] array4 = array3; foreach (int num15 in array4) { if (num9 / num15 <= 6) { num14 = num15; break; } } for (int l = num14; l <= num9; l += num14) { float num16 = ((Rect)(ref plot)).yMax - ((Rect)(ref plot)).height * (float)l / (float)num9; GuiLine(new Vector2(((Rect)(ref plot)).xMin, num16), new Vector2(((Rect)(ref plot)).xMax, num16), new Color(1f, 1f, 1f, 0.08f), 1f); GUI.Label(new Rect(num5 + 2f, num16 - 11f, num3 - 6f, 22f), $"{l}", _scoreGraphLbl); } if (flag) { GUI.Label(new Rect(((Rect)(ref plot)).xMax + 4f, ((Rect)(ref plot)).yMin - 11f, num4 - 4f, 22f), $"{num13}", _scoreGraphLbl); GUI.Label(new Rect(((Rect)(ref plot)).xMax + 4f, ((Rect)(ref plot)).yMax - 11f, num4 - 4f, 22f), "0", _scoreGraphLbl); } DrawPointMarkers(plot, maxT, reg.pointTimes, reg.pointTimeline, drawNow: true); Action action = delegate(int[] vals, int maxV, Color col) { //IL_00ac: 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_00b9: Unknown result type (might be due to invalid IL or missing references) for (int m = 1; m < vals.Length; m++) { float num18 = ((Rect)(ref plot)).xMin + ((Rect)(ref plot)).width * ((float)(m - 1) * 3f / maxT); float num19 = ((Rect)(ref plot)).xMin + ((Rect)(ref plot)).width * ((float)m * 3f / maxT); float num20 = ((Rect)(ref plot)).yMax - ((Rect)(ref plot)).height * (float)Mathf.Min(vals[m - 1], maxV) / (float)maxV; float num21 = ((Rect)(ref plot)).yMax - ((Rect)(ref plot)).height * (float)Mathf.Min(vals[m], maxV) / (float)maxV; GuiLine(new Vector2(num18, num20), new Vector2(num19, num21), col, 2f); } }; action(first, num9, arg2); action(second, num13, arg); string text5; if (flag) { text5 = $"{first[num7 - 1]} dmg taken · {second[num7 - 1]} successful blocks · markers = points scored"; } else { float num17 = ((first[num7 - 1] > 0) ? (100f * (float)second[num7 - 1] / (float)first[num7 - 1]) : 0f); text5 = $"{first[num7 - 1]} fired · {second[num7 - 1]} hit · {num17:F0}% · markers = points scored"; } GUI.Label(new Rect(num5 + 8f, num6 + num2 - 22f, num - 16f, 22f), text5, _scoreGraphLbl); } private static void DrawPlayerComboGraph(FpsGraphRegion reg, Vector2 mp) { //IL_009a: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0218: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) int[] array = ParseFpsSeries(reg.mySeries); int[] array2 = ParseFpsSeries(reg.oppSeries); int[] first = null; int[] second = null; int[] first2 = null; int[] second2 = null; ParsePairSeries(reg.pairHit, out first, out second); ParsePairSeries(reg.pairBlock, out first2, out second2); if (array == null && array2 == null && first == null && first2 == null) { return; } bool subjectIsOpp = reg.subjectIsOpp; Color val = (subjectIsOpp ? new Color(1f, 0.69f, 0.53f, 0.95f) : new Color(0.55f, 0.8f, 1f, 0.95f)); Color arg = (subjectIsOpp ? new Color(0.72f, 0.5f, 0.4f, 0.85f) : new Color(0.42f, 0.58f, 0.72f, 0.85f)); string text = (subjectIsOpp ? "#FFB086" : "#8CCFFF"); if (_scoreGraphLbl == null) { _scoreGraphLbl = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, clipping = (TextClipping)0, wordWrap = false }; } float num = 430f; float num2 = 306f; float num3 = Mathf.Min(mp.x + 18f, (float)Screen.width - num - 8f); float num4 = Mathf.Clamp((float)Screen.height - mp.y - num2 / 2f, 8f, (float)Screen.height - num2 - 8f); GUI.DrawTexture(new Rect(num3 - 4f, num4 - 4f, num + 8f, num2 + 8f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.93f), 0f, 0f); GUI.Label(new Rect(num3 + 8f, num4 + 2f, num - 16f, 22f), "" + reg.subjectLabel + " — match telemetry", _scoreGraphLbl); float num5 = (num - 30f) / 2f; float num6 = (num2 - 40f) / 2f; Action action = delegate(Rect r, string title, int[] s1, int[] s2, Color c1, Color c2, string foot) { //IL_0027: 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_0072: 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_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y - 4f, ((Rect)(ref r)).width, 18f), title, _scoreGraphLbl); Rect plot = new Rect(((Rect)(ref r)).x + 26f, ((Rect)(ref r)).y + 16f, ((Rect)(ref r)).width - 30f, ((Rect)(ref r)).height - 40f); int maxV = 1; if (s1 != null) { foreach (int num14 in s1) { if (num14 > maxV) { maxV = num14; } } } if (s2 != null) { foreach (int num15 in s2) { if (num15 > maxV) { maxV = num15; } } } maxV = Mathf.CeilToInt((float)maxV * 1.08f); GuiLine(new Vector2(((Rect)(ref plot)).xMin, ((Rect)(ref plot)).yMax), new Vector2(((Rect)(ref plot)).xMax, ((Rect)(ref plot)).yMax), new Color(1f, 1f, 1f, 0.15f), 1f); GuiLine(new Vector2(((Rect)(ref plot)).xMin, ((Rect)(ref plot)).yMin), new Vector2(((Rect)(ref plot)).xMax, ((Rect)(ref plot)).yMin), new Color(1f, 1f, 1f, 0.06f), 1f); GUI.Label(new Rect(((Rect)(ref r)).x - 2f, ((Rect)(ref plot)).yMin - 10f, 30f, 20f), $"{maxV}", _scoreGraphLbl); int nMax = Mathf.Max((s1 != null) ? s1.Length : 0, (s2 != null) ? s2.Length : 0); if (nMax >= 2) { Action action2 = delegate(int[] vals, Color col) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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) if (vals != null && vals.Length >= 2) { for (int k = 1; k < vals.Length; k++) { float num16 = ((Rect)(ref plot)).xMin + ((Rect)(ref plot)).width * (float)(k - 1) / (float)(nMax - 1); float num17 = ((Rect)(ref plot)).xMin + ((Rect)(ref plot)).width * (float)k / (float)(nMax - 1); float num18 = ((Rect)(ref plot)).yMax - ((Rect)(ref plot)).height * (float)Mathf.Min(vals[k - 1], maxV) / (float)maxV; float num19 = ((Rect)(ref plot)).yMax - ((Rect)(ref plot)).height * (float)Mathf.Min(vals[k], maxV) / (float)maxV; GuiLine(new Vector2(num16, num18), new Vector2(num17, num19), col, 2f); } } }; action2(s1, c1); action2(s2, c2); if (!string.IsNullOrEmpty(foot)) { GUI.Label(new Rect(((Rect)(ref r)).x + 4f, ((Rect)(ref r)).yMax - 18f, ((Rect)(ref r)).width - 8f, 18f), foot, _scoreGraphLbl); } } }; string arg2 = ((first != null && first.Length > 1) ? $"{first[^1]} fired / {second[^1]} hit ({((first[^1] > 0) ? (100f * (float)second[^1] / (float)first[^1]) : 0f):F0}%)" : ""); string arg3 = ((first2 != null && first2.Length > 1) ? $"{first2[^1]} dmg / {second2[^1]} blocks" : ""); int[] array3 = null; if (first2 != null && second2 != null) { int num7 = 1; int num8 = 1; int[] array4 = first2; foreach (int num10 in array4) { if (num10 > num7) { num7 = num10; } } int[] array5 = second2; foreach (int num12 in array5) { if (num12 > num8) { num8 = num12; } } array3 = new int[second2.Length]; for (int num13 = 0; num13 < second2.Length; num13++) { array3[num13] = (int)((long)second2[num13] * (long)num7 / num8); } } action(new Rect(num3 + 10f, num4 + 40f, num5, num6), "FPS", array, null, val, val, ""); action(new Rect(num3 + 20f + num5, num4 + 40f, num5, num6), "Ping (ms)", array2, null, val, val, ""); action(new Rect(num3 + 10f, num4 + 44f + num6, num5, num6), "Shots fired vs hits", first, second, arg, val, arg2); action(new Rect(num3 + 20f + num5, num4 + 44f + num6, num5, num6), "Dmg taken vs blocks", first2, array3, arg, val, arg3); } public static void RegisterCardHoverRegion(Rect screenRect, string fullCardLine, bool isOpponent) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) RegisterCardHoverRegion(screenRect, fullCardLine, isOpponent, null, null, null, null, -1f, null); } public static void RegisterCardHoverRegion(Rect screenRect, string fullCardLine, bool isOpponent, string titleOverride, string bodyOverride) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) RegisterCardHoverRegion(screenRect, fullCardLine, isOpponent, titleOverride, bodyOverride, null, null, -1f, null); } public static void RegisterCardHoverRegion(Rect screenRect, string fullCardLine, bool isOpponent, string titleOverride, string bodyOverride, RectTransform sourceRT, Camera sourceCam, float widthFrac, RectTransform clipRT, object sourceTxt = null) { //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 (!string.IsNullOrEmpty(fullCardLine) || !string.IsNullOrEmpty(bodyOverride)) { _cardHoverRegions.Add(new CardHoverRegion { screenRect = screenRect, fullCardLine = fullCardLine, isOpponent = isOpponent, titleOverride = titleOverride, bodyOverride = bodyOverride, sourceRT = sourceRT, sourceCam = sourceCam, widthFrac = widthFrac, clipRT = clipRT, sourceTxt = sourceTxt }); } } private static void DrawCardHoverTooltip() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: 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_0146: 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_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_0176: 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_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_0585: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7 || !NativeUI.IsOpen || (NativeUI.CurrentTab != 0 && NativeUI.CurrentTab != 8) || _cardHoverRegions.Count == 0) { return; } Vector2 val = Vector2.op_Implicit(Input.mousePosition); CardHoverRegion? cardHoverRegion = null; for (int num = _cardHoverRegions.Count - 1; num >= 0; num--) { CardHoverRegion value = _cardHoverRegions[num]; float frac = LiveWidthFrac(value.sourceTxt, value.sourceRT, value.widthFrac); Rect val2 = LiveRegionRect(value.sourceRT, value.sourceCam, frac, value.clipRT, value.screenRect); if (((Rect)(ref val2)).Contains(val)) { cardHoverRegion = value; break; } } if (!cardHoverRegion.HasValue) { return; } if (_cardTipTitleStyle == null) { _cardTipTitleStyle = new GUIStyle(GUI.skin.label) { fontSize = 13, richText = true, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; _cardTipBodyStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, wordWrap = true, alignment = (TextAnchor)0 }; } string text; int num2; if (cardHoverRegion.Value.bodyOverride != null) { text = cardHoverRegion.Value.bodyOverride; num2 = 1; for (int i = 0; i < text.Length; i++) { if (text[i] == '\n') { num2++; } } } else { string fullCardLine = cardHoverRegion.Value.fullCardLine; string[] array; try { array = fullCardLine.Split(','); } catch { array = new string[1] { fullCardLine }; } num2 = 0; StringBuilder stringBuilder = new StringBuilder(); string[] array2 = array; foreach (string text2 in array2) { string value2 = text2.Trim(); if (!string.IsNullOrEmpty(value2)) { num2++; stringBuilder.Append("• ").Append(value2).Append('\n'); } } text = stringBuilder.ToString().TrimEnd(); } string text3 = ((cardHoverRegion.Value.titleOverride != null) ? cardHoverRegion.Value.titleOverride : (cardHoverRegion.Value.isOpponent ? "Opponent's picks" : "Your picks")); bool flag = !string.IsNullOrEmpty(text3); float num3 = 260f; float num4 = 16f; float num5 = (flag ? 22f : 6f); float num6 = num5 + (float)num2 * num4 + 8f; float num7 = Input.mousePosition.x + 14f; float num8 = (float)Screen.height - Input.mousePosition.y + 14f; if (num7 + num3 > (float)Screen.width) { num7 = (float)Screen.width - num3 - 4f; } if (num8 + num6 > (float)Screen.height) { num8 = (float)Screen.height - num6 - 4f; } if (num8 < 4f) { num8 = 4f; } GUI.DrawTexture(new Rect(num7, num8, num3, num6), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.06f, 0.07f, 0.1f, 0.97f), 0f, 0f); Color val3 = (cardHoverRegion.Value.isOpponent ? new Color(0.95f, 0.55f, 0.45f, 0.9f) : new Color(0.4f, 0.7f, 1f, 0.9f)); GUI.DrawTexture(new Rect(num7, num8, num3, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val3, 0f, 0f); GUI.DrawTexture(new Rect(num7, num8 + num6 - 1f, num3, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val3, 0f, 0f); GUI.DrawTexture(new Rect(num7, num8, 1f, num6), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val3, 0f, 0f); GUI.DrawTexture(new Rect(num7 + num3 - 1f, num8, 1f, num6), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val3, 0f, 0f); if (flag) { GUI.Label(new Rect(num7 + 8f, num8 + 6f, num3 - 16f, 18f), "" + text3 + "", _cardTipTitleStyle); } GUI.Label(new Rect(num7 + 8f, num8 + num5, num3 - 16f, num6 - num5 - 4f), "" + text + "", _cardTipBodyStyle); } private static void DrawMatchFoundStuckOverlay() { //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0056: 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_006b: Expected O, but got Unknown //IL_0075: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown if (!GameStateWatcher.ShouldShowMatchFoundStuckOverlay || NativeUI.IsOpen) { return; } if (stuckTitleStyle == null) { stuckTitleStyle = new GUIStyle(GUI.skin.label) { fontSize = 17, richText = true, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; stuckTextStyle = new GUIStyle(GUI.skin.label) { fontSize = 13, richText = true, wordWrap = true, alignment = (TextAnchor)0 }; stuckButtonStyle = new GUIStyle(GUI.skin.button) { fontSize = 14 }; } float num = 560f; float num2 = 132f; float num3 = ((float)Screen.width - num) / 2f; float num4 = 60f; GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.1f, 0.06f, 0.06f, 0.94f), 0f, 0f); Color val = default(Color); ((Color)(ref val))..ctor(0.95f, 0.65f, 0.2f, 0.9f); GUI.DrawTexture(new Rect(num3, num4, num, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val, 0f, 0f); GUI.DrawTexture(new Rect(num3, num4 + num2 - 1f, num, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val, 0f, 0f); GUI.DrawTexture(new Rect(num3, num4, 1f, num2), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val, 0f, 0f); GUI.DrawTexture(new Rect(num3 + num - 1f, num4, 1f, num2), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val, 0f, 0f); int secondsInUnstartedRoom = GameStateWatcher.SecondsInUnstartedRoom; GUI.Label(new Rect(num3 + 14f, num4 + 8f, num - 28f, 22f), "Match-found screen might be stuck", stuckTitleStyle); GUI.Label(new Rect(num3 + 14f, num4 + 32f, num - 28f, 50f), $"In this Photon room for {secondsInUnstartedRoom}s with no match started. " + "Vanilla matchmaking sometimes hangs here when one player has ROUNDS unfocused. Click into the ROUNDS window first and try space again, or use the escape hatch below.", stuckTextStyle); if (GUI.Button(new Rect(num3 + 14f, num4 + num2 - 38f, 220f, 28f), "Force exit room", stuckButtonStyle)) { try { PhotonNetwork.LeaveRoom(true); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[STUCK] LeaveRoom failed: " + ex.Message)); } GameStateWatcher.DismissMatchFoundStuckOverlay(); } if (GUI.Button(new Rect(num3 + num - 174f, num4 + num2 - 38f, 160f, 28f), "Dismiss (1 min)", stuckButtonStyle)) { GameStateWatcher.DismissMatchFoundStuckOverlay(); } } private static void EnsureBugLogLayout(string reportId, string meta, string log, float width) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown string text = reportId + "|" + (meta?.Length ?? 0) + "|" + (log?.Length ?? 0); if (text == bugAdminLayoutKey && Mathf.Approximately(width, bugAdminLayoutW)) { return; } bugAdminLayoutKey = text; bugAdminLayoutW = width; bugAdminLogChunks = new List(); bugAdminLogHeights = new List(); bugAdminLogTotalH = 0f; try { bugAdminMetaH = bugAdminDetailStyle.CalcHeight(new GUIContent(meta ?? ""), width) + 8f; if (!string.IsNullOrEmpty(log)) { for (int i = 0; i < log.Length; i += 12000) { string text2 = log.Substring(i, Math.Min(12000, log.Length - i)); float num = bugAdminLogStyle.CalcHeight(new GUIContent(text2), width); bugAdminLogChunks.Add(text2); bugAdminLogHeights.Add(num); bugAdminLogTotalH += num; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BUG-ADMIN] log layout: " + ex.Message)); bugAdminMetaH = 400f; } } public static void OpenBugReportAdminViewer() { bugAdminOpen = true; bugAdminSelectedId = null; ApiClient.CachedBugReportDetail = null; bugAdminLoading = true; bugAdminCommentDraft = ""; bugAdminActionStatus = ""; string localSteamId = MatchTracker.LocalSteamId; ApiClient.FetchBugReports(localSteamId, delegate { bugAdminLoading = false; }); } private static void DrawBugReportAdminViewer() { //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0315: 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_004e: Invalid comparison between Unknown and I4 //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0277: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown //IL_013c: 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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0174: 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_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Expected O, but got Unknown //IL_0624: Unknown result type (might be due to invalid IL or missing references) //IL_0629: Unknown result type (might be due to invalid IL or missing references) //IL_063c: Unknown result type (might be due to invalid IL or missing references) //IL_0641: Unknown result type (might be due to invalid IL or missing references) //IL_0646: Unknown result type (might be due to invalid IL or missing references) //IL_06cd: Unknown result type (might be due to invalid IL or missing references) //IL_06b2: Unknown result type (might be due to invalid IL or missing references) //IL_0b0e: Unknown result type (might be due to invalid IL or missing references) //IL_0b33: Unknown result type (might be due to invalid IL or missing references) //IL_06d2: Unknown result type (might be due to invalid IL or missing references) //IL_06d4: Unknown result type (might be due to invalid IL or missing references) //IL_06e2: Unknown result type (might be due to invalid IL or missing references) //IL_0ae0: Unknown result type (might be due to invalid IL or missing references) //IL_0b8c: Unknown result type (might be due to invalid IL or missing references) //IL_0c20: Unknown result type (might be due to invalid IL or missing references) //IL_0c67: Unknown result type (might be due to invalid IL or missing references) //IL_0cdf: Unknown result type (might be due to invalid IL or missing references) //IL_0d86: Unknown result type (might be due to invalid IL or missing references) //IL_0937: Unknown result type (might be due to invalid IL or missing references) //IL_097b: Unknown result type (might be due to invalid IL or missing references) //IL_0a02: Unknown result type (might be due to invalid IL or missing references) //IL_0a23: Unknown result type (might be due to invalid IL or missing references) //IL_12cb: Unknown result type (might be due to invalid IL or missing references) //IL_12d0: Unknown result type (might be due to invalid IL or missing references) //IL_12e3: Unknown result type (might be due to invalid IL or missing references) //IL_12e8: Unknown result type (might be due to invalid IL or missing references) //IL_12ed: Unknown result type (might be due to invalid IL or missing references) //IL_1300: Unknown result type (might be due to invalid IL or missing references) //IL_13b3: Unknown result type (might be due to invalid IL or missing references) //IL_13e8: Unknown result type (might be due to invalid IL or missing references) //IL_144f: Unknown result type (might be due to invalid IL or missing references) //IL_1346: Unknown result type (might be due to invalid IL or missing references) if (!bugAdminOpen) { return; } if (!NativeUI.IsOpen) { bugAdminOpen = false; return; } Event current = Event.current; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { bugAdminOpen = false; current.Use(); return; } if (bugAdminRowStyle == null) { bugAdminRowStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, wordWrap = false }; bugAdminDetailStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, wordWrap = true, alignment = (TextAnchor)0 }; bugAdminLogStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = false, wordWrap = true, alignment = (TextAnchor)0 }; bugAdminTabStyle = new GUIStyle(GUI.skin.button) { fontSize = 12 }; GUIStyle val = new GUIStyle(GUI.skin.button) { fontSize = 12, fontStyle = (FontStyle)1 }; val.normal.background = Texture2D.whiteTexture; val.normal.textColor = Color.black; val.hover.background = Texture2D.whiteTexture; val.hover.textColor = Color.black; bugAdminTabActiveStyle = val; } float num = Mathf.Min(Screen.width - 40, 1280); float num2 = Mathf.Min(Screen.height - 60, 760); float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.55f), 0f, 0f); GUI.DrawTexture(new Rect(num3 - 10f, num4 - 10f, num + 20f, num2 + 20f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.05f, 0.06f, 0.08f, 0.98f), 0f, 0f); try { EnsureBugStyles(); } catch { } GUI.Label(new Rect(num3, num4, num, 24f), "Bug Reports", bugTitleStyle ?? GUI.skin.label); if (GUI.Button(new Rect(num3 + num - 100f, num4, 100f, 26f), "Close")) { bugAdminOpen = false; return; } if (GUI.Button(new Rect(num3 + num - 210f, num4, 100f, 26f), "Refresh")) { bugAdminLoading = true; string localSteamId = MatchTracker.LocalSteamId; ApiClient.FetchBugReports(localSteamId, delegate { bugAdminLoading = false; }); if (!string.IsNullOrEmpty(bugAdminSelectedId)) { ApiClient.FetchBugReportDetail(localSteamId, bugAdminSelectedId); } } if (bugAdminLoading) { GUI.Label(new Rect(num3 + 200f, num4, 200f, 24f), "loading...", bugAdminRowStyle); } float num5 = num * 0.4f; float num6 = num4 + 36f; float num7 = num2 - 46f; GUI.DrawTexture(new Rect(num3, num6, num5 - 6f, num7), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.08f, 0.1f, 0.13f, 0.95f), 0f, 0f); float num8 = num6 + 4f; GUI.Label(new Rect(num3 + 6f, num8 + 2f, 48f, 22f), "Find:", bugAdminRowStyle); bugAdminLookup = GUI.TextField(new Rect(num3 + 56f, num8, num5 - 70f, 22f), bugAdminLookup ?? ""); List list = ApiClient.CachedBugReports ?? new List(); List list2 = list; string text = (bugAdminLookup ?? "").Trim(); if (!string.IsNullOrEmpty(text)) { list2 = new List(); int result; bool flag = int.TryParse(text, out result); string value = text.ToLowerInvariant(); foreach (ApiClient.BugReportSummary item in list) { if (flag && item.bug_number == result) { list2.Add(item); } else if ((item.description ?? "").ToLowerInvariant().Contains(value)) { list2.Add(item); } else if ((item.display_name ?? "").ToLowerInvariant().Contains(value)) { list2.Add(item); } else if ((item.steam_id ?? "").Contains(text)) { list2.Add(item); } } } float num9 = num8 + 28f; float num10 = num7 - 28f - 4f; float num11 = num5 - 18f; float num12 = num11 - 16f; float num13 = Mathf.Max(num10 - 8f, (float)list2.Count * 88f + 8f); bugAdminListScroll = GUI.BeginScrollView(new Rect(num3 + 4f, num9, num11, num10), bugAdminListScroll, new Rect(0f, 0f, num12, num13)); Rect val2 = default(Rect); for (int num14 = 0; num14 < list2.Count; num14++) { ApiClient.BugReportSummary bugReportSummary = list2[num14]; ((Rect)(ref val2))..ctor(2f, (float)num14 * 88f + 2f, num12 - 6f, 84f); Color val3 = ((bugReportSummary.id == bugAdminSelectedId) ? new Color(0.2f, 0.3f, 0.45f, 0.95f) : new Color(0.13f, 0.15f, 0.19f, 0.95f)); GUI.DrawTexture(val2, (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val3, 0f, 0f); string text2 = ((bugReportSummary.severity == "crash") ? "#FF5555" : ((bugReportSummary.severity == "high") ? "#FF9966" : ((bugReportSummary.severity == "medium") ? "#FFCC66" : "#88AABB"))); string text3 = ((bugReportSummary.status == "resolved") ? "#88FF88" : ((bugReportSummary.status == "wontfix") ? "#888888" : ((bugReportSummary.status == "dupe") ? "#888888" : ((bugReportSummary.status == "triaged") ? "#FFCC66" : "#FF6688")))); string text4 = ((bugReportSummary.bug_number > 0) ? $"#{bugReportSummary.bug_number} " : ""); string text5 = text4 + "[" + (bugReportSummary.severity ?? "?").ToUpper() + "/" + (bugReportSummary.category ?? "?").ToUpper() + "] " + (bugReportSummary.status ?? "?").ToUpper() + ""; string text6 = (bugReportSummary.display_name ?? bugReportSummary.steam_id ?? "?") + " (" + (bugReportSummary.mod_version ?? "?") + ")"; string text7 = ShortDate(bugReportSummary.created_at); string text8 = (bugReportSummary.description ?? "").Replace("\n", " "); if (text8.Length > 70) { text8 = text8.Substring(0, 70) + "..."; } GUI.Label(new Rect(((Rect)(ref val2)).x + 8f, ((Rect)(ref val2)).y + 6f, ((Rect)(ref val2)).width - 16f, 20f), text5, bugAdminRowStyle); GUI.Label(new Rect(((Rect)(ref val2)).x + 8f, ((Rect)(ref val2)).y + 6f + 20f, ((Rect)(ref val2)).width - 16f, 20f), "" + text6 + " " + text7 + "" + (bugReportSummary.has_log ? " [log]" : ""), bugAdminRowStyle); GUI.Label(new Rect(((Rect)(ref val2)).x + 8f, ((Rect)(ref val2)).y + 6f + 40f, ((Rect)(ref val2)).width - 16f, 20f), "" + text8 + "", bugAdminRowStyle); if (GUI.Button(val2, GUIContent.none, GUIStyle.none)) { bugAdminSelectedId = bugReportSummary.id; ApiClient.CachedBugReportDetail = null; bugAdminCommentDraft = ""; bugAdminActionStatus = ""; string localSteamId2 = MatchTracker.LocalSteamId; ApiClient.FetchBugReportDetail(localSteamId2, bugReportSummary.id); } } if (list2.Count == 0) { string text9 = (string.IsNullOrEmpty(text) ? "(no reports yet)" : ("(no reports match '" + text + "')")); GUI.Label(new Rect(8f, 8f, num5 - 40f, 30f), text9, bugAdminRowStyle); } GUI.EndScrollView(); float num15 = num3 + num5; float num16 = num - num5; GUI.DrawTexture(new Rect(num15, num6, num16, num7), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.05f, 0.07f, 0.1f, 0.95f), 0f, 0f); ApiClient.BugReportDetail d = ApiClient.CachedBugReportDetail; if (d == null || string.IsNullOrEmpty(bugAdminSelectedId)) { GUI.Label(new Rect(num15 + 12f, num6 + 12f, num16 - 24f, 30f), "Click a report on the left to view full detail + log.", bugAdminRowStyle); return; } int num17 = Array.IndexOf(BUG_STATUSES, (d.status ?? "open").ToLower()); if (num17 < 0) { num17 = 0; } if (bugAdminStatusIdx < 0 || bugAdminStatusIdx >= BUG_STATUSES.Length) { bugAdminStatusIdx = num17; } float num18 = num6 + 8f; GUI.Label(new Rect(num15 + 8f, num18, 80f, 22f), "Status:", bugAdminRowStyle); for (int num19 = 0; num19 < BUG_STATUSES.Length; num19++) { bool flag2 = num19 == bugAdminStatusIdx; if (GUI.Button(new Rect(num15 + 80f + (float)(num19 * 76), num18 - 2f, 72f, 24f), BUG_STATUSES[num19].ToUpper(), flag2 ? bugAdminTabActiveStyle : bugAdminTabStyle)) { bugAdminStatusIdx = num19; } } if (GUI.Button(new Rect(num15 + 80f + (float)(BUG_STATUSES.Length * 76) + 8f, num18 - 2f, 96f, 24f), "Apply Status")) { string sid = MatchTracker.LocalSteamId; string newStatus = BUG_STATUSES[bugAdminStatusIdx]; bugAdminActionStatus = "updating..."; ApiClient.AdminBugReportStatus(sid, d.id, newStatus, null, delegate(bool ok, string resp) { bugAdminActionStatus = (ok ? "status updated" : ("fail: " + (resp ?? "").Replace("\n", " ") + "")); if (ok) { ApiClient.FetchBugReportDetail(sid, d.id); ApiClient.FetchBugReports(sid); } }); } if (!string.IsNullOrEmpty(bugAdminActionStatus)) { GUI.Label(new Rect(num15 + 8f, num18 + 24f, num16 - 16f, 18f), bugAdminActionStatus, bugAdminRowStyle); } StringBuilder stringBuilder = new StringBuilder(); string text10 = ((d.bug_number > 0) ? $"#{d.bug_number} " : ""); stringBuilder.AppendLine(text10 + "" + (d.display_name ?? d.steam_id) + " " + d.steam_id + ""); stringBuilder.AppendLine("" + ShortDate(d.created_at) + " | mod=" + d.mod_version + " | game=" + d.game_version + ""); stringBuilder.AppendLine("severity: " + d.severity + " category: " + d.category + " status: " + d.status); stringBuilder.AppendLine(); stringBuilder.AppendLine("Description:"); stringBuilder.AppendLine(d.description ?? "(empty)"); if (!string.IsNullOrEmpty(d.repro_steps)) { stringBuilder.AppendLine(); stringBuilder.AppendLine("Repro:"); stringBuilder.AppendLine(d.repro_steps); } if (d.events != null && d.events.Count > 0) { stringBuilder.AppendLine(); stringBuilder.AppendLine($"Activity ({d.events.Count}):"); foreach (ApiClient.BugReportEventEntry @event in d.events) { string text11 = ShortDate(@event.created_at); string text12 = @event.actor_name ?? "?"; if (@event.event_type == "status_change") { stringBuilder.AppendLine(" " + text11 + " " + text12 + " " + (@event.old_status ?? "?") + " -> " + (@event.new_status ?? "?") + "" + (string.IsNullOrEmpty(@event.comment) ? "" : (" -- " + @event.comment))); } else if (@event.event_type == "created") { stringBuilder.AppendLine(" " + text11 + " " + text12 + " filed report"); } else { stringBuilder.AppendLine(" " + text11 + " " + text12 + ": " + @event.comment); } } } string text13 = null; string text14 = null; if (!string.IsNullOrEmpty(d.log_text)) { int length = d.log_text.Length; text13 = d.log_text; string arg = ""; if (text13.Length > 200000) { text13 = "[... earlier content trimmed for display - see ssh bug-log:" + d.bug_number + " for full ...]\n" + text13.Substring(text13.Length - 200000); arg = $" — showing last {200000:N0} of {length:N0} chars"; } stringBuilder.AppendLine(); text14 = $"Attached log ({d.log_bytes:N0} bytes gzipped on disk, {length:N0} chars decoded){arg}:"; stringBuilder.AppendLine(text14); } string text15 = stringBuilder.ToString(); float num20 = num18 + 48f; float num21 = 96f; float num22 = num7 - (num20 - num6) - num21 - 8f; float num23 = num16 - 24f; float num24 = num23 - 12f; EnsureBugLogLayout(d.id, text15, text13, num24); float num25 = bugAdminMetaH; float num26 = Mathf.Max(num22, bugAdminLogTotalH + num25 + 40f); bugAdminDetailScroll = GUI.BeginScrollView(new Rect(num15 + 8f, num20, num16 - 12f, num22), bugAdminDetailScroll, new Rect(0f, 0f, num24, num26)); GUI.Label(new Rect(4f, 4f, num24, num25), text15, bugAdminDetailStyle); if (bugAdminLogChunks != null) { float num27 = 4f + num25; for (int num28 = 0; num28 < bugAdminLogChunks.Count; num28++) { GUI.Label(new Rect(4f, num27, num24, bugAdminLogHeights[num28]), bugAdminLogChunks[num28], bugAdminLogStyle); num27 += bugAdminLogHeights[num28]; } } GUI.EndScrollView(); float num29 = num6 + num7 - num21; GUI.Label(new Rect(num15 + 8f, num29, 200f, 18f), "Add comment:", bugAdminRowStyle); bugAdminCommentDraft = GUI.TextArea(new Rect(num15 + 8f, num29 + 20f, num16 - 130f, num21 - 26f), bugAdminCommentDraft ?? "", 2000); bool enabled = !string.IsNullOrEmpty((bugAdminCommentDraft ?? "").Trim()); GUI.enabled = enabled; if (GUI.Button(new Rect(num15 + num16 - 116f, num29 + 20f, 108f, num21 - 26f), "Post Comment")) { string sid2 = MatchTracker.LocalSteamId; string comment = (bugAdminCommentDraft ?? "").Trim(); bugAdminActionStatus = "posting..."; ApiClient.AdminBugReportComment(sid2, d.id, comment, delegate(bool ok, string resp) { bugAdminActionStatus = (ok ? "comment posted" : ("fail: " + (resp ?? "").Replace("\n", " ") + "")); if (ok) { bugAdminCommentDraft = ""; ApiClient.FetchBugReportDetail(sid2, d.id); } }); } GUI.enabled = true; } private static string ShortDate(string isoStr) { if (string.IsNullOrEmpty(isoStr)) { return "?"; } try { return DateTime.Parse(isoStr, null, DateTimeStyles.RoundtripKind).ToLocalTime().ToString("M/d HH:mm", CultureInfo.InvariantCulture); } catch { return isoStr; } } private static void DrawInputOverlay() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown if (Event.current != null && (int)Event.current.type == 7 && Plugin.ShowInputOverlay != null && Plugin.ShowInputOverlay.Value && GameStateWatcher.IsInMatch) { if (inputKeyStyle == null) { inputKeyStyle = new GUIStyle(GUI.skin.label) { fontSize = 18, richText = true, alignment = (TextAnchor)4, fontStyle = (FontStyle)1 }; inputKeySmallStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, alignment = (TextAnchor)4, fontStyle = (FontStyle)1 }; } bool key = Input.GetKey((KeyCode)119); bool key2 = Input.GetKey((KeyCode)97); bool key3 = Input.GetKey((KeyCode)115); bool key4 = Input.GetKey((KeyCode)100); bool key5 = Input.GetKey((KeyCode)32); bool mouseButton = Input.GetMouseButton(0); bool mouseButton2 = Input.GetMouseButton(1); float num = 38f; float num2 = 38f; float num3 = 4f; float num4 = 14f; float num5 = Screen.height - 14; float num6 = num5 - num2; float num7 = num * 1.6f; DrawKeyBox(new Rect(num4, num6, num7, num2), "LMB", mouseButton, small: true); DrawKeyBox(new Rect(num4 + num7 + num3, num6, num7, num2), "RMB", mouseButton2, small: true); float num8 = num7 * 2f + num3; float num9 = num6 - 10f - num2; float num10 = num4 + num + num3; DrawKeyBox(new Rect(num4, num9, num, num2), "A", key2, small: false); DrawKeyBox(new Rect(num4 + num + num3, num9, num, num2), "S", key3, small: false); DrawKeyBox(new Rect(num4 + (num + num3) * 2f, num9, num, num2), "D", key4, small: false); float num11 = num9 - num2 - num3; DrawKeyBox(new Rect(num4 + num + num3, num11, num, num2), "W", key, small: false); float num12 = num6 - 6f - num2; float num13 = (num + num3) * 3f - num3; DrawKeyBox(new Rect(num4 + (num + num3) * 3f + 8f, num9, num13, num2), "SPACE", key5, small: true); } } private static void DrawKeyBox(Rect r, string label, bool pressed, bool small) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0071: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: 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_01c3: Unknown result type (might be due to invalid IL or missing references) Color val = (pressed ? new Color(0.85f, 0.18f, 0.18f, 0.92f) : new Color(0.1f, 0.1f, 0.13f, 0.78f)); Color val2 = (pressed ? new Color(1f, 0.5f, 0.5f, 0.9f) : new Color(1f, 1f, 1f, 0.35f)); GUI.DrawTexture(r, (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, ((Rect)(ref r)).width, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + ((Rect)(ref r)).height - 1f, ((Rect)(ref r)).width, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, 1f, ((Rect)(ref r)).height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref r)).x + ((Rect)(ref r)).width - 1f, ((Rect)(ref r)).y, 1f, ((Rect)(ref r)).height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val2, 0f, 0f); Color contentColor = GUI.contentColor; GUI.contentColor = Color.white; GUI.Label(r, label, small ? inputKeySmallStyle : inputKeyStyle); GUI.contentColor = contentColor; } private static void DrawBlockDebug() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00cc: Expected O, but got Unknown //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7 || Plugin.ShowBlockDebug == null || !Plugin.ShowBlockDebug.Value || !GameStateWatcher.IsInMatch) { return; } if (blockDbgStyle == null) { blockDbgStyle = new GUIStyle(GUI.skin.label) { fontSize = 15, richText = true, alignment = (TextAnchor)0, fontStyle = (FontStyle)1 }; blockDbgSmallStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = true, alignment = (TextAnchor)0 }; } int localBlocksActivatedThisMatch = GameStateWatcher.LocalBlocksActivatedThisMatch; int localBlocksSuccessfulThisMatch = GameStateWatcher.LocalBlocksSuccessfulThisMatch; int localBlockRawAbsorbs = GameStateWatcher.LocalBlockRawAbsorbs; int localBlockDedupeDrops = GameStateWatcher.LocalBlockDedupeDrops; float time = Time.time; float num = time - GameStateWatcher.LastBlockActivatedTime; float num2 = time - GameStateWatcher.LastBlockSuccessfulTime; float num3 = time - GameStateWatcher.LastBlockAbsorbTime; float num4 = time - GameStateWatcher.LastBlockMissTime; string text = GameStateWatcher.LastBlockEventLabel ?? ""; float num5 = 270f; float num6 = 110f; float num7 = 6f; float num8 = (float)Screen.width - num5 - 12f; float num9 = 12f; Color val = default(Color); ((Color)(ref val))..ctor(0f, 0f, 0f, 0.72f); float num10 = Mathf.Min(num, Mathf.Min(num2, Mathf.Min(num3, num4))); if (num10 >= 0f && num10 < 0.35f) { float num11 = 1f - num10 / 0.35f; Color val2 = default(Color); if (num4 <= num10 + 0.001f) { ((Color)(ref val2))..ctor(0.95f, 0.25f, 0.25f, 0.9f); } else if (num2 <= num10 + 0.001f) { ((Color)(ref val2))..ctor(0.2f, 0.9f, 0.2f, 0.85f); } else if (num <= num10 + 0.001f) { ((Color)(ref val2))..ctor(0.3f, 0.55f, 1f, 0.85f); } else { ((Color)(ref val2))..ctor(0.95f, 0.7f, 0.1f, 0.85f); } val = Color.Lerp(val, val2, num11); } GUI.DrawTexture(new Rect(num8, num9, num5, num6), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val, 0f, 0f); GUI.DrawTexture(new Rect(num8, num9, num5, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(1f, 1f, 1f, 0.5f), 0f, 0f); Color contentColor = GUI.contentColor; GUI.contentColor = Color.white; GUI.Label(new Rect(num8 + num7, num9 + num7, num5 - num7 * 2f, 20f), "BLOCK DEBUG", blockDbgStyle); string text2 = $"Act: {localBlocksActivatedThisMatch} " + $"Succ: {localBlocksSuccessfulThisMatch} " + $"Raw: {localBlockRawAbsorbs}"; GUI.Label(new Rect(num8 + num7, num9 + num7 + 22f, num5 - num7 * 2f, 20f), text2, blockDbgStyle); string arg = ((localBlocksActivatedThisMatch > 0) ? $"{(float)localBlocksSuccessfulThisMatch * 100f / (float)localBlocksActivatedThisMatch:F0}%" : "-"); string text3 = $"Drops: {localBlockDedupeDrops} Rate: {arg}"; GUI.Label(new Rect(num8 + num7, num9 + num7 + 44f, num5 - num7 * 2f, 18f), text3, blockDbgSmallStyle); string text4 = ""; if (!string.IsNullOrEmpty(text) && num10 < 5f && num10 >= 0f) { text4 = $"{text} (+{num10:F1}s)"; } GUI.Label(new Rect(num8 + num7, num9 + num7 + 64f, num5 - num7 * 2f, 18f), text4, blockDbgSmallStyle); GUI.Label(new Rect(num8 + num7, num9 + num7 + 82f, num5 - num7 * 2f, 14f), "debug overlay — CompetitiveUI.BlockDebugEnabled", blockDbgSmallStyle); GUI.contentColor = contentColor; } private static ChatLineLayout MeasureChatLine(string line, float w) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown if (chatLayoutCache.TryGetValue(line, out var value)) { return value; } if (chatLayoutCache.Count > 256) { chatLayoutCache.Clear(); } float num = ingameChatStyle.lineHeight * 3f + 4f; ChatLineLayout chatLineLayout = new ChatLineLayout { Disp = line }; chatLineLayout.H = ingameChatStyle.CalcHeight(new GUIContent(line), w); if (chatLineLayout.H > num) { int num2 = line.LastIndexOf('>') + 1; if (num2 < 1) { num2 = 1; } if (num2 >= line.Length - 1) { chatLayoutCache[line] = chatLineLayout; return chatLineLayout; } int num3 = Math.Min(num2 + 1, line.Length); int num4 = line.Length; int length = num3; while (num3 <= num4) { int num5 = (num3 + num4) / 2; string text = line.Substring(0, num5).TrimEnd() + " ... [see F5]"; if (ingameChatStyle.CalcHeight(new GUIContent(text), w) <= num) { length = num5; num3 = num5 + 1; } else { num4 = num5 - 1; } } chatLineLayout.Disp = line.Substring(0, length).TrimEnd() + " ... [see F5]"; chatLineLayout.H = ingameChatStyle.CalcHeight(new GUIContent(chatLineLayout.Disp), w); } chatLayoutCache[line] = chatLineLayout; return chatLineLayout; } private static void DrawInGameChat() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7 || (Plugin.ShowIngameChat != null && !Plugin.ShowIngameChat.Value) || !Plugin.DataConsentGranted || NativeUI.IsOpen) { return; } NativeUI.CopyChatTail(_chatEntryScratch, 8); List chatEntryScratch = _chatEntryScratch; if (chatEntryScratch.Count == 0) { return; } if (ingameChatStyle == null) { ingameChatStyle = new GUIStyle(GUI.skin.label) { fontSize = 14, wordWrap = true, richText = true, alignment = (TextAnchor)0 }; } DateTime utcNow = DateTime.UtcNow; if (_chatAlphaScratch.Length < chatEntryScratch.Count) { _chatAlphaScratch = new float[chatEntryScratch.Count]; } float[] chatAlphaScratch = _chatAlphaScratch; float num = 0f; int num2 = 0; for (int i = 0; i < chatEntryScratch.Count; i++) { double totalSeconds = (utcNow - chatEntryScratch[i].AddedUtc).TotalSeconds; float num3 = (chatAlphaScratch[i] = ((totalSeconds < 25.0) ? 1f : ((totalSeconds < 35.0) ? (1f - (float)((totalSeconds - 25.0) / 10.0)) : 0f))); if (num3 > 0.02f) { num2++; if (num3 > num) { num = num3; } } } if (num2 == 0) { return; } float num4 = 440f; float num5 = 6f; float num6 = 2f; float num7 = 12f; if (_chatLayoutScratch.Length < chatEntryScratch.Count) { _chatLayoutScratch = new ChatLineLayout[chatEntryScratch.Count]; } ChatLineLayout[] chatLayoutScratch = _chatLayoutScratch; float num8 = 0f; for (int j = 0; j < chatEntryScratch.Count; j++) { if (!(chatAlphaScratch[j] <= 0.02f)) { chatLayoutScratch[j] = MeasureChatLine(chatEntryScratch[j].Line, num4); num8 += chatLayoutScratch[j].H + num6; } } float num9 = num8 - num6 + num5 * 2f; float num10 = Screen.height - 90; float num11 = num10 - num9; GUI.DrawTexture(new Rect(num7 - 4f, num11, num4 + 8f, num9), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.55f * num), 0f, 0f); float num12 = num10 - num5; for (int num13 = chatEntryScratch.Count - 1; num13 >= 0; num13--) { float num14 = chatAlphaScratch[num13]; if (!(num14 <= 0.02f)) { Color contentColor = GUI.contentColor; GUI.contentColor = new Color(1f, 1f, 1f, num14); num12 -= chatLayoutScratch[num13].H; GUI.Label(new Rect(num7, num12, num4, chatLayoutScratch[num13].H), chatLayoutScratch[num13].Disp, ingameChatStyle); GUI.contentColor = contentColor; num12 -= num6; } } } public static void OpenAdminPrompt(string mode) { adminPromptMode = mode ?? ""; adminInputA = ""; adminInputB = ((mode == "grant") ? ADMIN_ACHIEVEMENT_KEYS[0] : ""); adminPromptOpen = true; } public static void OpenConfirm(string message, Action onYes) { confirmMessage = message ?? "Are you sure?"; confirmOnYes = onYes; confirmOpen = true; } private static void DrawConfirm() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_00e0: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) if (!confirmOpen) { return; } if (!NativeUI.IsOpen) { confirmOpen = false; confirmOnYes = null; return; } Event current = Event.current; bool flag = false; bool flag2 = false; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { flag2 = true; current.Use(); } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } float num = 540f; float num2 = 170f; float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(num3 - 8f, num4 - 8f, num + 16f, num2 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.94f), 0f, 0f); GUI.Label(new Rect(num3 + 12f, num4 + 10f, num - 24f, 26f), "Confirm", new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1 }); GUI.Label(new Rect(num3 + 12f, num4 + 42f, num - 24f, 70f), confirmMessage, new GUIStyle(adminLabelStyle) { fontSize = 14, wordWrap = true }); if (GUI.Button(new Rect(num3 + 12f, num4 + num2 - 40f, 120f, 30f), "Cancel")) { flag2 = true; } if (GUI.Button(new Rect(num3 + num - 132f, num4 + num2 - 40f, 120f, 30f), "Confirm")) { flag = true; } if (flag2) { confirmOpen = false; confirmOnYes = null; } else if (flag) { Action action = confirmOnYes; confirmOpen = false; confirmOnYes = null; try { action?.Invoke(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ADMIN] confirm action: " + ex.Message)); } } } public static void OpenArtistInput(string title, string label, string initial, Action onSubmit) { artistPromptTitle = title ?? "Artist action"; artistPromptLabel = label ?? "Value"; artistPromptValue = initial ?? ""; artistPromptOnSubmit = onSubmit; artistPromptOpen = true; } public static void OpenArtistPicker(string title, string[] names, string[] ids, Action onPick, string actionLabel = "Assign", bool showClear = true) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (names != null && ids != null && names.Length != 0 && names.Length == ids.Length) { artistPickerTitle = title ?? "Pick an artist"; artistPickerNames = names; artistPickerIds = ids; artistPickerIdx = 0; artistPickerOnPick = onPick; artistPickerAction = (string.IsNullOrEmpty(actionLabel) ? "Assign" : actionLabel); artistPickerShowClear = showClear; artistPickerScroll = Vector2.zero; artistPickerOpen = true; } } private static void DrawArtistPicker() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_007e: 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_0091: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) if (!artistPickerOpen) { return; } if (!NativeUI.IsOpen) { artistPickerOpen = false; artistPickerOnPick = null; return; } Event current = Event.current; bool flag = false; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { flag = true; current.Use(); } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } if (pickerRowStyle == null) { pickerRowStyle = new GUIStyle(GUI.skin.button) { fontSize = 14, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, richText = true }; } int num = artistPickerNames.Length; artistPickerIdx = Mathf.Clamp(artistPickerIdx, 0, num - 1); float num2 = 32f; float num3 = Mathf.Min((float)num * num2 + 4f, 330f); float num4 = 540f; float num5 = 118f + num3; float num6 = ((float)Screen.width - num4) / 2f; float num7 = ((float)Screen.height - num5) / 2f; GUI.DrawTexture(new Rect(num6 - 8f, num7 - 8f, num4 + 16f, num5 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.93f), 0f, 0f); GUI.Label(new Rect(num6 + 12f, num7 + 10f, num4 - 24f, 26f), string.Format("{0} ({1} artist{2})", artistPickerTitle, num, (num == 1) ? "" : "s"), new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1, richText = true }); artistPickerScroll = GUI.BeginScrollView(new Rect(num6 + 12f, num7 + 44f, num4 - 24f, num3), artistPickerScroll, new Rect(0f, 0f, num4 - 45f, (float)num * num2)); for (int i = 0; i < num; i++) { bool flag2 = i == artistPickerIdx; if (flag2) { GUI.DrawTexture(new Rect(0f, (float)i * num2, num4 - 45f, num2 - 2f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.25f, 0.45f, 0.25f, 0.85f), 0f, 0f); } string text = (flag2 ? "> " : "") + artistPickerNames[i] + " " + artistPickerIds[i] + ""; if (GUI.Button(new Rect(0f, (float)i * num2, num4 - 45f, num2 - 2f), text, pickerRowStyle)) { artistPickerIdx = i; } } GUI.EndScrollView(); if (GUI.Button(new Rect(num6 + 12f, num7 + num5 - 40f, 110f, 30f), "Cancel")) { flag = true; } if (artistPickerShowClear && GUI.Button(new Rect(num6 + (num4 - 130f) / 2f, num7 + num5 - 40f, 130f, 30f), "Clear (house)")) { Action action = artistPickerOnPick; artistPickerOpen = false; artistPickerOnPick = null; try { action?.Invoke(""); return; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ARTIST] picker clear: " + ex.Message)); return; } } if (GUI.Button(new Rect(num6 + num4 - 122f, num7 + num5 - 40f, 110f, 30f), artistPickerAction)) { Action action2 = artistPickerOnPick; string obj = artistPickerIds[artistPickerIdx]; artistPickerOpen = false; artistPickerOnPick = null; try { action2?.Invoke(obj); return; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[ARTIST] picker pick: " + ex2.Message)); return; } } if (flag) { artistPickerOpen = false; artistPickerOnPick = null; } } public static void OpenPlayerSearch(string title, Action onPick) { playerSearchTitle = title ?? "Find a player"; playerSearchQuery = ""; playerSearchPrevQuery = ""; playerSearchLastFetched = null; playerSearchBusy = false; playerSearchStatus = "Type at least 2 letters of the player's name."; playerSearchResults.Clear(); playerSearchOnPick = onPick; playerSearchOpen = true; } private static void DrawPlayerSearch() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_007e: 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_0091: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Invalid comparison between Unknown and I4 //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Expected O, but got Unknown //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Unknown result type (might be due to invalid IL or missing references) if (!playerSearchOpen) { return; } if (!NativeUI.IsOpen) { playerSearchOpen = false; playerSearchOnPick = null; return; } Event current = Event.current; bool flag = false; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { flag = true; current.Use(); } if (adminFieldStyle == null) { adminFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 15 }; } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } if (pickerRowStyle == null) { pickerRowStyle = new GUIStyle(GUI.skin.button) { fontSize = 14, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, richText = true }; } int count = playerSearchResults.Count; float num = 32f; float num2 = Mathf.Max(64f, Mathf.Min((float)count * num + 4f, 8f * num)); float num3 = 560f; float num4 = 158f + num2; float num5 = ((float)Screen.width - num3) / 2f; float num6 = ((float)Screen.height - num4) / 2f; GUI.DrawTexture(new Rect(num5 - 8f, num6 - 8f, num3 + 16f, num4 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.93f), 0f, 0f); GUI.Label(new Rect(num5 + 12f, num6 + 10f, num3 - 24f, 26f), playerSearchTitle, new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1 }); GUI.Label(new Rect(num5 + 12f, num6 + 40f, num3 - 24f, 20f), "Steam name", adminLabelStyle); playerSearchQuery = GUI.TextField(new Rect(num5 + 12f, num6 + 62f, num3 - 24f, 28f), playerSearchQuery ?? "", adminFieldStyle); if (playerSearchQuery != playerSearchPrevQuery) { playerSearchPrevQuery = playerSearchQuery; playerSearchTypedAt = Time.unscaledTime; } string text = (playerSearchQuery ?? "").Trim(); if (current != null && (int)current.type == 7 && !playerSearchBusy && text.Length >= 2 && text != playerSearchLastFetched && Time.unscaledTime - playerSearchTypedAt > 0.35f) { playerSearchBusy = true; playerSearchStatus = "Searching..."; string sent = text; ApiClient.SearchPlayers(sent, delegate(bool ok, List list) { playerSearchBusy = false; if (playerSearchOpen) { playerSearchLastFetched = sent; if (ok) { playerSearchResults = list ?? new List(); playerSearchStatus = ((playerSearchResults.Count == 0) ? "No players match." : "Click a player. The elo beside the name is live - an imposter with a copied name won't have their rating."); } else { playerSearchStatus = "Search failed - server unreachable?"; } } }); } GUI.Label(new Rect(num5 + 12f, num6 + 92f, num3 - 24f, 20f), playerSearchStatus, new GUIStyle(adminLabelStyle) { fontSize = 12, wordWrap = false }); float num7 = num6 + 114f; for (int num8 = 0; num8 < count && num8 < 8; num8++) { ApiClient.PlayerSearchResult playerSearchResult = playerSearchResults[num8]; string text2 = $"{playerSearchResult.display_name} {playerSearchResult.rating} elo {playerSearchResult.steam_id}"; if (GUI.Button(new Rect(num5 + 12f, num7 + (float)num8 * num, num3 - 24f, num - 2f), text2, pickerRowStyle)) { Action action = playerSearchOnPick; string steam_id = playerSearchResult.steam_id; string display_name = playerSearchResult.display_name; playerSearchOpen = false; playerSearchOnPick = null; try { action?.Invoke(steam_id, display_name); return; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SEARCH] pick: " + ex.Message)); return; } } } if (GUI.Button(new Rect(num5 + 12f, num6 + num4 - 40f, 110f, 30f), "Cancel")) { flag = true; } if (flag) { playerSearchOpen = false; playerSearchOnPick = null; } } public static void OpenCosmeticTestPreview(byte[] pngBytes, string name, string slot, Action onSubmit, float initialScale = 1.3f, float initialOffsetX = 0f, float initialOffsetY = 0f, string submitLabel = "Submit", bool isRevision = false) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) Texture2D val = null; try { val = new Texture2D(2, 2, (TextureFormat)4, false); if (pngBytes == null || !ImageConversion.LoadImage(val, pngBytes)) { Object.Destroy((Object)(object)val); ShowNotification("Could not open that cosmetic preview.", new Color(1f, 0.45f, 0.4f)); return; } } catch { try { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } catch { } ShowNotification("Could not open that cosmetic preview.", new Color(1f, 0.45f, 0.4f)); return; } CloseCosmeticTestPreview(submit: false); artistPickerOpen = false; artistPickerOnPick = null; cosTestTex = val; cosTestName = name ?? "Cosmetic"; cosTestSlot = slot ?? "detail"; cosTestScale = Mathf.Clamp(initialScale, 0.5f, 2.25f); cosTestInitialOffset = Vector2.ClampMagnitude(new Vector2(initialOffsetX, initialOffsetY), 4.5f); cosTestOffset = cosTestInitialOffset; cosTestDragging = false; cosTestSubmitLabel = (string.IsNullOrEmpty(submitLabel) ? "Submit" : submitLabel); cosTestIsRevision = isRevision; cosTestOnSubmit = onSubmit; cosTestOpen = true; } private static void CloseCosmeticTestPreview(bool submit) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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) Action action = (submit ? cosTestOnSubmit : null); float arg = Mathf.Clamp(cosTestScale, 0.5f, 2.25f); cosTestOpen = false; cosTestDragging = false; cosTestOnSubmit = null; try { if ((Object)(object)cosTestTex != (Object)null) { Object.Destroy((Object)(object)cosTestTex); } } catch { } cosTestTex = null; cosTestName = ""; cosTestSlot = ""; cosTestOffset = Vector2.zero; Vector2 val = cosTestInitialOffset; cosTestInitialOffset = Vector2.zero; if (action != null) { try { action(arg, val.x, val.y); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] preview submit: " + ex.Message)); } } } private static void DrawRectOutline(Rect r, Color color, float thickness = 1f) { //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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, ((Rect)(ref r)).width, thickness), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, color, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).yMax - thickness, ((Rect)(ref r)).width, thickness), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, color, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, thickness, ((Rect)(ref r)).height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, color, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref r)).xMax - thickness, ((Rect)(ref r)).y, thickness, ((Rect)(ref r)).height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, color, 0f, 0f); } private static void DrawCosmeticScalePreview(Rect bounds, Texture2D tex, float scale, Vector2 offset) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) GUI.DrawTexture(bounds, (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.16f, 0.17f, 0.2f, 1f), 0f, 4f); float num = ((Rect)(ref bounds)).width * 0.5f; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref bounds)).center.x - num / 2f, ((Rect)(ref bounds)).center.y - num / 2f, num, num); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, COS_BODY_ORANGE, 0f, num / 2f); float num2 = num * 0.7728302f * Mathf.Clamp(scale, 0.5f, 2.25f); float num3 = num / 6.625f; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(((Rect)(ref bounds)).center.x + offset.x * num3, ((Rect)(ref bounds)).center.y - offset.y * num3); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(val2.x - num2 / 2f, val2.y - num2 / 2f, num2, num2); DrawRectOutline(val3, new Color(1f, 1f, 1f, 0.55f)); if ((Object)(object)tex != (Object)null) { GUI.DrawTexture(val3, (Texture)(object)tex, (ScaleMode)2, true); } } private static void HandleCosmeticPlacementDrag(Rect bounds, ref Vector2 offset, ref bool dragging, ref Vector2 lastMouse) { //IL_0015: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Invalid comparison between Unknown and I4 //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) Event current = Event.current; if (current != null) { if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref bounds)).Contains(current.mousePosition)) { dragging = true; lastMouse = current.mousePosition; current.Use(); } else if (((int)current.type == 3 && current.button == 0) & dragging) { float num = ((Rect)(ref bounds)).width * 0.5f; float num2 = 6.625f / Mathf.Max(1f, num); Vector2 val = current.mousePosition - lastMouse; offset += new Vector2(val.x * num2, (0f - val.y) * num2); offset = Vector2.ClampMagnitude(offset, 4.5f); lastMouse = current.mousePosition; current.Use(); } else if (((int)current.type == 1 && current.button == 0) & dragging) { dragging = false; current.Use(); } } } private static void DrawCosmeticTestPreview() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Expected O, but got Unknown //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Expected O, but got Unknown //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_0594: Unknown result type (might be due to invalid IL or missing references) //IL_05c4: Unknown result type (might be due to invalid IL or missing references) //IL_05eb: Unknown result type (might be due to invalid IL or missing references) //IL_05f0: Unknown result type (might be due to invalid IL or missing references) //IL_05f9: Unknown result type (might be due to invalid IL or missing references) //IL_0606: Expected O, but got Unknown //IL_0622: Unknown result type (might be due to invalid IL or missing references) //IL_065e: Unknown result type (might be due to invalid IL or missing references) if (!cosTestOpen) { return; } if (!NativeUI.IsOpen) { CloseCosmeticTestPreview(submit: false); return; } Event current = Event.current; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { current.Use(); CloseCosmeticTestPreview(submit: false); return; } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } float num = Mathf.Min(760f, Mathf.Max(500f, (float)Screen.width - 24f)); float num2 = Mathf.Min(560f, Mathf.Max(450f, (float)Screen.height - 24f)); float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(num3 - 8f, num4 - 8f, num + 16f, num2 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.96f), 0f, 0f); GUI.Label(new Rect(num3 + 12f, num4 + 10f, num - 24f, 26f), "Placement preview: '" + cosTestName + "' (" + cosTestSlot + ")", new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1 }); GUI.Label(new Rect(num3 + 12f, num4 + 40f, num - 24f, 38f), "Orange circle = player body. Drag to preview positions (visual aid only - position is never saved; items spawn centered and players drag them in the character editor). White square = your 512x512 canvas.", new GUIStyle(adminLabelStyle) { fontSize = 12, wordWrap = true }); float num5 = Mathf.Min(num2 - 142f, num - 330f); num5 = Mathf.Clamp(num5, 300f, 414f); Rect bounds = default(Rect); ((Rect)(ref bounds))..ctor(num3 + 12f, num4 + 80f, num5, num5); DrawCosmeticScalePreview(bounds, cosTestTex, cosTestScale, cosTestOffset); HandleCosmeticPlacementDrag(bounds, ref cosTestOffset, ref cosTestDragging, ref cosTestLastMouse); float num6 = ((Rect)(ref bounds)).xMax + 18f; float num7 = num3 + num - 12f - num6; GUI.Label(new Rect(num6, num4 + 84f, num7, 24f), $"Render scale: {cosTestScale:F2}x", new GUIStyle(adminLabelStyle) { fontSize = 16, fontStyle = (FontStyle)1 }); int num8 = Mathf.RoundToInt(662.5f / cosTestScale); GUI.Label(new Rect(num6, num4 + 112f, num7, 52f), $"At this scale, the player body is about {num8}px across in your source image.\n" + "Transparent pixels still count toward the 512px canvas.", new GUIStyle(adminLabelStyle) { fontSize = 12, wordWrap = true }); cosTestScale = GUI.HorizontalSlider(new Rect(num6, num4 + 158f, num7, 22f), cosTestScale, 0.5f, 2.25f); cosTestScale = Mathf.Round(cosTestScale * 20f) / 20f; if (GUI.Button(new Rect(num6, num4 + 184f, 42f, 28f), "-")) { cosTestScale -= 0.05f; } if (GUI.Button(new Rect(num6 + 50f, num4 + 184f, 42f, 28f), "+")) { cosTestScale += 0.05f; } if (GUI.Button(new Rect(num6 + 100f, num4 + 184f, Mathf.Max(64f, num7 - 100f), 28f), "Center")) { cosTestOffset = Vector2.zero; } cosTestScale = Mathf.Clamp(cosTestScale, 0.5f, 2.25f); GUI.Label(new Rect(num6, num4 + 218f, num7, 22f), $"Preview offset: {cosTestOffset.x:F2}, {cosTestOffset.y:F2} (not saved)", adminLabelStyle); GUI.Label(new Rect(num6, num4 + 244f, num7, 22f), "Useful scale presets:", adminLabelStyle); float num9 = (num7 - 8f) / 2f; if (GUI.Button(new Rect(num6, num4 + 268f, num9, 28f), "1.00 compact")) { cosTestScale = 1f; } if (GUI.Button(new Rect(num6 + num9 + 8f, num4 + 268f, num9, 28f), "1.30 body")) { cosTestScale = 1.3f; } if (GUI.Button(new Rect(num6, num4 + 302f, num9, 28f), "1.70 cape")) { cosTestScale = 1.7f; } if (GUI.Button(new Rect(num6 + num9 + 8f, num4 + 302f, num9, 28f), "2.10 wings")) { cosTestScale = 2.1f; } GUI.Label(new Rect(num6, num4 + 336f, num7, 72f), (cosTestIsRevision ? "Changing scale or placement sends this cosmetic back to admin review. Its last approved placement stays active meanwhile. " : "Scale and placement are part of approval. ") + "Badly scaled, obstructive, or misplaced art will be rejected or rescaled/repositioned by an admin.", new GUIStyle(adminLabelStyle) { fontSize = 12, wordWrap = true }); if (GUI.Button(new Rect(num3 + 12f, num4 + num2 - 42f, 110f, 30f), "Cancel")) { CloseCosmeticTestPreview(submit: false); } else if (GUI.Button(new Rect(num3 + num - 152f, num4 + num2 - 42f, 140f, 30f), cosTestSubmitLabel)) { CloseCosmeticTestPreview(submit: true); } } public static void OpenCosmeticReview() { cosReleaseOpen = false; cosReviewOpen = true; cosReviewSubs = null; cosReviewIdx = 0; cosReviewBusy = true; cosReviewStatus = "Loading pending submissions..."; cosReviewDenialReason = ""; cosReviewDragging = false; ApiClient.FetchCosmeticSubmissionsAdmin(MatchTracker.LocalSteamId, delegate(bool ok, List list) { cosReviewBusy = false; if (cosReviewOpen) { if (!ok) { cosReviewStatus = "Fetch failed - are you an admin?"; } else { cosReviewSubs = list; cosReviewStatus = ((list.Count == 0) ? "No pending submissions." : ""); } } }); } private static void CloseCosmeticReview() { cosReviewOpen = false; foreach (Texture2D value in cosReviewTex.Values) { try { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } catch { } } cosReviewTex.Clear(); cosReviewSubs = null; cosReviewDenialReason = ""; cosReviewDragging = false; } private static Texture2D CosReviewTexture(ApiClient.CosmeticSubmission s) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if (cosReviewTex.TryGetValue(s.id, out var value)) { return value; } try { byte[] array = Convert.FromBase64String(s.png_base64 ?? ""); value = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(value, array)) { Object.Destroy((Object)(object)value); value = null; } } catch { value = null; } cosReviewTex[s.id] = value; return value; } private static void RemoveCosReview(int id) { if (cosReviewSubs == null) { return; } cosReviewSubs.RemoveAll((ApiClient.CosmeticSubmission q) => q.id == id); if (cosReviewTex.TryGetValue(id, out var value)) { try { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } catch { } cosReviewTex.Remove(id); } if (cosReviewSubs.Count == 0) { cosReviewStatus = "All reviewed!"; } cosReviewDenialReason = ""; cosReviewDragging = false; } private static string CosTrunc(string s, int n) { return string.IsNullOrEmpty(s) ? "" : ((s.Length <= n) ? s : s.Substring(0, n)); } private static void DrawCosmeticReview() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_007e: 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_0091: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Expected O, but got Unknown //IL_01dd: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Expected O, but got Unknown //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Expected O, but got Unknown //IL_0473: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Expected O, but got Unknown //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_05b8: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_04d3: Unknown result type (might be due to invalid IL or missing references) //IL_05fa: Unknown result type (might be due to invalid IL or missing references) //IL_0649: Unknown result type (might be due to invalid IL or missing references) //IL_0698: Unknown result type (might be due to invalid IL or missing references) //IL_06a7: Unknown result type (might be due to invalid IL or missing references) //IL_06ac: Unknown result type (might be due to invalid IL or missing references) //IL_06b5: Unknown result type (might be due to invalid IL or missing references) //IL_06c2: Expected O, but got Unknown //IL_065f: Unknown result type (might be due to invalid IL or missing references) //IL_0664: Unknown result type (might be due to invalid IL or missing references) //IL_075c: Unknown result type (might be due to invalid IL or missing references) //IL_0768: Unknown result type (might be due to invalid IL or missing references) //IL_076d: Unknown result type (might be due to invalid IL or missing references) //IL_0776: Unknown result type (might be due to invalid IL or missing references) //IL_077e: Unknown result type (might be due to invalid IL or missing references) //IL_078b: Expected O, but got Unknown //IL_07b9: Unknown result type (might be due to invalid IL or missing references) //IL_07c8: Unknown result type (might be due to invalid IL or missing references) //IL_07cd: Unknown result type (might be due to invalid IL or missing references) //IL_07d6: Unknown result type (might be due to invalid IL or missing references) //IL_07e3: Expected O, but got Unknown //IL_07fd: Unknown result type (might be due to invalid IL or missing references) //IL_0843: Unknown result type (might be due to invalid IL or missing references) //IL_0884: Unknown result type (might be due to invalid IL or missing references) //IL_0922: Unknown result type (might be due to invalid IL or missing references) //IL_0a11: Unknown result type (might be due to invalid IL or missing references) //IL_0998: Unknown result type (might be due to invalid IL or missing references) if (!cosReviewOpen) { return; } if (!NativeUI.IsOpen) { CloseCosmeticReview(); return; } Event current = Event.current; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { current.Use(); CloseCosmeticReview(); return; } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } if (cosReviewReasonStyle == null) { cosReviewReasonStyle = new GUIStyle(GUI.skin.textArea) { fontSize = 13, wordWrap = true }; } float num = Mathf.Min(720f, Mathf.Max(500f, (float)Screen.width - 24f)); float num2 = Mathf.Min(620f, Mathf.Max(500f, (float)Screen.height - 24f)); float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(num3 - 8f, num4 - 8f, num + 16f, num2 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.94f), 0f, 0f); GUI.Label(new Rect(num3 + 12f, num4 + 10f, num - 24f, 26f), "Cosmetic submissions", new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1 }); if (GUI.Button(new Rect(num3 + num - 90f, num4 + 10f, 78f, 26f), "Close")) { CloseCosmeticReview(); return; } GUI.Label(new Rect(num3 + 12f, num4 + 42f, num - 24f, 118f), "Approval guidelines\n1. All cosmetics must have a transparent background.\n2. All cosmetics must be tasteful, attractive, and fitting with the current cosmetics.\n3. Cosmetics must not be large just to be large, purposely distracting or flashing, or made only for one player's personal use.\n4. The cosmetic type must fit the art (for example, no mouths in the eyes section).\n5. Scale and placement must fit the body/slot and not obscure play; reject or adjust anything disproportionate or misplaced.", new GUIStyle(adminLabelStyle) { fontSize = 11, richText = true, wordWrap = true }); List list = cosReviewSubs; if (cosReviewBusy || list == null || list.Count == 0) { GUI.Label(new Rect(num3 + 12f, num4 + 164f, num - 24f, 30f), string.IsNullOrEmpty(cosReviewStatus) ? "..." : cosReviewStatus, adminLabelStyle); return; } cosReviewIdx = Mathf.Clamp(cosReviewIdx, 0, list.Count - 1); ApiClient.CosmeticSubmission cosmeticSubmission = list[cosReviewIdx]; int num5 = ((cosmeticSubmission.png_base64 != null) ? (cosmeticSubmission.png_base64.Length * 3 / 4) : 0) / 1024; string text = ((cosmeticSubmission.review_kind == "placement") ? "PLACEMENT CHANGE" : "NEW COSMETIC"); GUI.Label(new Rect(num3 + 12f, num4 + 164f, num - 24f, 22f), $"[{text}] #{cosmeticSubmission.id} rev {cosmeticSubmission.placement_revision} '{cosmeticSubmission.name}' ({cosmeticSubmission.slot}) by {cosmeticSubmission.artist_name} {num5} KB - {cosReviewIdx + 1}/{list.Count}", new GUIStyle(adminLabelStyle) { fontStyle = (FontStyle)1 }); float num6 = Mathf.Clamp(num2 - 320f, 170f, 235f); Rect bounds = default(Rect); ((Rect)(ref bounds))..ctor(num3 + 12f, num4 + 192f, num6, num6); Texture2D val = CosReviewTexture(cosmeticSubmission); if (cosmeticSubmission.render_scale <= 0f) { cosmeticSubmission.render_scale = 1f; } if (cosReviewPreviewSubId != cosmeticSubmission.id) { cosReviewPreviewSubId = cosmeticSubmission.id; cosReviewPreviewOffset = new Vector2(cosmeticSubmission.render_offset_x, cosmeticSubmission.render_offset_y); } DrawCosmeticScalePreview(bounds, val, cosmeticSubmission.render_scale, cosReviewPreviewOffset); HandleCosmeticPlacementDrag(bounds, ref cosReviewPreviewOffset, ref cosReviewDragging, ref cosReviewLastMouse); if ((Object)(object)val == (Object)null) { GUI.Label(new Rect(((Rect)(ref bounds)).x, ((Rect)(ref bounds)).center.y - 15f, ((Rect)(ref bounds)).width, 30f), " (preview failed to decode)", adminLabelStyle); } float num7 = ((Rect)(ref bounds)).xMax + 14f; float num8 = num3 + num - 12f - num7; GUI.Label(new Rect(num7, num4 + 194f, num8, 24f), $"Render scale: {cosmeticSubmission.render_scale:F2}x", new GUIStyle(adminLabelStyle) { fontSize = 15, fontStyle = (FontStyle)1 }); cosmeticSubmission.render_scale = GUI.HorizontalSlider(new Rect(num7, num4 + 222f, num8, 20f), cosmeticSubmission.render_scale, 0.5f, 2.25f); cosmeticSubmission.render_scale = Mathf.Round(cosmeticSubmission.render_scale * 20f) / 20f; if (GUI.Button(new Rect(num7, num4 + 248f, 42f, 27f), "-")) { cosmeticSubmission.render_scale -= 0.05f; } if (GUI.Button(new Rect(num7 + 50f, num4 + 248f, 42f, 27f), "+")) { cosmeticSubmission.render_scale += 0.05f; } if (GUI.Button(new Rect(num7 + 100f, num4 + 248f, Mathf.Max(64f, num8 - 100f), 27f), "Center")) { cosReviewPreviewOffset = Vector2.zero; } cosmeticSubmission.render_scale = Mathf.Clamp(cosmeticSubmission.render_scale, 0.5f, 2.25f); GUI.Label(new Rect(num7, num4 + 282f, num8, 38f), "Drag to preview positions (visual aid only - the position is\nnever saved; items spawn centered and players drag them).", new GUIStyle(adminLabelStyle) { fontSize = 12, wordWrap = true }); string text2 = ((cosmeticSubmission.approved_placement_revision > 0) ? ($"Scale: {cosmeticSubmission.approved_render_scale:F2}x (current, rev {cosmeticSubmission.approved_placement_revision})" + $" -> {cosmeticSubmission.render_scale:F2}x (proposed)" + ((Mathf.Abs(cosmeticSubmission.render_scale - cosmeticSubmission.approved_render_scale) < 0.005f) ? " [unchanged]" : "")) : $"First placement for this art — proposed scale {cosmeticSubmission.render_scale:F2}x."); GUI.Label(new Rect(num7, num4 + 324f, num8, 34f), text2, new GUIStyle(adminLabelStyle) { fontSize = 12, wordWrap = true, fontStyle = (FontStyle)1 }); float num9 = num4 + num2 - 108f; GUI.Label(new Rect(num7, num4 + 360f, num8, Mathf.Max(24f, num9 - (num4 + 366f))), "Approve saves the values shown here. New art and approved revisions take effect only after those exact values ship in a mod update.", new GUIStyle(adminLabelStyle) { fontSize = 11, wordWrap = true }); GUI.Label(new Rect(num3 + 12f, num9 + 4f, 130f, 22f), "Denial reason:", adminLabelStyle); float num10 = num4 + num2 - 46f; cosReviewDenialReason = GUI.TextArea(new Rect(num3 + 142f, num9, num - 154f, Mathf.Max(42f, num10 - num9 - 8f)), cosReviewDenialReason ?? "", 200, cosReviewReasonStyle); if (!cosReviewBusy && GUI.Button(new Rect(num3 + 12f, num10, 120f, 32f), "Approve")) { cosReviewBusy = true; int sid = cosmeticSubmission.id; string nm = cosmeticSubmission.name; ApiClient.AdminReviewCosmetic(MatchTracker.LocalSteamId, sid, approve: true, cosmeticSubmission.placement_revision, cosmeticSubmission.render_scale, cosmeticSubmission.render_offset_x, cosmeticSubmission.render_offset_y, "", delegate(bool ok, string resp) { //IL_007f: 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) cosReviewBusy = false; if (cosReviewOpen) { if (ok) { ShowNotification("Approved '" + nm + "'.", new Color(0.4f, 0.9f, 0.5f)); RemoveCosReview(sid); } else { ShowNotification("Approve failed: " + CosTrunc(resp, 90), new Color(1f, 0.45f, 0.4f), 6f); } } }); } if (!cosReviewBusy && GUI.Button(new Rect(num3 + 142f, num10, 120f, 32f), "Deny")) { int sid2 = cosmeticSubmission.id; string nm2 = cosmeticSubmission.name; string text3 = (cosReviewDenialReason ?? "").Trim(); if (string.IsNullOrEmpty(text3)) { ShowNotification("Enter a denial reason first.", new Color(1f, 0.7f, 0.4f), 4f); } else { cosReviewBusy = true; ApiClient.AdminReviewCosmetic(MatchTracker.LocalSteamId, sid2, approve: false, cosmeticSubmission.placement_revision, cosmeticSubmission.render_scale, cosmeticSubmission.render_offset_x, cosmeticSubmission.render_offset_y, text3, delegate(bool ok, string resp) { //IL_007f: 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) cosReviewBusy = false; if (cosReviewOpen) { if (ok) { ShowNotification("Denied '" + nm2 + "'.", new Color(1f, 0.7f, 0.4f), 4f); RemoveCosReview(sid2); } else { ShowNotification("Deny failed: " + CosTrunc(resp, 90), new Color(1f, 0.45f, 0.4f), 6f); } } }); } } if (list.Count > 1 && GUI.Button(new Rect(num3 + num - 132f, num10, 120f, 32f), "Next >")) { cosReviewIdx = (cosReviewIdx + 1) % list.Count; cosReviewDenialReason = ""; cosReviewDragging = false; } } public static void OpenCosmeticReleaseQueue() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (cosReviewOpen) { CloseCosmeticReview(); } cosReleaseOpen = true; cosReleaseBusy = true; cosReleaseStatus = "Loading approved cosmetics..."; cosReleaseScroll = Vector2.zero; cosReleaseCandidates.Clear(); ApiClient.FetchCosmeticReleaseCandidatesAdmin(MatchTracker.LocalSteamId, delegate(bool ok, List list, string resp) { cosReleaseBusy = false; if (cosReleaseOpen) { if (!ok) { cosReleaseStatus = "Fetch failed: " + CosTrunc(resp, 120); } else { cosReleaseCandidates = list ?? new List(); cosReleaseStatus = ((cosReleaseCandidates.Count == 0) ? "Nothing is waiting for a client update." : ""); } } }); } private static string CosReleaseSafe(string value) { return string.IsNullOrEmpty(value) ? "" : value.Replace("<", "[").Replace(">", "]"); } private static void DrawCosmeticReleaseQueue() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0164: 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_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown //IL_01aa: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Expected O, but got Unknown //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_05e4: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Expected O, but got Unknown //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Expected O, but got Unknown //IL_050a: Unknown result type (might be due to invalid IL or missing references) //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Expected O, but got Unknown //IL_056c: Unknown result type (might be due to invalid IL or missing references) //IL_0587: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_0595: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Expected O, but got Unknown if (!cosReleaseOpen) { return; } if (!NativeUI.IsOpen) { cosReleaseOpen = false; return; } Event current = Event.current; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { current.Use(); cosReleaseOpen = false; return; } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } float num = Mathf.Min(780f, Mathf.Max(520f, (float)Screen.width - 24f)); float num2 = Mathf.Min(600f, Mathf.Max(480f, (float)Screen.height - 24f)); float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(num3 - 8f, num4 - 8f, num + 16f, num2 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.96f), 0f, 0f); GUI.Label(new Rect(num3 + 12f, num4 + 10f, num - 118f, 28f), "Approved cosmetics awaiting a client update", new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1 }); if (GUI.Button(new Rect(num3 + num - 92f, num4 + 10f, 80f, 28f), "Close")) { cosReleaseOpen = false; return; } GUI.Label(new Rect(num3 + 12f, num4 + 45f, num - 24f, 58f), "This is the implementation queue. Approval saves an exact PNG, scale, and offset, but installed clients do not change until those values are copied into the append-only catalog and released. Rows disappear only after that revision is marked published.", new GUIStyle(adminLabelStyle) { fontSize = 12, wordWrap = true }); if (cosReleaseBusy || cosReleaseCandidates.Count == 0) { GUI.Label(new Rect(num3 + 12f, num4 + 112f, num - 150f, 30f), string.IsNullOrEmpty(cosReleaseStatus) ? "..." : cosReleaseStatus, adminLabelStyle); if (!cosReleaseBusy && GUI.Button(new Rect(num3 + num - 132f, num4 + 108f, 120f, 28f), "Refresh")) { OpenCosmeticReleaseQueue(); } return; } float num5 = num4 + 108f; float num6 = num2 - 158f; float num7 = 104f; float num8 = num - 45f; cosReleaseScroll = GUI.BeginScrollView(new Rect(num3 + 12f, num5, num - 24f, num6), cosReleaseScroll, new Rect(0f, 0f, num8, Mathf.Max(num6 - 2f, (float)cosReleaseCandidates.Count * num7))); for (int i = 0; i < cosReleaseCandidates.Count; i++) { ApiClient.CosmeticReleaseCandidate cosmeticReleaseCandidate = cosReleaseCandidates[i]; float num9 = (float)i * num7; GUI.DrawTexture(new Rect(0f, num9, num8, num7 - 6f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.11f, 0.13f, 0.17f, 0.98f), 0f, 4f); string arg = (cosmeticReleaseCandidate.catalog_ready ? "PLACEMENT UPDATE" : "NEW COSMETIC"); string text = (cosmeticReleaseCandidate.catalog_ready ? $"Published rev {cosmeticReleaseCandidate.published_placement_revision} remains live" : "Not yet available in any released client"); GUI.Label(new Rect(10f, num9 + 7f, num8 - 20f, 23f), $"{arg} #{cosmeticReleaseCandidate.id} {CosReleaseSafe(cosmeticReleaseCandidate.name)} " + "by " + CosReleaseSafe(cosmeticReleaseCandidate.artist_name) + "", new GUIStyle(adminLabelStyle) { fontSize = 14, richText = true }); GUI.Label(new Rect(10f, num9 + 31f, num8 - 20f, 21f), CosReleaseSafe(cosmeticReleaseCandidate.shop_sku) + " (" + cosmeticReleaseCandidate.slot + ", " + $"{Mathf.Max(0, cosmeticReleaseCandidate.png_bytes) / 1024} KB)", new GUIStyle(adminLabelStyle) { fontSize = 12, richText = true }); GUI.Label(new Rect(10f, num9 + 53f, num8 - 20f, 21f), $"Approved rev {cosmeticReleaseCandidate.placement_revision}: {cosmeticReleaseCandidate.render_scale:F2}x", new GUIStyle(adminLabelStyle) { fontSize = 13, fontStyle = (FontStyle)1 }); GUI.Label(new Rect(10f, num9 + 75f, num8 - 20f, 20f), "" + text + "", new GUIStyle(adminLabelStyle) { fontSize = 12, richText = true }); } GUI.EndScrollView(); GUI.Label(new Rect(num3 + 12f, num4 + num2 - 38f, num - 160f, 25f), $"{cosReleaseCandidates.Count} approved revision(s) waiting", adminLabelStyle); if (GUI.Button(new Rect(num3 + num - 132f, num4 + num2 - 42f, 120f, 30f), "Refresh")) { OpenCosmeticReleaseQueue(); } } public static void OpenFlagEvidence(ApiClient.FlaggedMatchEntry entry) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (entry != null) { flagEvidenceEntry = entry; flagEvidenceScroll = Vector2.zero; flagEvidenceBusy = false; flagRepairConfirm = false; flagEvidenceOpen = true; } } private static void CloseFlagEvidence() { flagEvidenceOpen = false; flagEvidenceBusy = false; flagRepairConfirm = false; flagEvidenceEntry = null; } private static void SubmitFlagEvidenceVerdict(string action) { ApiClient.FlaggedMatchEntry entry = flagEvidenceEntry; string adminId = MatchTracker.LocalSteamId; if (entry == null || string.IsNullOrEmpty(entry.id) || string.IsNullOrEmpty(adminId)) { return; } flagEvidenceBusy = true; ApiClient.AdminReviewFlag(adminId, entry.id, action, entry.discord_evidence_revision, delegate(bool ok, string resp) { //IL_0054: 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) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) flagEvidenceBusy = false; if (flagEvidenceOpen && flagEvidenceEntry == entry) { if (!ok) { ShowNotification("Flag review failed: " + CosTrunc(resp, 100), new Color(1f, 0.45f, 0.4f), 6f); } else { bool flag = resp != null && (resp.Contains("\"restoration_required\":true") || resp.Contains("\"restoration_required\": true")); ShowNotification(flag ? "False positive recorded. The auto-invalidation still needs a manual reward/series repair." : ((action == "confirmed_cheat") ? "Flag marked as confirmed." : "Flag marked false positive."), flag ? new Color(1f, 0.72f, 0.32f) : new Color(0.45f, 0.9f, 0.55f), flag ? 9f : 5f); CloseFlagEvidence(); ApiClient.FetchFlaggedMatches(adminId); } } }); } private static void SubmitFlagRestorationComplete() { ApiClient.FlaggedMatchEntry entry = flagEvidenceEntry; string adminId = MatchTracker.LocalSteamId; if (entry == null || !entry.restoration_required || string.IsNullOrEmpty(entry.id) || string.IsNullOrEmpty(adminId)) { return; } flagEvidenceBusy = true; ApiClient.AdminResolveFlagRestoration(adminId, entry.id, delegate(bool ok, string resp) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) flagEvidenceBusy = false; if (flagEvidenceOpen && flagEvidenceEntry == entry) { if (!ok) { ShowNotification("Could not close repair reminder: " + CosTrunc(resp, 100), new Color(1f, 0.45f, 0.4f), 6f); } else { ShowNotification("Manual restoration marked complete.", new Color(0.45f, 0.9f, 0.55f)); CloseFlagEvidence(); ApiClient.FetchFlaggedMatches(adminId); } } }); } private static void DrawFlagEvidence() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: 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_009b: Expected O, but got Unknown //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Expected O, but got Unknown //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_044f: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Expected O, but got Unknown //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Unknown result type (might be due to invalid IL or missing references) //IL_050d: Unknown result type (might be due to invalid IL or missing references) //IL_0512: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Expected O, but got Unknown //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_05ec: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Unknown result type (might be due to invalid IL or missing references) //IL_0574: Unknown result type (might be due to invalid IL or missing references) //IL_0580: Expected O, but got Unknown //IL_0592: Unknown result type (might be due to invalid IL or missing references) //IL_0668: Unknown result type (might be due to invalid IL or missing references) //IL_078d: Unknown result type (might be due to invalid IL or missing references) //IL_06d0: Unknown result type (might be due to invalid IL or missing references) //IL_07dc: Unknown result type (might be due to invalid IL or missing references) //IL_071c: Unknown result type (might be due to invalid IL or missing references) //IL_074d: Unknown result type (might be due to invalid IL or missing references) if (!flagEvidenceOpen) { return; } if (!NativeUI.IsOpen || flagEvidenceEntry == null) { CloseFlagEvidence(); return; } Event current = Event.current; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { current.Use(); CloseFlagEvidence(); return; } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } ApiClient.FlaggedMatchEntry flaggedMatchEntry = flagEvidenceEntry; float num = Mathf.Min(920f, Mathf.Max(540f, (float)Screen.width - 24f)); float num2 = Mathf.Min(700f, Mathf.Max(500f, (float)Screen.height - 24f)); float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(num3 - 8f, num4 - 8f, num + 16f, num2 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.96f), 0f, 0f); GUIStyle val = new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1, richText = false }; GUI.Label(new Rect(num3 + 12f, num4 + 10f, num - 112f, 28f), "Flag evidence: " + flaggedMatchEntry.flag_reason, val); if (GUI.Button(new Rect(num3 + num - 90f, num4 + 10f, 78f, 26f), "Close")) { CloseFlagEvidence(); return; } string text = flaggedMatchEntry.p1_name + " [" + flaggedMatchEntry.p1_steam_id + "]\n" + flaggedMatchEntry.p2_name + " [" + flaggedMatchEntry.p2_steam_id + "]\nSuspect(s): " + flaggedMatchEntry.suspect_steam_text; string text2 = (flaggedMatchEntry.is_ranked ? "Ranked" : "Casual") + " | game code " + flaggedMatchEntry.game_code + " | match " + flaggedMatchEntry.match_id + (string.IsNullOrEmpty(flaggedMatchEntry.series_id) ? "" : (" | series " + flaggedMatchEntry.series_id)) + "\n" + flaggedMatchEntry.score_summary + "\nDetector action: " + (flaggedMatchEntry.auto_invalidated ? "auto-invalidated" : "advisory only") + "; match is currently " + (flaggedMatchEntry.match_invalidated ? "invalidated" : "valid") + ((flaggedMatchEntry.match_invalidated && !string.IsNullOrEmpty(flaggedMatchEntry.match_invalidation_reason)) ? (" (" + flaggedMatchEntry.match_invalidation_reason + ")") : "") + "." + (flaggedMatchEntry.restoration_required ? ("\nFALSE POSITIVE RECORDED — manual reward/series repair remains required." + (flagRepairConfirm ? "\nCONFIRM ONLY after rewards, rating, and series state have been repaired." : "")) : ""); string[] array = new string[8] { "Participants / Steam IDs", "Match and point state", "Detector evidence", "Point progression", "Cards picked", "Combat and input telemetry", "FPS / connection telemetry", "Reporter context" }; string[] array2 = new string[8] { text, text2, flaggedMatchEntry.evidence_summary, flaggedMatchEntry.point_progress, flaggedMatchEntry.cards_summary, flaggedMatchEntry.telemetry_summary, flaggedMatchEntry.connection_summary, flaggedMatchEntry.match_context }; GUIStyle val2 = new GUIStyle(adminLabelStyle) { fontSize = 13, fontStyle = (FontStyle)1, richText = false }; GUIStyle val3 = new GUIStyle(adminLabelStyle) { fontSize = 12, wordWrap = true, richText = false }; float num5 = num - 54f; float num6 = 10f; for (int i = 0; i < array.Length; i++) { num6 += 20f; num6 += Mathf.Max(22f, val3.CalcHeight(new GUIContent(array2[i] ?? "not recorded"), num5)); num6 += 10f; } Rect val4 = default(Rect); ((Rect)(ref val4))..ctor(num3 + 12f, num4 + 46f, num - 24f, num2 - 104f); flagEvidenceScroll = GUI.BeginScrollView(val4, flagEvidenceScroll, new Rect(0f, 0f, ((Rect)(ref val4)).width - 18f, num6)); float num7 = 4f; for (int j = 0; j < array.Length; j++) { GUI.Label(new Rect(4f, num7, num5, 20f), array[j], val2); num7 += 20f; string text3 = (string.IsNullOrEmpty(array2[j]) ? "not recorded" : array2[j]); float num8 = Mathf.Max(22f, val3.CalcHeight(new GUIContent(text3), num5)); GUI.Label(new Rect(4f, num7, num5, num8), text3, val3); num7 += num8 + 10f; } GUI.EndScrollView(); float num9 = num4 + num2 - 46f; if (GUI.Button(new Rect(num3 + 12f, num9, 92f, 30f), "Copy P1 ID")) { GUIUtility.systemCopyBuffer = flaggedMatchEntry.p1_steam_id ?? ""; } if (GUI.Button(new Rect(num3 + 112f, num9, 92f, 30f), "Copy P2 ID")) { GUIUtility.systemCopyBuffer = flaggedMatchEntry.p2_steam_id ?? ""; } if (GUI.Button(new Rect(num3 + 212f, num9, 104f, 30f), "Copy game ID")) { GUIUtility.systemCopyBuffer = flaggedMatchEntry.game_code ?? flaggedMatchEntry.match_id ?? ""; } if (flaggedMatchEntry.restoration_required) { if (!flagEvidenceBusy && !flagRepairConfirm && GUI.Button(new Rect(num3 + num - 182f, num9, 170f, 30f), "Mark repair complete...")) { flagRepairConfirm = true; } else if (!flagEvidenceBusy && flagRepairConfirm) { if (GUI.Button(new Rect(num3 + num - 292f, num9, 140f, 30f), "Not repaired yet")) { flagRepairConfirm = false; } if (GUI.Button(new Rect(num3 + num - 142f, num9, 130f, 30f), "Repair is done")) { SubmitFlagRestorationComplete(); } } } else { if (!flagEvidenceBusy && GUI.Button(new Rect(num3 + num - 292f, num9, 140f, 30f), flaggedMatchEntry.auto_invalidated ? "False+ (manual fix)" : "False positive")) { SubmitFlagEvidenceVerdict("false_positive"); } if (!flagEvidenceBusy && GUI.Button(new Rect(num3 + num - 142f, num9, 130f, 30f), "Confirm cheat")) { SubmitFlagEvidenceVerdict("confirmed_cheat"); } } } private static void DrawArtistInput() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Invalid comparison between Unknown and I4 //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Invalid comparison between Unknown and I4 //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Expected O, but got Unknown //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Invalid comparison between Unknown and I4 //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) if (!artistPromptOpen) { return; } if (!NativeUI.IsOpen) { artistPromptOpen = false; artistPromptOnSubmit = null; return; } Event current = Event.current; bool flag = false; bool flag2 = false; if (current != null && (int)current.type == 4) { if ((int)current.keyCode == 27) { flag2 = true; current.Use(); } else if ((int)current.keyCode == 13 || (int)current.keyCode == 271) { flag = true; current.Use(); } } if (adminFieldStyle == null) { adminFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 15 }; } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } float num = 520f; float num2 = 168f; float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(num3 - 8f, num4 - 8f, num + 16f, num2 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.93f), 0f, 0f); GUI.Label(new Rect(num3 + 12f, num4 + 10f, num - 24f, 26f), artistPromptTitle, new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1 }); GUI.Label(new Rect(num3 + 12f, num4 + 44f, num - 24f, 20f), artistPromptLabel, adminLabelStyle); artistPromptValue = GUI.TextField(new Rect(num3 + 12f, num4 + 68f, num - 24f, 28f), artistPromptValue ?? "", adminFieldStyle); if (GUI.Button(new Rect(num3 + 12f, num4 + num2 - 40f, 110f, 30f), "Cancel")) { flag2 = true; } if (GUI.Button(new Rect(num3 + num - 122f, num4 + num2 - 40f, 110f, 30f), "Submit")) { flag = true; } if (flag2) { artistPromptOpen = false; artistPromptOnSubmit = null; } else if (flag) { Action action = artistPromptOnSubmit; string text = artistPromptValue; artistPromptOpen = false; artistPromptOnSubmit = null; try { action?.Invoke(text?.Trim() ?? ""); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ARTIST] prompt action: " + ex.Message)); } } } private static void DrawAdminPrompt() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 //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_008d: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00b8: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) if (!adminPromptOpen) { return; } if (!NativeUI.IsOpen) { adminPromptOpen = false; return; } Event current = Event.current; bool flag = false; bool flag2 = false; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { flag2 = true; current.Use(); } if (adminFieldStyle == null) { adminFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 15 }; } if (adminLabelStyle == null) { adminLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14 }; } float num = 560f; float num2 = 220f; float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(num3 - 8f, num4 - 8f, num + 16f, num2 + 16f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.92f), 0f, 0f); string text = adminPromptMode switch { "ban" => "Ban a player", "grant" => "Grant an achievement", "reverse" => "Reverse a ranked series", _ => "Admin action", }; GUI.Label(new Rect(num3 + 10f, num4 + 8f, num - 20f, 24f), text, new GUIStyle(adminLabelStyle) { fontSize = 17, fontStyle = (FontStyle)1 }); string text2; string text3; switch (adminPromptMode) { case "ban": text2 = "Target Steam ID"; text3 = "Reason"; break; case "grant": text2 = "Target Steam ID"; text3 = "Achievement key"; break; case "reverse": text2 = "Series ID (UUID)"; text3 = "Reason"; break; default: text2 = "ID"; text3 = "Detail"; break; } GUI.Label(new Rect(num3 + 10f, num4 + 38f, 200f, 20f), text2, adminLabelStyle); adminInputA = GUI.TextField(new Rect(num3 + 10f, num4 + 60f, num - 20f, 26f), adminInputA ?? "", adminFieldStyle); GUI.Label(new Rect(num3 + 10f, num4 + 96f, 200f, 20f), text3, adminLabelStyle); if (adminPromptMode == "grant") { if (GUI.Button(new Rect(num3 + 10f, num4 + 118f, 30f, 26f), "<")) { int num5 = Math.Max(0, Array.IndexOf(ADMIN_ACHIEVEMENT_KEYS, adminInputB)); num5 = (num5 - 1 + ADMIN_ACHIEVEMENT_KEYS.Length) % ADMIN_ACHIEVEMENT_KEYS.Length; adminInputB = ADMIN_ACHIEVEMENT_KEYS[num5]; } GUI.Label(new Rect(num3 + 50f, num4 + 122f, num - 100f, 22f), adminInputB, adminLabelStyle); if (GUI.Button(new Rect(num3 + num - 40f, num4 + 118f, 30f, 26f), ">")) { int num6 = Math.Max(0, Array.IndexOf(ADMIN_ACHIEVEMENT_KEYS, adminInputB)); num6 = (num6 + 1) % ADMIN_ACHIEVEMENT_KEYS.Length; adminInputB = ADMIN_ACHIEVEMENT_KEYS[num6]; } } else { adminInputB = GUI.TextField(new Rect(num3 + 10f, num4 + 118f, num - 20f, 26f), adminInputB ?? "", adminFieldStyle); } if (GUI.Button(new Rect(num3 + 10f, num4 + num2 - 36f, 100f, 28f), "Cancel")) { flag2 = true; } if (GUI.Button(new Rect(num3 + num - 110f, num4 + num2 - 36f, 100f, 28f), "Submit")) { flag = true; } if (flag2) { adminPromptOpen = false; } else { if (!flag) { return; } string sid = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(sid)) { Plugin.Log.LogWarning((object)"[ADMIN] No local Steam ID"); adminPromptOpen = false; return; } string text4 = (adminInputA ?? "").Trim(); string text5 = (adminInputB ?? "").Trim(); if (string.IsNullOrEmpty(text4)) { return; } Action callback = delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)("[ADMIN] " + adminPromptMode + " -> " + (ok ? "OK" : "FAIL") + " " + resp)); if (ok) { ApiClient.FetchFlaggedMatches(sid); ApiClient.FetchBannedUsers(sid); } }; switch (adminPromptMode) { case "ban": ApiClient.AdminBan(sid, text4, string.IsNullOrEmpty(text5) ? "violation" : text5, callback); break; case "grant": ApiClient.AdminGrantAchievement(sid, text4, text5, callback); break; case "reverse": ApiClient.AdminReverseSeries(sid, text4, string.IsNullOrEmpty(text5) ? "admin_reverse" : text5, callback); break; } adminPromptOpen = false; } } public static void OpenBugReportModal() { bugModalOpen = true; bugSubmitStatus = ""; bugSubmitting = false; } private static void EnsureBugStyles() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0051: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0076: 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_0089: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown if (bugTitleStyle == null) { bugTitleStyle = new GUIStyle(GUI.skin.label) { fontSize = 19, fontStyle = (FontStyle)1, richText = true, alignment = (TextAnchor)3 }; bugLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 13, richText = true }; bugFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 14 }; bugAreaStyle = new GUIStyle(GUI.skin.textArea) { fontSize = 13, wordWrap = true }; bugButtonStyle = new GUIStyle(GUI.skin.button) { fontSize = 13 }; GUIStyle val = new GUIStyle(GUI.skin.button) { fontSize = 13, fontStyle = (FontStyle)1 }; val.normal.background = Texture2D.whiteTexture; val.normal.textColor = Color.black; val.hover.background = Texture2D.whiteTexture; val.hover.textColor = Color.black; val.active.background = Texture2D.whiteTexture; val.active.textColor = Color.black; bugBtnPickedStyle = val; } } private static void DrawBugReportModal() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_00ad: 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_0104: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: 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) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Unknown result type (might be due to invalid IL or missing references) //IL_0569: Unknown result type (might be due to invalid IL or missing references) //IL_056b: Unknown result type (might be due to invalid IL or missing references) //IL_0579: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) //IL_05b6: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Unknown result type (might be due to invalid IL or missing references) //IL_0604: Unknown result type (might be due to invalid IL or missing references) //IL_0633: Unknown result type (might be due to invalid IL or missing references) //IL_0644: Unknown result type (might be due to invalid IL or missing references) //IL_0681: Unknown result type (might be due to invalid IL or missing references) //IL_0692: Unknown result type (might be due to invalid IL or missing references) //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_073b: Unknown result type (might be due to invalid IL or missing references) //IL_06b8: Unknown result type (might be due to invalid IL or missing references) //IL_06bd: Unknown result type (might be due to invalid IL or missing references) //IL_06c6: Unknown result type (might be due to invalid IL or missing references) //IL_06ce: Unknown result type (might be due to invalid IL or missing references) //IL_06d8: Expected O, but got Unknown //IL_06d8: Unknown result type (might be due to invalid IL or missing references) //IL_077f: Unknown result type (might be due to invalid IL or missing references) //IL_07e1: Unknown result type (might be due to invalid IL or missing references) //IL_0833: Unknown result type (might be due to invalid IL or missing references) if (!bugModalOpen) { return; } if (!NativeUI.IsOpen) { bugModalOpen = false; return; } EnsureBugStyles(); Event current = Event.current; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { bugModalOpen = false; current.Use(); return; } float num = 680f; float num2 = 580f; float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.45f), 0f, 0f); GUI.DrawTexture(new Rect(num3 - 10f, num4 - 10f, num + 20f, num2 + 20f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.07f, 0.08f, 0.11f, 0.97f), 0f, 0f); GUI.DrawTexture(new Rect(num3 - 10f, num4 - 10f, num + 20f, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(1f, 1f, 1f, 0.4f), 0f, 0f); GUI.Label(new Rect(num3, num4, num, 28f), "Report a Bug", bugTitleStyle); GUI.Label(new Rect(num3, num4 + 30f, num, 18f), "Reports go to the mod team. Be specific — what happened, when, what you were doing.", bugLabelStyle); GUI.Label(new Rect(num3, num4 + 56f, 120f, 22f), "Severity:", bugLabelStyle); for (int i = 0; i < BUG_SEVERITIES.Length; i++) { bool flag = i == bugSeverityIdx; if (GUI.Button(new Rect(num3 + 100f + (float)(i * 88), num4 + 54f, 84f, 26f), BUG_SEVERITIES[i].ToUpper(), flag ? bugBtnPickedStyle : bugButtonStyle)) { bugSeverityIdx = i; } } GUI.Label(new Rect(num3, num4 + 92f, 120f, 22f), "Category:", bugLabelStyle); for (int j = 0; j < BUG_CATEGORIES.Length; j++) { bool flag2 = j == bugCategoryIdx; if (GUI.Button(new Rect(num3 + 100f + (float)(j * 88), num4 + 90f, 84f, 26f), BUG_CATEGORIES[j].ToUpper(), flag2 ? bugBtnPickedStyle : bugButtonStyle)) { bugCategoryIdx = j; } } GUI.Label(new Rect(num3, num4 + 126f, num, 18f), "What happened? (required)", bugLabelStyle); bugDescScroll = GUI.BeginScrollView(new Rect(num3, num4 + 146f, num, 140f), bugDescScroll, new Rect(0f, 0f, num - 20f, (float)Mathf.Max(140, (bugDescription?.Length ?? 0) / 4))); bugDescription = GUI.TextArea(new Rect(0f, 0f, num - 20f, (float)Mathf.Max(140, (bugDescription?.Length ?? 0) / 4)), bugDescription ?? "", 4000, bugAreaStyle); GUI.EndScrollView(); GUI.Label(new Rect(num3, num4 + 296f, num, 18f), "How to reproduce? (optional)", bugLabelStyle); bugReproScroll = GUI.BeginScrollView(new Rect(num3, num4 + 316f, num, 100f), bugReproScroll, new Rect(0f, 0f, num - 20f, (float)Mathf.Max(100, (bugRepro?.Length ?? 0) / 4))); bugRepro = GUI.TextArea(new Rect(0f, 0f, num - 20f, (float)Mathf.Max(100, (bugRepro?.Length ?? 0) / 4)), bugRepro ?? "", 4000, bugAreaStyle); GUI.EndScrollView(); float num5 = num3; float num6 = 280f; Rect val = default(Rect); ((Rect)(ref val))..ctor(num5, num4 + 428f, num6, 26f); if (GUI.Button(val, GUIContent.none, GUIStyle.none)) { bugSendLogs = !bugSendLogs; } Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(num5 + 2f, num4 + 430f, 20f, 20f); Color val3 = (bugSendLogs ? new Color(0.25f, 0.7f, 0.3f, 0.95f) : new Color(0.18f, 0.18f, 0.22f, 0.95f)); GUI.DrawTexture(val2, (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, val3, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, ((Rect)(ref val2)).width, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, Color.white, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + ((Rect)(ref val2)).height - 1f, ((Rect)(ref val2)).width, 1f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, Color.white, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, 1f, ((Rect)(ref val2)).height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, Color.white, 0f, 0f); GUI.DrawTexture(new Rect(((Rect)(ref val2)).x + ((Rect)(ref val2)).width - 1f, ((Rect)(ref val2)).y, 1f, ((Rect)(ref val2)).height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, Color.white, 0f, 0f); if (bugSendLogs) { GUIStyle val4 = new GUIStyle(bugLabelStyle) { fontSize = 16, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; GUI.Label(val2, "X", val4); } GUI.Label(new Rect(num5 + 28f, num4 + 428f, num6 - 32f, 26f), "Attach game logs (recommended)", bugLabelStyle); float num7 = num5 + num6 + 16f; if (GUI.Button(new Rect(num7, num4 + 428f, 140f, 24f), "Preview logs", bugButtonStyle)) { OpenLogViewer(); } if (!string.IsNullOrEmpty(bugSubmitStatus)) { GUI.Label(new Rect(num3, num4 + 460f, num, 20f), bugSubmitStatus, bugLabelStyle); } bool flag3 = bugSubmitting || string.IsNullOrEmpty(bugDescription) || bugDescription.Trim().Length < 4; GUI.enabled = !bugSubmitting; if (GUI.Button(new Rect(num3, num4 + num2 - 44f, 120f, 30f), "Cancel", bugButtonStyle)) { bugModalOpen = false; GUI.enabled = true; return; } GUI.enabled = !flag3; if (GUI.Button(new Rect(num3 + num - 160f, num4 + num2 - 44f, 160f, 30f), bugSubmitting ? "Submitting..." : "Submit Report", bugButtonStyle)) { SubmitBugReportNow(); } GUI.enabled = true; } private static void SubmitBugReportNow() { bugSubmitting = true; bugSubmitStatus = "Submitting..."; string localSteamId = MatchTracker.LocalSteamId; string displayName = MatchTracker.LocalDisplayName ?? ""; string description = (bugDescription ?? "").Trim(); string reproSteps = (bugRepro ?? "").Trim(); string severity = BUG_SEVERITIES[Mathf.Clamp(bugSeverityIdx, 0, BUG_SEVERITIES.Length - 1)]; string category = BUG_CATEGORIES[Mathf.Clamp(bugCategoryIdx, 0, BUG_CATEGORIES.Length - 1)]; string logText = (bugSendLogs ? BuildLogBundle() : null); ApiClient.SubmitBugReport(localSteamId, displayName, description, reproSteps, severity, category, logText, delegate(bool ok, string resp) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) bugSubmitting = false; if (ok) { int num = ApiClient.ExtractJsonIntPublic(resp ?? "", "bug_number"); string text = ((num > 0) ? $" Filed as #{num}." : ""); bugSubmitStatus = "Sent! Thank you." + text + ""; bugDescription = ""; bugRepro = ""; string text2 = ((num > 0) ? $"Bug report sent. Thanks! (#{num})" : "Bug report sent. Thanks!"); ShowNotification(text2, new Color(0.5f, 1f, 0.5f)); bugModalOpen = false; } else { bugSubmitStatus = "Failed: " + (resp ?? "").Replace("\n", " ") + ""; } }); } private static string BuildLogBundle() { string text = ApiClient.ReadLogTail(BepInExLogPath(), 1500000); string text2 = ApiClient.ReadLogTail(BepInExLogPreviousPath(), 1000000); string text3 = ApiClient.ReadLogTail(UnityLogPath(), 1000000); StringBuilder stringBuilder = new StringBuilder(); if (!string.IsNullOrEmpty(text2)) { stringBuilder.AppendLine($"===== BepInEx LogOutput-prev.log [{BepInExLogPreviousPath()}] ({text2.Length:N0} chars, cap {1000000:N0}) ====="); stringBuilder.AppendLine(text2); stringBuilder.AppendLine(); } stringBuilder.AppendLine(string.Format("===== BepInEx LogOutput.log [{0}] ({1:N0} chars, cap {2:N0}) =====", BepInExLogPath() ?? "(path unknown)", text?.Length ?? 0, 1500000)); stringBuilder.AppendLine(string.IsNullOrEmpty(text) ? "(not found)" : text); stringBuilder.AppendLine(); stringBuilder.AppendLine(string.Format("===== Unity Player.log [{0}] ({1:N0} chars, cap {2:N0}) =====", UnityLogPath() ?? "(path unknown)", text3?.Length ?? 0, 1000000)); stringBuilder.AppendLine(string.IsNullOrEmpty(text3) ? "(not found)" : text3); return stringBuilder.ToString(); } private static string BepInExDir() { try { string location = typeof(Plugin).Assembly.Location; if (string.IsNullOrEmpty(location)) { return null; } string directoryName = Path.GetDirectoryName(Path.GetDirectoryName(location)); if (string.IsNullOrEmpty(directoryName)) { return null; } return Path.GetDirectoryName(directoryName); } catch { return null; } } private static string GameRoot() { try { string text = BepInExDir(); return string.IsNullOrEmpty(text) ? null : Path.GetDirectoryName(text); } catch { return null; } } private static string BepInExLogPath() { string text = BepInExDir(); if (string.IsNullOrEmpty(text)) { return null; } return Path.Combine(text, "LogOutput.log"); } public static string BepInExLogPathPublic() { return BepInExLogPath(); } public static string BepInExLogPreviousPath() { string text = BepInExDir(); return string.IsNullOrEmpty(text) ? null : Path.Combine(text, "LogOutput-prev.log"); } private static string UnityLogPath() { try { string text = GameRoot(); if (!string.IsNullOrEmpty(text)) { string text2 = Path.Combine(text, "output_log.txt"); if (File.Exists(text2)) { return text2; } } string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); if (!string.IsNullOrEmpty(folderPath)) { string[] array = new string[2] { "Landfall Games", "Landfall" }; foreach (string text3 in array) { string fullPath = Path.GetFullPath(Path.Combine(folderPath, "..", "LocalLow", text3, "ROUNDS", "Player.log")); if (File.Exists(fullPath)) { return fullPath; } } } } catch { } return null; } private static void OpenLogViewer() { logViewerOpen = true; logViewerBepCache = ApiClient.ReadLogTail(BepInExLogPath(), 400000); logViewerBepPrevCache = ApiClient.ReadLogTail(BepInExLogPreviousPath(), 400000); logViewerUniCache = ApiClient.ReadLogTail(UnityLogPath(), 400000); Plugin.Log.LogInfo((object)($"[BUG-REPORT-VIEWER] bep_path={BepInExLogPath()} bep_chars={logViewerBepCache?.Length ?? 0}; " + $"prev_path={BepInExLogPreviousPath()} prev_chars={logViewerBepPrevCache?.Length ?? 0}; " + $"uni_path={UnityLogPath()} uni_chars={logViewerUniCache?.Length ?? 0}")); } private static void DrawLogViewerModal() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_00fb: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Invalid comparison between Unknown and I4 //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Invalid comparison between Unknown and I4 //IL_0191: 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) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) if (!logViewerOpen) { return; } if (!NativeUI.IsOpen) { logViewerOpen = false; return; } if (logViewerStyle == null) { logViewerStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, richText = false, alignment = (TextAnchor)0, wordWrap = false }; logViewerTabStyle = new GUIStyle(GUI.skin.button) { fontSize = 13 }; GUIStyle val = new GUIStyle(GUI.skin.button) { fontSize = 13, fontStyle = (FontStyle)1 }; val.normal.background = Texture2D.whiteTexture; val.normal.textColor = Color.black; val.hover.background = Texture2D.whiteTexture; val.hover.textColor = Color.black; logViewerTabActiveStyle = val; } Event current = Event.current; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { logViewerOpen = false; current.Use(); return; } float num = Mathf.Min(Screen.width - 60, 1100); float num2 = Mathf.Min(Screen.height - 80, 720); float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.55f), 0f, 0f); GUI.DrawTexture(new Rect(num3 - 10f, num4 - 10f, num + 20f, num2 + 20f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.05f, 0.06f, 0.08f, 0.98f), 0f, 0f); GUI.Label(new Rect(num3, num4, num, 24f), "Game logs (tail) — included with your report when the box is checked.", bugLabelStyle ?? GUI.skin.label); if (GUI.Button(new Rect(num3, num4 + 28f, 160f, 26f), "BepInEx (current)", (logViewerTab == 0) ? logViewerTabActiveStyle : logViewerTabStyle)) { logViewerTab = 0; } if (GUI.Button(new Rect(num3 + 168f, num4 + 28f, 180f, 26f), "BepInEx (prev session)", (logViewerTab == 1) ? logViewerTabActiveStyle : logViewerTabStyle)) { logViewerTab = 1; } if (GUI.Button(new Rect(num3 + 356f, num4 + 28f, 140f, 26f), "Unity / Game", (logViewerTab == 2) ? logViewerTabActiveStyle : logViewerTabStyle)) { logViewerTab = 2; } if (GUI.Button(new Rect(num3 + num - 200f, num4 + 28f, 90f, 26f), "Refresh", logViewerTabStyle)) { logViewerBepCache = ApiClient.ReadLogTail(BepInExLogPath(), 400000); logViewerBepPrevCache = ApiClient.ReadLogTail(BepInExLogPreviousPath(), 400000); logViewerUniCache = ApiClient.ReadLogTail(UnityLogPath(), 400000); } if (GUI.Button(new Rect(num3 + num - 100f, num4 + 28f, 100f, 26f), "Close", logViewerTabStyle)) { logViewerOpen = false; return; } string text; string text2; switch (logViewerTab) { case 0: text = logViewerBepCache; text2 = BepInExLogPath(); break; case 1: text = logViewerBepPrevCache; text2 = BepInExLogPreviousPath(); break; default: text = logViewerUniCache; text2 = UnityLogPath(); break; } if (string.IsNullOrEmpty(text)) { text = ((logViewerTab != 1) ? ("(no log content read from: " + (text2 ?? "unknown path") + ")") : ("(no previous-session log yet — gets written by the mod when ROUNDS is closed cleanly, so on first ever launch this is empty)\n\nExpected path: " + (text2 ?? "unknown"))); } float num5 = num4 + 64f; float num6 = num2 - 70f; float num7 = num - 30f; float num8 = (float)text.Length / 110f + 4f; float num9 = Mathf.Max(num6 - 12f, num8 * 14f); logViewerScroll = GUI.BeginScrollView(new Rect(num3, num5, num, num6), logViewerScroll, new Rect(0f, 0f, num7, num9)); GUI.Label(new Rect(4f, 4f, num7 - 8f, num9 - 4f), text, logViewerStyle); GUI.EndScrollView(); } private static bool IsAnotherTextInputActive() { try { if (s_eventSystemType == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { s_eventSystemType = assembly.GetType("UnityEngine.EventSystems.EventSystem"); if (s_eventSystemType != null) { break; } } if (s_eventSystemType == null) { return false; } BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public; s_eventSystemCurrentProp = s_eventSystemType.GetProperty("current", bindingAttr); s_eventSystemSelectedProp = s_eventSystemType.GetProperty("currentSelectedGameObject", BindingFlags.Instance | BindingFlags.Public); } object obj = s_eventSystemCurrentProp?.GetValue(null); if (obj == null) { return false; } object? obj2 = s_eventSystemSelectedProp?.GetValue(obj); GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)val == (Object)null) { return false; } if (!val.activeInHierarchy) { return false; } Component[] components = val.GetComponents(); foreach (Component val2 in components) { if ((Object)(object)val2 == (Object)null) { continue; } string name = ((object)val2).GetType().Name; if (name != "InputField" && name != "TMP_InputField" && !name.EndsWith("InputField")) { continue; } PropertyInfo property = ((object)val2).GetType().GetProperty("isFocused", BindingFlags.Instance | BindingFlags.Public); if (property != null) { if ((bool)property.GetValue(val2)) { return true; } continue; } PropertyInfo property2 = ((object)val2).GetType().GetProperty("isActiveAndEnabled", BindingFlags.Instance | BindingFlags.Public); if (property2 != null && (bool)property2.GetValue(val2)) { return true; } } return false; } catch { return false; } } private static FieldInfo DevConsoleIsTypingField() { if (s_devConsoleLookedUp) { return s_devConsoleIsTyping; } s_devConsoleLookedUp = true; try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { type = assembly.GetType("DevConsole"); } catch { } if (type != null) { break; } } if (type != null) { s_devConsoleIsTyping = type.GetField("isTyping", BindingFlags.Static | BindingFlags.Public); } } catch { } Plugin.Log.LogInfo((object)((s_devConsoleIsTyping != null) ? "[CHAT] Vanilla chat detection armed (DevConsole.isTyping)" : "[CHAT] DevConsole.isTyping NOT found — T chat will not defer to the Enter chat")); return s_devConsoleIsTyping; } private static bool IsVanillaChatTyping() { try { FieldInfo fieldInfo = DevConsoleIsTypingField(); if (fieldInfo == null) { return false; } return (bool)fieldInfo.GetValue(null) && !weHoldTypingFlag; } catch { return false; } } private static bool IsVanillaChatTypingRaw() { try { FieldInfo fieldInfo = DevConsoleIsTypingField(); return fieldInfo != null && (bool)fieldInfo.GetValue(null); } catch { return false; } } private static bool VanillaChatBoxActive() { try { Type type = DevConsoleIsTypingField()?.DeclaringType; if (type == null) { return false; } object obj = s_devConsoleInstance; Object val = (Object)((obj is Object) ? obj : null); if (val == (Object)null) { s_devConsoleInstance = Object.FindObjectOfType(type); object obj2 = s_devConsoleInstance; val = (Object)((obj2 is Object) ? obj2 : null); if (val == (Object)null) { return false; } } if (s_devConsoleField == null) { s_devConsoleField = type.GetField("inputField", BindingFlags.Instance | BindingFlags.Public); } object? obj3 = s_devConsoleField?.GetValue(s_devConsoleInstance); Component val2 = (Component)((obj3 is Component) ? obj3 : null); return (Object)(object)val2 != (Object)null && val2.gameObject.activeSelf; } catch { return false; } } private static void SetGameplayInputLock(bool on) { try { if (on) { gameplayInputLockHeld = true; GameManager.lockInput = true; FieldInfo fieldInfo = DevConsoleIsTypingField(); if (fieldInfo != null) { fieldInfo.SetValue(null, true); weHoldTypingFlag = true; } } else { if (!gameplayInputLockHeld) { return; } gameplayInputLockHeld = false; bool flag = VanillaChatBoxActive(); if (weHoldTypingFlag) { weHoldTypingFlag = false; FieldInfo fieldInfo2 = DevConsoleIsTypingField(); if (fieldInfo2 != null) { fieldInfo2.SetValue(null, flag); } } GameManager.lockInput = flag; } } catch { gameplayInputLockHeld = false; weHoldTypingFlag = false; } } internal static void TickChatLockWatchdog() { try { if ((chatInputOpen || gameplayInputLockHeld) && !(Time.unscaledTime - chatDrawStampedAt < 0.5f)) { Plugin.Log.LogWarning((object)"[CHAT] chat box went unrendered for >0.5s — force-closing and releasing the input lock"); CloseChatInput(); } } catch { } } private static void CloseChatInput() { chatInputOpen = false; chatJustOpened = false; chatInputText = ""; SetGameplayInputLock(on: false); } private static void DrawChatInput() { //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Invalid comparison between Unknown and I4 //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Invalid comparison between Unknown and I4 //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Invalid comparison between Unknown and I4 //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Invalid comparison between Unknown and I4 //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Invalid comparison between Unknown and I4 //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Invalid comparison between Unknown and I4 //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Invalid comparison between Unknown and I4 chatDrawStampedAt = Time.unscaledTime; if (!Plugin.DataConsentGranted) { CloseChatInput(); return; } if (bugModalOpen || logViewerOpen || bugAdminOpen || compareSearchFocused || lbSearchFocused || NativeUI.CustomBetPromptOpen || NativeUI.LfpPromptOpen || ArtistPromptOpen) { CloseChatInput(); return; } Event current = Event.current; if (!chatInputOpen) { SetGameplayInputLock(on: false); if (!IsVanillaChatTyping() && !IsAnotherTextInputActive() && current != null && (int)current.type == 4 && (int)current.keyCode == 116) { chatInputOpen = true; chatJustOpened = true; chatInputText = ""; current.Use(); SetGameplayInputLock(on: true); } return; } if (IsVanillaChatTyping()) { CloseChatInput(); return; } SetGameplayInputLock(on: true); if (chatJustOpened) { chatJustOpened = false; if (current != null && (int)current.type == 4) { current.Use(); } return; } if (chatStyle == null) { chatStyle = new GUIStyle(GUI.skin.textField) { fontSize = 16 }; } bool flag = false; bool flag2 = false; if (current != null && (int)current.type == 4) { if ((int)current.keyCode == 13 || (int)current.keyCode == 271) { flag = true; current.Use(); } else if ((int)current.keyCode == 27) { flag2 = true; current.Use(); } } float num = 1000f; float num2 = 56f; float num3 = 20f; float num4 = Screen.height - 130; GUI.DrawTexture(new Rect(num3 - 6f, num4 - 24f, num + 12f, num2 + 30f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.82f), 0f, 0f); GUI.Label(new Rect(num3, num4 - 22f, num, 20f), "Chat — Enter to send, Esc to cancel"); GUI.SetNextControlName("CRChat"); chatInputText = GUI.TextField(new Rect(num3, num4, num, num2), chatInputText ?? "", 480, chatStyle); GUI.FocusControl("CRChat"); if (flag) { string text = (chatInputText ?? "").Trim(); if (!string.IsNullOrEmpty(text)) { if (text.StartsWith("/mute ", StringComparison.OrdinalIgnoreCase) || text.StartsWith("/unmute ", StringComparison.OrdinalIgnoreCase) || text.Equals("/muted", StringComparison.OrdinalIgnoreCase)) { NativeUI.HandleMuteCommand(text); } else { ChatClient.Send(GameStateWatcher.LocalSteamId, GameStateWatcher.LocalDisplayName, text); Plugin.Log.LogInfo((object)("[CHAT] -> sent: " + text)); } } CloseChatInput(); } else if (flag2) { CloseChatInput(); } } private static void EnsureConsentBlocker() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //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_016a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)consentBlockerGO != (Object)null) { return; } try { consentBlockerGO = new GameObject("CR_ConsentBlocker"); ((Object)consentBlockerGO).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)consentBlockerGO); if (UIFactory.tCanvas != null) { Component obj = consentBlockerGO.AddComponent(UIFactory.tCanvas); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; PropertyInfo property = UIFactory.tCanvas.GetProperty("renderMode", bindingAttr); property?.SetValue(obj, Enum.ToObject(property.PropertyType, 0)); UIFactory.tCanvas.GetProperty("sortingOrder", bindingAttr)?.SetValue(obj, 29998); } if (UIFactory.tGR != null) { consentBlockerGO.AddComponent(UIFactory.tGR); } RectTransform val = consentBlockerGO.AddComponent(); val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.offsetMin = Vector2.zero; val.offsetMax = Vector2.zero; if (UIFactory.tImage != null) { Component obj2 = consentBlockerGO.AddComponent(UIFactory.tImage); BindingFlags bindingAttr2 = BindingFlags.Instance | BindingFlags.Public; UIFactory.tImage.GetProperty("color", bindingAttr2)?.SetValue(obj2, (object)new Color(0f, 0f, 0f, 0.001f)); UIFactory.tImage.GetProperty("raycastTarget", bindingAttr2)?.SetValue(obj2, true); } Plugin.Log.LogInfo((object)"[CONSENT] Blocker canvas created"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CONSENT] blocker create failed: " + ex.Message)); } } private static void DestroyConsentBlocker() { if (!((Object)(object)consentBlockerGO == (Object)null)) { try { Object.Destroy((Object)(object)consentBlockerGO); } catch { } consentBlockerGO = null; } } private static void DrawConsentModal() { //IL_003a: 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_00a0: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Invalid comparison between Unknown and I4 //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Invalid comparison between Unknown and I4 //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Invalid comparison between Unknown and I4 if (Plugin.DataConsentAsked) { DestroyConsentBlocker(); return; } EnsureConsentBlocker(); Texture2D whiteTexture = Texture2D.whiteTexture; GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.78f), 0f, 0f); float num = 680f; float num2 = 420f; float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)whiteTexture, (ScaleMode)0, true, 0f, new Color(0.1f, 0.11f, 0.16f, 0.97f), 0f, 0f); if (consentTitleStyle == null) { consentTitleStyle = new GUIStyle(GUI.skin.label) { fontSize = 22, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; } if (consentBodyStyle == null) { consentBodyStyle = new GUIStyle(GUI.skin.label) { fontSize = 14, wordWrap = true, alignment = (TextAnchor)0 }; } GUI.Label(new Rect(num3, num4 + 14f, num, 30f), "Competitive ROUNDS — Data Consent", consentTitleStyle); string text = "This mod sends data to a private server run by the mod author to power the leaderboard and ranked matchmaking.\n\nWhat gets recorded if you allow:\n • Your Steam ID and in-game display name\n • Your Discord ID and username, ONLY if you link your Discord via the in-game link code\n • Each match you play: rounds won, points, duration, cards picked, cards offered, opponent\n • Your Glicko-2 rating history\n\nWhat you can do later:\n • Revoke consent anytime (F5 → Settings → Revoke). Reporting stops.\n • Delete your data (F5 → Settings → Delete my data). Steam ID, display name, and Discord link are scrubbed. Matches stay so other players' ratings and histories aren't disturbed. Deletion is IRREVERSIBLE — you cannot re-register this Steam ID later.\n\nChoose Allow to use the leaderboard. Choose Decline to run the mod fully offline."; GUI.Label(new Rect(num3 + 24f, num4 + 50f, num - 48f, num2 - 120f), text, consentBodyStyle); if (GUI.Button(new Rect(num3 + 50f, num4 + num2 - 56f, 260f, 38f), "Allow data reporting")) { Plugin.DataConsent.Value = "granted"; Plugin.Log.LogInfo((object)"[CONSENT] User granted data reporting"); ApiClient.OnConsentChanged(); } if (GUI.Button(new Rect(num3 + num - 310f, num4 + num2 - 56f, 260f, 38f), "Decline (offline mode)")) { Plugin.DataConsent.Value = "denied"; Plugin.Log.LogInfo((object)"[CONSENT] User declined data reporting"); ApiClient.OnConsentChanged(); } if (Event.current != null) { EventType type = Event.current.type; if ((int)type == 0 || (int)type == 1 || (int)type == 4 || (int)type == 5) { Event.current.Use(); } } } private static void DrawFPS() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7) { return; } bool flag = Plugin.ShowFps == null || Plugin.ShowFps.Value; bool flag2 = Plugin.ShowRegionPing == null || Plugin.ShowRegionPing.Value; if (!flag && !flag2) { return; } fpsCnt++; fpsTimer += Time.deltaTime; if (fpsStyle == null) { fpsStyle = new GUIStyle(GUI.skin.label); fpsStyle.fontSize = 11; fpsStyle.normal.textColor = new Color(0.5f, 0.5f, 0.5f, 0.7f); } if (fpsTimer >= 0.5f || fpsLabelShowFps != flag || fpsLabelShowRegion != flag2) { if (fpsTimer >= 0.5f) { fpsVal = (float)fpsCnt / fpsTimer; fpsCnt = 0; fpsTimer = 0f; } fpsLabelShowFps = flag; fpsLabelShowRegion = flag2; fpsLabel = (flag ? $"{fpsVal:F0} FPS" : ""); fpsLabelWidth = 60f; if (flag2) { try { if (PhotonNetwork.IsConnected && PhotonNetwork.InRoom) { int ping = PhotonNetwork.GetPing(); string text = PhotonNetwork.CloudRegion ?? ""; if (!string.IsNullOrEmpty(text)) { int num = text.IndexOf('/'); if (num > 0) { text = text.Substring(0, num); } text = text.ToUpperInvariant(); } string text2 = $"{ping}ms {text}"; fpsLabel = (flag ? (fpsLabel + " | " + text2) : text2); fpsLabelWidth = 200f; } } catch { } } } if (!string.IsNullOrEmpty(fpsLabel)) { GUI.Label(new Rect(6f, 4f, fpsLabelWidth, 18f), fpsLabel, fpsStyle); } } private static void DrawNotification() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: 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_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0215: 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) //IL_00e5: Expected O, but got Unknown if (Event.current == null || (int)Event.current.type != 7) { return; } if (notifTimer <= 0f && notifQueue.Count > 0) { QueuedNotif queuedNotif = notifQueue[0]; notifQueue.RemoveAt(0); notifText = queuedNotif.text; notifColor = queuedNotif.color; notifTimer = queuedNotif.dur; } if (!(notifTimer <= 0f)) { notifTimer -= Time.unscaledDeltaTime; float num = Mathf.Clamp01(notifTimer / 0.75f); if (notifStyle == null) { notifStyle = new GUIStyle(GUI.skin.label); notifStyle.fontSize = 16; notifStyle.fontStyle = (FontStyle)1; notifStyle.alignment = (TextAnchor)4; notifStyle.wordWrap = true; notifStyle.clipping = (TextClipping)0; } Color contentColor = default(Color); ((Color)(ref contentColor))..ctor(notifColor.r, notifColor.g, notifColor.b, num); Color contentColor2 = GUI.contentColor; GUI.contentColor = contentColor; float num2 = 500f; float num3 = ((float)Screen.width - num2) / 2f; float num4 = Mathf.Clamp(notifStyle.CalcHeight(new GUIContent(notifText), num2), 24f, 120f); float num5 = (float)(Screen.height - 80) - (num4 - 24f); Texture2D whiteTexture = Texture2D.whiteTexture; GUI.DrawTexture(new Rect(num3, num5 - 6f, num2, num4 + 12f), (Texture)(object)whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, num * 0.5f), 0f, 0f); GUI.Label(new Rect(num3, num5, num2, num4), notifText, notifStyle); GUI.contentColor = contentColor2; } } private static void RefreshMatchStatusCache(bool isRanked) { //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_04a5: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) matchStatusCacheUntil = Time.unscaledTime + 0.25f; matchStatusCachedRanked = isRanked; matchStatusSeries = ""; matchStatusH2H = ""; matchStatusIsOvt = false; string text = ""; try { Room currentRoom = PhotonNetwork.CurrentRoom; text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; } catch { } if (text.StartsWith("ovt_", StringComparison.Ordinal)) { matchStatusIsOvt = true; int ovtSoloWins = GameStateWatcher.OvtSoloWins; int ovtDuoWins = GameStateWatcher.OvtDuoWins; matchStatusSeries = ((GameStateWatcher.LocalTeamId == 0) ? $"1v2 Series: You {ovtSoloWins} - {ovtDuoWins} Duo" : $"1v2 Series: Duo {ovtDuoWins} - {ovtSoloWins} Solo"); List list = new List(); List list2 = new List(); try { int result = -1; Player localPlayer = PhotonNetwork.LocalPlayer; Hashtable val = ((localPlayer != null) ? localPlayer.CustomProperties : null); if (val != null && ((Dictionary)(object)val).ContainsKey((object)"t_id")) { int.TryParse(val[(object)"t_id"]?.ToString(), out result); } Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val2 in playerList) { if (val2 != null && !val2.IsLocal) { string text2 = GameStateWatcher.StripRichText(val2.NickName ?? "?"); if (string.IsNullOrEmpty(text2)) { text2 = "?"; } if (text2.Length > 14) { text2 = text2.Substring(0, 14); } int result2 = -1; if (val2.CustomProperties != null && ((Dictionary)(object)val2.CustomProperties).ContainsKey((object)"t_id")) { int.TryParse(val2.CustomProperties[(object)"t_id"]?.ToString(), out result2); } if (result2 >= 0 && result >= 0 && result2 == result) { list.Add(text2); } else { list2.Add(text2); } } } } catch { } matchStatusH2HTint = new Color(0.82f, 0.82f, 0.82f); matchStatusH2H = ((list.Count > 0) ? ("w/ " + string.Join(" + ", list.ToArray()) + " ") : "") + ((list2.Count > 0) ? ("vs " + string.Join(" + ", list2.ToArray())) : ""); return; } if (isRanked) { matchStatusSeries = $"Series Score: {GameStateWatcher.CurrentSeriesGamesWon} - {GameStateWatcher.CurrentSeriesGamesLost}"; try { string opponentSteamId = GameStateWatcher.OpponentSteamId; if (!string.IsNullOrEmpty(opponentSteamId) && !opponentSteamId.StartsWith("photon_")) { ApiClient.FetchOpponentLifetime(opponentSteamId); if (ApiClient.CachedOppLifetime.TryGetValue(opponentSteamId, out var value) && value != null && value.Length >= 4) { matchStatusSeries += $" (Total Series {value[2]} - {value[3]})"; } } } catch { } } try { string opponentSteamId2 = GameStateWatcher.OpponentSteamId; string opponentDisplayName = GameStateWatcher.OpponentDisplayName; Room currentRoom2 = PhotonNetwork.CurrentRoom; Hashtable val3 = ((currentRoom2 != null) ? ((RoomInfo)currentRoom2).CustomProperties : null); if ((val3 == null || !((Dictionary)(object)val3).ContainsKey((object)"cr_ff")) && !string.IsNullOrEmpty(opponentDisplayName) && !(opponentDisplayName == "Opponent") && (opponentSteamId2 == null || !opponentSteamId2.StartsWith("photon_"))) { int num = 0; int num2 = 0; Dictionary sessionWLByOpponent = GameStateWatcher.SessionWLByOpponent; if (sessionWLByOpponent != null && sessionWLByOpponent.TryGetValue(opponentDisplayName, out var value2) && value2 != null && value2.Length >= 4) { num = value2[0] + value2[2]; num2 = value2[1] + value2[3]; } string text3 = ((opponentDisplayName.Length > 18) ? opponentDisplayName.Substring(0, 18) : opponentDisplayName); if (num + num2 > 0) { matchStatusH2HTint = ((num > num2) ? new Color(0.6f, 1f, 0.6f) : ((num < num2) ? new Color(1f, 0.6f, 0.6f) : new Color(0.85f, 0.85f, 0.85f))); matchStatusH2H = $"vs {text3}: {num}-{num2} this session"; } else { matchStatusH2HTint = new Color(0.7f, 0.7f, 0.7f); matchStatusH2H = "vs " + text3 + ": first game this session"; } } } catch { } } private static void DrawMatchStatus() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0112: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) if (Event.current == null || (int)Event.current.type != 7 || !MatchTracker.IsInMatch) { return; } try { if (FfaMode.EngineActive()) { return; } } catch { } bool matchIsRanked = GameStateWatcher.MatchIsRanked; if (statusStyle == null) { statusStyle = new GUIStyle(GUI.skin.label); statusStyle.fontSize = 11; statusStyle.fontStyle = (FontStyle)1; statusStyle.alignment = (TextAnchor)4; } if (scoreStyle == null) { scoreStyle = new GUIStyle(GUI.skin.label); scoreStyle.fontSize = 14; scoreStyle.fontStyle = (FontStyle)1; scoreStyle.alignment = (TextAnchor)4; } if (Time.unscaledTime >= matchStatusCacheUntil || matchStatusCachedRanked != matchIsRanked) { RefreshMatchStatusCache(matchIsRanked); } Color contentColor = GUI.contentColor; bool flag = matchStatusIsOvt; bool flag2 = flag || matchIsRanked; float num; if (flag2) { GUI.contentColor = (Color)(flag ? new Color(0.55f, 0.8f, 1f) : Color.green); GUI.Label(new Rect((float)(Screen.width - 220) / 2f, 8f, 220f, 18f), flag ? "1v2 BETA - Unranked" : "RANKED - Recording", statusStyle); num = 28f; } else { num = 8f; } float num2 = num; if (flag2 && !string.IsNullOrEmpty(matchStatusSeries)) { GUI.contentColor = new Color(1f, 0.85f, 0.3f); GUI.Label(new Rect((float)(Screen.width - 380) / 2f, num, 380f, 22f), matchStatusSeries, scoreStyle); num2 = num + 18f; } if (!string.IsNullOrEmpty(matchStatusH2H)) { float num3 = (flag ? 560f : 360f); GUI.contentColor = matchStatusH2HTint; GUI.Label(new Rect(((float)Screen.width - num3) / 2f, num2, num3, 20f), matchStatusH2H, scoreStyle); } GUI.contentColor = contentColor; } } internal static class CursorColorCosmetic { private static string _activeSku = ""; private static Color _activeColor = Color.white; private static Texture2D _activeTex; private static Vector2 _activeHotspot = new Vector2(1f, 1f); private static Coroutine _maintainLoop; private static bool _started; private static readonly Dictionary _texCache = new Dictionary(); public static readonly string[] Shapes = new string[5] { "default", "arrow", "dot", "crosshair", "circle" }; public static readonly string[] ShapeLabels = new string[5] { "ROUNDS default", "Arrow", "Dot", "Crosshair", "Circle" }; private const string SHAPE_PREF = "cr_cursor_shape"; private static string _shape; private static Texture2D _vanillaCursor; private static bool _vanillaSearched; private const int SZ = 32; private static readonly Vector2[] ARROW = (Vector2[])(object)new Vector2[7] { new Vector2(0f, 0f), new Vector2(0f, 0.78f), new Vector2(0.22f, 0.6f), new Vector2(0.36f, 0.92f), new Vector2(0.5f, 0.86f), new Vector2(0.34f, 0.55f), new Vector2(0.6f, 0.55f) }; public static string CurrentShape { get { if (_shape == null) { _shape = LoadShape(); } return _shape; } } private static string LoadShape() { try { string text = PlayerPrefs.GetString("cr_cursor_shape", "default"); return (Array.IndexOf(Shapes, text) >= 0) ? text : "default"; } catch { return "default"; } } public static string CurrentShapeLabel() { int num = Array.IndexOf(Shapes, CurrentShape); return (num >= 0) ? ShapeLabels[num] : "ROUNDS default"; } public static void CycleShape() { int num = Array.IndexOf(Shapes, CurrentShape); _shape = Shapes[(Mathf.Max(0, num) + 1) % Shapes.Length]; try { PlayerPrefs.SetString("cr_cursor_shape", _shape); PlayerPrefs.Save(); } catch { } ApplyFromStats(); } public static void Initialize() { if (_started) { return; } try { if (!((Object)(object)Plugin.Instance == (Object)null)) { _maintainLoop = ((MonoBehaviour)Plugin.Instance).StartCoroutine(MaintainLoop()); _started = true; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CURSOR] init failed: " + ex.Message)); } } public static void ApplyFromStats() { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; string sku = cachedPlayerStats?.active_cursor_color_sku ?? ""; string hex = cachedPlayerStats?.active_cursor_color_hex ?? ""; Apply(sku, hex); } public static void Apply(string sku, string hex) { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) try { if (!_started) { Initialize(); } string text = CurrentShape; if (text == "default") { if (string.IsNullOrEmpty(sku)) { _activeSku = ""; _activeTex = null; Cursor.SetCursor((Texture2D)null, Vector2.zero, (CursorMode)0); return; } Texture2D tintedVanillaCursor = GetTintedVanillaCursor(hex); if ((Object)(object)tintedVanillaCursor != (Object)null) { _activeSku = "default|" + sku; _activeColor = ParseHex(hex, Color.white); _activeTex = tintedVanillaCursor; _activeHotspot = new Vector2((float)((Texture)tintedVanillaCursor).width / 2f, (float)((Texture)tintedVanillaCursor).height / 2f); Cursor.SetCursor(_activeTex, _activeHotspot, (CursorMode)0); return; } text = "arrow"; } Color val = (string.IsNullOrEmpty(sku) ? Color.white : ParseHex(hex, Color.white)); _activeSku = text + "|" + sku; _activeColor = val; _activeTex = GetTintedCursor(text, hex, val); _activeHotspot = ((text == "arrow") ? new Vector2(1f, 1f) : new Vector2(16f, 16f)); if ((Object)(object)_activeTex != (Object)null) { Cursor.SetCursor(_activeTex, _activeHotspot, (CursorMode)0); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CURSOR] Apply failed: " + ex.Message)); } } private static IEnumerator MaintainLoop() { WaitForSeconds wait = new WaitForSeconds(2.5f); while (true) { yield return wait; try { if (!string.IsNullOrEmpty(_activeSku) && (Object)(object)_activeTex != (Object)null) { Cursor.SetCursor(_activeTex, _activeHotspot, (CursorMode)0); } } catch { } } } private static Texture2D GetTintedCursor(string shape, string hex, Color c) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) string key = shape + ":" + (string.IsNullOrEmpty(hex) ? "#FFFFFF" : hex); if (_texCache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { return value; } bool[] solid = BuildShapeMask(shape); Texture2D val = BuildFromMask(solid, c); _texCache[key] = val; return val; } private static Texture2D FindVanillaCursor() { if (_vanillaSearched) { return _vanillaCursor; } _vanillaSearched = true; try { Texture2D val = null; Texture2D[] array = Resources.FindObjectsOfTypeAll(); foreach (Texture2D val2 in array) { if (!((Object)(object)val2 == (Object)null)) { string text = (((Object)val2).name ?? "").ToLowerInvariant(); if (text.Contains("cursor") && ((Texture)val2).width <= 128 && ((Texture)val2).height <= 128 && ((Object)(object)val == (Object)null || ((Object)val2).name.Length < ((Object)val).name.Length)) { val = val2; } } } _vanillaCursor = val; Plugin.Log.LogInfo((object)(((Object)(object)val != (Object)null) ? $"[CURSOR] vanilla cursor texture: '{((Object)val).name}' {((Texture)val).width}x{((Texture)val).height}" : "[CURSOR] no vanilla cursor texture found - default shape can't be tinted this session")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CURSOR] vanilla search: " + ex.Message)); } return _vanillaCursor; } private static Texture2D GetTintedVanillaCursor(string hex) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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) string key = "vanilla:" + (string.IsNullOrEmpty(hex) ? "#FFFFFF" : hex); if (_texCache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { return value; } Texture2D val = FindVanillaCursor(); if ((Object)(object)val == (Object)null) { return null; } try { RenderTexture temporary = RenderTexture.GetTemporary(((Texture)val).width, ((Texture)val).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; Graphics.Blit((Texture)(object)val, temporary); RenderTexture.active = temporary; Texture2D val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, false); val2.ReadPixels(new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), 0, 0); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).filterMode = (FilterMode)1; ((Object)val2).hideFlags = (HideFlags)61; Color val3 = ParseHex(hex, Color.white); Color32[] pixels = val2.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { pixels[i].r = (byte)((float)(int)pixels[i].r * val3.r); pixels[i].g = (byte)((float)(int)pixels[i].g * val3.g); pixels[i].b = (byte)((float)(int)pixels[i].b * val3.b); } val2.SetPixels32(pixels); val2.Apply(); _texCache[key] = val2; return val2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CURSOR] vanilla tint failed: " + ex.Message)); return null; } } private static bool[] BuildShapeMask(string shape) { //IL_0278: Unknown result type (might be due to invalid IL or missing references) bool[] array = new bool[1024]; float num = 16f; float num2 = 16f; switch (shape) { case "dot": { float num15 = 4.5f; for (int num16 = 0; num16 < 32; num16++) { for (int num17 = 0; num17 < 32; num17++) { float num18 = (float)num17 + 0.5f - num; float num19 = (float)num16 + 0.5f - num2; if (num18 * num18 + num19 * num19 <= num15 * num15) { array[num16 * 32 + num17] = true; } } } break; } case "circle": { float num5 = 9f; float num6 = 6f; for (int k = 0; k < 32; k++) { for (int l = 0; l < 32; l++) { float num7 = (float)l + 0.5f - num; float num8 = (float)k + 0.5f - num2; float num9 = num7 * num7 + num8 * num8; if (num9 <= num5 * num5 && num9 >= num6 * num6) { array[k * 32 + l] = true; } } } break; } case "crosshair": { int num10 = 1; int num11 = 3; int num12 = 11; for (int m = 0; m < 32; m++) { for (int n = 0; n < 32; n++) { float num13 = (float)n + 0.5f - num; float num14 = (float)m + 0.5f - num2; bool flag = Mathf.Abs(num14) <= (float)num10 && Mathf.Abs(num13) >= (float)num11 && Mathf.Abs(num13) <= (float)num12; bool flag2 = Mathf.Abs(num13) <= (float)num10 && Mathf.Abs(num14) >= (float)num11 && Mathf.Abs(num14) <= (float)num12; bool flag3 = num13 * num13 + num14 * num14 <= 2.5600002f; if (flag || flag2 || flag3) { array[m * 32 + n] = true; } } } break; } default: { for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num3 = (float)j / 31f; float num4 = 1f - (float)i / 31f; if (PointInPoly(new Vector2(num3, num4), ARROW)) { array[i * 32 + j] = true; } } } break; } } return array; } private static Texture2D BuildFromMask(bool[] solid, Color fill) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0073: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; ((Object)val).hideFlags = (HideFlags)61; Color[] array = (Color[])(object)new Color[1024]; for (int i = 0; i < array.Length; i++) { array[i] = (Color)(solid[i] ? fill : new Color(0f, 0f, 0f, 0f)); } float num = fill.r * 0.299f + fill.g * 0.587f + fill.b * 0.114f; Color val2 = ((num > 0.5f) ? new Color(0.05f, 0.05f, 0.05f, 1f) : new Color(0.95f, 0.95f, 0.95f, 1f)); Color[] array2 = (Color[])array.Clone(); for (int j = 0; j < 32; j++) { for (int k = 0; k < 32; k++) { if (solid[j * 32 + k]) { continue; } bool flag = false; for (int l = -1; l <= 1; l++) { if (flag) { break; } for (int m = -1; m <= 1; m++) { int num2 = k + m; int num3 = j + l; if (num2 >= 0 && num3 >= 0 && num2 < 32 && num3 < 32 && solid[num3 * 32 + num2]) { flag = true; break; } } } if (flag) { array2[j * 32 + k] = val2; } } } val.SetPixels(array2); val.Apply(); return val; } private static Texture2D BuildArrowTex(Color fill) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_00dd: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_020b: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; ((Object)val).hideFlags = (HideFlags)61; Color[] array = (Color[])(object)new Color[1024]; bool[] array2 = new bool[1024]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = (float)j / 31f; float num2 = 1f - (float)i / 31f; array[i * 32 + j] = (Color)((array2[i * 32 + j] = PointInPoly(new Vector2(num, num2), ARROW)) ? fill : new Color(0f, 0f, 0f, 0f)); } } float num3 = fill.r * 0.299f + fill.g * 0.587f + fill.b * 0.114f; Color val2 = ((num3 > 0.5f) ? new Color(0.05f, 0.05f, 0.05f, 1f) : new Color(0.95f, 0.95f, 0.95f, 1f)); Color[] array3 = (Color[])array.Clone(); for (int k = 0; k < 32; k++) { for (int l = 0; l < 32; l++) { if (array2[k * 32 + l]) { continue; } bool flag = false; for (int m = -1; m <= 1; m++) { if (flag) { break; } for (int n = -1; n <= 1; n++) { int num4 = l + n; int num5 = k + m; if (num4 >= 0 && num5 >= 0 && num4 < 32 && num5 < 32 && array2[num5 * 32 + num4]) { flag = true; break; } } } if (flag) { array3[k * 32 + l] = val2; } } } val.SetPixels(array3); val.Apply(); return val; } private static bool PointInPoly(Vector2 p, Vector2[] poly) { //IL_001f: 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_003d: 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) bool flag = false; int num = poly.Length; int num2 = 0; int num3 = num - 1; while (num2 < num) { if (poly[num2].y > p.y != poly[num3].y > p.y && p.x < (poly[num3].x - poly[num2].x) * (p.y - poly[num2].y) / (poly[num3].y - poly[num2].y) + poly[num2].x) { flag = !flag; } num3 = num2++; } return flag; } private static Color ParseHex(string hex, Color fallback) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(hex)) { return fallback; } if (hex.StartsWith("#")) { hex = hex.Substring(1); } if (hex.Length != 6) { return fallback; } try { int num = Convert.ToInt32(hex.Substring(0, 2), 16); int num2 = Convert.ToInt32(hex.Substring(2, 2), 16); int num3 = Convert.ToInt32(hex.Substring(4, 2), 16); return new Color((float)num / 255f, (float)num2 / 255f, (float)num3 / 255f, 1f); } catch { return fallback; } } } internal static class CustomCosmetics { internal class CosmeticDef { public string Sku; public string DisplayName; public CharacterItemType Slot; public string PngFile; public float Scale = 1f; public Vector2 Offset = Vector2.zero; public float Fps = 10f; public int Id; public CharacterItem Template; } internal class CosmeticFrameCycler : MonoBehaviour { public Sprite[] frames; public float fps = 10f; private SpriteRenderer sr; private int lastFrame = -1; private void Awake() { sr = ((Component)this).GetComponent(); } private void Update() { if (frames == null || frames.Length < 2 || (Object)(object)sr == (Object)null || fps <= 0f) { return; } if (Plugin.AnimatedCosmetics != null && !Plugin.AnimatedCosmetics.Value) { if (lastFrame != 0 || (Object)(object)sr.sprite != (Object)(object)frames[0]) { sr.sprite = frames[0]; lastFrame = 0; } return; } int num = (int)(Time.unscaledTime * fps) % frames.Length; if (num != lastFrame || !((Object)(object)sr.sprite == (Object)(object)frames[num])) { sr.sprite = frames[num]; lastFrame = num; } } } public const int CUSTOM_ID_BASE = 1000; private const string TEMPLATE_PREFIX = "CRCOS_"; private static readonly CosmeticDef[] Catalog = new CosmeticDef[33] { new CosmeticDef { Sku = "face_eyes_star", DisplayName = "Star Eyes", Slot = (CharacterItemType)0, PngFile = "eyes_star.png", Scale = 1f, Offset = new Vector2(0f, 0.1f) }, new CosmeticDef { Sku = "face_eyes_hearts", DisplayName = "Heart Eyes", Slot = (CharacterItemType)0, PngFile = "eyes_hearts.png", Scale = 1f, Offset = new Vector2(0f, 0.1f) }, new CosmeticDef { Sku = "face_mouth_stache", DisplayName = "Moustache", Slot = (CharacterItemType)1, PngFile = "mouth_stache.png", Scale = 0.9f, Offset = new Vector2(0f, -0.15f) }, new CosmeticDef { Sku = "face_mouth_stitch", DisplayName = "Stitched Grin", Slot = (CharacterItemType)1, PngFile = "mouth_stitch.png", Scale = 0.8f, Offset = new Vector2(0f, -0.15f) }, new CosmeticDef { Sku = "face_detail_crown", DisplayName = "Crown", Slot = (CharacterItemType)2, PngFile = "detail_crown.png", Scale = 1.6f, Offset = new Vector2(-0.028f, 4.499f) }, new CosmeticDef { Sku = "face_detail_halo", DisplayName = "Halo", Slot = (CharacterItemType)2, PngFile = "detail_halo.png", Scale = 1.1f, Offset = new Vector2(0f, 0.75f) }, new CosmeticDef { Sku = "face_detail_sprout", DisplayName = "Sprout", Slot = (CharacterItemType)2, PngFile = "detail_sprout.png", Scale = 1.1f, Offset = new Vector2(0f, 0.55f) }, new CosmeticDef { Sku = "face_detail_earmuffs", DisplayName = "Star Earmuffs", Slot = (CharacterItemType)2, PngFile = "detail_earmuffs.png", Scale = 1.1f, Offset = new Vector2(0f, 0.2f) }, new CosmeticDef { Sku = "face_eyes_crazed", DisplayName = "Crazed Eyes", Slot = (CharacterItemType)0, PngFile = "eyes_crazed.png", Scale = 1.35f, Offset = new Vector2(0f, 0.1f) }, new CosmeticDef { Sku = "face_eyes_yinyang", DisplayName = "Yin & Yang", Slot = (CharacterItemType)0, PngFile = "eyes_yinyang.png", Scale = 1.35f, Offset = new Vector2(0f, 0.1f) }, new CosmeticDef { Sku = "face_detail_devil_horns", DisplayName = "Devil Horns", Slot = (CharacterItemType)2, PngFile = "detail_devil_horns.png", Scale = 1.1f, Offset = new Vector2(0f, 0.45f) }, new CosmeticDef { Sku = "face_detail_alien_antennae", DisplayName = "Alien Antennae", Slot = (CharacterItemType)2, PngFile = "detail_alien_antennae.png", Scale = 1.1f, Offset = new Vector2(0f, 0.55f) }, new CosmeticDef { Sku = "face_detail_storm_halo", DisplayName = "Storm Halo", Slot = (CharacterItemType)2, PngFile = "detail_storm_halo.png", Scale = 1.2f, Offset = new Vector2(0f, 0.8f), Fps = 8f }, new CosmeticDef { Sku = "face_detail_flame_crest", DisplayName = "Flame Crest", Slot = (CharacterItemType)2, PngFile = "detail_flame_crest.png", Scale = 1.1f, Offset = new Vector2(0f, 0.6f), Fps = 8f }, new CosmeticDef { Sku = "face_detail_demon_wings", DisplayName = "Demon Wings", Slot = (CharacterItemType)2, PngFile = "detail_demon_wings.png", Scale = 2.1f, Offset = new Vector2(0f, 0.05f) }, new CosmeticDef { Sku = "face_detail_thorn_crown", DisplayName = "Thorn Crown", Slot = (CharacterItemType)2, PngFile = "detail_thorn_crown.png", Scale = 1f, Offset = new Vector2(0f, 0f) }, new CosmeticDef { Sku = "face_detail_sun_halo", DisplayName = "Sunburst Halo", Slot = (CharacterItemType)2, PngFile = "detail_sun_halo.png", Scale = 1.1f, Offset = new Vector2(0f, 0.1f) }, new CosmeticDef { Sku = "face_detail_knight_helm", DisplayName = "Knight Great-Helm", Slot = (CharacterItemType)2, PngFile = "detail_knight_helm.png", Scale = 1.55f, Offset = new Vector2(0f, 0.05f) }, new CosmeticDef { Sku = "face_detail_mini_flags", DisplayName = "Rally Flags", Slot = (CharacterItemType)2, PngFile = "detail_mini_flags.png", Scale = 1f, Offset = new Vector2(0f, 0.15f) }, new CosmeticDef { Sku = "face_detail_dark_aura", DisplayName = "Dark Aura", Slot = (CharacterItemType)2, PngFile = "detail_dark_aura.png", Scale = 2.25f, Offset = new Vector2(0.032f, 1.17f), Fps = 7f }, new CosmeticDef { Sku = "face_detail_energy_orbs", DisplayName = "Energy Orbs", Slot = (CharacterItemType)2, PngFile = "detail_energy_orbs.png", Scale = 1f, Offset = new Vector2(0f, 0.05f), Fps = 7f }, new CosmeticDef { Sku = "face_detail_tattered_cape", DisplayName = "Tattered Cape", Slot = (CharacterItemType)2, PngFile = "detail_tattered_cape.png", Scale = 2.15f, Offset = new Vector2(0f, -0.1f) }, new CosmeticDef { Sku = "face_detail_party_crown", DisplayName = "Party Crown", Slot = (CharacterItemType)2, PngFile = "detail_party_crown.png", Scale = 1.2f, Offset = new Vector2(0f, 0.55f), Fps = 3.6f }, new CosmeticDef { Sku = "face_detail_rounds_cat", DisplayName = "Rounds Cat", Slot = (CharacterItemType)2, PngFile = "detail_rounds_cat.png", Scale = 1f, Offset = Vector2.zero }, new CosmeticDef { Sku = "face_detail_star_spin", DisplayName = "Star Spin", Slot = (CharacterItemType)2, PngFile = "detail_star_spin.png", Scale = 1f, Offset = Vector2.zero, Fps = 6f }, new CosmeticDef { Sku = "face_detail_spooky_head_bouncers", DisplayName = "Spooky Head-Bouncers", Slot = (CharacterItemType)2, PngFile = "detail_spooky_head_bouncers.png", Scale = 1.3f, Offset = new Vector2(0.113f, 3.665f) }, new CosmeticDef { Sku = "face_detail_ballooniphones", DisplayName = "Ballooniphones", Slot = (CharacterItemType)2, PngFile = "Ballooniphones.png", Scale = 1.7f, Offset = new Vector2(-0.192f, 2.112f) }, new CosmeticDef { Sku = "face_detail_soda_helm", DisplayName = "Soda Helm", Slot = (CharacterItemType)2, PngFile = "SodaHelm.png", Scale = 1.3f, Offset = new Vector2(-0.096f, 2.4f) }, new CosmeticDef { Sku = "face_detail_brain_cane", DisplayName = "Brain Cane", Slot = (CharacterItemType)2, PngFile = "detail_brain_cane.png", Scale = 1.3f, Offset = Vector2.zero }, new CosmeticDef { Sku = "face_mouth_casi_s_mouth", DisplayName = "Casi's mouth", Slot = (CharacterItemType)1, PngFile = "mouth_casi_s_mouth.png", Scale = 1.3f, Offset = Vector2.zero }, new CosmeticDef { Sku = "face_eyes_casicorn_s_eyes", DisplayName = "Casicorn's Eyes", Slot = (CharacterItemType)0, PngFile = "eyes_casicorn_s_eyes.png", Scale = 1.3f, Offset = Vector2.zero }, new CosmeticDef { Sku = "face_detail_little_pink_buddy", DisplayName = "Little Pink Buddy", Slot = (CharacterItemType)2, PngFile = "detail_little_pink_buddy.png", Scale = 1.3f, Offset = Vector2.zero }, new CosmeticDef { Sku = "face_detail_sniper_medal", DisplayName = "Sniper Medal", Slot = (CharacterItemType)2, PngFile = "detail_sniper_medal.png", Scale = 1.3f, Offset = Vector2.zero } }; private static readonly Dictionary byId = new Dictionary(); private static readonly Dictionary byTemplateName = new Dictionary(); private static readonly Dictionary _spriteBySku = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary _shopFramesBySku = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool initialized; private static string _cosmeticsDir = ""; private static Material _vanillaItemMat; public static Sprite GetShopSprite(string sku) { if (string.IsNullOrEmpty(sku)) { return null; } Sprite value; return _spriteBySku.TryGetValue(sku, out value) ? value : null; } public static bool TryGetPublishedPlacement(string sku, out string slot, out float scale, out Vector2 offset, out byte[] pngBytes) { //IL_0010: 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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Invalid comparison between Unknown and I4 //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) slot = ""; scale = 1f; offset = Vector2.zero; pngBytes = null; if (string.IsNullOrEmpty(sku)) { return false; } CosmeticDef cosmeticDef = null; for (int i = 0; i < Catalog.Length; i++) { if (string.Equals(Catalog[i].Sku, sku, StringComparison.OrdinalIgnoreCase)) { cosmeticDef = Catalog[i]; break; } } if (cosmeticDef == null) { return false; } slot = (((int)cosmeticDef.Slot == 0) ? "eyes" : (((int)cosmeticDef.Slot == 1) ? "mouth" : "detail")); scale = cosmeticDef.Scale; offset = cosmeticDef.Offset; try { string text = _cosmeticsDir; if (string.IsNullOrEmpty(text)) { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); text = Path.Combine(directoryName, "cosmetics"); } string path = Path.Combine(text, cosmeticDef.PngFile); if (!File.Exists(path)) { return false; } pngBytes = File.ReadAllBytes(path); return pngBytes.Length != 0; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] could not read published art for " + sku + ": " + ex.Message)); pngBytes = null; return false; } } public static Sprite[] GetShopFrames(string sku, out float fps) { fps = 0f; if (string.IsNullOrEmpty(sku)) { return null; } if (_shopFramesBySku.TryGetValue(sku, out (Sprite[], float) value)) { fps = value.Item2; return value.Item1; } return null; } public static void Initialize() { if (!initialized) { initialized = true; try { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); _cosmeticsDir = Path.Combine(directoryName, "cosmetics"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] plugin dir resolve failed: " + ex.Message)); return; } int num = BuildFromDisk(); if (num > 0) { Plugin.Log.LogWarning((object)$"[COSMETIC] {num} art file(s) missing at {_cosmeticsDir} — reinstall via the mod manager (Thunderstore bundles ship the art)."); } } } private static int BuildFromDisk() { //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Invalid comparison between Unknown and I4 //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) int num = 0; int num2 = 0; string cosmeticsDir = _cosmeticsDir; for (int i = 0; i < Catalog.Length; i++) { CosmeticDef cosmeticDef = Catalog[i]; cosmeticDef.Id = 1000 + i; if ((Object)(object)cosmeticDef.Template != (Object)null) { continue; } try { string path = Path.Combine(cosmeticsDir, cosmeticDef.PngFile); if (!File.Exists(path)) { num2++; Plugin.Log.LogWarning((object)("[COSMETIC] missing art " + cosmeticDef.PngFile + " — '" + cosmeticDef.DisplayName + "' disabled this session")); continue; } Sprite val = LoadCosmeticSprite(path); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("[COSMETIC] LoadImage failed for " + cosmeticDef.PngFile)); continue; } List list = new List { val }; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(cosmeticDef.PngFile); int num3 = 2; while (true) { string path2 = Path.Combine(cosmeticsDir, $"{fileNameWithoutExtension}__f{num3}.png"); if (!File.Exists(path2)) { break; } Sprite val2 = LoadCosmeticSprite(path2); if ((Object)(object)val2 == (Object)null) { break; } list.Add(val2); num3++; } GameObject val3 = new GameObject("CRCOS_" + cosmeticDef.Sku, new Type[2] { typeof(SpriteRenderer), typeof(CharacterItem) }); SpriteRenderer component = val3.GetComponent(); component.sprite = val; if ((Object)(object)_vanillaItemMat != (Object)null) { ((Renderer)component).sharedMaterial = _vanillaItemMat; } if (list.Count >= 2) { CosmeticFrameCycler cosmeticFrameCycler = val3.AddComponent(); cosmeticFrameCycler.frames = list.ToArray(); cosmeticFrameCycler.fps = cosmeticDef.Fps; _shopFramesBySku[cosmeticDef.Sku] = (list.ToArray(), cosmeticDef.Fps); Plugin.Log.LogInfo((object)$"[COSMETIC] '{cosmeticDef.DisplayName}' animated: {list.Count} frames @ {cosmeticDef.Fps:F0}fps"); } val3.layer = LayerMask.NameToLayer("Player"); ((Renderer)component).sortingLayerID = SortingLayer.NameToID("MostFront"); ((Renderer)component).sortingOrder = (((int)cosmeticDef.Slot == 0) ? 3 : (((int)cosmeticDef.Slot == 1) ? 4 : 5)); CharacterItem component2 = val3.GetComponent(); component2.sprite = val; component2.itemType = cosmeticDef.Slot; component2.scale = cosmeticDef.Scale; component2.offset = cosmeticDef.Offset; ((Object)val3).hideFlags = (HideFlags)61; val3.transform.position = new Vector3(0f, 100000f, 0f); val3.transform.localScale = Vector3.zero; cosmeticDef.Template = component2; byId[cosmeticDef.Id] = cosmeticDef; byTemplateName[((Object)val3).name] = cosmeticDef; _spriteBySku[cosmeticDef.Sku] = val; num++; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] build failed for " + cosmeticDef.Sku + ": " + ex.Message)); } } Plugin.Log.LogInfo((object)$"[COSMETIC] Initialized {num}/{Catalog.Length} custom cosmetics this pass (id base {1000}, {num2} missing art)"); return num2; } private static Sprite LoadCosmeticSprite(string path) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) try { byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { return null; } ((Object)val).hideFlags = (HideFlags)61; Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)val2).hideFlags = (HideFlags)61; return val2; } catch { return null; } } internal static void EnsureVanillaItemMaterial() { if ((Object)(object)_vanillaItemMat != (Object)null) { return; } try { CharacterCreatorItemLoader instance = CharacterCreatorItemLoader.instance; if ((Object)(object)instance == (Object)null || instance.eyes == null || instance.eyes.Length == 0) { return; } SpriteRenderer component = ((Component)instance.eyes[0]).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)((Renderer)component).sharedMaterial == (Object)null) { return; } _vanillaItemMat = ((Renderer)component).sharedMaterial; ManualLogSource log = Plugin.Log; Shader shader = _vanillaItemMat.shader; log.LogInfo((object)("[COSMETIC] adopting vanilla item material, shader=" + ((shader != null) ? ((Object)shader).name : null))); CosmeticDef[] catalog = Catalog; foreach (CosmeticDef cosmeticDef in catalog) { SpriteRenderer val = (((Object)(object)cosmeticDef.Template != (Object)null) ? ((Component)cosmeticDef.Template).GetComponent() : null); if ((Object)(object)val != (Object)null) { ((Renderer)val).sharedMaterial = _vanillaItemMat; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] material adopt failed: " + ex.Message)); } } public static CharacterItem GetItem(int itemID, CharacterItemType itemType) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) EnsureVanillaItemMaterial(); if (byId.TryGetValue(itemID, out var value) && value.Slot == itemType && (Object)(object)value.Template != (Object)null) { return value.Template; } return null; } public static bool TryGetId(CharacterItem item, out int id) { id = -1; if ((Object)(object)item == (Object)null) { return false; } string text = ((Object)((Component)item).gameObject).name; if (!text.StartsWith("CRCOS_", StringComparison.Ordinal)) { return false; } while (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - 7).TrimEnd(); } if (byTemplateName.TryGetValue(text, out var value)) { id = value.Id; return true; } return false; } public static List OwnedItemsFor(CharacterItemType slot) { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) List list = new List(); List cachedShopItems = ApiClient.CachedShopItems; if (cachedShopItems == null) { try { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.FetchShopItems(localSteamId); } } catch { } return list; } HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (ApiClient.ShopItemData item in cachedShopItems) { if (item != null && item.owned && item.kind == "face" && !string.IsNullOrEmpty(item.sku)) { hashSet.Add(item.sku); } } CosmeticDef[] catalog = Catalog; foreach (CosmeticDef cosmeticDef in catalog) { if ((Object)(object)cosmeticDef.Template != (Object)null && cosmeticDef.Slot == slot && hashSet.Contains(cosmeticDef.Sku)) { list.Add(cosmeticDef); } } return list; } internal static int CurrentFaceIdFor(CharacterCreator creator, CharacterItemType slot, int slotNr) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 if ((Object)(object)creator == (Object)null || creator.currentPlayerFace == null) { return -1; } PlayerFace currentPlayerFace = creator.currentPlayerFace; if ((int)slot == 0) { return currentPlayerFace.eyeID; } if ((int)slot == 1) { return currentPlayerFace.mouthID; } return (slotNr == 0) ? currentPlayerFace.detailID : currentPlayerFace.detail2ID; } } [HarmonyPatch(typeof(CharacterCreatorItemLoader), "GetItem")] internal static class CosmeticGetItemPatch { private static bool Prefix(int itemID, CharacterItemType itemType, ref CharacterItem __result) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (itemID < 1000) { return true; } __result = CustomCosmetics.GetItem(itemID, itemType); return false; } } [HarmonyPatch(typeof(CharacterCreatorItemLoader), "GetItemID")] internal static class CosmeticGetItemIdPatch { private static bool Prefix(CharacterItem newSprite, ref int __result) { if (CustomCosmetics.TryGetId(newSprite, out var id)) { __result = id; return false; } return true; } } [HarmonyPatch(typeof(CharacterCreatorButtonSpawner), "OpenMenu", new Type[] { typeof(CharacterItemType), typeof(int) })] internal static class CosmeticButtonSpawnerPatch { private static void Postfix(CharacterCreatorButtonSpawner __instance, CharacterItemType target, int slotNr) { //IL_0008: 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_00af: 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_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_0175: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) try { CustomCosmetics.EnsureVanillaItemMaterial(); List list = CustomCosmetics.OwnedItemsFor(target); if (list.Count == 0) { return; } CharacterCreator component = ((Component)__instance).GetComponent(); GameObject sourceButton = __instance.sourceButton; if ((Object)(object)sourceButton == (Object)null) { return; } int num = CustomCosmetics.CurrentFaceIdFor(component, target, slotNr); foreach (CustomCosmetics.CosmeticDef item in list) { GameObject val = Object.Instantiate(sourceButton, sourceButton.transform.parent); val.SetActive(true); Transform val2 = val.transform.Find("ItemParent"); GameObject val3 = Object.Instantiate(((Component)item.Template).gameObject, val2); val.GetComponent().itemType = target; val.GetComponent().slotNr = slotNr; CharacterItem componentInChildren = val.GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.sprite = item.Template.sprite; } CharacterItem componentInChildren2 = val3.GetComponentInChildren(); SpriteRenderer componentInChildren3 = val3.GetComponentInChildren(); if ((Object)(object)componentInChildren2 != (Object)null) { ((Renderer)((Component)componentInChildren2).GetComponent()).sortingOrder = ((Renderer)((Component)item.Template).GetComponent()).sortingOrder; componentInChildren2.scale = item.Scale; componentInChildren2.itemType = target; componentInChildren2.offset = item.Offset; componentInChildren2.slotNr = slotNr; } if ((Object)(object)componentInChildren3 != (Object)null) { ((Component)componentInChildren3).transform.localPosition = Vector2.op_Implicit(item.Offset); ((Component)componentInChildren3).transform.localScale = Vector2.op_Implicit(item.Scale * Vector2.one); } if (num == item.Id) { Transform val4 = val.transform.Find("SelectedDot"); if ((Object)(object)val4 != (Object)null) { ((Component)val4).gameObject.SetActive(true); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] OpenMenu inject failed: " + ex.Message)); } } } [HarmonyPatch(typeof(CharacterCreatorButtonSpawner), "SelectButton")] internal static class CosmeticSelectButtonPatch { private static void Postfix(CharacterCreatorButtonSpawner __instance, CharacterItemType itemType, int slotNr) { //IL_000a: 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_0062: Expected O, but got Unknown try { CharacterCreator component = ((Component)__instance).GetComponent(); int num = CustomCosmetics.CurrentFaceIdFor(component, itemType, slotNr); if (num < 1000) { return; } GameObject sourceButton = __instance.sourceButton; if ((Object)(object)sourceButton == (Object)null) { return; } foreach (Transform item in sourceButton.transform.parent) { Transform val = item; if (!((Component)val).gameObject.activeSelf) { continue; } CharacterItem componentInChildren = ((Component)val).GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null) && CustomCosmetics.TryGetId(componentInChildren, out var id) && id == num) { Transform val2 = val.Find("SelectedDot"); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(true); } } } } catch { } } } internal static class CustomMapColors { private struct Preset { public string BaseArt; public Color? MapBlockColor; public Color? SecondaryColor; public Color? Sparkle; public Action Configure; } private static readonly Dictionary _profileCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary _presets = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "mapcolor_soft", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.52f, 0.6f, 0.72f), SecondaryColor = new Color(0.92f, 0.66f, 0.48f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-24f); ((ParameterOverride)(object)cg.temperature).Override(4f); ((ParameterOverride)(object)cg.postExposure).Override(-0.35f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.5f, 0.5f, 0.54f)); } } }, { "mapcolor_moss", new Preset { BaseArt = "Poison", MapBlockColor = new Color(0.44f, 0.64f, 0.4f), SecondaryColor = new Color(0.78f, 0.62f, 0.38f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-18f); ((ParameterOverride)(object)cg.temperature).Override(8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.5f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.42f, 0.47f, 0.42f)); } } }, { "mapcolor_cream", new Preset { BaseArt = "Gold", MapBlockColor = new Color(0.9f, 0.82f, 0.62f), SecondaryColor = new Color(0.56f, 0.74f, 0.92f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-16f); ((ParameterOverride)(object)cg.temperature).Override(-8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.32f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.54f, 0.53f, 0.52f)); } } }, { "mapcolor_lavender", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.72f, 0.62f, 0.92f), SecondaryColor = new Color(0.92f, 0.8f, 0.5f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-18f); ((ParameterOverride)(object)cg.temperature).Override(4f); ((ParameterOverride)(object)cg.postExposure).Override(-0.4f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.5f, 0.48f, 0.55f)); } } }, { "mapcolor_dusk", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.34f, 0.46f, 0.78f), SecondaryColor = new Color(0.96f, 0.64f, 0.3f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-14f); ((ParameterOverride)(object)cg.temperature).Override(8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.6f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.39f, 0.4f, 0.48f)); } } }, { "mapcolor_sand", new Preset { BaseArt = "Gold", MapBlockColor = new Color(0.9f, 0.72f, 0.42f), SecondaryColor = new Color(0.38f, 0.72f, 0.74f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-14f); ((ParameterOverride)(object)cg.temperature).Override(-8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.4f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.52f, 0.5f, 0.45f)); } } }, { "mapcolor_mono", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.82f, 0.82f, 0.83f), SecondaryColor = new Color(0.42f, 0.42f, 0.43f), Configure = delegate(ColorGrading cg) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-100f); ((ParameterOverride)(object)cg.postExposure).Override(-0.42f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.49f, 0.49f, 0.49f)); } } }, { "mapcolor_forest", new Preset { BaseArt = "Poison", MapBlockColor = new Color(0.26f, 0.54f, 0.3f), SecondaryColor = new Color(0.46f, 0.72f, 0.34f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-8f); ((ParameterOverride)(object)cg.temperature).Override(10f); ((ParameterOverride)(object)cg.postExposure).Override(-0.66f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.42f, 0.41f, 0.35f)); } } }, { "mapcolor_amethyst", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.66f, 0.42f, 0.88f), SecondaryColor = new Color(0.9f, 0.72f, 0.38f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-10f); ((ParameterOverride)(object)cg.temperature).Override(8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.48f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.45f, 0.42f, 0.49f)); } } }, { "mapcolor_charcoal", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.74f, 0.75f, 0.76f), SecondaryColor = new Color(0.44f, 0.45f, 0.47f), Configure = delegate(ColorGrading cg) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-80f); ((ParameterOverride)(object)cg.postExposure).Override(-0.72f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.39f, 0.39f, 0.41f)); } } }, { "mapcolor_crimson_map", new Preset { BaseArt = "Soviet", MapBlockColor = new Color(0.84f, 0.28f, 0.3f), SecondaryColor = new Color(0.3f, 0.68f, 0.64f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-10f); ((ParameterOverride)(object)cg.temperature).Override(-8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.56f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.44f, 0.39f, 0.4f)); } } }, { "mapcolor_slate", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.46f, 0.58f, 0.74f), SecondaryColor = new Color(0.84f, 0.56f, 0.32f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-20f); ((ParameterOverride)(object)cg.temperature).Override(6f); ((ParameterOverride)(object)cg.postExposure).Override(-0.46f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.46f, 0.48f, 0.51f)); } } }, { "mapcolor_rose", new Preset { BaseArt = "Gold", MapBlockColor = new Color(0.88f, 0.52f, 0.6f), SecondaryColor = new Color(0.44f, 0.74f, 0.64f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-14f); ((ParameterOverride)(object)cg.temperature).Override(4f); ((ParameterOverride)(object)cg.postExposure).Override(-0.4f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.52f, 0.48f, 0.51f)); } } }, { "mapcolor_mint", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.56f, 0.88f, 0.7f), SecondaryColor = new Color(0.98f, 0.58f, 0.5f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-10f); ((ParameterOverride)(object)cg.temperature).Override(-2f); ((ParameterOverride)(object)cg.postExposure).Override(-0.4f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.48f, 0.52f, 0.5f)); } } }, { "mapcolor_sunset", new Preset { BaseArt = "Gold", MapBlockColor = new Color(0.98f, 0.56f, 0.3f), SecondaryColor = new Color(0.56f, 0.42f, 0.78f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-6f); ((ParameterOverride)(object)cg.temperature).Override(-6f); ((ParameterOverride)(object)cg.postExposure).Override(-0.48f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.48f, 0.43f, 0.47f)); } } }, { "mapcolor_obsidian", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.42f, 0.48f, 0.6f), SecondaryColor = new Color(0.66f, 0.74f, 0.88f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-30f); ((ParameterOverride)(object)cg.temperature).Override(-8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.7f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.36f, 0.37f, 0.42f)); } } }, { "mapcolor_abyss", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.24f, 0.52f, 0.64f), SecondaryColor = new Color(0.42f, 0.86f, 0.88f), Configure = delegate(ColorGrading cg) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-10f); ((ParameterOverride)(object)cg.temperature).Override(-22f); ((ParameterOverride)(object)cg.tint).Override(-8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.7f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.34f, 0.4f, 0.44f)); } } }, { "mapcolor_pine", new Preset { BaseArt = "Poison", MapBlockColor = new Color(0.28f, 0.52f, 0.44f), SecondaryColor = new Color(0.44f, 0.68f, 0.52f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-14f); ((ParameterOverride)(object)cg.temperature).Override(-6f); ((ParameterOverride)(object)cg.postExposure).Override(-0.6f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.37f, 0.43f, 0.41f)); } } }, { "mapcolor_iron", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.56f, 0.6f, 0.66f), SecondaryColor = new Color(0.82f, 0.5f, 0.28f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-30f); ((ParameterOverride)(object)cg.temperature).Override(4f); ((ParameterOverride)(object)cg.postExposure).Override(-0.54f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.42f, 0.43f, 0.46f)); } } }, { "mapcolor_burgundy", new Preset { BaseArt = "Soviet", MapBlockColor = new Color(0.68f, 0.24f, 0.36f), SecondaryColor = new Color(0.38f, 0.54f, 0.82f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-10f); ((ParameterOverride)(object)cg.temperature).Override(6f); ((ParameterOverride)(object)cg.postExposure).Override(-0.64f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.41f, 0.36f, 0.42f)); } } }, { "mapcolor_magma", new Preset { BaseArt = "Soviet", MapBlockColor = new Color(0.82f, 0.26f, 0.16f), SecondaryColor = new Color(0.99f, 0.76f, 0.24f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-4f); ((ParameterOverride)(object)cg.temperature).Override(20f); ((ParameterOverride)(object)cg.postExposure).Override(-0.54f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.46f, 0.4f, 0.35f)); } } }, { "mapcolor_velvet", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.5f, 0.28f, 0.7f), SecondaryColor = new Color(0.9f, 0.7f, 0.36f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-4f); ((ParameterOverride)(object)cg.temperature).Override(8f); ((ParameterOverride)(object)cg.postExposure).Override(-0.7f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.42f, 0.36f, 0.48f)); } } }, { "mapcolor_blackwood", new Preset { BaseArt = "Gold", MapBlockColor = new Color(0.5f, 0.5f, 0.54f), SecondaryColor = new Color(0.9f, 0.54f, 0.24f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-26f); ((ParameterOverride)(object)cg.temperature).Override(12f); ((ParameterOverride)(object)cg.postExposure).Override(-0.66f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.38f, 0.37f, 0.38f)); } } }, { "mapcolor_gilded", new Preset { BaseArt = "Gold", MapBlockColor = new Color(1f, 0.8f, 0.26f), SecondaryColor = new Color(0.94f, 0.62f, 0.18f), Sparkle = new Color(1f, 0.97f, 0.8f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(8f); ((ParameterOverride)(object)cg.temperature).Override(18f); ((ParameterOverride)(object)cg.postExposure).Override(-0.52f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.5f, 0.45f, 0.36f)); } } }, { "mapcolor_platinum", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.8f, 0.84f, 0.9f), SecondaryColor = new Color(0.58f, 0.62f, 0.7f), Sparkle = new Color(1f, 1f, 1f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(-55f); ((ParameterOverride)(object)cg.temperature).Override(-4f); ((ParameterOverride)(object)cg.postExposure).Override(-0.54f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.44f, 0.45f, 0.48f)); } } }, { "mapcolor_aurora", new Preset { BaseArt = "Sky", MapBlockColor = new Color(0.22f, 0.88f, 0.62f), SecondaryColor = new Color(0.58f, 0.36f, 0.96f), Sparkle = new Color(0.55f, 0.95f, 1f), Configure = delegate(ColorGrading cg) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ((ParameterOverride)(object)cg.saturation).Override(10f); ((ParameterOverride)(object)cg.temperature).Override(-10f); ((ParameterOverride)(object)cg.postExposure).Override(-0.66f); ((ParameterOverride)(object)cg.colorFilter).Override(new Color(0.38f, 0.42f, 0.47f)); } } } }; private static readonly Dictionary _backgroundColors = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "mapcolor_soft", new Color(0.62f, 0.5f, 0.4f) }, { "mapcolor_moss", new Color(0.3f, 0.42f, 0.22f) }, { "mapcolor_cream", new Color(0.72f, 0.52f, 0.3f) }, { "mapcolor_lavender", new Color(0.52f, 0.42f, 0.68f) }, { "mapcolor_dusk", new Color(0.24f, 0.26f, 0.52f) }, { "mapcolor_sand", new Color(0.72f, 0.46f, 0.22f) }, { "mapcolor_mono", new Color(0.28f, 0.28f, 0.3f) }, { "mapcolor_forest", new Color(0.44f, 0.3f, 0.16f) }, { "mapcolor_amethyst", new Color(0.5f, 0.24f, 0.46f) }, { "mapcolor_charcoal", new Color(0.07f, 0.07f, 0.08f) }, { "mapcolor_crimson_map", new Color(0.48f, 0.14f, 0.18f) }, { "mapcolor_slate", new Color(0.52f, 0.36f, 0.24f) }, { "mapcolor_rose", new Color(0.56f, 0.26f, 0.34f) }, { "mapcolor_mint", new Color(0.2f, 0.44f, 0.28f) }, { "mapcolor_sunset", new Color(0.66f, 0.28f, 0.3f) }, { "mapcolor_obsidian", new Color(0.06f, 0.07f, 0.13f) }, { "mapcolor_abyss", new Color(0.03f, 0.09f, 0.18f) }, { "mapcolor_pine", new Color(0.2f, 0.4f, 0.34f) }, { "mapcolor_iron", new Color(0.4f, 0.3f, 0.22f) }, { "mapcolor_burgundy", new Color(0.36f, 0.14f, 0.24f) }, { "mapcolor_magma", new Color(0.64f, 0.28f, 0.06f) }, { "mapcolor_velvet", new Color(0.34f, 0.18f, 0.44f) }, { "mapcolor_blackwood", new Color(0.1f, 0.06f, 0.04f) }, { "mapcolor_gilded", new Color(0.42f, 0.3f, 0.1f) }, { "mapcolor_platinum", new Color(0.24f, 0.26f, 0.29f) }, { "mapcolor_aurora", new Color(0.05f, 0.08f, 0.18f) } }; internal static IEnumerable CachedClones => _profileCache.Values; public static bool IsCustomSku(string sku) { return sku != null && _presets.ContainsKey(sku); } public static bool IsVanillaStyled(string sku) { if (string.IsNullOrEmpty(sku)) { return false; } if (!IsCustomSku(sku)) { return true; } try { string text = FriendlyName(sku); string baseArt = GetBaseArt(sku); return !string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(baseArt) && string.Equals(text, baseArt, StringComparison.OrdinalIgnoreCase); } catch { return false; } } public static string FriendlyName(string sku) { if (string.IsNullOrEmpty(sku)) { return "Default"; } string text = (sku.StartsWith("mapcolor_", StringComparison.OrdinalIgnoreCase) ? sku.Substring(9) : sku); if (text.EndsWith("_map", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - 4); } text = text.Replace('_', ' ').Trim(); if (text.Length == 0) { return "Default"; } string[] array = text.Split(' '); for (int i = 0; i < array.Length; i++) { if (array[i].Length > 0) { array[i] = char.ToUpperInvariant(array[i][0]) + array[i].Substring(1); } } return string.Join(" ", array); } public static string GetBaseArt(string sku) { if (sku != null && _presets.TryGetValue(sku, out var value)) { return value.BaseArt; } return null; } public static Color? GetMapBlockColor(string sku) { if (sku != null && _presets.TryGetValue(sku, out var value)) { return value.MapBlockColor; } return null; } public static Color GetSecondaryColor(string sku) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0087: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (sku != null && _presets.TryGetValue(sku, out var value) && value.SecondaryColor.HasValue) { return value.SecondaryColor.Value; } Color val = (Color)(((??)GetMapBlockColor(sku)) ?? Color.white); return new Color(val.r * 0.6f, val.g * 0.6f, val.b * 0.6f, val.a); } public static Color? GetBackgroundColor(string sku) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (sku != null && _backgroundColors.TryGetValue(sku, out var value)) { return value; } return null; } public static Color? GetSparkleColor(string sku) { if (sku != null && _presets.TryGetValue(sku, out var value)) { return value.Sparkle; } return null; } public static PostProcessProfile BuildOrGetClone(string sku, PostProcessProfile baseProfile) { //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)baseProfile == (Object)null || !_presets.TryGetValue(sku, out var value)) { return null; } if (_profileCache.TryGetValue(sku, out var value2) && (Object)(object)value2 != (Object)null) { return value2; } try { PostProcessProfile val = Object.Instantiate(baseProfile); ((Object)val).name = "CR_MapColor_" + sku; ((Object)val).hideFlags = (HideFlags)61; if (val.HasSettings()) { val.RemoveSettings(); } ColorGrading val2 = ScriptableObject.CreateInstance(); ((Object)val2).hideFlags = (HideFlags)61; ((ParameterOverride)(object)((PostProcessEffectSettings)val2).enabled).Override(true); ((ParameterOverride)(object)val2.gradingMode).Override((GradingMode)0); value.Configure(val2); try { Color val3 = (Color)(((??)GetMapBlockColor(sku)) ?? new Color(0.5f, 0.5f, 0.5f)); Color val4 = default(Color); ((Color)(ref val4))..ctor(Mathf.Clamp01(0.35f + val3.r * 0.75f), Mathf.Clamp01(0.35f + val3.g * 0.75f), Mathf.Clamp01(0.35f + val3.b * 0.75f)); Color val5 = Color.Lerp(new Color(0.5f, 0.5f, 0.5f), val4, 0.3f); ((ParameterOverride)(object)val2.colorFilter).Override(val5); float num = Mathf.Max(val3.r, Mathf.Max(val3.g, val3.b)); float num2 = Mathf.Min(val3.r, Mathf.Min(val3.g, val3.b)); if (!(num - num2 < 0.08f)) { ((ParameterOverride)(object)val2.saturation).Override(12f); } } catch { } val.AddSettings((PostProcessEffectSettings)(object)val2); try { Bloom val6 = default(Bloom); if (val.TryGetSettings(ref val6) && (Object)(object)val6 != (Object)null) { Plugin.Log.LogInfo((object)$"[MAPCOLOR] {sku}: base bloom intensity={((ParameterOverride)(object)val6.intensity).value:F1} tint={((ParameterOverride)(object)val6.color).value} threshold={((ParameterOverride)(object)val6.threshold).value:F2}"); ((ParameterOverride)(object)val6.intensity).Override(Mathf.Min(((ParameterOverride)(object)val6.intensity).value, 1.2f)); ((ParameterOverride)(object)val6.color).Override(Color.white); ((ParameterOverride)(object)val6.threshold).Override(Mathf.Max(((ParameterOverride)(object)val6.threshold).value, 1.05f)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MAPCOLOR] bloom tune failed for " + sku + ": " + ex.Message)); } _profileCache[sku] = val; return val; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[MAPCOLOR] Clone " + sku + " failed: " + ex2.Message)); return null; } } } internal static class FfaMapScale { [HarmonyPatch(typeof(MapTransition), "SetStartPos")] private class MapTransition_SetStartPos_FfaScale_Patch { private static void Postfix(Map map) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)map == (Object)null) { return; } if (!FfaMode.EngineActive()) { Reset(); return; } int num = ReadPublishedCount(); if (num <= 0) { Reset(); return; } float num2 = FactorFor(num); if (num2 <= 1.001f) { Reset(); return; } ((Component)map).transform.localScale = new Vector3(num2, num2, 1f); map.size *= num2; CurrentFactor = num2; Plugin.Log.LogInfo((object)$"[FFA-SCALE] map scaled x{num2:F2} for {num} players (size {map.size:F1})"); try { FfaSpawnPoints.ScanForMap(map, num2, ((Component)map).transform.position, Math.Max(0, Diag2v2.PlayersNeeded() - 4)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-SPAWN] scan hook: " + ex.Message)); } } catch (Exception ex2) { Reset(); Plugin.Log.LogWarning((object)("[FFA-SCALE] SetStartPos: " + ex2.Message)); } } } [HarmonyPatch(typeof(PlayerManager), "MovePlayers")] private class PlayerManager_MovePlayers_FfaScale_Patch { private static bool Prefix(PlayerManager __instance, SpawnPoint[] spawnPoints) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) try { float num = CurrentFactor; if (!FfaMode.EngineActive()) { return true; } if (__instance?.players == null || spawnPoints == null) { return true; } if (num < 1f) { num = 1f; } List list = new List(); IList list2 = ((num > 1.001f) ? FfaSpawnPoints.Extras : null); int num2 = 0; for (int i = 0; i < __instance.players.Count && i < spawnPoints.Length; i++) { Player val = __instance.players[i]; if ((Object)(object)val == (Object)null || (Object)(object)spawnPoints[i] == (Object)null) { continue; } Vector3 val2 = spawnPoints[i].localStartPos * num; bool flag = false; for (int j = 0; j < list.Count; j++) { Vector3 val3 = list[j] - val2; if (((Vector3)(ref val3)).sqrMagnitude < 0.01f) { flag = true; break; } } if (flag && list2 != null && num2 < list2.Count) { val2 = list2[num2++]; } list.Add(val2); ((MonoBehaviour)__instance).StartCoroutine(__instance.Move(val.data.playerVel, val2)); PlaySpawnSound(__instance, i, ((Component)val).transform); } return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-SCALE] MovePlayers: " + ex.Message)); return true; } } } [HarmonyPatch(typeof(PhotonMapObject), "Start")] private class PhotonMapObject_Start_FfaScale_Patch { private static int lastLogMapId = int.MinValue; private static int lastSkipLogMapId = int.MinValue; private static void Postfix(PhotonMapObject __instance) { //IL_00b2: 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_00cc: 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) try { float currentFactor = CurrentFactor; if (currentFactor <= 1.001f || !FfaMode.EngineActive() || (Object)(object)__instance == (Object)null || !__instance.photonSpawned) { return; } Transform transform = ((Component)__instance).transform; int num = 0; try { num = (((Object)(object)transform.parent != (Object)null) ? ((Object)transform.parent).GetInstanceID() : 0); } catch { } if (!RoomAdvertisesScaleCapability()) { if (num != lastSkipLogMapId) { lastSkipLogMapId = num; Plugin.Log.LogInfo((object)"[FFA-SCALE] not every client in the room has the rescale capability — networked map objects stay vanilla-scaled this map"); } return; } transform.localScale = new Vector3(transform.localScale.x * currentFactor, transform.localScale.y * currentFactor, transform.localScale.z); if (num != lastLogMapId) { lastLogMapId = num; Plugin.Log.LogInfo((object)$"[FFA-SCALE] networked map objects rescaled x{currentFactor:F2} (logged once per map)"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-SCALE] PhotonMapObject.Start: " + ex.Message)); } } } [HarmonyPatch(typeof(OutOfBoundsHandler), "LateUpdate")] private class OutOfBoundsHandler_FfaScale_Patch { private static bool Prefix(OutOfBoundsHandler __instance) { //IL_00ab: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04d0: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_0532: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0492: Unknown result type (might be due to invalid IL or missing references) try { float f = CurrentFactor; if (f <= 1.001f || !FfaMode.EngineActive()) { return true; } if (!Object.op_Implicit((Object)(object)__instance.data)) { Object.Destroy((Object)(object)((Component)__instance).gameObject); } else { if (!__instance.data.playerVel.simulated || !__instance.data.isPlaying) { return false; } float num = Mathf.InverseLerp(-35.56f * f, 35.56f * f, ((Component)__instance.data).transform.position.x); float num2 = Mathf.InverseLerp(-20f * f, 20f * f, ((Component)__instance.data).transform.position.y); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(num, num2, 0f); ((Vector3)(ref val))..ctor(Mathf.Clamp(val.x, 0f, 1f), Mathf.Clamp(val.y, 0f, 1f), val.z); __instance.almostOutOfBounds = false; __instance.outOfBounds = false; if (val.x <= 0f || val.x >= 1f || val.y >= 1f || val.y <= 0f) { __instance.outOfBounds = true; } else if (val.x < __instance.warningPercentage || val.x > 1f - __instance.warningPercentage || val.y > 1f - __instance.warningPercentage || val.y < __instance.warningPercentage) { __instance.almostOutOfBounds = true; if (val.x < __instance.warningPercentage) { val.x = 0f; } if (val.x > 1f - __instance.warningPercentage) { val.x = 1f; } if (val.y < __instance.warningPercentage) { val.y = 0f; } if (val.y > 1f - __instance.warningPercentage) { val.y = 1f; } } __instance.counter += TimeHandler.deltaTime; if (__instance.almostOutOfBounds && !__instance.data.dead) { ((Component)__instance).transform.position = GetPoint(val); ((Component)__instance).transform.rotation = Quaternion.LookRotation(Vector3.forward, -(((Component)__instance.data).transform.position - ((Component)__instance).transform.position)); if (__instance.counter > 0.1f) { __instance.counter = 0f; __instance.warning.Play(); } } if (!__instance.outOfBounds || __instance.data.dead) { return false; } __instance.data.sinceGrounded = 0f; ((Component)__instance).transform.position = GetPoint(val); ((Component)__instance).transform.rotation = Quaternion.LookRotation(Vector3.forward, -(((Component)__instance.data).transform.position - ((Component)__instance).transform.position)); if (__instance.counter > 0.1f && __instance.data.view.IsMine) { __instance.counter = 0f; if (__instance.data.block.IsBlocking()) { __instance.rpc.CallFunction("ShieldOutOfBounds"); PlayerVelocity playerVel = __instance.data.playerVel; playerVel.velocity *= 0f; __instance.data.healthHandler.CallTakeForce(Vector2.op_Implicit(((Component)__instance).transform.up * 400f * __instance.data.playerVel.mass), (ForceMode2D)1, false, true, 0f); ((Component)__instance.data).transform.position = ((Component)__instance).transform.position; } else { __instance.rpc.CallFunction("OutOfBounds"); __instance.data.healthHandler.CallTakeForce(Vector2.op_Implicit(((Component)__instance).transform.up * 200f * __instance.data.playerVel.mass), (ForceMode2D)1, false, true, 0f); ((Damagable)__instance.data.healthHandler).CallTakeDamage(Vector2.op_Implicit(51f * ((Component)__instance).transform.up), Vector2.op_Implicit(((Component)__instance.data).transform.position), (GameObject)null, (Player)null, true, (DamageSource)1); } } } return false; Vector3 GetPoint(Vector3 p) { //IL_0019: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) float num3 = Mathf.Lerp(-35.56f * f, 35.56f * f, p.x); float num4 = Mathf.Lerp(-20f * f, 20f * f, p.y); return new Vector3(num3, num4, 0f); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-SCALE] OutOfBounds: " + ex.Message)); return true; } } } public const string PropKey = "cr_ffa_scl"; public const float PerPlayer = 0.06f; public const float MaxFactor = 1.4f; private static FieldInfo fiSpawnSounds; private static PropertyInfo piSoundInstance; private static MethodInfo miSoundPlay; private static bool soundReflectResolved; public const string ScaleCapabilityProp = "cr_msv2"; public static float CurrentFactor { get; private set; } = 1f; public static void Reset() { try { CurrentFactor = 1f; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-SCALE] Reset: " + ex.Message)); } } public static void MasterPublishCount() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown try { if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return; } int num = 0; List list = PlayerManager.instance?.players; if (list != null) { foreach (Player item in list) { if ((Object)(object)item != (Object)null && (Object)(object)((Component)item).gameObject != (Object)null) { num++; } } } if (num == 0) { Room currentRoom = PhotonNetwork.CurrentRoom; num = ((currentRoom != null) ? currentRoom.PlayerCount : 0); } num = Math.Max(2, num); Hashtable val = new Hashtable(); val[(object)"cr_ffa_scl"] = num; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-SCALE] MasterPublishCount: " + ex.Message)); } } private static float FactorFor(int playerCount) { return Mathf.Clamp(1f + 0.06f * (float)(playerCount - 4), 1f, 1.4f); } private static int ReadPublishedCount() { try { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = ((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null); if (val == null || !((Dictionary)(object)val).ContainsKey((object)"cr_ffa_scl")) { return -1; } if (val[(object)"cr_ffa_scl"] is int result) { return result; } if (val[(object)"cr_ffa_scl"] is string s && int.TryParse(s, out var result2)) { return result2; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA-SCALE] ReadPublishedCount: " + ex.Message)); } return -1; } private static void PlaySpawnSound(PlayerManager pm, int index, Transform at) { try { if (!soundReflectResolved) { soundReflectResolved = true; fiSpawnSounds = typeof(PlayerManager).GetField("soundCharacterSpawn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Type type = AccessTools.TypeByName("Sonigon.SoundManager"); if (type != null) { piSoundInstance = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "Play")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 2 && parameters[1].ParameterType == typeof(Transform)) { miSoundPlay = methodInfo; break; } } } } } if (!(fiSpawnSounds == null) && !(miSoundPlay == null) && !(piSoundInstance == null) && fiSpawnSounds.GetValue(pm) is Array { Length: not 0 } array) { object value = piSoundInstance.GetValue(null, null); if (value != null) { miSoundPlay.Invoke(value, new object[2] { array.GetValue(index % array.Length), at }); } } } catch { } } private static bool RoomAdvertisesScaleCapability() { try { if (PhotonNetwork.OfflineMode) { return true; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null || playerList.Length == 0) { return false; } Player[] array = playerList; foreach (Player val in array) { if (val == null) { return false; } Hashtable customProperties = val.CustomProperties; if (customProperties == null || !((Dictionary)(object)customProperties).ContainsKey((object)"cr_msv2")) { return false; } } return true; } catch { return false; } } } internal static class FfaMode { public class FfaLeaver { public string displayName; public int slot; public int roundsWon; public int pointsTotal; public int kills; public int leftGameNumber; } private class FfaBaseline { public bool captured; public float gravityForce; public float regeneration; public int jumps; public float ammoReg; public GameObject projectile; } public const int RoundsToWin = 5; public const int PointsToWinRound = 2; public const int CardCap = 5; private const float PickBaseSeconds = 45f; private const float PickGraceSeconds = 20f; private const float PickCapSeconds = 90f; private const float ManifestWaitSeconds = 8f; private const float AutoPickLeadSeconds = 5f; private const float AutoPickLeadFallbackSeconds = 12f; private const string PropCycle = "cr_ffa_cyc"; private const string PropResult = "cr_ffa_res"; private const string PropDeadline = "cr_ffa_dl"; private const string PropPick = "cr_ffa_pk"; private static readonly Dictionary points = new Dictionary(); private static readonly Dictionary rounds = new Dictionary(); private static readonly Dictionary pointsTotal = new Dictionary(); private static readonly Dictionary kills = new Dictionary(); private static readonly List timelineEvents = new List(); private static readonly Dictionary> decks = new Dictionary>(); private static readonly Dictionary> pickHistory = new Dictionary>(); private static readonly Dictionary baselines = new Dictionary(); public static readonly Dictionary Leavers = new Dictionary(); private static int gameNumber = 0; private static int cycleNumber = 0; private static bool isTransitioning = false; private static bool pointLatched = false; private static bool gameOverFired = false; private static bool freshGameCancelFired = false; private static float matchStartRealtime = 0f; private static readonly HashSet deckViewRebuilds = new HashSet(); private static bool pickPhaseActive = false; private static float pickDeadlineRealtime = 0f; private static bool pickDeadlineShared = false; private static bool localPickOpen = false; private static readonly Dictionary damageDealt = new Dictionary(); private static readonly Dictionary> killTimeline = new Dictionary>(); private static readonly Dictionary> damageTimeline = new Dictionary>(); private const int FFA_TIMELINE_CAP = 128; public const float SpawnGraceSeconds = 1f; private static float spawnGraceUntil = 0f; private static bool lastLocalPlaying = false; private static readonly List localCardObjects = new List(); public static string TimelineString => string.Join(",", timelineEvents.ToArray()); public static bool PickPhaseActive => pickPhaseActive; public static bool LocalPickOpen => localPickOpen; private static float CurrentAutoPickLead => pickDeadlineShared ? 5f : 12f; public static float PickSecondsLeft => pickPhaseActive ? Mathf.Max(0f, pickDeadlineRealtime - CurrentAutoPickLead - Time.realtimeSinceStartup) : 0f; public static float PickWindowSecondsLeft => pickPhaseActive ? Mathf.Max(0f, pickDeadlineRealtime - Time.realtimeSinceStartup) : 0f; public static int GameNumber => gameNumber; public static bool InFfaMatch => EngineActive() && matchStartRealtime > 0f; public static float MatchStartRealtime => matchStartRealtime; public static bool SpawnGraceActive => spawnGraceUntil > 0f && Time.realtimeSinceStartup < spawnGraceUntil && EngineActive(); public static float SpawnGraceLeft => SpawnGraceActive ? Mathf.Max(0f, spawnGraceUntil - Time.realtimeSinceStartup) : 0f; public static bool EngineActive() { try { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return false; } if (!(PhotonNetwork.CurrentRoom.Name ?? "").StartsWith("ffa_")) { return false; } if (!string.IsNullOrEmpty(ApiClient.ActiveFfaLobbyId)) { return true; } return ((Dictionary)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties)?.ContainsKey((object)"cr_ffa_n") ?? false; } catch { return false; } } public static int RoundsFor(int teamId) { int value; return rounds.TryGetValue(teamId, out value) ? value : 0; } public static int PointsFor(int teamId) { int value; return points.TryGetValue(teamId, out value) ? value : 0; } public static int PointsTotalFor(int teamId) { int value; return pointsTotal.TryGetValue(teamId, out value) ? value : 0; } public static int KillsFor(int teamId) { int value; return kills.TryGetValue(teamId, out value) ? value : 0; } public static int ComparePlacement(int teamA, int teamB) { int num = RoundsFor(teamB).CompareTo(RoundsFor(teamA)); if (num != 0) { return num; } num = PointsTotalFor(teamB).CompareTo(PointsTotalFor(teamA)); if (num != 0) { return num; } return KillsFor(teamB).CompareTo(KillsFor(teamA)); } public static int DamageDealtFor(int teamId) { float value; return damageDealt.TryGetValue(teamId, out value) ? ((int)value) : 0; } public static void RecordDamageDealt(Player dealer, Player victim, float amount) { try { if (!gameOverFired && !((Object)(object)dealer == (Object)null) && !((Object)(object)victim == (Object)null) && dealer.TeamID != victim.TeamID && amount > 0f && !(amount > 10000f)) { damageDealt.TryGetValue(dealer.TeamID, out var value); damageDealt[dealer.TeamID] = value + amount; } } catch { } } public static void SampleTimelines() { try { if (!EngineActive()) { return; } PlayerManager instance = PlayerManager.instance; if (instance?.players == null) { return; } for (int i = 0; i < instance.players.Count; i++) { Player val = instance.players[i]; if (!((Object)(object)val == (Object)null)) { int teamID = val.TeamID; if (!killTimeline.TryGetValue(teamID, out var value)) { value = new List(32); killTimeline[teamID] = value; } if (value.Count < 128) { value.Add(KillsFor(teamID)); } if (!damageTimeline.TryGetValue(teamID, out var value2)) { value2 = new List(32); damageTimeline[teamID] = value2; } if (value2.Count < 128) { value2.Add(DamageDealtFor(teamID)); } } } } catch { } } public static string KillTimelineFor(int teamId) { if (!killTimeline.TryGetValue(teamId, out var value) || value.Count == 0) { return null; } return string.Join(",", value.ConvertAll((int v) => v.ToString()).ToArray()); } public static string DamageTimelineFor(int teamId) { if (!damageTimeline.TryGetValue(teamId, out var value) || value.Count == 0) { return null; } return string.Join(",", value.ConvertAll((int v) => v.ToString()).ToArray()); } public static void RecordKillFor(Player killed) { try { if (!gameOverFired && !((Object)(object)killed == (Object)null) && !((Object)(object)killed.data == (Object)null)) { Player lastSourceOfDamage = killed.data.lastSourceOfDamage; if (!((Object)(object)lastSourceOfDamage == (Object)null) && !((Object)(object)((Component)lastSourceOfDamage).gameObject == (Object)null) && !((Object)(object)lastSourceOfDamage.data == (Object)null) && lastSourceOfDamage.TeamID != killed.TeamID) { kills[lastSourceOfDamage.TeamID] = KillsFor(lastSourceOfDamage.TeamID) + 1; } } } catch { } } private static void ClearLastDamageSources() { try { PlayerManager instance = PlayerManager.instance; if (instance?.players == null) { return; } foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null) && !((Object)(object)((Component)player).gameObject == (Object)null) && !((Object)(object)player.data == (Object)null)) { player.data.lastSourceOfDamage = null; } } } catch { } } public static List PickHistoryFor(int teamId) { List value; return pickHistory.TryGetValue(teamId, out value) ? value : new List(); } public static Player CurrentLeader() { try { if ((Object)(object)PlayerManager.instance == (Object)null) { return null; } Player result = null; int num = -1; int num2 = -1; bool flag = false; foreach (Player player in PlayerManager.instance.players) { if (!((Object)(object)player == (Object)null) && !((Object)(object)((Component)player).gameObject == (Object)null) && !((Object)(object)player.data == (Object)null)) { int num3 = RoundsFor(player.TeamID); int num4 = PointsFor(player.TeamID); if (num3 > num || (num3 == num && num4 > num2)) { result = player; num = num3; num2 = num4; flag = false; } else if (num3 == num && num4 == num2) { flag = true; } } } if (flag || (num == 0 && num2 == 0)) { return null; } return result; } catch { return null; } } public static string ScoreLine() { try { if ((Object)(object)PlayerManager.instance == (Object)null) { return ""; } List<(string, int, int, bool)> list = new List<(string, int, int, bool)>(); foreach (Player player in PlayerManager.instance.players) { if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null || (Object)(object)player.data == (Object)null) { continue; } string text = "P" + player.PlayerID; try { PhotonView view = player.data.view; object obj; if (view == null) { obj = null; } else { Player owner = view.Owner; obj = ((owner != null) ? owner.NickName : null); } if (obj == null) { obj = text; } text = (string)obj; } catch { } if (text.Length > 12) { text = text.Substring(0, 12); } list.Add((text, RoundsFor(player.TeamID), PointsFor(player.TeamID), player.data.dead)); } list.Sort(((string name, int r, int p, bool dead) a, (string name, int r, int p, bool dead) b) => (b.r != a.r) ? b.r.CompareTo(a.r) : b.p.CompareTo(a.p)); StringBuilder stringBuilder = new StringBuilder(); foreach (var item in list) { if (stringBuilder.Length > 0) { stringBuilder.Append(" "); } stringBuilder.Append(item.Item1).Append(' ').Append(item.Item2) .Append('R'); if (item.Item3 > 0) { stringBuilder.Append('+').Append(item.Item3); } } return stringBuilder.ToString(); } catch { return ""; } } public static void TickSpawnGrace() { try { if (!EngineActive()) { lastLocalPlaying = false; return; } bool flag = false; PlayerManager instance = PlayerManager.instance; if (instance?.players != null) { foreach (Player player in instance.players) { if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null || (Object)(object)player.data?.view == (Object)null || !player.data.view.IsMine) { continue; } flag = player.data.isPlaying && (Object)(object)player.data.playerVel != (Object)null && player.data.playerVel.simulated; break; } } if (flag && !lastLocalPlaying) { spawnGraceUntil = Time.realtimeSinceStartup + 1f; } lastLocalPlaying = flag; } catch { } } private static void ClearSpawnGrace() { spawnGraceUntil = 0f; lastLocalPlaying = false; } public static void OnGameStart() { gameNumber++; cycleNumber = 0; points.Clear(); rounds.Clear(); pointsTotal.Clear(); kills.Clear(); damageDealt.Clear(); killTimeline.Clear(); damageTimeline.Clear(); timelineEvents.Clear(); decks.Clear(); pickHistory.Clear(); baselines.Clear(); foreach (KeyValuePair leaver in Leavers) { leaver.Value.roundsWon = 0; leaver.Value.pointsTotal = 0; leaver.Value.kills = 0; } isTransitioning = false; pointLatched = false; gameOverFired = false; ClearSpawnGrace(); freshGameCancelFired = false; deckViewRebuilds.Clear(); matchStartRealtime = Time.realtimeSinceStartup; try { GameStateWatcher.OnFfaMatchStarted(); } catch (Exception ex) { Plugin.Log.LogError((object)("[FFA] match-start hook: " + ex.Message)); } Plugin.Log.LogInfo((object)$"[FFA] Game {gameNumber} starting (players needed: {Diag2v2.PlayersNeeded()})"); } public static void OnRoomLeft() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown try { Hashtable val = new Hashtable(); val[(object)"cr_ffa_pk"] = ""; Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer != null) { localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch { } matchStartRealtime = 0f; gameNumber = 0; points.Clear(); rounds.Clear(); pointsTotal.Clear(); kills.Clear(); damageDealt.Clear(); killTimeline.Clear(); damageTimeline.Clear(); timelineEvents.Clear(); decks.Clear(); pickHistory.Clear(); baselines.Clear(); Leavers.Clear(); isTransitioning = false; gameOverFired = false; freshGameCancelFired = false; deckViewRebuilds.Clear(); pickPhaseActive = false; pickDeadlineRealtime = 0f; pickDeadlineShared = false; localPickOpen = false; try { FfaMapScale.Reset(); } catch { } try { FfaSpawnPoints.Clear(); } catch { } ClearSpawnGrace(); } public static void RecordLeaver(string steamId, string displayName, int teamId) { if (!string.IsNullOrEmpty(steamId)) { Leavers[steamId] = new FfaLeaver { displayName = (displayName ?? "Player"), slot = teamId, roundsWon = RoundsFor(teamId), pointsTotal = PointsTotalFor(teamId), kills = KillsFor(teamId), leftGameNumber = gameNumber }; Plugin.Log.LogInfo((object)$"[FFA] leaver recorded: {steamId} slot={teamId} r={RoundsFor(teamId)}"); } } public static void PurgeDepartedPlayers(string reason) { try { PlayerManager instance = PlayerManager.instance; if (instance?.players == null) { return; } int num = instance.players.RemoveAll((Player p) => (Object)(object)p == (Object)null || (Object)(object)((Component)p).gameObject == (Object)null || (Object)(object)p.data == (Object)null); try { PlayerAssigner.instance?.players?.RemoveAll((CharacterData cd) => (Object)(object)cd == (Object)null || (Object)(object)((Component)cd).gameObject == (Object)null); } catch { } if (num > 0) { Plugin.Log.LogInfo((object)$"[FFA] purged {num} departed player entry(ies) ({reason})"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] purge failed: " + ex.Message)); } } private static List AlivePlayers() { List list = new List(); if ((Object)(object)PlayerManager.instance == (Object)null) { return list; } foreach (Player player in PlayerManager.instance.players) { if (!((Object)(object)player == (Object)null) && !((Object)(object)((Component)player).gameObject == (Object)null) && !((Object)(object)player.data == (Object)null) && !player.data.dead) { list.Add(player); } } return list; } public static IEnumerator CheckRoundAfterLeave() { yield return (object)new WaitForSecondsRealtime(0.7f); if (!EngineActive()) { yield break; } PurgeDepartedPlayers("after leave"); int remaining = 0; try { Room currentRoom = PhotonNetwork.CurrentRoom; remaining = ((currentRoom != null) ? currentRoom.PlayerCount : 0); } catch { } bool battle = false; try { battle = (Object)(object)GameManager.instance != (Object)null && GameManager.instance.battleOngoing; } catch { } int scored = TotalPointsScored(); if (!gameOverFired && battle && remaining > 0 && remaining < 3 && scored < 2) { if (!freshGameCancelFired) { freshGameCancelFired = true; LeaveBelowMinimum($"[FFA] fresh game cancelled - {remaining} player(s), {scored} half-point(s) scored", "FFA cancelled - not enough players for a fresh game."); } yield break; } if (!gameOverFired && battle) { GM_ArmsRace gm = GM_ArmsRace.instance; if ((Object)(object)gm != (Object)null) { HandlePlayerDied(gm); } } if (remaining > 1) { yield break; } yield return (object)new WaitForSecondsRealtime(2.5f); if (!EngineActive()) { yield break; } try { Room currentRoom2 = PhotonNetwork.CurrentRoom; remaining = ((currentRoom2 != null) ? currentRoom2.PlayerCount : 0); } catch { } if (remaining > 1) { yield break; } Plugin.Log.LogInfo((object)"[FFA] last player in the room — ending the FFA and returning to menu"); try { CompetitiveUI.ShowNotification("Everyone else left the FFA — returning to menu.", new Color(1f, 0.8f, 0.4f), 7f); } catch { } try { NetworkConnectionHandler.instance.NetworkRestart(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] NetworkRestart failed: " + ex.Message)); } } public static void HandlePlayerDied(GM_ArmsRace gm) { try { if (gameOverFired || !GameManager.instance.battleOngoing) { return; } List list = AlivePlayers(); if (list.Count > 1) { return; } TimeHandler.instance.DoSlowDown(); if (PhotonNetwork.IsMasterClient && !pointLatched && !isTransitioning) { pointLatched = true; if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ResolvePointEndOfFrame(gm)); } else { ResolvePointNow(gm); } } } catch (Exception ex) { Plugin.Log.LogError((object)("[FFA] HandlePlayerDied: " + ex.Message)); } } private static IEnumerator ResolvePointEndOfFrame(GM_ArmsRace gm) { yield return (object)new WaitForEndOfFrame(); ResolvePointNow(gm); } private static void ResolvePointNow(GM_ArmsRace gm) { try { if (gameOverFired || isTransitioning) { pointLatched = false; return; } List list = AlivePlayers(); if (list.Count > 1) { pointLatched = false; return; } int num = ((list.Count == 1) ? list[0].TeamID : (-1)); try { FfaMapScale.MasterPublishCount(); } catch { } gm.view.RPC("RPCA_NextRound", (RpcTarget)0, new object[6] { num, num, 0, 0, 0, 0 }); } catch (Exception ex) { pointLatched = false; Plugin.Log.LogError((object)("[FFA] ResolvePointNow: " + ex.Message)); } } public static void HandleNextRound(GM_ArmsRace gm, int winnerTeam) { if (isTransitioning || gameOverFired) { return; } isTransitioning = true; pointLatched = false; GameManager.instance.battleOngoing = false; PurgeDepartedPlayers("next round"); try { PlayerManager.instance.SetPlayersSimulated(false); } catch { } bool flag = false; bool flag2 = false; if (winnerTeam >= 0) { points[winnerTeam] = PointsFor(winnerTeam) + 1; pointsTotal[winnerTeam] = PointsTotalFor(winnerTeam) + 1; if (points[winnerTeam] >= 2) { rounds[winnerTeam] = RoundsFor(winnerTeam) + 1; points.Clear(); flag = true; flag2 = rounds[winnerTeam] >= 5; } if (timelineEvents.Count < 400) { timelineEvents.Add(string.Format("{0}{1}{2}", winnerTeam, flag ? "R" : "", flag2 ? "G" : "")); } } Plugin.Log.LogInfo((object)($"[FFA] point over: winner team={winnerTeam} " + $"roundOver={flag} gameOver={flag2} scores=[{ScoreLine()}]")); if (flag2) { if (!gameOverFired) { gameOverFired = true; try { GameStateWatcher.OnFfaGameOver(winnerTeam); } catch (Exception ex) { Plugin.Log.LogError((object)("[FFA] game-over report hook: " + ex.Message)); } try { Room currentRoom = PhotonNetwork.CurrentRoom; int num = ((currentRoom != null) ? currentRoom.PlayerCount : 0); if (num < 3 && (Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(EndSittingBelowMinimum()); } } catch { } } int num2 = winnerTeam; if (PlayerManager.instance.GetPlayersInTeam(winnerTeam).Length == 0) { List list = AlivePlayers(); if (list.Count > 0) { num2 = list[0].TeamID; } else { foreach (Player player in PlayerManager.instance.players) { if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null) { num2 = player.TeamID; break; } } } } gm.currentWinningTeamID = num2; ((MonoBehaviour)gm).StartCoroutine(gm.GameOverTransition(num2)); isTransitioning = false; } else { ((MonoBehaviour)gm).StartCoroutine(FfaTransition(gm, winnerTeam, flag)); } } private static IEnumerator FfaTransition(GM_ArmsRace gm, int winnerTeam, bool roundOver) { PurgeDepartedPlayers("transition start"); yield return (object)new WaitForSecondsRealtime(1f); try { MapManager.instance.LoadNextLevel(false, false); } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogError((object)("[FFA] LoadNextLevel: " + ex2.Message)); } yield return (object)new WaitForSecondsRealtime(roundOver ? 1.3f : 0.5f); yield return BoundedSyncUp(gm, 10f); if (roundOver && gm.pickPhase) { try { PlayerManager.instance.SetPlayersVisible(false); } catch { } yield return FfaPickPhase(gm, winnerTeam); try { PlayerManager.instance.SetPlayersVisible(true); } catch { } } yield return BoundedSyncUp(gm, 10f); PurgeDepartedPlayers("pre-move"); try { MapManager.instance.CallInNewMapAndMovePlayers(MapManager.instance.currentLevelID); } catch (Exception ex3) { Plugin.Log.LogError((object)("[FFA] CallInNewMap: " + ex3.Message)); } try { PlayerManager.instance.RevivePlayers(); } catch (Exception ex4) { Plugin.Log.LogError((object)("[FFA] RevivePlayers: " + ex4.Message)); } ClearLastDamageSources(); yield return (object)new WaitForSecondsRealtime(0.3f); try { TimeHandler.instance.DoSpeedUp(); } catch { } isTransitioning = false; GameManager.instance.battleOngoing = true; } private static IEnumerator BoundedSyncUp(GM_ArmsRace gm, float maxSeconds) { if (PhotonNetwork.OfflineMode) { yield break; } int others = 0; try { Room currentRoom = PhotonNetwork.CurrentRoom; others = ((currentRoom == null) ? 1 : currentRoom.PlayerCount) - 1; } catch { } if (others > 0) { float start = Time.realtimeSinceStartup; gm.isWaiting = true; try { gm.view.RPC("RPCO_RequestSyncUp", (RpcTarget)1, Array.Empty()); } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogWarning((object)("[FFA] sync-up RPC failed: " + ex2.Message)); gm.isWaiting = false; yield break; } while (gm.isWaiting && Time.realtimeSinceStartup - start < maxSeconds) { yield return null; } if (gm.isWaiting) { gm.isWaiting = false; Plugin.Log.LogWarning((object)$"[FFA] sync-up timed out after {maxSeconds:0}s — continuing"); } } } private static int RoomCount() { try { Room currentRoom = PhotonNetwork.CurrentRoom; return (currentRoom != null) ? currentRoom.PlayerCount : 0; } catch { return 0; } } private static int TotalPointsScored() { int num = 0; try { foreach (int value in pointsTotal.Values) { num += value; } } catch { } return num; } private static void LeaveBelowMinimum(string logMessage, string notification) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)logMessage); try { CompetitiveUI.ShowNotification(notification, new Color(1f, 0.8f, 0.4f), 7f); } catch { } try { ApiClient.FfaLeaveQueue(); } catch { } try { NetworkConnectionHandler.instance.NetworkRestart(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] end-sitting NetworkRestart: " + ex.Message)); } } private static IEnumerator EndSittingBelowMinimum() { yield return (object)new WaitForSecondsRealtime(4f); if (!EngineActive()) { yield break; } int remaining = RoomCount(); if (remaining >= 3) { yield break; } Plugin.Log.LogInfo((object)$"[FFA] {remaining} player(s) left in the room (<3) — ending the sitting"); try { CompetitiveUI.ShowNotification("Not enough players to continue the FFA - returning to menu.", new Color(1f, 0.8f, 0.4f), 7f); } catch { } try { ApiClient.FfaLeaveQueue(); } catch { } try { NetworkConnectionHandler.instance.NetworkRestart(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] end-sitting NetworkRestart: " + ex.Message)); } } private static IEnumerator ResyncLocalFace() { yield return (object)new WaitForSecondsRealtime(2.5f); if (!EngineActive()) { yield break; } try { Player lp = LocalPlayer(); if (!((Object)(object)lp == (Object)null) && !((Object)(object)lp.data == (Object)null) && !((Object)(object)lp.data.view == (Object)null)) { PlayerFace face = CharacterCreatorHandler.instance.selectedPlayerFaces[0]; if (face.eyeID == 0 && face.mouthID == 0 && face.detailID == 0 && face.detail2ID == 0) { Plugin.Log.LogInfo((object)"[FFA] face resync skipped — all-zero default face"); yield break; } lp.data.view.RPC("RPCA_SetFace", (RpcTarget)1, new object[8] { face.eyeID, face.eyeOffset, face.mouthID, face.mouthOffset, face.detailID, face.detailOffset, face.detail2ID, face.detail2Offset }); Plugin.Log.LogInfo((object)"[FFA] face resync sent (bug #102)"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] face resync: " + ex.Message)); } } public static IEnumerator FfaDoStartGame(GM_ArmsRace gm) { OnGameStart(); PurgeDepartedPlayers("game start"); if (gameNumber > 1) { float waitUntil = Time.realtimeSinceStartup + 4f; int remaining0 = RoomCount(); while (remaining0 > 0 && remaining0 < 3 && Time.realtimeSinceStartup < waitUntil) { yield return (object)new WaitForSecondsRealtime(0.5f); remaining0 = RoomCount(); } if (remaining0 > 0 && remaining0 < 3) { Plugin.Log.LogInfo((object)$"[FFA] rematch aborted — {remaining0} player(s) (<3) — ending the sitting"); try { CompetitiveUI.ShowNotification("Not enough players to continue the FFA - returning to menu.", new Color(1f, 0.8f, 0.4f), 7f); } catch { } try { ApiClient.FfaLeaveQueue(); } catch { } try { NetworkConnectionHandler.instance.NetworkRestart(); yield break; } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogWarning((object)("[FFA] end-sitting NetworkRestart: " + ex2.Message)); yield break; } } } GameManager.instance.battleOngoing = false; yield return (object)new WaitForSeconds(0.25f); try { UIHandler.instance.HideJoinGameText(); } catch { } PlayerManager.instance.SetPlayersSimulated(false); PlayerManager.instance.SetPlayersVisible(false); if (PhotonNetwork.IsMasterClient) { try { FfaMapScale.MasterPublishCount(); } catch { } } MapManager.instance.LoadNextLevel(false, false); TimeHandler.instance.DoSpeedUp(); yield return (object)new WaitForSecondsRealtime(1f); if (gm.pickPhase) { yield return FfaPickPhase(gm, -1); } PurgeDepartedPlayers("pre-move start"); try { MapManager.instance.CallInNewMapAndMovePlayers(MapManager.instance.currentLevelID); } catch (Exception ex3) { Plugin.Log.LogError((object)("[FFA] CallInNewMap(start): " + ex3.Message)); } ClearLastDamageSources(); TimeHandler.instance.DoSpeedUp(); TimeHandler.instance.StartGame(); GameManager.instance.battleOngoing = true; try { PlayerManager.instance.SetPlayersVisible(true); } catch (Exception ex4) { Plugin.Log.LogError((object)("[FFA] SetPlayersVisible(start): " + ex4.Message)); } CompetitiveUI.ShowNotification($"FFA - {Diag2v2.PlayersNeeded()} players - first to {5} points!", new Color(0.7f, 1f, 0.7f)); try { if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ResyncLocalFace()); } } catch { } } private static IEnumerator FfaPickPhase(GM_ArmsRace gm, int roundWinnerTeam) { cycleNumber++; int cycle = cycleNumber; int game = gameNumber; float phaseStart = Time.realtimeSinceStartup; Debug.Log((object)"PICK PHASE"); PurgeDepartedPlayers("pick phase"); List pickerIds = new List(); foreach (Player p in PlayerManager.instance.players) { if (!((Object)(object)p == (Object)null) && !((Object)(object)((Component)p).gameObject == (Object)null) && !((Object)(object)p.data == (Object)null) && (roundWinnerTeam < 0 || p.TeamID != roundWinnerTeam)) { pickerIds.Add(p.PlayerID); } } pickerIds.Sort(); if (PhotonNetwork.IsMasterClient) { SetRoomProp("cr_ffa_cyc", string.Format("{0}:{1}:{2}", game, cycle, string.Join(",", pickerIds))); } List manifest = null; while (Time.realtimeSinceStartup - phaseStart < 8f) { manifest = ReadCycleManifest(game, cycle); if (manifest != null) { break; } if (PhotonNetwork.IsMasterClient && Time.realtimeSinceStartup - phaseStart > 2f) { SetRoomProp("cr_ffa_cyc", string.Format("{0}:{1}:{2}", game, cycle, string.Join(",", pickerIds))); } yield return null; } if (manifest == null) { Plugin.Log.LogWarning((object)$"[FFA] pick cycle {cycle}: no manifest after {8f}s — using local picker set"); manifest = pickerIds; } Player localPlayer = LocalPlayer(); bool iPick = (Object)(object)localPlayer != (Object)null && manifest.Contains(localPlayer.PlayerID); Coroutine localUi = null; if (iPick) { localUi = ((MonoBehaviour)gm).StartCoroutine(FfaLocalPickUI(gm, localPlayer, game, cycle)); } float deadline = phaseStart + 45f; int lastGotCount = 0; float lastCollect = -999f; bool wasMaster = PhotonNetwork.IsMasterClient; pickPhaseActive = true; pickDeadlineRealtime = deadline; pickDeadlineShared = wasMaster; double lastPublishedPhotonDeadline = -1.0; if (wasMaster) { PublishSharedDeadline(game, cycle, deadline, ref lastPublishedPhotonDeadline); } Dictionary result; while (true) { result = ReadCycleResult(game, cycle); if (result != null) { break; } float now = Time.realtimeSinceStartup; if (now - lastCollect > 0.25f) { lastCollect = now; Dictionary got = CollectPicks(manifest, game, cycle); if (got.Count > lastGotCount) { lastGotCount = got.Count; deadline = Mathf.Max(deadline, Mathf.Min(phaseStart + 90f, now + 20f)); } if (PhotonNetwork.IsMasterClient && !wasMaster) { wasMaster = true; pickDeadlineShared = true; deadline = Mathf.Max(deadline, now + 20f); Plugin.Log.LogInfo((object)$"[FFA] pick cycle {cycle}: became master mid-cycle — extending window"); } if (PhotonNetwork.IsMasterClient) { PublishSharedDeadline(game, cycle, deadline, ref lastPublishedPhotonDeadline); } else { float shared = ReadSharedDeadline(game, cycle); if (shared > 0f) { deadline = shared; pickDeadlineShared = true; } } pickDeadlineRealtime = deadline; if (PhotonNetwork.IsMasterClient) { bool allIn = got.Count >= CountStillPresent(manifest); if (allIn || now > deadline) { StringBuilder sb = new StringBuilder(); sb.Append(game).Append(':').Append(cycle) .Append(':'); bool first = true; foreach (KeyValuePair kv in got.OrderBy((KeyValuePair k) => k.Key)) { if (!first) { sb.Append('|'); } sb.Append(kv.Key).Append('=').Append(kv.Value); first = false; } SetRoomProp("cr_ffa_res", sb.ToString()); if (!allIn) { Plugin.Log.LogWarning((object)$"[FFA] pick cycle {cycle} closed with {got.Count}/{manifest.Count} picks (window ended)"); } result = got; break; } } } if (now > deadline + 15f && now - phaseStart > 20f) { Plugin.Log.LogWarning((object)$"[FFA] pick cycle {cycle}: no result manifest — proceeding without picks"); result = new Dictionary(); break; } yield return null; } pickPhaseActive = false; pickDeadlineRealtime = 0f; pickDeadlineShared = false; if (localUi != null) { try { ((MonoBehaviour)gm).StopCoroutine(localUi); } catch { } } CleanupLocalPickUI(); if (iPick && (Object)(object)localPlayer != (Object)null && !result.ContainsKey(localPlayer.PlayerID)) { Plugin.Log.LogWarning((object)$"[FFA] cycle {cycle}: local pick missed the window — no card this cycle (auto-confirm lost the close race?)"); try { CompetitiveUI.ShowNotification("Pick window closed - no card this round.", new Color(1f, 0.75f, 0.4f)); } catch { } } foreach (KeyValuePair kv2 in result.OrderBy((KeyValuePair k) => k.Key)) { yield return ApplyManifestPick(kv2.Key, kv2.Value, cycle); } Plugin.Log.LogInfo((object)$"[FFA] pick cycle {cycle} applied ({result.Count} picks)"); } private static Player LocalPlayer() { try { foreach (Player player in PlayerManager.instance.players) { if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null && (Object)(object)player.data != (Object)null && (Object)(object)player.data.view != (Object)null && player.data.view.IsMine) { return player; } } } catch { } return null; } private static int CountStillPresent(List manifest) { int num = 0; foreach (int item in manifest) { PlayerManager instance = PlayerManager.instance; Player val = ((instance != null) ? instance.GetPlayerWithID(item) : null); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null) { CharacterData data = val.data; object obj; if (data == null) { obj = null; } else { PhotonView view = data.view; obj = ((view != null) ? view.Owner : null); } if (obj != null) { num++; } } } return Math.Max(1, num); } private static void SetRoomProp(string key, string value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown try { Hashtable val = new Hashtable(); val[(object)key] = value; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] SetRoomProp " + key + ": " + ex.Message)); } } private static List ReadCycleManifest(int game, int cycle) { try { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = ((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null); if (val == null || !((Dictionary)(object)val).ContainsKey((object)"cr_ffa_cyc")) { return null; } string[] array = ((val[(object)"cr_ffa_cyc"] as string) ?? "").Split(new char[1] { ':' }, 3); if (array.Length != 3) { return null; } if (int.Parse(array[0]) != game || int.Parse(array[1]) != cycle) { return null; } List list = new List(); string[] array2 = array[2].Split(','); foreach (string s in array2) { if (int.TryParse(s, out var result)) { list.Add(result); } } return list; } catch { return null; } } private static Dictionary ReadCycleResult(int game, int cycle) { try { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = ((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null); if (val == null || !((Dictionary)(object)val).ContainsKey((object)"cr_ffa_res")) { return null; } string[] array = ((val[(object)"cr_ffa_res"] as string) ?? "").Split(new char[1] { ':' }, 3); if (array.Length != 3) { return null; } if (int.Parse(array[0]) != game || int.Parse(array[1]) != cycle) { return null; } Dictionary dictionary = new Dictionary(); if (array[2].Length > 0) { string[] array2 = array[2].Split('|'); foreach (string text in array2) { int num = text.IndexOf('='); if (num > 0 && int.TryParse(text.Substring(0, num), out var result)) { dictionary[result] = text.Substring(num + 1); } } } return dictionary; } catch { return null; } } private static void PublishSharedDeadline(int game, int cycle, float localDeadline, ref double lastPublished) { try { double num = PhotonNetwork.Time + (double)(localDeadline - Time.realtimeSinceStartup); if (!(Math.Abs(num - lastPublished) < 0.5)) { lastPublished = num; SetRoomProp("cr_ffa_dl", $"{game}:{cycle}:" + num.ToString("F2", CultureInfo.InvariantCulture)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] deadline publish: " + ex.Message)); } } private static float ReadSharedDeadline(int game, int cycle) { try { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = ((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null); if (val == null || !((Dictionary)(object)val).ContainsKey((object)"cr_ffa_dl")) { return -1f; } string[] array = ((val[(object)"cr_ffa_dl"] as string) ?? "").Split(new char[1] { ':' }, 3); if (array.Length != 3) { return -1f; } if (int.Parse(array[0]) != game || int.Parse(array[1]) != cycle) { return -1f; } double num = double.Parse(array[2], CultureInfo.InvariantCulture); return Time.realtimeSinceStartup + (float)(num - PhotonNetwork.Time); } catch { return -1f; } } private static string RoomNonce() { try { Room currentRoom = PhotonNetwork.CurrentRoom; return ((currentRoom != null) ? currentRoom.Name : null) ?? ""; } catch { return ""; } } private static Dictionary CollectPicks(List manifest, int game, int cycle) { Dictionary dictionary = new Dictionary(); try { string text = $"{RoomNonce()}:{game}:{cycle}:"; foreach (int item in manifest) { PlayerManager instance = PlayerManager.instance; Player val = ((instance != null) ? instance.GetPlayerWithID(item) : null); object obj; if (val == null) { obj = null; } else { CharacterData data = val.data; if (data == null) { obj = null; } else { PhotonView view = data.view; obj = ((view != null) ? view.Owner : null); } } Player val2 = (Player)obj; Hashtable val3 = ((val2 != null) ? val2.CustomProperties : null); if (val3 != null && ((Dictionary)(object)val3).ContainsKey((object)"cr_ffa_pk")) { string text2 = (val3[(object)"cr_ffa_pk"] as string) ?? ""; if (text2.StartsWith(text) && text2.Length > text.Length) { dictionary[item] = text2.Substring(text.Length); } } } } catch { } return dictionary; } private static IEnumerator FfaLocalPickUI(GM_ArmsRace gm, Player localPlayer, int game, int cycle) { CardChoice choice = CardChoice.instance; if ((Object)(object)choice == (Object)null) { yield break; } List slots = new List(); for (int i = 0; i < ((Component)choice).transform.childCount && i < 5; i++) { slots.Add(((Component)choice).transform.GetChild(i)); } if (slots.Count == 0) { yield break; } try { ArtHandler.instance.SetSpecificArt(choice.cardPickArt); } catch { } List candidates = new List(); List candidateObjs = new List(); int guard = 0; while (candidates.Count < slots.Count && guard++ < 200) { CardInfo c = PickRandomCard(choice); if ((Object)(object)c == (Object)null) { break; } if (IsCardAllowedFor(localPlayer, c, candidates)) { candidates.Add(c); } } List shown = new List(); for (int j = 0; j < candidates.Count; j++) { GameObject vis = null; try { vis = choice.AddCardVisual(candidates[j], slots[j].position); vis.transform.rotation = slots[j].rotation; DamagableEvent dmg = vis.GetComponentInChildren(); Behaviour col = (Behaviour)(((Object)(object)dmg != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)col != (Object)null) { col.enabled = false; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] card visual spawn: " + ex.Message)); } if ((Object)(object)vis != (Object)null) { candidateObjs.Add(vis); localCardObjects.Add(vis); shown.Add(candidates[j]); } } if (candidateObjs.Count == 0) { yield break; } CompetitiveUI.ShowNotification("Pick a card! (left/right + jump)", new Color(0.8f, 0.9f, 1f), 4f); int selected = 0; int lastDir = 0; float started = Time.realtimeSinceStartup; int chosen = -1; bool autoPicked = false; localPickOpen = true; while (chosen < 0) { if (pickPhaseActive && PickSecondsLeft <= 0f && Time.realtimeSinceStartup - started > 0.35f) { chosen = selected; autoPicked = true; break; } PlayerActions actions = localPlayer?.data?.playerActions; if (CompetitiveUI.AnyChatTyping) { lastDir = 0; } else if (actions != null) { int dir = 0; try { if (((OneAxisInputControl)actions.Right).Value > 0.7f) { dir = 1; } else if (((OneAxisInputControl)actions.Left).Value > 0.7f) { dir = -1; } } catch { } if (dir != lastDir && dir != 0) { selected = Mathf.Clamp(selected + dir, 0, candidateObjs.Count - 1); } lastDir = dir; try { if (Time.realtimeSinceStartup - started > 0.35f && ((OneAxisInputControl)actions.Jump).WasPressed) { chosen = selected; } } catch { } } for (int k = 0; k < candidateObjs.Count; k++) { try { CardVisuals cv = (((Object)(object)candidateObjs[k] != (Object)null) ? candidateObjs[k].GetComponentInChildren() : null); if ((Object)(object)cv != (Object)null) { cv.ChangeSelected(k == selected); } } catch { } } yield return null; } localPickOpen = false; string cardName = ((Object)((Component)shown[chosen]).gameObject).name.Replace("(Clone)", ""); try { Hashtable h = new Hashtable(); h[(object)"cr_ffa_pk"] = $"{RoomNonce()}:{game}:{cycle}:{cardName}"; PhotonNetwork.LocalPlayer.SetCustomProperties(h, (Hashtable)null, (WebFlags)null); } catch (Exception ex2) { Exception ex3 = ex2; Plugin.Log.LogWarning((object)("[FFA] pick publish: " + ex3.Message)); } Plugin.Log.LogInfo((object)(autoPicked ? $"[FFA] local pick AUTO-CONFIRMED at window expiry: {cardName} (cycle {cycle})" : $"[FFA] local pick published: {cardName} (cycle {cycle})")); if (autoPicked) { try { string display = shown[chosen].cardName; if (string.IsNullOrEmpty(display)) { display = cardName; } CompetitiveUI.ShowNotification("Time's up - " + display + " picked automatically.", new Color(1f, 0.85f, 0.5f)); } catch { } } try { GameStateWatcher.RecordFfaLocalPick(cardName, RoundsTotalAll()); } catch { } for (int l = 0; l < candidateObjs.Count; l++) { try { CardVisuals cv2 = (((Object)(object)candidateObjs[l] != (Object)null) ? candidateObjs[l].GetComponentInChildren() : null); if (!((Object)(object)cv2 == (Object)null)) { if (l == chosen) { cv2.Pick(); } else { cv2.Leave(); } } } catch { } } yield return (object)new WaitForSecondsRealtime(0.8f); CleanupLocalPickUI(); } private static void CleanupLocalPickUI() { localPickOpen = false; foreach (GameObject localCardObject in localCardObjects) { try { if ((Object)(object)localCardObject != (Object)null) { Object.Destroy((Object)(object)localCardObject); } } catch { } } localCardObjects.Clear(); } private static int RoundsTotalAll() { int num = 0; foreach (KeyValuePair round in rounds) { num += round.Value; } return num; } private static CardInfo PickRandomCard(CardChoice choice) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) try { CardInfo[] cards = choice.cards; if (cards == null || cards.Length == 0) { return null; } float num = 0f; CardInfo[] array = cards; foreach (CardInfo val in array) { num += RarityWeight(val.rarity); } float num2 = Random.Range(0f, num); CardInfo[] array2 = cards; foreach (CardInfo val2 in array2) { num2 -= RarityWeight(val2.rarity); if (num2 <= 0f) { return val2; } } return cards[^1]; } catch { return null; } } private static float RarityWeight(Rarity r) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected I4, but got Unknown return (int)r switch { 0 => 10f, 1 => 4f, 2 => 1f, _ => 4f, }; } private static bool IsCardAllowedFor(Player player, CardInfo candidate, List alreadyOffered) { try { foreach (CardInfo item in alreadyOffered) { if ((Object)(object)item == (Object)(object)candidate) { return false; } } if ((Object)(object)player?.data == (Object)null) { return true; } Holding component = ((Component)player.data).GetComponent(); Holdable val = (((Object)(object)component != (Object)null) ? component.holdable : null); if ((Object)(object)val != (Object)null) { Gun component2 = ((Component)val).GetComponent(); Gun component3 = ((Component)candidate).GetComponent(); if ((Object)(object)component3 != (Object)null && (Object)(object)component2 != (Object)null && component3.lockGunToDefault && component2.lockGunToDefault) { return false; } } List currentCards = player.data.currentCards; if (currentCards != null) { foreach (CardInfo item2 in currentCards) { if ((Object)(object)item2 == (Object)null) { continue; } if (!item2.allowMultiple && ((Object)item2).name == ((Object)candidate).name) { return false; } if (item2.blacklistedCategories == null || candidate.categories == null) { continue; } CardCategory[] blacklistedCategories = item2.blacklistedCategories; foreach (CardCategory val2 in blacklistedCategories) { CardCategory[] categories = candidate.categories; foreach (CardCategory val3 in categories) { if ((Object)(object)val3 == (Object)(object)val2) { return false; } } } } } return true; } catch { return true; } } private static IEnumerator ApplyManifestPick(int pid, string cardName, int cycle) { deckViewRebuilds.Remove(pid); PlayerManager instance = PlayerManager.instance; Player player = ((instance != null) ? instance.GetPlayerWithID(pid) : null); if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null || (Object)(object)player.data == (Object)null) { Plugin.Log.LogWarning((object)$"[FFA] apply skipped — player {pid} gone (card {cardName})"); yield break; } CardInfo prefab = ResolveCard(cardName); if ((Object)(object)prefab == (Object)null) { Plugin.Log.LogWarning((object)$"[FFA] apply skipped — unknown card '{cardName}' for pid {pid}"); yield break; } if (!decks.TryGetValue(pid, out var deck)) { deck = new List(); decks[pid] = deck; } CaptureBaselineIfNeeded(player); bool rebuiltDeck = false; if (deck.Count >= 5) { List survivors = deck.Skip(deck.Count - 4).ToList(); Plugin.Log.LogInfo((object)$"[FFA] rolling removal for pid {pid}: dropping '{((Object)((Component)deck[0]).gameObject).name}'"); try { string droppedCanon = CardRarityLookup.GetCanonicalName(((Object)((Component)deck[0]).gameObject).name.Replace("(Clone)", "")); if (pickHistory.TryGetValue(pid, out var hist0)) { foreach (MatchTracker.CardPickData h in hist0) { if (!h.Rolled && h.CardName == droppedCanon) { h.Rolled = true; break; } } } } catch { } deckViewRebuilds.Add(pid); rebuiltDeck = true; yield return RollingResetAndReplay(player, survivors); deck.Clear(); deck.AddRange(survivors); } ApplyCardTo(player, prefab); deck.Add(prefab); if (rebuiltDeck) { yield return null; RebuildDeckViews(player, deck); deckViewRebuilds.Remove(pid); } if (!pickHistory.TryGetValue(pid, out var hist1)) { hist1 = new List(); pickHistory[pid] = hist1; } string rarity = ""; try { rarity = ((object)Unsafe.As(ref prefab.rarity)/*cast due to .constrained prefix*/).ToString(); } catch { } hist1.Add(new MatchTracker.CardPickData { CardName = CardRarityLookup.GetCanonicalName(cardName), CardRarity = rarity, PickOrder = hist1.Count + 1, RoundNumber = Math.Max(1, RoundsTotalAll() + 1) }); } private static CardInfo ResolveCard(string cardName) { try { CardInfo[] array = CardChoice.instance?.cards; if (array == null) { return null; } CardInfo[] array2 = array; foreach (CardInfo val in array2) { if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == cardName) { return val; } } } catch { } return null; } private static void ApplyCardTo(Player player, CardInfo prefab) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) GameObject val = null; try { int num = BlockReflect.ScrubPlayerDelegates(player); if (num > 0) { Plugin.Log.LogWarning((object)$"[FFA] pre-apply scrub removed {num} stale handler(s) for pid {player.PlayerID}"); } val = Object.Instantiate(((Component)prefab).gameObject, new Vector3(2000f, 2000f, 0f), Quaternion.identity); CardInfo component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.sourceCard = prefab; } ApplyCardStats componentInChildren = val.GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null) { Plugin.Log.LogWarning((object)("[FFA] no ApplyCardStats on '" + ((Object)((Component)prefab).gameObject).name + "'")); return; } componentInChildren.Start(); componentInChildren.OFFLINE_Pick((Player[])(object)new Player[1] { player }); } catch (Exception ex) { ManualLogSource log = Plugin.Log; object obj; if (prefab == null) { obj = null; } else { GameObject gameObject = ((Component)prefab).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } log.LogError((object)("[FFA] ApplyCardTo(" + (string?)obj + "): " + ex.Message)); } finally { try { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } catch { } } } private static void RebuildDeckViews(Player player, List deck) { try { List list = player?.data?.currentCards; if (list != null) { list.Clear(); TabStatsOverlay.RecordCardBaseline(player); foreach (CardInfo item in deck) { if ((Object)(object)item != (Object)null) { list.Add(item); } } } if ((Object)(object)player?.data?.view != (Object)null && player.data.view.IsMine) { CardBar[] array = (((Object)(object)CardBarHandler.instance != (Object)null) ? CardBarHandler.instance.cardBars : null); if (array != null && array.Length != 0) { array[0].ClearBar(); foreach (CardInfo item2 in deck) { if ((Object)(object)item2 != (Object)null) { array[0].AddCard(item2); } } } } Plugin.Log.LogInfo((object)$"[FFA] deck views rebuilt for pid {player.PlayerID}: {deck.Count} card(s)"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] deck-view rebuild: " + ex.Message)); } } internal static bool SuppressCardBarAdd(int playerId) { return deckViewRebuilds.Contains(playerId); } internal static uint SpawnShuffleSeed() { uint hash = 2166136261u; string text = ""; try { Room currentRoom = PhotonNetwork.CurrentRoom; text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; } catch { } string text2 = text; foreach (char c in text2) { hash = (hash ^ (byte)(c & 0xFF)) * 16777619; hash = (hash ^ (byte)((int)c >> 8)) * 16777619; } MixSeedInt(ref hash, gameNumber); for (int j = 0; j < 10; j++) { MixSeedInt(ref hash, RoundsFor(j)); MixSeedInt(ref hash, PointsFor(j)); MixSeedInt(ref hash, PointsTotalFor(j)); } return (hash == 0) ? 2654435769u : hash; } private static void MixSeedInt(ref uint hash, int value) { uint num = (uint)value; for (int i = 0; i < 4; i++) { hash = (hash ^ (byte)(num & 0xFF)) * 16777619; num >>= 8; } } private static void CaptureBaselineIfNeeded(Player player) { int playerID = player.PlayerID; if (!baselines.TryGetValue(playerID, out var value) || !value.captured) { FfaBaseline ffaBaseline = new FfaBaseline { captured = true }; try { Gravity component = ((Component)player).GetComponent(); ffaBaseline.gravityForce = (((Object)(object)component != (Object)null) ? component.gravityForce : 0f); HealthHandler component2 = ((Component)player).GetComponent(); ffaBaseline.regeneration = (((Object)(object)component2 != (Object)null) ? component2.regeneration : 0f); CharacterData component3 = ((Component)player).GetComponent(); ffaBaseline.jumps = ((!((Object)(object)component3 != (Object)null)) ? 1 : component3.jumps); Holding component4 = ((Component)player.data).GetComponent(); Gun val = (((Object)(object)component4 != (Object)null && (Object)(object)component4.holdable != (Object)null) ? ((Component)component4.holdable).GetComponent() : null); GunAmmo val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInChildren() : null); ffaBaseline.ammoReg = (((Object)(object)val2 != (Object)null) ? val2.ammoReg : 0f); ffaBaseline.projectile = (((Object)(object)val != (Object)null && val.projectiles != null && val.projectiles.Length != 0) ? val.projectiles[0].objectToSpawn : null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] baseline capture: " + ex.Message)); } baselines[playerID] = ffaBaseline; } } private static IEnumerator RollingResetAndReplay(Player player, List survivors) { int pid = player.PlayerID; try { player.FullReset(); if (baselines.TryGetValue(pid, out var b) && b.captured) { try { Gravity g = ((Component)player).GetComponent(); if ((Object)(object)g != (Object)null) { g.gravityForce = b.gravityForce; } } catch { } try { HealthHandler hh = ((Component)player).GetComponent(); if ((Object)(object)hh != (Object)null) { hh.regeneration = b.regeneration; } } catch { } try { CharacterData cd = ((Component)player).GetComponent(); if ((Object)(object)cd != (Object)null) { cd.jumps = b.jumps; } } catch { } try { Holding holding = ((Component)player.data).GetComponent(); Gun gun = (((Object)(object)holding != (Object)null && (Object)(object)holding.holdable != (Object)null) ? ((Component)holding.holdable).GetComponent() : null); if ((Object)(object)gun != (Object)null) { GunAmmo ammo = ((Component)gun).GetComponentInChildren(); if ((Object)(object)ammo != (Object)null) { ammo.ammoReg = b.ammoReg; } if (gun.projectiles != null && gun.projectiles.Length != 0) { gun.projectiles[0].objectToSpawn = b.projectile; } gun.dontAllowAutoFire = false; } } catch { } } player.data.currentCards.Clear(); try { PlayerAudioModifyers pam = ((Component)player).GetComponent(); if ((Object)(object)pam != (Object)null && pam.modifyers != null) { foreach (AudioModifyer m in pam.modifyers) { try { if (m != null) { PlayerAudioModifyers.activeModifyer?.Remove(m.modifier); } } catch { } } pam.modifyers.Clear(); } } catch { } TabStatsOverlay.RecordCardBaseline(player); if ((Object)(object)player.data.view != (Object)null && player.data.view.IsMine) { try { CardBar[] bars = (((Object)(object)CardBarHandler.instance != (Object)null) ? CardBarHandler.instance.cardBars : null); if (bars != null && bars.Length != 0) { bars[0].ClearBar(); } } catch { } } } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogError((object)$"[FFA] rolling reset({pid}): {ex2.Message}"); } yield return null; try { GMArmsRaceStartGameBlockResetPatch.RunSweep("FFA rolling removal"); } catch { } foreach (CardInfo card in survivors) { ApplyCardTo(player, card); yield return null; } } } [HarmonyPatch(typeof(GM_ArmsRace), "PlayerDied")] internal class GMArmsRace_PlayerDied_Ffa_Patch { private static bool Prefix(GM_ArmsRace __instance, Player killedPlayer, int playersAlive) { if (!FfaMode.EngineActive()) { return true; } FfaMode.RecordKillFor(killedPlayer); FfaMode.HandlePlayerDied(__instance); return false; } } [HarmonyPatch(typeof(PlayerManager), "PlayerDied")] internal class PlayerManager_PlayerDied_Ffa_Patch { private static bool Prefix(PlayerManager __instance, Player player) { if (!FfaMode.EngineActive()) { return true; } try { int num = 0; foreach (Player player2 in __instance.players) { if (!((Object)(object)player2 == (Object)null) && !((Object)(object)((Component)player2).gameObject == (Object)null) && !((Object)(object)player2.data == (Object)null) && !player2.data.dead) { num++; } } __instance.PlayerDiedAction?.Invoke(player, num); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] PlayerDied relay: " + ex.Message)); } return false; } } [HarmonyPatch(typeof(GM_ArmsRace), "RPCA_NextRound")] internal class GMArmsRace_NextRound_Ffa_Patch { private static bool Prefix(GM_ArmsRace __instance, int losingTeamID, int winningTeamID, int p1PointsSet, int p2PointsSet, int p1RoundsSet, int p2RoundsSet) { if (!FfaMode.EngineActive()) { return true; } FfaMode.HandleNextRound(__instance, winningTeamID); return false; } } [HarmonyPatch(typeof(GM_ArmsRace), "DoStartGame")] internal class GMArmsRace_DoStartGame_Ffa_Patch { private static bool Prefix(GM_ArmsRace __instance, ref IEnumerator __result) { if (!FfaMode.EngineActive()) { return true; } __result = FfaMode.FfaDoStartGame(__instance); return false; } } [HarmonyPatch(typeof(CardBarHandler), "AddCard")] internal class CardBarHandler_AddCard_Ffa_Patch { private static bool Prefix(CardBarHandler __instance, int teamId, CardInfo card) { if (!FfaMode.EngineActive()) { return true; } try { if (FfaMode.SuppressCardBarAdd(teamId)) { return false; } Player val = PlayerManager.instance?.players?.FirstOrDefault((Func)((Player p) => (Object)(object)p != (Object)null && (Object)(object)((Component)p).gameObject != (Object)null && (Object)(object)p.data?.view != (Object)null && p.data.view.IsMine)); if ((Object)(object)val == (Object)null || teamId != val.PlayerID) { return false; } CardBar[] cardBars = __instance.cardBars; if (cardBars == null || cardBars.Length == 0) { return false; } cardBars[0].AddCard(card); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] card bar add: " + ex.Message)); } return false; } } [HarmonyPatch(typeof(MapManager), "GetSpawnPoints")] internal class MapManager_GetSpawnPoints_FfaShuffle_Patch { [HarmonyPriority(0)] private static void Postfix(ref SpawnPoint[] __result) { try { if (!FfaMode.EngineActive() || __result == null || __result.Length < 2) { return; } int num = Diag2v2.PlayersNeeded(); if (__result.Length < num) { Plugin.Log.LogWarning((object)$"[FFA] spawn shuffle saw {__result.Length}/{num} points - sort/pad postfix did not run first"); return; } SpawnPoint[] array = (SpawnPoint[])__result.Clone(); uint num2 = FfaMode.SpawnShuffleSeed(); for (int num3 = array.Length - 1; num3 > 0; num3--) { num2 ^= num2 << 13; num2 ^= num2 >> 17; num2 ^= num2 << 5; int num4 = (int)(num2 % (uint)(num3 + 1)); SpawnPoint val = array[num3]; array[num3] = array[num4]; array[num4] = val; } __result = array; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] spawn shuffle: " + ex.Message)); } } } [HarmonyPatch(typeof(NetworkConnectionHandler), "OnPlayerLeftRoom")] internal class NCH_OnPlayerLeftRoom_Ffa_Patch { private static bool Prefix(Player otherPlayer) { if (!FfaMode.EngineActive()) { return true; } try { Room currentRoom = PhotonNetwork.CurrentRoom; int num = ((currentRoom != null) ? currentRoom.PlayerCount : 0); Plugin.Log.LogInfo((object)$"[FFA] player left, {num} remain — match continues (vanilla end-cascade suppressed)"); if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(FfaMode.CheckRoundAfterLeave()); } return false; } catch { } return true; } } [HarmonyPatch(typeof(PlayerManager), "GetOtherPlayer")] internal class PlayerManager_GetOtherPlayer_Ffa_Patch { private static bool Prefix(PlayerManager __instance, Player asker, ref Player __result) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!FfaMode.EngineActive()) { return true; } try { __result = FfaTargeting.NearestOpponent(__instance, ((Component)asker).transform.position, asker.TeamID); return false; } catch { return true; } } } [HarmonyPatch(typeof(PlayerManager), "GetClosestPlayerInTeam")] internal class PlayerManager_GetClosestPlayerInTeam_Ffa_Patch { private static bool Prefix(PlayerManager __instance, Vector3 position, int team, bool needVision, ref Player __result) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!FfaMode.EngineActive()) { return true; } try { __result = FfaTargeting.NearestOpponent(__instance, position, -1, needVision); return false; } catch { return true; } } } internal static class FfaTargeting { public static Player NearestOpponent(PlayerManager pm, Vector3 position, int excludeTeam, bool needVision = false) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) Player result = null; float num = float.PositiveInfinity; if (pm?.players == null) { return null; } foreach (Player player in pm.players) { if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null || (Object)(object)player.data == (Object)null || player.data.dead || (excludeTeam >= 0 && player.TeamID == excludeTeam)) { continue; } float num2 = Vector2.Distance(Vector2.op_Implicit(position), Vector2.op_Implicit(((Component)player).transform.position)); if (num2 < 0.01f || num2 >= num) { continue; } if (needVision) { try { if (!pm.CanSeePlayer(Vector2.op_Implicit(position), player).canSee) { continue; } } catch { } } num = num2; result = player; } return result; } } [HarmonyPatch(typeof(WeaponHandler), "Attack")] internal class WeaponHandler_FfaSpawnGrace_Patch { private static float lastDenyLog = -999f; private static bool Prefix(WeaponHandler __instance) { try { if (!FfaMode.SpawnGraceActive) { return true; } CharacterData val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent() : null); if ((Object)(object)val == (Object)null || (Object)(object)val.view == (Object)null || !val.view.IsMine) { return true; } if (Time.realtimeSinceStartup - lastDenyLog > 1f) { lastDenyLog = Time.realtimeSinceStartup; Plugin.Log.LogInfo((object)$"[FFA-GRACE] fire suppressed ({FfaMode.SpawnGraceLeft:F2}s left)"); } return false; } catch { return true; } } } [HarmonyPatch(typeof(GeneralInput), "Update")] internal class GeneralInput_FfaSpawnGrace_Patch { private static float lastDenyLog = -999f; private static void Postfix(GeneralInput __instance) { try { if (!FfaMode.SpawnGraceActive || (Object)(object)__instance == (Object)null || !__instance.shieldWasPressed) { return; } CharacterData data = __instance.data; if (!((Object)(object)data == (Object)null) && !((Object)(object)data.view == (Object)null) && data.view.IsMine) { __instance.shieldWasPressed = false; if (Time.realtimeSinceStartup - lastDenyLog > 1f) { lastDenyLog = Time.realtimeSinceStartup; Plugin.Log.LogInfo((object)$"[FFA-GRACE] block suppressed ({FfaMode.SpawnGraceLeft:F2}s left)"); } } } catch { } } } [HarmonyPatch(typeof(Block), "TryBlock")] internal class Block_FfaSpawnGrace_Patch { private static bool Prefix(Block __instance) { try { if (!FfaMode.SpawnGraceActive) { return true; } CharacterData val = (((Object)(object)__instance != (Object)null) ? __instance.data : null); if ((Object)(object)val == (Object)null || (Object)(object)val.view == (Object)null || !val.view.IsMine) { return true; } return false; } catch { return true; } } } internal static class FfaSpawnPoints { private const int SampleColumns = 71; private const float StandOffset = 1.1f; private const float ClearRadius = 0.8f; private const float MinSeparation = 5f; private const float EdgeMargin = 3f; private static int cachedMapId = int.MinValue; private static float cachedFactor = -1f; private static readonly List cached = new List(); public static IList Extras => cached; public static void Clear() { cachedMapId = int.MinValue; cachedFactor = -1f; cached.Clear(); } public static void ScanForMap(Map map, float factor, Vector3 parkedOrigin, int needExtra) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)map == (Object)null) { Clear(); return; } int instanceID = ((Object)map).GetInstanceID(); if (instanceID == cachedMapId && Mathf.Approximately(factor, cachedFactor)) { return; } cachedMapId = instanceID; cachedFactor = factor; cached.Clear(); if (needExtra <= 0) { return; } Physics2D.SyncTransforms(); float num = Mathf.Max(1f, factor); float num2 = 35.56f * num - 3f; float num3 = 20f * num; int mask = LayerMask.GetMask(new string[1] { "Default" }); List list = new List(); try { SpawnPoint[] componentsInChildren = ((Component)map).GetComponentsInChildren(true); if (componentsInChildren != null) { SpawnPoint[] array = componentsInChildren; foreach (SpawnPoint val in array) { if ((Object)(object)val != (Object)null) { list.Add(val.localStartPos * num); } } } } catch { } List list2 = new List(); Vector2 val2 = default(Vector2); Vector3 val5 = default(Vector3); Vector2 val6 = default(Vector2); for (int j = 0; j < 71; j++) { float num4 = 0f - num2 + 2f * num2 * (((float)j + 0.5f) / 71f); ((Vector2)(ref val2))..ctor(parkedOrigin.x + num4, parkedOrigin.y + num3); RaycastHit2D[] array2 = Physics2D.RaycastAll(val2, Vector2.down, 2f * num3 + 4f, mask); if (array2 == null || array2.Length == 0) { continue; } RaycastHit2D val3 = default(RaycastHit2D); bool flag = false; for (int k = 0; k < array2.Length; k++) { RaycastHit2D val4 = array2[k]; if (!((Object)(object)((RaycastHit2D)(ref val4)).collider == (Object)null) && !((Object)(object)((RaycastHit2D)(ref val4)).rigidbody != (Object)null) && !IsMovable(((Component)((RaycastHit2D)(ref val4)).collider).gameObject) && !(((RaycastHit2D)(ref val4)).normal.y < 0.7f)) { val3 = val4; flag = true; break; } } if (!flag) { continue; } ((Vector3)(ref val5))..ctor(num4, ((RaycastHit2D)(ref val3)).point.y - parkedOrigin.y + 1.1f, 0f); if (!(Mathf.Abs(val5.y) > 20f * num - 3f)) { ((Vector2)(ref val6))..ctor(val2.x, ((RaycastHit2D)(ref val3)).point.y + 1.1f); Collider2D[] array3 = Physics2D.OverlapCircleAll(val6, 0.8f, mask); if ((array3 == null || array3.Length == 0) && !TooClose(val5, list) && !TooClose(val5, list2)) { list2.Add(val5); } } } List list3 = new List(); List list4 = new List(list2); while (list3.Count < needExtra && list4.Count > 0) { int index = 0; float num5 = float.NegativeInfinity; for (int l = 0; l < list4.Count; l++) { float num6 = NearestDistance(list4[l], list, list3); if (num6 > num5) { num5 = num6; index = l; } } list3.Add(list4[index]); list4.RemoveAt(index); } cached.AddRange(list3); Plugin.Log.LogInfo((object)($"[FFA-SPAWN] scanned map {instanceID} x{num:F2}: " + $"{list2.Count} candidate(s), {cached.Count}/{needExtra} used")); } catch (Exception ex) { cached.Clear(); Plugin.Log.LogWarning((object)("[FFA-SPAWN] scan failed, using duplicates: " + ex.Message)); } } private static bool IsMovable(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } Transform val = go.transform; while ((Object)(object)val != (Object)null) { GameObject gameObject = ((Component)val).gameObject; if ((Object)(object)gameObject.GetComponent("Rigidbody2D") != (Object)null) { return true; } if ((Object)(object)gameObject.GetComponent("CodeAnimation") != (Object)null) { return true; } if ((Object)(object)gameObject.GetComponent("PhotonMapObject") != (Object)null) { return true; } if ((Object)(object)gameObject.GetComponent("NetworkPhysicsObject") != (Object)null) { return true; } val = val.parent; } return false; } private static bool TooClose(Vector3 p, List others) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < others.Count; i++) { Vector3 val = others[i] - p; if (((Vector3)(ref val)).sqrMagnitude < 25f) { return true; } } return false; } private static float NearestDistance(Vector3 p, List a, List b) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) float num = float.MaxValue; Vector3 val; for (int i = 0; i < a.Count; i++) { float num2 = num; val = a[i] - p; num = Mathf.Min(num2, ((Vector3)(ref val)).sqrMagnitude); } for (int j = 0; j < b.Count; j++) { float num3 = num; val = b[j] - p; num = Mathf.Min(num3, ((Vector3)(ref val)).sqrMagnitude); } return (num == float.MaxValue) ? 0f : num; } } public static class GameStateWatcher { private class PeerTelemetry { public int lastSeq = -1; public string lastRaw = ""; public readonly List fps = new List(); public readonly List ping = new List(); public readonly List hit = new List(); public readonly List block = new List(); } private enum RqPhase { Idle, KillSweep, Restarting, AwaitMenu, Settle, Queue } [CompilerGenerated] private static class <>O { public static LogCallback <0>__OnUnityLog; } private static bool wasInRoom = false; private static bool isTracking = false; private static bool wasGameInProgress = false; private static bool pcolorRoomApplied = false; private static DateTime matchStartTime; private static int lastP1Points = 0; private static int lastP2Points = 0; private static int lastP1Rounds = 0; private static int lastP2Rounds = 0; private static int p1Points = 0; private static int p2Points = 0; private static int p1Rounds = 0; private static int p2Rounds = 0; private static int currentRound = 1; private static string localSteamId = ""; private static string localDisplayName = ""; private static string opponentSteamId = ""; private static string opponentDisplayName = ""; private static int localTeamId = -1; private static bool playersIdentified = false; private static bool opponentSteamIdResolved = false; private static bool opponentIsRanked = false; private static bool opponentRankChecked = false; private static float lastOpponentRankCheck = -999f; private static bool seriesPreflightSent = false; private static bool rankedRoomStallHandled = false; private static bool rankedRoomStallWarned = false; private static bool rankedRoomEverFull = false; private static bool matchIsRanked = false; private static bool opponentCardsViaHarmony = false; private static List preMatchOpponentCards = new List(); private static List localCards = new List(); private static List opponentCards = new List(); private static List localOffers = new List(); private static readonly List emptyOffers = new List(); private static int lastKnownP1CardCount = 0; private static int lastKnownP2CardCount = 0; private static List broadcastCardNames = new List(); private static int lastKnownOpponentBroadcastCount = 0; private const string CARD_PROP_KEY = "cr_cards"; private const string FPS_PROP_KEY = "cr_fps"; private static int fpsFrameCount = 0; private static float fpsTimeAccum = 0f; private static float fpsBroadcastTimer = 0f; private static int opponentAvgFps = 0; private static readonly List localFpsTimeline = new List(); private static int tlFrames = 0; private static float tlAccum = 0f; private static int bcFrames = 0; private static float bcAccum = 0f; private static int gstatsSeq = 0; private static int lastBroadcastRecentFps = 0; private static readonly List oppFpsTimeline = new List(); private static readonly List oppPingTimeline = new List(); private static int lastOppGstatsSeq = -1; private static float lastOppSeqAdvanceTime = -1f; private static int localFreezeCount = 0; private static int localFreezeFocusedCount = 0; private static float localFreezeTotalSec = 0f; private static readonly List pingSamples = new List(); private static int localRecvGapCount = 0; private static int localRecvGapMaxMs = 0; private static bool _recvGapOpen = false; private static int oppHbGapCount = 0; private static bool _oppHbGapOpen = false; private static int oppFreezeCount = 0; private static int oppFreezeFocusedCount = 0; private static int oppRecvGapCount = 0; private static long _lastTickStopwatchMs = -1L; private static readonly Stopwatch _tickStopwatch = Stopwatch.StartNew(); private static readonly List localHitTimeline = new List(); private static readonly List localBlockTimeline = new List(); private static readonly List oppHitTimeline = new List(); private static readonly List oppBlockTimeline = new List(); private static readonly List localFps3sTimeline = new List(); private static readonly List pointTimes = new List(); private static readonly Dictionary peerTele = new Dictionary(); private static List preMatchCards = new List(); private static int preMatchPickCount = 0; private static string photonRoomId = ""; private static string photonRegion = ""; private const string GAME_TOKEN_PROP_KEY = "cr_game_token"; private const string GAME_TOKEN_CAP_PROP_KEY = "cr_game_token_v"; private static string sharedGameToken = ""; private static string previousGameToken = ""; private static int matchStartServerTimestamp; private static bool gameOverReported = false; private static bool oneVOneMatchAtStart = false; private static bool macroEvidenceDispatched = false; private static bool opponentWasPresent = false; private static bool opponentDCReported = false; private static FieldInfo f_p1Points; private static FieldInfo f_p2Points; private static FieldInfo f_p1Rounds; private static FieldInfo f_p2Rounds; private static FieldInfo f_roundsToWinGame; private static bool fieldsResolved = false; private static int roundsToWin = 5; private static float pollTimer = 0f; private static DateTime roomJoinTime; private static DateTime sessionStartTime = DateTime.UtcNow; private static Dictionary sessionTimeByOpponent = new Dictionary(); private static int sessionMatchCount = 0; private static Dictionary sessionWLByOpponent = new Dictionary(); private static int sessionRankedWins = 0; private static int sessionRankedLosses = 0; private static int sessionRankedSeriesWins = 0; private static int sessionRankedSeriesLosses = 0; private static int ovtSoloWins = 0; private static int ovtDuoWins = 0; private static int sessionOvtWins = 0; private static int sessionOvtLosses = 0; private static int sessionFfaWins = 0; private static int sessionFfaLosses = 0; private static readonly List sessionFfaPlacements = new List(); private static int currentSeriesGamesWon = 0; private static int currentSeriesGamesLost = 0; private static int sessionCasualWins = 0; private static int sessionCasualLosses = 0; private static int sessionTeamSeriesWins = 0; private static int sessionTeamSeriesLosses = 0; private static bool achTookDamage = false; private static bool achPhoenixUsed = false; private static bool achDied = false; private static int achMaxOpponentRounds = 0; private static bool achWasDown04 = false; private static bool lastDeadState = false; private static int lastRemainingRespawns = -1; private static bool achFiredShot = false; private static bool achMoved = false; private static bool achJumped = false; public static bool achLeftmostViolated = false; private static int abyssalRoundsActivated = 0; private static bool abyssalActivatedThisRound = false; private static bool _loggedFirstFire; private static bool _loggedFirstHit; private static bool _loggedFirstBlockAct; private static bool _loggedFirstBlockOk; private static bool _loggedHitBudgetDrop; private static bool _activationSuccessCredited = true; private static int _hitsRemaining; private const float BLOCK_ACTIVE_WINDOW = 0.5f; private static bool inPickPhase = false; private const string SID_STEAM_ID = "76561198040410653"; private static bool sessionSeriesCounted = false; private static bool casualDowngradeNotified = false; private const double SESSION_INACTIVITY_HOURS = 3.0; private const string PP_SESSION_LAST_ACTIVITY = "cr_session_last_activity_unix"; private const string PP_SESSION_START = "cr_session_start_unix"; private const string PP_SESSION_MATCHES = "cr_session_match_count"; private const string PP_SESSION_RW = "cr_session_ranked_wins"; private const string PP_SESSION_RL = "cr_session_ranked_losses"; private const string PP_SESSION_CW = "cr_session_casual_wins"; private const string PP_SESSION_CL = "cr_session_casual_losses"; private const string PP_SESSION_RSW = "cr_session_rseries_wins"; private const string PP_SESSION_RSL = "cr_session_rseries_losses"; private const string PP_SESSION_T2W = "cr_session_tseries_wins"; private const string PP_SESSION_T2L = "cr_session_tseries_losses"; private const string PP_SESSION_OVW = "cr_session_ovt_wins"; private const string PP_SESSION_OVL = "cr_session_ovt_losses"; private const string PP_SESSION_FFW = "cr_session_ffa_wins"; private const string PP_SESSION_FFL = "cr_session_ffa_losses"; private const string PP_SESSION_FFA_PLACES = "cr_session_ffa_places"; private const string PP_SESSION_WL_BY_OPP_FFA = "cr_session_wl_by_opp_ffa"; private const string PP_SESSION_WL_BY_OPP = "cr_session_wl_by_opp"; private const string PP_SESSION_WL_BY_OPP_1V2 = "cr_session_wl_by_opp_1v2"; private const string PP_SESSION_TIME_BY_OPP = "cr_session_time_by_opp"; private static RqPhase rqPhase = RqPhase.Idle; private static float rqPhaseAt; private static bool rqQuickmatch; private static bool rqForcedGoToMenu; private static int rqAttemptsWindow; private static float rqWindowStart = -1f; private static float roomlessSince = -1f; private static float fullRoomNoGameSince = -1f; private static object _lastClientState; private static float _clientStateChangedAt; private const int MACRO_EVENTS_PER_SEC = 25; private static float inputBucketTimer = 0f; private static int inputBucketCount = 0; private static int inputBucketKeyCount = 0; private static int inputBucketClickCount = 0; private static long inputBucketStartedAtMs = -1L; private static readonly List inputSuspectWindows = new List(); private static float lastMacroLogAt = -999f; private const string GSTATS_PROP_KEY = "cr_gstats"; private static readonly List matchPointTimeline = new List(); private static bool _runInBackgroundOverridden = false; private static bool _origRunInBackground = false; private static DateTime _stuckOverlayDismissedAt = DateTime.MinValue; private static bool _rankedSyncSent; private static float lastContinuationRequestTime = -999f; private static float lastOvtContinuationRequestTime = -999f; public static bool pendingRegicideCheck = false; private static bool logListenerRegistered = false; private static int pickCountThisMatch = 0; private static string _lastLocalPickedCardName; public static bool IsTracking => isTracking; public static int LocalAvgFps => (fpsTimeAccum > 0.5f) ? ((int)Math.Round((double)fpsFrameCount / (double)fpsTimeAccum)) : 0; public static int OpponentAvgFps => opponentAvgFps; public static float LocalDamageTakenThisMatch { get; private set; } public static int LocalShotsThisMatch { get; private set; } public static int LocalBlocksThisMatch { get; private set; } public static int LocalKeysThisMatch { get; private set; } public static int LocalMacroSuspectSeconds { get; private set; } public static int LocalMacroPeakKeysPerSecond { get; private set; } public static int LocalMacroPeakClicksPerSecond { get; private set; } public static int LocalMacroPeakEventsPerSecond { get; private set; } public static string LocalMacroTimeline => string.Join(",", inputSuspectWindows.ToArray()); public static float LocalActiveSecondsThisMatch { get; private set; } public static int LocalBulletsFiredThisMatch { get; private set; } public static int LocalBulletsHitThisMatch { get; private set; } public static int LocalBlocksActivatedThisMatch { get; private set; } public static int LocalBlocksSuccessfulThisMatch { get; private set; } private static bool BlockDebugEnabled => Plugin.ShowBlockDebug != null && Plugin.ShowBlockDebug.Value; public static int LocalBlockRawAbsorbs { get; private set; } public static int LocalBlockDedupeDrops { get; private set; } public static float LastBlockActivatedTime { get; private set; } = -999f; public static float LastBlockSuccessfulTime { get; private set; } = -999f; public static float LastBlockAbsorbTime { get; private set; } = -999f; public static float LastLocalHitTime { get; private set; } = -999f; public static float LastBlockMissTime { get; private set; } = -999f; public static string LastBlockEventLabel { get; private set; } = ""; public static MatchTracker.MatchResult LastResult { get; private set; } public static bool HasPendingResult { get; private set; } = false; public static bool MatchIsRanked => matchIsRanked; public static int LastP1Points => p1Points; public static int LastP2Points => p2Points; public static Dictionary SessionTimeByOpponent => sessionTimeByOpponent; public static Dictionary SessionWLByOpponent => sessionWLByOpponent; public static int SessionMatchCount => sessionMatchCount; public static int SessionRankedWins => sessionRankedWins; public static int SessionRankedLosses => sessionRankedLosses; public static int SessionRankedSeriesWins => sessionRankedSeriesWins; public static int SessionRankedSeriesLosses => sessionRankedSeriesLosses; public static int CurrentSeriesGamesWon => currentSeriesGamesWon; public static int CurrentSeriesGamesLost => currentSeriesGamesLost; public static int OvtSoloWins => ovtSoloWins; public static int OvtDuoWins => ovtDuoWins; public static int SessionOvtWins => sessionOvtWins; public static int SessionFfaWins => sessionFfaWins; public static int SessionFfaLosses => sessionFfaLosses; public static string SessionFfaPlacementsCsv { get { try { return string.Join(",", sessionFfaPlacements.ConvertAll((int p) => p.ToString()).ToArray()); } catch { return ""; } } } public static int SessionOvtLosses => sessionOvtLosses; public static int SessionCasualWins => sessionCasualWins; public static int SessionCasualLosses => sessionCasualLosses; public static int SessionTeamSeriesWins => sessionTeamSeriesWins; public static int SessionTeamSeriesLosses => sessionTeamSeriesLosses; public static DateTime SessionStartTime => sessionStartTime; public static int OppStatBulletsFired { get; private set; } public static int OppStatBulletsHit { get; private set; } public static int OppStatBlocksActivated { get; private set; } public static int OppStatBlocksSuccessful { get; private set; } public static int OppStatKeysPressed { get; private set; } public static float OppStatActiveSeconds { get; private set; } public static int OppStatMacroSuspectSeconds { get; private set; } public static int OppStatMacroPeakKeysPerSecond { get; private set; } public static int OppStatMacroPeakClicksPerSecond { get; private set; } public static int OppStatMacroPeakEventsPerSecond { get; private set; } public static string OppStatMacroTimeline { get; private set; } = ""; public static bool ShouldShowMatchFoundStuckOverlay { get; private set; } public static int SecondsInUnstartedRoom { get; private set; } public static bool LocalAliveInCombatNow { get; private set; } public static bool IsInMatch => isTracking; public static bool IsInRoom => wasInRoom; public static bool IsInOnlineRoom { get { if (!wasInRoom) { return false; } try { return !PhotonNetwork.OfflineMode; } catch { return true; } } } public static bool LeavingForRanked { get; set; } = false; public static string LocalSteamId => localSteamId; public static string LocalDisplayName => localDisplayName; public static string OpponentDisplayName => opponentDisplayName; public static string OpponentSteamId => opponentSteamId; public static int P1Rounds => p1Rounds; public static int P2Rounds => p2Rounds; public static int P1Points => p1Points; public static int P2Points => p2Points; public static int LocalTeamId => localTeamId; public static int CurrentRound => currentRound; public static int LocalOffersCount => localOffers.Count; public static string LastLocalPickedCardName => _lastLocalPickedCardName; public static void OnAbyssalActivatedLocal() { if (!abyssalActivatedThisRound) { abyssalActivatedThisRound = true; Plugin.Log.LogInfo((object)"[ACH] Abyssal activated this round"); } } public static void OnLocalBulletFired(int projectiles) { if (isTracking && !inPickPhase) { if (projectiles < 1) { projectiles = 1; } LocalBulletsFiredThisMatch += projectiles; _hitsRemaining += projectiles; if (!_loggedFirstFire) { _loggedFirstFire = true; Plugin.Log.LogInfo((object)$"[STATS] first bullet fired this match (projectiles={projectiles})"); } } } public static void OnLocalBulletHit() { if (!isTracking) { return; } if (_hitsRemaining <= 0) { if (BlockDebugEnabled && !_loggedHitBudgetDrop) { _loggedHitBudgetDrop = true; Plugin.Log.LogInfo((object)$"[HIT-DROP] budget exhausted (fired={LocalBulletsFiredThisMatch} hit={LocalBulletsHitThisMatch})"); } return; } _hitsRemaining--; LocalBulletsHitThisMatch++; if (!_loggedFirstHit) { _loggedFirstHit = true; Plugin.Log.LogInfo((object)"[STATS] first bullet-hit this match"); } } public static void OnLocalBlockActivated() { if (!isTracking || inPickPhase) { return; } LocalBlocksActivatedThisMatch++; _activationSuccessCredited = false; if (!BlockDebugEnabled) { if (!_loggedFirstBlockAct) { _loggedFirstBlockAct = true; Plugin.Log.LogInfo((object)"[STATS] first block activation this match"); } return; } LastBlockActivatedTime = Time.time; float num = Time.time - LastLocalHitTime; if (num >= 0f && num < 0.25f) { LastBlockMissTime = Time.time; LastBlockEventLabel = $"TOO SLOW (block +{num * 1000f:F0}ms after hit)"; Plugin.Log.LogInfo((object)$"[BLOCK-DBG] TOO-SLOW act={LocalBlocksActivatedThisMatch} hit_to_block={num * 1000f:F0}ms"); } else { LastBlockEventLabel = $"ACTIVATED #{LocalBlocksActivatedThisMatch}"; Plugin.Log.LogInfo((object)$"[BLOCK-DBG] ACTIVATED act={LocalBlocksActivatedThisMatch} succ={LocalBlocksSuccessfulThisMatch}/{LocalBlockRawAbsorbs}"); } if (!_loggedFirstBlockAct) { _loggedFirstBlockAct = true; Plugin.Log.LogInfo((object)"[STATS] first block activation this match"); } } public static void OnLocalPlayerHit(float damage) { if (!isTracking || inPickPhase) { return; } if (damage > 0f && damage < 10000f) { LocalDamageTakenThisMatch += damage; } if (BlockDebugEnabled) { LastLocalHitTime = Time.time; LastBlockMissTime = Time.time; float num = Time.time - LastBlockActivatedTime; if (num > 0f && num < 0.5f) { LastBlockEventLabel = $"HIT (block active, {num * 1000f:F0}ms in) — unblockable?"; Plugin.Log.LogInfo((object)$"[BLOCK-DBG] HIT-ACTIVE act={LocalBlocksActivatedThisMatch} since_act={num * 1000f:F0}ms dmg={damage:F1}"); } else if (num > 0.5f && num < 2f) { LastBlockEventLabel = $"TOO EARLY (blocked {num * 1000f:F0}ms before hit)"; Plugin.Log.LogInfo((object)$"[BLOCK-DBG] TOO-EARLY since_act={num * 1000f:F0}ms dmg={damage:F1}"); } else { LastBlockEventLabel = "HIT (no recent block)"; Plugin.Log.LogInfo((object)$"[BLOCK-DBG] HIT-NOBLK since_act={num:F1}s dmg={damage:F1}"); } } } public static void OnLocalBlockSuccessful(bool userChain) { if (!isTracking || inPickPhase) { return; } LocalBlockRawAbsorbs++; bool blockDebugEnabled = BlockDebugEnabled; if (blockDebugEnabled) { LastBlockAbsorbTime = Time.time; } if (!userChain) { LocalBlockDedupeDrops++; if (blockDebugEnabled) { LastBlockEventLabel = "ABSORB (auto-block, not counted)"; Plugin.Log.LogInfo((object)$"[BLOCK-DBG] ABSORB-NONUSER raw={LocalBlockRawAbsorbs} credited={LocalBlocksSuccessfulThisMatch}"); } return; } if (_activationSuccessCredited) { LocalBlockDedupeDrops++; if (blockDebugEnabled) { LastBlockEventLabel = "ABSORB (already credited)"; Plugin.Log.LogInfo((object)$"[BLOCK-DBG] ABSORB-DEDUP raw={LocalBlockRawAbsorbs} credited={LocalBlocksSuccessfulThisMatch}"); } return; } _activationSuccessCredited = true; LocalBlocksSuccessfulThisMatch++; if (blockDebugEnabled) { LastBlockSuccessfulTime = Time.time; LastBlockEventLabel = $"SUCCESSFUL #{LocalBlocksSuccessfulThisMatch}"; Plugin.Log.LogInfo((object)$"[BLOCK-DBG] SUCCESS act={LocalBlocksActivatedThisMatch} succ={LocalBlocksSuccessfulThisMatch} raw={LocalBlockRawAbsorbs} drops={LocalBlockDedupeDrops}"); } if (!_loggedFirstBlockOk) { _loggedFirstBlockOk = true; Plugin.Log.LogInfo((object)"[STATS] first successful block this match"); } } public static void IncrementSessionRankedSeries(bool won) { if (sessionSeriesCounted) { currentSeriesGamesWon = 0; currentSeriesGamesLost = 0; return; } sessionSeriesCounted = true; if (won) { sessionRankedSeriesWins++; } else { sessionRankedSeriesLosses++; } currentSeriesGamesWon = 0; currentSeriesGamesLost = 0; try { ApiClient.OnSeriesCompletedVsOpponent(opponentSteamId, won); } catch { } Plugin.Log.LogInfo((object)$"[SESSION] Ranked series tally: {sessionRankedSeriesWins}-{sessionRankedSeriesLosses}; current series counters reset"); SaveSessionState(); } public static void ResetCurrentSeriesScore() { currentSeriesGamesWon = 0; currentSeriesGamesLost = 0; } public static void AdoptSeriesScore(int myWins, int oppWins) { currentSeriesGamesWon = Mathf.Max(0, myWins); currentSeriesGamesLost = Mathf.Max(0, oppWins); Plugin.Log.LogInfo((object)$"[SESSION] Adopted resumed series score {currentSeriesGamesWon}-{currentSeriesGamesLost} from preflight"); } public static void DowngradeToCasual(string reason) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) bool flag = matchIsRanked; matchIsRanked = false; if (flag) { Plugin.Log.LogInfo((object)("[POLL] Match downgraded to CASUAL (" + reason + ")")); } if (casualDowngradeNotified) { return; } casualDowngradeNotified = true; try { string text = (string.IsNullOrEmpty(opponentDisplayName) ? "your opponent" : opponentDisplayName); CompetitiveUI.QueueNotification("CASUAL match — " + text + " has Ranked disabled (fix: F5 top row - Enable)", new Color(0.85f, 0.8f, 0.5f), 12f); } catch { } } public static void RecordSessionTeamSeries(bool won) { if (won) { sessionTeamSeriesWins++; } else { sessionTeamSeriesLosses++; } SaveSessionState(); } private static long _DtToUnix(DateTime utc) { DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); return (long)(utc.ToUniversalTime() - dateTime).TotalSeconds; } private static DateTime _UnixToDt(long secs) { return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(secs); } public static void SaveSessionState() { try { PlayerPrefs.SetString("cr_session_last_activity_unix", _DtToUnix(DateTime.UtcNow).ToString()); PlayerPrefs.SetString("cr_session_start_unix", _DtToUnix(sessionStartTime).ToString()); PlayerPrefs.SetInt("cr_session_match_count", sessionMatchCount); PlayerPrefs.SetInt("cr_session_ranked_wins", sessionRankedWins); PlayerPrefs.SetInt("cr_session_ranked_losses", sessionRankedLosses); PlayerPrefs.SetInt("cr_session_casual_wins", sessionCasualWins); PlayerPrefs.SetInt("cr_session_casual_losses", sessionCasualLosses); PlayerPrefs.SetInt("cr_session_rseries_wins", sessionRankedSeriesWins); PlayerPrefs.SetInt("cr_session_rseries_losses", sessionRankedSeriesLosses); PlayerPrefs.SetInt("cr_session_tseries_wins", sessionTeamSeriesWins); PlayerPrefs.SetInt("cr_session_tseries_losses", sessionTeamSeriesLosses); PlayerPrefs.SetInt("cr_session_ovt_wins", sessionOvtWins); PlayerPrefs.SetInt("cr_session_ovt_losses", sessionOvtLosses); PlayerPrefs.SetInt("cr_session_ffa_wins", sessionFfaWins); PlayerPrefs.SetInt("cr_session_ffa_losses", sessionFfaLosses); PlayerPrefs.SetString("cr_session_ffa_places", SessionFfaPlacementsCsv); StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder2 = new StringBuilder(); StringBuilder stringBuilder3 = new StringBuilder(); bool flag = true; bool flag2 = true; bool flag3 = true; foreach (KeyValuePair item in sessionWLByOpponent) { if (item.Value == null || item.Value.Length < 4) { continue; } string value = (item.Key ?? "").Replace("|", "/").Replace("=", "-").Replace(",", "."); if (!flag) { stringBuilder.Append('|'); } stringBuilder.Append(value).Append('=').Append(item.Value[0]) .Append(',') .Append(item.Value[1]) .Append(',') .Append(item.Value[2]) .Append(',') .Append(item.Value[3]); flag = false; int num = ((item.Value.Length > 4) ? item.Value[4] : 0); int num2 = ((item.Value.Length > 5) ? item.Value[5] : 0); if (num != 0 || num2 != 0) { if (!flag2) { stringBuilder2.Append('|'); } stringBuilder2.Append(value).Append('=').Append(num) .Append(',') .Append(num2); flag2 = false; } int num3 = ((item.Value.Length > 6) ? item.Value[6] : 0); int num4 = ((item.Value.Length > 7) ? item.Value[7] : 0); if (num3 != 0 || num4 != 0) { if (!flag3) { stringBuilder3.Append('|'); } stringBuilder3.Append(value).Append('=').Append(num3) .Append(',') .Append(num4); flag3 = false; } } PlayerPrefs.SetString("cr_session_wl_by_opp", stringBuilder.ToString()); PlayerPrefs.SetString("cr_session_wl_by_opp_1v2", stringBuilder2.ToString()); PlayerPrefs.SetString("cr_session_wl_by_opp_ffa", stringBuilder3.ToString()); StringBuilder stringBuilder4 = new StringBuilder(); bool flag4 = true; foreach (KeyValuePair item2 in sessionTimeByOpponent) { string value2 = (item2.Key ?? "").Replace("|", "/").Replace("=", "-"); if (!flag4) { stringBuilder4.Append('|'); } stringBuilder4.Append(value2).Append('=').Append(item2.Value.ToString("F2", CultureInfo.InvariantCulture)); flag4 = false; } PlayerPrefs.SetString("cr_session_time_by_opp", stringBuilder4.ToString()); PlayerPrefs.Save(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SESSION] save failed: " + ex.Message)); } } private static void LoadSessionStateOrReset() { try { string text = PlayerPrefs.GetString("cr_session_last_activity_unix", ""); if (string.IsNullOrEmpty(text)) { sessionStartTime = DateTime.UtcNow; Plugin.Log.LogInfo((object)"[SESSION] no prior session - starting fresh"); return; } if (!long.TryParse(text, out var result)) { sessionStartTime = DateTime.UtcNow; return; } DateTime dateTime = _UnixToDt(result); double totalHours = (DateTime.UtcNow - dateTime).TotalHours; if (totalHours > 3.0 || totalHours < 0.0) { sessionStartTime = DateTime.UtcNow; Plugin.Log.LogInfo((object)$"[SESSION] last activity {totalHours:F1}h ago (>{3.0}h) - starting fresh"); return; } long secs = long.Parse(PlayerPrefs.GetString("cr_session_start_unix", result.ToString())); sessionStartTime = _UnixToDt(secs); sessionMatchCount = PlayerPrefs.GetInt("cr_session_match_count", 0); sessionRankedWins = PlayerPrefs.GetInt("cr_session_ranked_wins", 0); sessionRankedLosses = PlayerPrefs.GetInt("cr_session_ranked_losses", 0); sessionCasualWins = PlayerPrefs.GetInt("cr_session_casual_wins", 0); sessionCasualLosses = PlayerPrefs.GetInt("cr_session_casual_losses", 0); sessionRankedSeriesWins = PlayerPrefs.GetInt("cr_session_rseries_wins", 0); sessionRankedSeriesLosses = PlayerPrefs.GetInt("cr_session_rseries_losses", 0); sessionTeamSeriesWins = PlayerPrefs.GetInt("cr_session_tseries_wins", 0); sessionTeamSeriesLosses = PlayerPrefs.GetInt("cr_session_tseries_losses", 0); sessionOvtWins = PlayerPrefs.GetInt("cr_session_ovt_wins", 0); sessionOvtLosses = PlayerPrefs.GetInt("cr_session_ovt_losses", 0); sessionFfaWins = PlayerPrefs.GetInt("cr_session_ffa_wins", 0); sessionFfaLosses = PlayerPrefs.GetInt("cr_session_ffa_losses", 0); sessionFfaPlacements.Clear(); string[] array = (PlayerPrefs.GetString("cr_session_ffa_places", "") ?? "").Split(','); foreach (string s in array) { if (int.TryParse(s, out var result2) && result2 > 0) { sessionFfaPlacements.Add(result2); } } sessionWLByOpponent.Clear(); string[] array2 = (PlayerPrefs.GetString("cr_session_wl_by_opp", "") ?? "").Split('|'); foreach (string text2 in array2) { if (string.IsNullOrEmpty(text2)) { continue; } int num = text2.IndexOf('='); if (num <= 0) { continue; } string key = text2.Substring(0, num); string[] array3 = text2.Substring(num + 1).Split(','); if ((array3.Length == 4 || array3.Length == 6) && int.TryParse(array3[0], out var result3) && int.TryParse(array3[1], out var result4) && int.TryParse(array3[2], out var result5) && int.TryParse(array3[3], out var result6)) { int result7 = 0; int result8 = 0; if (array3.Length == 6) { int.TryParse(array3[4], out result7); int.TryParse(array3[5], out result8); } sessionWLByOpponent[key] = new int[6] { result3, result4, result5, result6, result7, result8 }; } } string[] array4 = (PlayerPrefs.GetString("cr_session_wl_by_opp_1v2", "") ?? "").Split('|'); foreach (string text3 in array4) { if (string.IsNullOrEmpty(text3)) { continue; } int num2 = text3.IndexOf('='); if (num2 <= 0) { continue; } string key2 = text3.Substring(0, num2); string[] array5 = text3.Substring(num2 + 1).Split(','); if (array5.Length != 2 || !int.TryParse(array5[0], out var result9) || !int.TryParse(array5[1], out var result10)) { continue; } if (!sessionWLByOpponent.TryGetValue(key2, out var value) || value == null || value.Length < 6) { int[] array6 = new int[6]; if (value != null) { Array.Copy(value, array6, Math.Min(value.Length, 6)); } value = (sessionWLByOpponent[key2] = array6); } value[4] = result9; value[5] = result10; } string[] array8 = (PlayerPrefs.GetString("cr_session_wl_by_opp_ffa", "") ?? "").Split('|'); foreach (string text4 in array8) { if (string.IsNullOrEmpty(text4)) { continue; } int num3 = text4.IndexOf('='); if (num3 <= 0) { continue; } string key3 = text4.Substring(0, num3); string[] array9 = text4.Substring(num3 + 1).Split(','); if (array9.Length != 2 || !int.TryParse(array9[0], out var result11) || !int.TryParse(array9[1], out var result12)) { continue; } if (!sessionWLByOpponent.TryGetValue(key3, out var value2) || value2 == null || value2.Length < 8) { int[] array10 = new int[8]; if (value2 != null) { Array.Copy(value2, array10, Math.Min(value2.Length, 8)); } value2 = (sessionWLByOpponent[key3] = array10); } value2[6] = result11; value2[7] = result12; } sessionTimeByOpponent.Clear(); string[] array12 = (PlayerPrefs.GetString("cr_session_time_by_opp", "") ?? "").Split('|'); foreach (string text5 in array12) { if (string.IsNullOrEmpty(text5)) { continue; } int num4 = text5.IndexOf('='); if (num4 > 0) { string key4 = text5.Substring(0, num4); if (float.TryParse(text5.Substring(num4 + 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var result13)) { sessionTimeByOpponent[key4] = result13; } } } Plugin.Log.LogInfo((object)($"[SESSION] restored prior session ({totalHours:F1}h since last activity): " + $"{sessionMatchCount} games, {sessionRankedWins}-{sessionRankedLosses}R / {sessionCasualWins}-{sessionCasualLosses}C, " + $"{sessionWLByOpponent.Count} opponents")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SESSION] load failed: " + ex.Message + " - starting fresh")); sessionStartTime = DateTime.UtcNow; } } public static void Initialize() { LoadSessionStateOrReset(); IdentifyLocalPlayer(); RegisterLogListener(); Plugin.Log.LogInfo((object)"GameStateWatcher initialized"); } public static void Poll() { pollTimer += Time.deltaTime; if (!(pollTimer < 0.1f)) { pollTimer = 0f; PollRoomState(); PollMatchState(); if (isTracking) { TryRefreshSharedGameToken(); } PollRoomlessGameScene(); } } private unsafe static void PollRoomlessGameScene() { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) try { if (rqPhase != RqPhase.Idle) { TickRequeueMachine(); return; } bool flag = PhotonNetwork.OfflineMode || !string.IsNullOrEmpty(Plugin.PendingRankedRoom) || Plugin.Pending2v2Slot >= 0 || Plugin.PendingOvtSlot >= 0 || LeavingForRanked || isTracking; try { flag = flag || EscapeMenuHandler.isEscMenu; } catch { } try { flag = flag || ((Object)(object)NetworkConnectionHandler.instance != (Object)null && NetworkConnectionHandler.instance.m_restarting); } catch { } if (flag) { roomlessSince = -1f; fullRoomNoGameSince = -1f; return; } try { ClientState networkClientState = PhotonNetwork.NetworkClientState; if (!((object)(*(ClientState*)(&networkClientState))/*cast due to .constrained prefix*/).Equals(_lastClientState)) { _lastClientState = networkClientState; _clientStateChangedAt = Time.unscaledTime; } } catch { } if (!((Object)(object)GM_ArmsRace.instance != (Object)null) || PhotonNetwork.InRoom) { roomlessSince = -1f; } else { if (roomlessSince < 0f) { roomlessSince = Time.unscaledTime; } float num = Time.unscaledTime - roomlessSince; bool sweepActive = QuickplayChurnAbandonGuardPatch.SweepActive; bool flag2 = Time.unscaledTime - _clientStateChangedAt >= 1.5f; if ((sweepActive && num >= 1f) || (!sweepActive && flag2 && num >= 3f)) { FireRequeue(sweepActive ? "roomless+sweep" : "roomless-stable"); return; } } bool flag3 = false; if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.PlayerCount >= 2 && (Object)(object)GM_ArmsRace.instance == (Object)null) { string text = PhotonNetwork.CurrentRoom.Name ?? ""; Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; bool flag4 = text.StartsWith("ranked_") || text.StartsWith("sct-") || text.StartsWith("ovt_") || text.StartsWith("ffa_") || (((Dictionary)(object)customProperties)?.ContainsKey((object)"cr_ff") ?? false); flag3 = !flag4; } if (!flag3) { fullRoomNoGameSince = -1f; } else if (fullRoomNoGameSince < 0f) { fullRoomNoGameSince = Time.unscaledTime; } else if (Time.unscaledTime - fullRoomNoGameSince >= 12f) { FireRequeue("full-room-no-game"); } } catch { roomlessSince = -1f; fullRoomNoGameSince = -1f; } } private static void FireRequeue(string why) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected I4, but got Unknown //IL_0169: 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_00cf: Unknown result type (might be due to invalid IL or missing references) roomlessSince = -1f; fullRoomNoGameSince = -1f; int num = 0; try { num = (int)NetworkConnectionHandler.instance.m_searchingType; } catch { } rqQuickmatch = num == 1 && (Plugin.AutoRequeueOnMatchmakingBug == null || Plugin.AutoRequeueOnMatchmakingBug.Value); if (rqQuickmatch) { if (rqWindowStart < 0f || Time.unscaledTime - rqWindowStart > 300f) { rqWindowStart = Time.unscaledTime; rqAttemptsWindow = 0; } if (++rqAttemptsWindow > 2) { rqQuickmatch = false; Plugin.Log.LogWarning((object)"[QUICKPLAY-GUARD] requeue loop cap hit — returning to menu instead"); try { CompetitiveUI.ShowNotification("Matchmaking keeps failing - returning to menu. Please try again in a minute.", new Color(1f, 0.5f, 0.4f), 8f); } catch { } } } Plugin.Log.LogWarning((object)("[QUICKPLAY-GUARD] dead matchmaking state (" + why + ") — " + (rqQuickmatch ? "auto-requeue" : "returning to menu"))); if (rqQuickmatch) { try { CompetitiveUI.ShowNotification("Matchmaking bug detected - putting you back in the quickplay queue...", new Color(1f, 0.8f, 0.3f), 6f); } catch { } } else { try { CompetitiveUI.ShowNotification("Connection was lost - returning to menu.", new Color(1f, 0.8f, 0.3f), 6f); } catch { } } rqForcedGoToMenu = false; rqPhase = RqPhase.KillSweep; rqPhaseAt = Time.unscaledTime; } private static void TickRequeueMachine() { //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) float unscaledTime = Time.unscaledTime; if (!string.IsNullOrEmpty(Plugin.PendingRankedRoom) || Plugin.Pending2v2Slot >= 0 || Plugin.PendingOvtSlot >= 0) { Plugin.Log.LogInfo((object)"[QUICKPLAY-GUARD] requeue aborted — mod pending room armed"); rqPhase = RqPhase.Idle; return; } switch (rqPhase) { case RqPhase.KillSweep: { QuickplayChurnAbandonGuardPatch.AbortSweep = true; if (QuickplayChurnAbandonGuardPatch.SweepActive && !(unscaledTime - rqPhaseAt > 1f)) { break; } bool flag2 = false; try { flag2 = (Object)(object)NetworkConnectionHandler.instance != (Object)null && NetworkConnectionHandler.instance.m_restarting; } catch { } if (flag2) { Plugin.Log.LogWarning((object)"[QUICKPLAY-GUARD] vanilla restart already hung — Disconnect + GoToMenu fallback"); try { PhotonNetwork.Disconnect(); } catch { } try { GameManager.instance.GoToMenu(); } catch { } rqForcedGoToMenu = true; } else { try { NetworkConnectionHandler.instance.NetworkRestart(); } catch { } } rqPhase = RqPhase.AwaitMenu; rqPhaseAt = unscaledTime; break; } case RqPhase.AwaitMenu: { bool flag = false; try { flag = (Object)(object)GM_ArmsRace.instance == (Object)null && !PhotonNetwork.InRoom && !PhotonNetwork.IsConnected && (Object)(object)NetworkConnectionHandler.instance != (Object)null && !NetworkConnectionHandler.instance.m_restarting && (Object)(object)MainMenuHandler.instance != (Object)null; } catch { } if (flag) { rqPhase = RqPhase.Settle; rqPhaseAt = unscaledTime; } else { if (!(unscaledTime - rqPhaseAt > 12f)) { break; } if (!rqForcedGoToMenu) { Plugin.Log.LogWarning((object)"[QUICKPLAY-GUARD] restart didn't land in 12s — Disconnect + GoToMenu fallback"); try { PhotonNetwork.Disconnect(); } catch { } try { GameManager.instance.GoToMenu(); } catch { } rqForcedGoToMenu = true; rqPhaseAt = unscaledTime; } else { Plugin.Log.LogWarning((object)"[QUICKPLAY-GUARD] recovery failed — giving up"); try { CompetitiveUI.ShowNotification("Couldn't recover automatically - please restart matchmaking from the menu.", new Color(1f, 0.5f, 0.4f), 8f); } catch { } rqPhase = RqPhase.Idle; } } break; } case RqPhase.Settle: if (unscaledTime - rqPhaseAt >= 0.7f) { rqPhase = RqPhase.Queue; rqPhaseAt = unscaledTime; } break; case RqPhase.Queue: rqPhase = RqPhase.Idle; if (!rqQuickmatch) { break; } try { if (PhotonNetwork.InRoom || PhotonNetwork.OfflineMode || (Object)(object)GM_ArmsRace.instance != (Object)null) { break; } try { CharacterCreatorHandler instance = CharacterCreatorHandler.instance; if (instance != null) { instance.CloseMenus(); } } catch { } try { MainMenuHandler instance2 = MainMenuHandler.instance; if (instance2 != null) { instance2.Close(); } } catch { } NetworkConnectionHandler.instance.QuickMatch(); Plugin.Log.LogInfo((object)"[QUICKPLAY-GUARD] re-entered quickplay queue after dead-state recovery"); try { CompetitiveUI.ShowNotification("Back in the quickplay queue - searching for an opponent.", new Color(0.5f, 1f, 0.6f)); break; } catch { break; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[QUICKPLAY-GUARD] requeue failed: " + ex.Message)); try { CompetitiveUI.ShowNotification("Couldn't recover automatically - please restart matchmaking from the menu.", new Color(1f, 0.5f, 0.4f), 8f); break; } catch { break; } } case RqPhase.Restarting: break; } } public static void TickFrame() { try { FfaMode.TickSpawnGrace(); } catch { } if (!isTracking) { _lastTickStopwatchMs = -1L; return; } float unscaledDeltaTime = Time.unscaledDeltaTime; long elapsedMilliseconds = _tickStopwatch.ElapsedMilliseconds; if (_lastTickStopwatchMs >= 0) { float num = (float)(elapsedMilliseconds - _lastTickStopwatchMs) / 1000f; float num2 = Math.Max(unscaledDeltaTime, num); if (num2 > 0.5f && !inPickPhase) { localFreezeCount++; localFreezeTotalSec += num2; bool flag = false; try { flag = Application.isFocused; } catch { } if (flag) { localFreezeFocusedCount++; } Plugin.Log.LogInfo((object)$"[FREEZE-DIAG] gap={num2:F2}s dt={unscaledDeltaTime:F2} wall={num:F2} focused={flag} n={localFreezeCount}"); } } _lastTickStopwatchMs = elapsedMilliseconds; if (unscaledDeltaTime <= 0f || unscaledDeltaTime > 1f) { return; } fpsFrameCount++; fpsTimeAccum += unscaledDeltaTime; fpsBroadcastTimer += unscaledDeltaTime; tlFrames++; tlAccum += unscaledDeltaTime; if (tlAccum >= 5f) { if (localFpsTimeline.Count < 90) { localFpsTimeline.Add((int)Math.Round((double)tlFrames / (double)tlAccum)); } tlFrames = 0; tlAccum = 0f; } bcFrames++; bcAccum += unscaledDeltaTime; if (fpsBroadcastTimer >= 3f) { fpsBroadcastTimer = 0f; BroadcastFps(); PollOpponentFps(); SampleConnectionQuality(); SampleOwnStatTimelines(); try { FfaMode.SampleTimelines(); } catch { } } TickInputSampling(unscaledDeltaTime); } private static void SampleConnectionQuality() { try { if (PhotonNetwork.OfflineMode || !PhotonNetwork.InRoom || !PhotonNetwork.IsConnected) { return; } int ping = PhotonNetwork.GetPing(); if (ping > 0 && pingSamples.Count < 200) { pingSamples.Add(ping); } LoadBalancingClient networkingClient = PhotonNetwork.NetworkingClient; LoadBalancingPeer val = ((networkingClient != null) ? networkingClient.LoadBalancingPeer : null); if (val != null) { int num = ((PhotonPeer)val).ConnectionTime - ((PhotonPeer)val).TimestampOfLastSocketReceive; if (num > 2000) { if (!_recvGapOpen) { _recvGapOpen = true; localRecvGapCount++; Plugin.Log.LogInfo((object)$"[LAG-DIAG] recv gap open silent={num}ms n={localRecvGapCount}"); } if (num > localRecvGapMaxMs) { localRecvGapMaxMs = num; } } else { _recvGapOpen = false; } } if (lastOppGstatsSeq < 0 || !(lastOppSeqAdvanceTime > 0f)) { return; } float num2 = Time.unscaledTime - lastOppSeqAdvanceTime; if (num2 > 8f) { if (!_oppHbGapOpen) { _oppHbGapOpen = true; oppHbGapCount++; Plugin.Log.LogInfo((object)$"[LAG-DIAG] opp heartbeat gap {num2:F1}s n={oppHbGapCount}"); } } else { _oppHbGapOpen = false; } } catch { } } private static void TickInputSampling(float dt) { if (!LocalAliveInCombatNow) { inputBucketTimer = 0f; inputBucketCount = 0; inputBucketKeyCount = 0; inputBucketClickCount = 0; inputBucketStartedAtMs = -1L; return; } bool flag = false; try { flag = CompetitiveUI.AnyChatTyping || NativeUI.IsOpen; } catch { } if (flag) { inputBucketTimer = 0f; inputBucketCount = 0; inputBucketKeyCount = 0; inputBucketClickCount = 0; inputBucketStartedAtMs = -1L; return; } LocalActiveSecondsThisMatch += dt; int num = 0; int num2 = 0; if (Input.GetKeyDown((KeyCode)119)) { num++; } if (Input.GetKeyDown((KeyCode)97)) { num++; } if (Input.GetKeyDown((KeyCode)115)) { num++; } if (Input.GetKeyDown((KeyCode)100)) { num++; } if (Input.GetKeyDown((KeyCode)32)) { num++; } if (Input.GetKeyDown((KeyCode)273)) { num++; } if (Input.GetKeyDown((KeyCode)274)) { num++; } if (Input.GetKeyDown((KeyCode)276)) { num++; } if (Input.GetKeyDown((KeyCode)275)) { num++; } if (Input.GetMouseButtonDown(0)) { num2++; LocalShotsThisMatch++; if (!achFiredShot) { achFiredShot = true; Plugin.Log.LogInfo((object)"[ACH] Player fired a shot"); } } if (Input.GetMouseButtonDown(1)) { num2++; LocalBlocksThisMatch++; } int num3 = num + num2; if (num3 > 0) { LocalKeysThisMatch += num3; } long elapsedMilliseconds = _tickStopwatch.ElapsedMilliseconds; if (inputBucketStartedAtMs < 0) { inputBucketStartedAtMs = elapsedMilliseconds; } inputBucketTimer = (float)(elapsedMilliseconds - inputBucketStartedAtMs) / 1000f; inputBucketCount += num3; inputBucketKeyCount += num; inputBucketClickCount += num2; if (!(inputBucketTimer >= 1f)) { return; } float num4 = Mathf.Max(0.001f, inputBucketTimer); int num5 = Mathf.RoundToInt((float)inputBucketKeyCount / num4); int num6 = Mathf.RoundToInt((float)inputBucketClickCount / num4); int num7 = Mathf.RoundToInt((float)inputBucketCount / num4); if (num5 > LocalMacroPeakKeysPerSecond) { LocalMacroPeakKeysPerSecond = num5; } if (num6 > LocalMacroPeakClicksPerSecond) { LocalMacroPeakClicksPerSecond = num6; } if (num7 > LocalMacroPeakEventsPerSecond) { LocalMacroPeakEventsPerSecond = num7; } if (num7 >= 25) { LocalMacroSuspectSeconds++; if (inputSuspectWindows.Count >= 48) { inputSuspectWindows.RemoveAt(0); } int num8 = Mathf.Max(0, Mathf.RoundToInt(LocalActiveSecondsThisMatch)); inputSuspectWindows.Add($"{num8}:{num5}:{num6}"); if (Time.realtimeSinceStartup - lastMacroLogAt > 10f) { lastMacroLogAt = Time.realtimeSinceStartup; Plugin.Log.LogWarning((object)$"[INPUT] macro-suspect second: {num7}/s gameplay events ({num5} keys/s, {num6} clicks/s; total suspect s: {LocalMacroSuspectSeconds})"); } BroadcastGstatsImmediate(); } inputBucketTimer = 0f; inputBucketCount = 0; inputBucketKeyCount = 0; inputBucketClickCount = 0; inputBucketStartedAtMs = elapsedMilliseconds; } private static string MacroTimelineForPeer() { int num = Math.Min(16, inputSuspectWindows.Count); if (num <= 0) { return ""; } int num2 = inputSuspectWindows.Count - num; StringBuilder stringBuilder = new StringBuilder(num * 12); for (int i = 0; i < num; i++) { if (i > 0) { stringBuilder.Append(','); } stringBuilder.Append(inputSuspectWindows[num2 + i]); } return stringBuilder.ToString(); } private static string BuildGstatsPayload(int recentFps, bool advanceSequence) { if (advanceSequence) { gstatsSeq++; } int num = 0; try { if (!PhotonNetwork.OfflineMode && PhotonNetwork.IsConnected) { num = PhotonNetwork.GetPing(); } } catch { } return string.Format("{0}|{1}|{2}|{3}|{4}|{5}", LocalBulletsFiredThisMatch, LocalBulletsHitThisMatch, LocalBlocksActivatedThisMatch, LocalBlocksSuccessfulThisMatch, LocalKeysThisMatch, LocalActiveSecondsThisMatch.ToString("F0", CultureInfo.InvariantCulture)) + $"|{recentFps}|{gstatsSeq}|{localFreezeCount}|{localFreezeFocusedCount}|{localRecvGapCount}|{num}|{(int)LocalDamageTakenThisMatch}" + $"|{LocalMacroSuspectSeconds}|{LocalMacroPeakKeysPerSecond}|{LocalMacroPeakClicksPerSecond}|{LocalMacroPeakEventsPerSecond}|{MacroTimelineForPeer()}"; } private static void BroadcastGstatsImmediate() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown try { if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) { Hashtable val = new Hashtable(); val[(object)"cr_gstats"] = BuildGstatsPayload(lastBroadcastRecentFps, advanceSequence: false); PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch { } } private static void BroadcastFps() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown try { if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) { Hashtable val = new Hashtable(); int localAvgFps = LocalAvgFps; if (localAvgFps > 0) { val[(object)"cr_fps"] = localAvgFps; } int num = ((bcAccum > 0.5f) ? ((int)Math.Round((double)bcFrames / (double)bcAccum)) : 0); bcFrames = 0; bcAccum = 0f; if (num > 0) { lastBroadcastRecentFps = num; } if (num > 0 && isTracking && localFps3sTimeline.Count < 128) { localFps3sTimeline.Add(num); } val[(object)"cr_gstats"] = BuildGstatsPayload(num, advanceSequence: true); if (((Dictionary)(object)val).Count > 0) { PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } } catch { } } private static void PollOpponentFps() { try { if (!PhotonNetwork.InRoom) { return; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null) { return; } bool flag = false; Player[] array = playerList; foreach (Player val in array) { if (val == null || val.IsLocal || val.CustomProperties == null) { continue; } bool flag2 = false; if (((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_gstats")) { flag2 = true; string text = (val.CustomProperties[(object)"cr_gstats"] as string) ?? ""; HarvestPeerTelemetry(val.ActorNumber, text); if (!flag) { try { string[] array2 = text.Split('|'); if (array2.Length >= 6) { OppStatBulletsFired = int.Parse(array2[0]); OppStatBulletsHit = int.Parse(array2[1]); OppStatBlocksActivated = int.Parse(array2[2]); OppStatBlocksSuccessful = int.Parse(array2[3]); OppStatKeysPressed = int.Parse(array2[4]); OppStatActiveSeconds = float.Parse(array2[5], CultureInfo.InvariantCulture); } if (array2.Length >= 18) { OppStatMacroSuspectSeconds = int.Parse(array2[13]); OppStatMacroPeakKeysPerSecond = int.Parse(array2[14]); OppStatMacroPeakClicksPerSecond = int.Parse(array2[15]); OppStatMacroPeakEventsPerSecond = int.Parse(array2[16]); OppStatMacroTimeline = array2[17] ?? ""; } if (array2.Length >= 11) { int num = int.Parse(array2[7]); if (num != lastOppGstatsSeq) { lastOppGstatsSeq = num; lastOppSeqAdvanceTime = Time.unscaledTime; int num2 = int.Parse(array2[6]); if (num2 > 0 && oppFpsTimeline.Count < 128) { oppFpsTimeline.Add(num2); } if (array2.Length >= 12) { int num3 = int.Parse(array2[11]); if (num3 > 0 && oppPingTimeline.Count < 128) { oppPingTimeline.Add(num3); } } if (int.TryParse(array2[0], out var result) && oppHitTimeline.Count > 0 && result < LastPairFirst(oppHitTimeline)) { oppHitTimeline.Clear(); oppBlockTimeline.Clear(); } if (oppHitTimeline.Count < 128) { oppHitTimeline.Add(array2[0] + ":" + array2[1]); } if (array2.Length >= 13 && oppBlockTimeline.Count < 128) { oppBlockTimeline.Add(array2[12] + ":" + array2[3]); } } oppFreezeCount = int.Parse(array2[8]); oppFreezeFocusedCount = int.Parse(array2[9]); oppRecvGapCount = int.Parse(array2[10]); } else if (array2.Length >= 6 && array2[0] == "0" && array2[1] == "0") { if (oppHitTimeline.Count > 0 || oppBlockTimeline.Count > 0) { oppHitTimeline.Clear(); oppBlockTimeline.Clear(); } OppStatMacroSuspectSeconds = 0; OppStatMacroPeakKeysPerSecond = 0; OppStatMacroPeakClicksPerSecond = 0; OppStatMacroPeakEventsPerSecond = 0; OppStatMacroTimeline = ""; } } catch { } } } if (((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_fps")) { flag2 = true; if (!flag) { try { opponentAvgFps = Convert.ToInt32(val.CustomProperties[(object)"cr_fps"]); } catch { } } } if (flag2) { flag = true; } } } catch { } } private static int LastPairFirst(List pairs) { if (pairs.Count == 0) { return -1; } string text = pairs[pairs.Count - 1]; int num = text.IndexOf(':'); if (num > 0 && int.TryParse(text.Substring(0, num), out var result)) { return result; } return -1; } private static void SampleOwnStatTimelines() { if (localHitTimeline.Count < 128) { localHitTimeline.Add(LocalBulletsFiredThisMatch + ":" + LocalBulletsHitThisMatch); } if (localBlockTimeline.Count < 128) { localBlockTimeline.Add((int)LocalDamageTakenThisMatch + ":" + LocalBlocksSuccessfulThisMatch); } } private static void HarvestPeerTelemetry(int actorNumber, string raw) { try { string[] array = raw.Split('|'); if (array.Length < 8) { if (array.Length >= 6 && array[0] == "0" && array[1] == "0") { peerTele.Remove(actorNumber); } return; } if (!peerTele.TryGetValue(actorNumber, out var value)) { value = new PeerTelemetry(); peerTele[actorNumber] = value; } value.lastRaw = raw; int num = int.Parse(array[7]); if (num == value.lastSeq) { return; } value.lastSeq = num; if (int.TryParse(array[0], out var result) && value.hit.Count > 0 && result < LastPairFirst(value.hit)) { value.fps.Clear(); value.ping.Clear(); value.hit.Clear(); value.block.Clear(); } int num2 = int.Parse(array[6]); if (num2 > 0 && value.fps.Count < 128) { value.fps.Add(num2); } if (array.Length >= 12) { int num3 = int.Parse(array[11]); if (num3 > 0 && value.ping.Count < 128) { value.ping.Add(num3); } } if (value.hit.Count < 128) { value.hit.Add(array[0] + ":" + array[1]); } if (array.Length >= 13 && value.block.Count < 128) { value.block.Add(array[12] + ":" + array[3]); } } catch { } } internal static bool TryGetPeerTelemetry(int actorNumber, out string fpsTl, out string pingTl, out string hitTl, out string blockTl, out int[] counters) { fpsTl = (pingTl = (hitTl = (blockTl = null))); counters = null; if (!peerTele.TryGetValue(actorNumber, out var value) || string.IsNullOrEmpty(value.lastRaw)) { return false; } try { string[] array = value.lastRaw.Split('|'); if (array.Length < 6) { return false; } fpsTl = string.Join(",", value.fps); pingTl = string.Join(",", value.ping); hitTl = string.Join(",", value.hit); blockTl = string.Join(",", value.block); counters = new int[6] { int.Parse(array[0]), int.Parse(array[1]), int.Parse(array[2]), int.Parse(array[3]), int.Parse(array[4]), (int)float.Parse(array[5], CultureInfo.InvariantCulture) }; return true; } catch { return false; } } private static bool TimelineAppend(int p1r, int p1p, int p2r, int p2p) { if (matchPointTimeline.Count >= 64) { return false; } if (p1p >= 2) { p1p = 0; } if (p2p >= 2) { p2p = 0; } string text = $"{p1r * 2 + p1p}:{p2r * 2 + p2p}"; if (matchPointTimeline.Count > 0 && matchPointTimeline[matchPointTimeline.Count - 1] == text) { return false; } matchPointTimeline.Add(text); return true; } private static void StampPointTime() { if (pointTimes.Count < 64) { int item = 0; try { item = (int)Math.Max(0.0, (DateTime.UtcNow - matchStartTime).TotalSeconds); } catch { } pointTimes.Add(item); } } public static void DismissMatchFoundStuckOverlay() { _stuckOverlayDismissedAt = DateTime.UtcNow; ShouldShowMatchFoundStuckOverlay = false; } private static void PollRoomState() { //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Expected O, but got Unknown //IL_0c30: Unknown result type (might be due to invalid IL or missing references) //IL_0cd1: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0857: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_09b2: Unknown result type (might be due to invalid IL or missing references) //IL_1148: Unknown result type (might be due to invalid IL or missing references) bool inRoom = PhotonNetwork.InRoom; if (inRoom && !_runInBackgroundOverridden) { try { _origRunInBackground = Application.runInBackground; Application.runInBackground = true; _runInBackgroundOverridden = true; Plugin.Log.LogInfo((object)$"[FOCUS] In Photon room — Application.runInBackground forced true (was {_origRunInBackground})"); } catch { } } else if (!inRoom && _runInBackgroundOverridden) { try { Application.runInBackground = _origRunInBackground; _runInBackgroundOverridden = false; Plugin.Log.LogInfo((object)$"[FOCUS] Left Photon room — runInBackground restored to {_origRunInBackground}"); } catch { } } if (inRoom && !isTracking && !inPickPhase) { int num = (SecondsInUnstartedRoom = (int)(DateTime.UtcNow - roomJoinTime).TotalSeconds); bool flag = false; bool flag2 = false; try { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = ((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null); Room currentRoom2 = PhotonNetwork.CurrentRoom; string text = ((currentRoom2 != null) ? currentRoom2.Name : null) ?? ""; flag = (val != null && ((Dictionary)(object)val).ContainsKey((object)"cr_ff")) || text.StartsWith("ranked_") || text.StartsWith("team_") || text.StartsWith("sct-") || text.StartsWith("ovt_") || FfaMode.EngineActive(); PlayerManager instance = PlayerManager.instance; flag2 = (Object)(object)instance != (Object)null && instance.players != null && instance.players.Count >= 1; } catch { } bool flag3 = false; try { flag3 = PhotonNetwork.OfflineMode; } catch { } bool flag4 = (DateTime.UtcNow - _stuckOverlayDismissedAt).TotalSeconds > 60.0; ShouldShowMatchFoundStuckOverlay = !flag && !flag3 && !flag2 && num >= 25 && flag4; } else { SecondsInUnstartedRoom = 0; ShouldShowMatchFoundStuckOverlay = false; } if (inRoom && !wasInRoom) { Room currentRoom3 = PhotonNetwork.CurrentRoom; photonRoomId = ((currentRoom3 != null) ? currentRoom3.Name : null) ?? ""; photonRegion = PhotonNetwork.CloudRegion ?? ""; roomJoinTime = DateTime.UtcNow; try { string text2 = Plugin.PendingRankedRoom ?? ""; bool flag5 = !string.IsNullOrEmpty(text2) && string.Equals(photonRoomId, text2, StringComparison.Ordinal); Room currentRoom4 = PhotonNetwork.CurrentRoom; Hashtable val2 = ((currentRoom4 != null) ? ((RoomInfo)currentRoom4).CustomProperties : null); bool flag6 = photonRoomId.StartsWith("ranked_") || photonRoomId.StartsWith("sct-") || photonRoomId.StartsWith("ovt_") || photonRoomId.StartsWith("ffa_") || photonRoomId.StartsWith("team_") || (((Dictionary)(object)val2)?.ContainsKey((object)"cr_ff") ?? false); if (!PhotonNetwork.OfflineMode && flag6 && ApiClient.CurrentQueueState == ApiClient.QueueState.Searching && !flag5) { ApiClient.LeaveQueue(LocalSteamId); CompetitiveUI.ShowNotification("Left 1v1 queue - you joined a game", Color.yellow); Plugin.Log.LogInfo((object)("[QUEUE] Left 1v1 queue after joining online room '" + photonRoomId + "'")); } else if (!PhotonNetwork.OfflineMode && flag6 && (ApiClient.CurrentQueueState == ApiClient.QueueState.Matched || ApiClient.CurrentQueueState == ApiClient.QueueState.ReadySent) && !flag5) { ApiClient.DeclineMatch(LocalSteamId); CompetitiveUI.ShowNotification("Declined 1v1 match - you joined a game", Color.yellow); Plugin.Log.LogInfo((object)("[QUEUE] Auto-declined pre-room 1v1 match after joining online room '" + photonRoomId + "'")); } if (!PhotonNetwork.OfflineMode && flag6 && !string.IsNullOrEmpty(ApiClient.OpenFfaLobbyId)) { Plugin.Log.LogInfo((object)("[FFA-LOBBY] joined competitive room '" + photonRoomId + "' while in an open lobby — leaving the lobby")); try { ApiClient.FfaLeaveQueue(); } catch { } CompetitiveUI.ShowNotification("Left your FFA lobby - you joined a competitive game", Color.yellow); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[QUEUE] Failed to leave 1v1 queue on room join: " + ex.Message)); } IdentifyLocalPlayer(); try { Room currentRoom5 = PhotonNetwork.CurrentRoom; Hashtable val3 = ((currentRoom5 != null) ? ((RoomInfo)currentRoom5).CustomProperties : null); if (val3 != null && ((Dictionary)(object)val3).ContainsKey((object)"cr_game_token")) { string text3 = val3[(object)"cr_game_token"]?.ToString() ?? ""; int num3 = text3.IndexOf(':'); string input = ((num3 > 0) ? text3.Substring(0, num3) : text3); if (Regex.IsMatch(input, "^\\d{6}$")) { previousGameToken = input; } } if (PhotonNetwork.LocalPlayer != null) { Hashtable val4 = new Hashtable(); val4[(object)"cr_game_token_v"] = photonRoomId + ":" + PhotonNetwork.LocalPlayer.ActorNumber.ToString(CultureInfo.InvariantCulture); PhotonNetwork.LocalPlayer.SetCustomProperties(val4, (Hashtable)null, (WebFlags)null); } } catch { } playersIdentified = false; opponentSteamIdResolved = false; opponentRankChecked = false; opponentIsRanked = false; matchIsRanked = false; casualDowngradeNotified = false; try { Room currentRoom6 = PhotonNetwork.CurrentRoom; Hashtable val5 = ((currentRoom6 != null) ? ((RoomInfo)currentRoom6).CustomProperties : null); Room currentRoom7 = PhotonNetwork.CurrentRoom; string text4 = ((currentRoom7 != null) ? currentRoom7.Name : null) ?? ""; if ((val5 != null && ((Dictionary)(object)val5).ContainsKey((object)"cr_ff")) || text4.StartsWith("ranked_") || text4.StartsWith("team_") || text4.StartsWith("sct-") || text4.StartsWith("ovt_") || FfaMode.EngineActive()) { matchIsRanked = true; opponentIsRanked = true; Plugin.Log.LogInfo((object)("[POLL] mod-issued competitive room detected (" + text4 + ") — matchIsRanked forced true")); } } catch { } seriesPreflightSent = false; lastOpponentRankCheck = -999f; rankedRoomStallHandled = false; rankedRoomStallWarned = false; rankedRoomEverFull = false; currentSeriesGamesWon = 0; currentSeriesGamesLost = 0; ovtSoloWins = 0; ovtDuoWins = 0; Plugin.Log.LogInfo((object)("[POLL] Joined room: " + photonRoomId + " (region: " + photonRegion + ")")); try { NametagStyler.PublishToPhoton(); } catch { } try { PlayerColorCosmetic.PublishLocalProps(); } catch { } try { TrailCosmetic.PublishLocalProps(); } catch { } try { PlayerEffectCosmetic.PublishLocalProps(); } catch { } } if (inRoom && isTracking && oneVOneMatchAtStart) { TryRefreshSharedGameToken(); } if (!inRoom && wasInRoom) { AccumulateSessionTime(); if (isTracking && !gameOverReported) { int num4 = ((localTeamId == 0) ? p1Rounds : p2Rounds); int num5 = ((localTeamId == 0) ? p2Rounds : p1Rounds); string arg = (matchIsRanked ? "RANKED" : "CASUAL"); if (num5 >= 4 && num5 > num4) { TryDispatchMacroEvidence(); } else if (!opponentDCReported && num4 >= 4 && num5 >= 4) { int reportP1Rounds = p1Rounds; int reportP2Rounds = p2Rounds; if (localTeamId == 0) { reportP2Rounds = 5; } else if (localTeamId == 1) { reportP1Rounds = 5; } TryDispatchMacroEvidence(null, reportP1Rounds, reportP2Rounds); } if (LeavingForRanked) { Plugin.Log.LogInfo((object)$"[POLL] === {arg} Canceled === Left for ranked queue at {num4}-{num5} (not counted)"); CompetitiveUI.ShowNotification("Left match for ranked queue", new Color(0.4f, 0.8f, 1f)); LeavingForRanked = false; } else if (opponentDCReported && num4 >= 4 && num5 >= 4) { Plugin.Log.LogInfo((object)$"[POLL] === {arg} DC Win (4-4 tiebreak) === Opponent DC'd at {num4}-{num5}"); int num6 = localTeamId; switch (num6) { case 0: p1Rounds = 5; break; case 1: p2Rounds = 5; break; } OnGameOver(num6); } else if (opponentDCReported && num4 >= 4) { Plugin.Log.LogInfo((object)$"[POLL] === {arg} DC Win === Opponent disconnected at {num4}-{num5}"); int winnerTeam = localTeamId; OnGameOver(winnerTeam); } else { if (num5 >= 4) { Plugin.Log.LogInfo((object)$"[POLL] === {arg} Canceled === Opp DC'd while ahead at {num4}-{num5} (no win awarded)"); } else { Plugin.Log.LogInfo((object)$"[POLL] === {arg} Canceled === Disconnect at {num4}-{num5} (not counted)"); } CompetitiveUI.ShowNotification("Match canceled (DC)", new Color(1f, 0.7f, 0.3f)); } } Plugin.Log.LogInfo((object)"[POLL] Left room"); ApiClient.ActiveRankedSeriesId = null; if ((photonRoomId ?? "").StartsWith("ovt_")) { ApiClient.ActiveOvt1v2SeriesId = null; try { Plugin.ClearPendingOvtSlot(); } catch { } } if ((photonRoomId ?? "").StartsWith("ffa_")) { try { ApiClient.FfaLeaveQueue(); } catch { } try { Plugin.ClearPendingFfaSlot(); } catch { } try { FfaMode.OnRoomLeft(); } catch { } } LeavingForRanked = false; PerfGate.DumpAndReset(); ResetMatchState(); } if (inRoom && !opponentSteamIdResolved) { TryResolveOpponent(); } if (inRoom && !rankedRoomStallHandled && (photonRoomId.StartsWith("ranked_") || photonRoomId.StartsWith("sct-") || photonRoomId.StartsWith("ovt_") || photonRoomId.StartsWith("ffa_"))) { bool flag7 = photonRoomId.StartsWith("sct-"); bool flag8 = photonRoomId.StartsWith("ovt_"); bool flag9 = FfaMode.EngineActive(); double num7 = (flag7 ? 360 : (flag9 ? 120 : (flag8 ? 90 : 60))); double num8 = (flag7 ? 90 : (flag9 ? 45 : (flag8 ? 35 : 25))); int num9 = (flag9 ? Diag2v2.PlayersNeeded() : (flag8 ? 3 : 2)); int num10 = 0; try { Room currentRoom8 = PhotonNetwork.CurrentRoom; num10 = ((currentRoom8 != null) ? currentRoom8.PlayerCount : 0); } catch { } if (num10 >= num9) { rankedRoomEverFull = true; } if (!rankedRoomEverFull && !isTracking) { double totalSeconds = (DateTime.UtcNow - roomJoinTime).TotalSeconds; if (!rankedRoomStallWarned && totalSeconds >= num8) { rankedRoomStallWarned = true; CompetitiveUI.ShowNotification(flag7 ? "Opponent hasn't connected yet — they have a few minutes of grace. Hang tight..." : (flag8 ? "Waiting for all 3 players to connect — hang tight..." : (flag9 ? $"Waiting for all {num9} players to connect — hang tight..." : "Opponent hasn't connected yet — hang tight...")), new Color(1f, 0.8f, 0.3f), 6f); } if (totalSeconds >= num7) { rankedRoomStallHandled = true; Plugin.Log.LogWarning((object)$"[QUEUE-STALL] Room {photonRoomId} never filled ({num10}/{num9}) after {(int)totalSeconds}s — returning to menu (no match started, no penalty)"); CompetitiveUI.ShowNotification(flag7 ? "Opponent never showed — their no-show forfeit should be recorded. Returning to menu." : (flag8 ? "1v2 lobby never filled — returning to menu. Requeue when ready." : (flag9 ? "FFA lobby never filled — returning to menu. Requeue when ready." : "Opponent failed to join — returning to menu. Requeue when ready.")), new Color(1f, 0.5f, 0.4f), 10f); if (flag8) { try { ApiClient.OvtLeaveQueue(); } catch { } } if (flag9) { try { ApiClient.FfaLeaveQueue(); } catch { } } try { NetworkConnectionHandler.instance.NetworkRestart(); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[QUEUE-STALL] NetworkRestart failed: " + ex2.Message)); } } } } if (inRoom && !seriesPreflightSent && opponentSteamIdResolved && !string.IsNullOrEmpty(opponentSteamId) && !opponentSteamId.StartsWith("photon_") && OpponentHasMod()) { ConfigEntry rankedEnabled = Plugin.RankedEnabled; if (rankedEnabled != null && rankedEnabled.Value && string.IsNullOrEmpty(ApiClient.ActiveRankedSeriesId) && !string.IsNullOrEmpty(localSteamId)) { bool flag10 = false; try { Room currentRoom9 = PhotonNetwork.CurrentRoom; flag10 = ((Dictionary)(object)((currentRoom9 != null) ? ((RoomInfo)currentRoom9).CustomProperties : null))?.ContainsKey((object)"cr_ff") ?? false; } catch { } string text5 = ""; try { Room currentRoom10 = PhotonNetwork.CurrentRoom; text5 = ((currentRoom10 != null) ? currentRoom10.Name : null) ?? ""; } catch { } if (!flag10 && !text5.StartsWith("team_") && !text5.StartsWith("ovt_") && !FfaMode.EngineActive()) { seriesPreflightSent = true; Plugin.Log.LogInfo((object)("[POLL] Eager preflight: opponent " + opponentSteamId + " has mod props — firing /series/preflight before /mod/check completes")); ApiClient.SendSeriesPreflight(localSteamId, opponentSteamId); } } } bool flag11 = false; try { Room currentRoom11 = PhotonNetwork.CurrentRoom; string text6 = ((currentRoom11 != null) ? currentRoom11.Name : null) ?? ""; Room currentRoom12 = PhotonNetwork.CurrentRoom; Hashtable val6 = ((currentRoom12 != null) ? ((RoomInfo)currentRoom12).CustomProperties : null); flag11 = text6.StartsWith("team_") || text6.StartsWith("ovt_") || FfaMode.EngineActive() || (((Dictionary)(object)val6)?.ContainsKey((object)"cr_ff") ?? false); } catch { } if (inRoom && !flag11 && opponentSteamIdResolved && !opponentSteamId.StartsWith("photon_")) { bool firstCheck = !opponentRankChecked; bool shouldRetry = !firstCheck && !opponentIsRanked && OpponentHasMod() && Time.realtimeSinceStartup - lastOpponentRankCheck >= 5f; if (firstCheck || shouldRetry) { opponentRankChecked = true; lastOpponentRankCheck = Time.realtimeSinceStartup; ApiClient.CheckOpponentRanked(opponentSteamId, delegate(bool isRanked) { bool flag13 = opponentIsRanked; opponentIsRanked = isRanked; bool flag14 = false; try { Room currentRoom14 = PhotonNetwork.CurrentRoom; flag14 = ((Dictionary)(object)((currentRoom14 != null) ? ((RoomInfo)currentRoom14).CustomProperties : null))?.ContainsKey((object)"cr_ff") ?? false; } catch { } if (flag14) { matchIsRanked = true; } else { matchIsRanked = Plugin.RankedEnabled.Value && opponentIsRanked && OpponentHasMod(); } if (flag13 != opponentIsRanked || firstCheck) { Plugin.Log.LogInfo((object)string.Format("[POLL] Opponent ranked: {0}, hasMod: {1}, Match ranked: {2}{3}", opponentIsRanked, OpponentHasMod(), matchIsRanked, shouldRetry ? " (retry)" : "")); } bool flag15 = false; try { Room currentRoom15 = PhotonNetwork.CurrentRoom; flag15 = (((currentRoom15 != null) ? currentRoom15.Name : null) ?? "").StartsWith("ovt_"); } catch { } if (matchIsRanked && !flag14 && !flag15 && !seriesPreflightSent && string.IsNullOrEmpty(ApiClient.ActiveRankedSeriesId) && !string.IsNullOrEmpty(localSteamId) && !string.IsNullOrEmpty(opponentSteamId) && !opponentSteamId.StartsWith("photon_")) { seriesPreflightSent = true; ApiClient.SendSeriesPreflight(localSteamId, opponentSteamId); } }); } } if (inRoom && isTracking && !gameOverReported) { try { Room currentRoom13 = PhotonNetwork.CurrentRoom; string text7 = ((currentRoom13 != null) ? currentRoom13.Name : null) ?? ""; if (text7.StartsWith("team_") || text7.StartsWith("ovt_") || FfaMode.EngineActive()) { wasInRoom = inRoom; return; } Player[] playerList = PhotonNetwork.PlayerList; int num11 = ((playerList != null) ? playerList.Length : 0); if (num11 >= 2) { opponentWasPresent = true; } if (num11 >= 2 && opponentDCReported) { opponentDCReported = false; Plugin.Log.LogInfo((object)"[POLL] Opponent returned to the room — cleared stale DC latch"); } if (opponentWasPresent && num11 <= 1 && !opponentDCReported) { opponentDCReported = true; int num12 = ((localTeamId == 0) ? p1Rounds : p2Rounds); int num13 = ((localTeamId == 0) ? p2Rounds : p1Rounds); int num14 = p1Points + p2Points; int num15 = p1Rounds + p2Rounds; try { string arg2 = (string.IsNullOrEmpty(opponentDisplayName) ? "Opponent" : opponentDisplayName); string text8 = ((num12 >= 4) ? $"{arg2} disconnected at {num12}-{num13} — leave to the menu, you get the win" : $"{arg2} disconnected at {num12}-{num13} — leave to the menu, game won't be counted"); CompetitiveUI.ShowNotification(text8, new Color(1f, 0.65f, 0.2f), 10f); } catch { } bool flag12 = num14 >= 2 || num15 >= 1; if (matchIsRanked && flag12 && num12 < 4 && num13 < 4 && opponentSteamIdResolved && !opponentSteamId.StartsWith("photon_")) { Plugin.Log.LogInfo((object)$"[DC] Opponent {opponentDisplayName} disconnected at game-rounds={num12}-{num13}, pts={num14}, series-games={num15} — reporting leave"); ApiClient.ReportDisconnect(localSteamId, opponentSteamId); } else { Plugin.Log.LogInfo((object)$"[DC] Opponent left (ranked={matchIsRanked}, pts={num14}, series-games={num15}, rounds={num12}-{num13}) — not eligible for leave tracking"); } } } catch { } } wasInRoom = inRoom; } public static void NotifyPlayerLeftRoom(Player p) { try { if (p == null || PhotonNetwork.OfflineMode) { return; } Room currentRoom = PhotonNetwork.CurrentRoom; string text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; bool flag = text.StartsWith("ovt_"); int num; if (!flag && !text.StartsWith("team_")) { Room currentRoom2 = PhotonNetwork.CurrentRoom; num = ((((currentRoom2 == null) ? ((bool?)null) : ((Dictionary)(object)((RoomInfo)currentRoom2).CustomProperties)?.ContainsKey((object)"cr_ff")) == true) ? 1 : 0); } else { num = 1; } bool flag2 = (byte)num != 0; bool flag3 = !flag && CurrentSeriesGamesWon + CurrentSeriesGamesLost >= 1 && CurrentSeriesGamesWon < 2 && CurrentSeriesGamesLost < 2; bool flag4 = flag && !string.IsNullOrEmpty(ApiClient.ActiveOvt1v2SeriesId) && ovtSoloWins + ovtDuoWins >= 1 && ovtSoloWins < 2 && ovtDuoWins < 2; bool flag5 = isTracking && !gameOverReported; if (!flag5 && !flag3 && !flag4) { return; } string text2 = ""; try { text2 = StripRichText(p.NickName ?? ""); } catch { } if (string.IsNullOrEmpty(text2)) { string text3 = null; if (p.CustomProperties != null && ((Dictionary)(object)p.CustomProperties).ContainsKey((object)"u_id")) { text3 = p.CustomProperties[(object)"u_id"]?.ToString(); } if (!string.IsNullOrEmpty(text3) && text3 == opponentSteamId && !string.IsNullOrEmpty(opponentDisplayName)) { text2 = opponentDisplayName; } } if (string.IsNullOrEmpty(text2)) { text2 = "A player"; } if (text2.Length > 24) { text2 = text2.Substring(0, 24); } bool flag6 = false; try { Player localPlayer = PhotonNetwork.LocalPlayer; Hashtable val = ((localPlayer != null) ? localPlayer.CustomProperties : null); if (p.CustomProperties != null && val != null && ((Dictionary)(object)p.CustomProperties).ContainsKey((object)"t_id") && ((Dictionary)(object)val).ContainsKey((object)"t_id")) { flag6 = p.CustomProperties[(object)"t_id"]?.ToString() == val[(object)"t_id"]?.ToString(); } } catch { } bool flag7 = false; try { flag7 = p.CustomProperties != null && ((Dictionary)(object)p.CustomProperties).ContainsKey((object)"cr_lv_rk") && p.CustomProperties[(object)"cr_lv_rk"]?.ToString() == "1"; } catch { } string text4 = (flag6 ? ("Your teammate " + text2 + "") : ("" + text2 + "")); string text5; bool red; if (flag7) { text5 = text4 + " left to join a ranked match"; red = false; } else if (flag5) { if (text.StartsWith("ffa_")) { try { string text6 = null; if (p.CustomProperties != null && ((Dictionary)(object)p.CustomProperties).ContainsKey((object)"u_id")) { text6 = p.CustomProperties[(object)"u_id"]?.ToString(); } int result = -1; if (p.CustomProperties != null && ((Dictionary)(object)p.CustomProperties).ContainsKey((object)"t_id")) { int.TryParse(p.CustomProperties[(object)"t_id"]?.ToString(), out result); } if (!string.IsNullOrEmpty(text6) && result >= 0) { FfaMode.RecordLeaver(text6, text2, result); } } catch { } Room currentRoom3 = PhotonNetwork.CurrentRoom; int num2 = ((currentRoom3 != null) ? currentRoom3.PlayerCount : 0); text5 = ((num2 >= 3) ? (text4 + " left the FFA — the game continues") : (text4 + " disconnected or quit mid-game")); red = num2 < 3; } else { text5 = text4 + " disconnected or quit mid-game"; red = true; } } else if (flag4) { text5 = text4 + " left — 1v2 series unfinished"; red = false; } else { if (!flag2) { string text7 = null; if (p.CustomProperties != null && ((Dictionary)(object)p.CustomProperties).ContainsKey((object)"u_id")) { text7 = p.CustomProperties[(object)"u_id"]?.ToString(); } if ((string.IsNullOrEmpty(text7) || !(text7 == opponentSteamId)) && (string.IsNullOrEmpty(opponentDisplayName) || !(text2 == StripRichText(opponentDisplayName)))) { return; } } text5 = $"{text4} left — series unfinished ({CurrentSeriesGamesWon}-{CurrentSeriesGamesLost})"; red = false; } Plugin.Log.LogInfo((object)string.Format("[LEAVER-BANNER] {0} (midGame={1} series={2} teammate={3})", text5.Replace("", "").Replace("", ""), flag5, flag3, flag6)); CompetitiveUI.ShowLeaverBanner(text5, red); } catch { } } private static void AccumulateSessionTime() { if (!string.IsNullOrEmpty(opponentDisplayName) && opponentDisplayName != "Opponent") { float num = (float)(DateTime.UtcNow - roomJoinTime).TotalMinutes; if (sessionTimeByOpponent.ContainsKey(opponentDisplayName)) { sessionTimeByOpponent[opponentDisplayName] += num; } else { sessionTimeByOpponent[opponentDisplayName] = num; } roomJoinTime = DateTime.UtcNow; } } private static void TryResolveOpponent() { try { Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null) { return; } Player[] array = playerList; foreach (Player val in array) { if (val == null || val.IsLocal) { continue; } opponentDisplayName = StripRichText(val.NickName ?? "Opponent"); Hashtable customProperties = val.CustomProperties; if (customProperties != null && ((Dictionary)(object)customProperties).Count > 0) { if (((Dictionary)(object)customProperties).ContainsKey((object)"u_id")) { opponentSteamId = customProperties[(object)"u_id"].ToString(); opponentSteamIdResolved = true; Plugin.Log.LogInfo((object)("[POLL] Opponent: " + opponentDisplayName + " (Steam: " + opponentSteamId + ")")); break; } if (((Dictionary)(object)customProperties).ContainsKey((object)"unity_id")) { opponentSteamId = customProperties[(object)"unity_id"].ToString(); opponentSteamIdResolved = true; Plugin.Log.LogInfo((object)("[POLL] Opponent: " + opponentDisplayName + " (Steam: " + opponentSteamId + ")")); break; } } if (!playersIdentified) { playersIdentified = true; opponentSteamId = $"photon_{val.ActorNumber}"; Plugin.Log.LogInfo((object)("[POLL] Opponent found: " + opponentDisplayName + " (waiting for Steam ID...)")); } break; } } catch { } } public static void EnsureIdentityResolved() { if (string.IsNullOrEmpty(localSteamId) || !(localSteamId != "unknown")) { IdentifyLocalPlayer(); } } private static void IdentifyLocalPlayer() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) try { CSteamID steamID = SteamUser.GetSteamID(); if (steamID.m_SteamID != 0) { localSteamId = steamID.m_SteamID.ToString(); string name = StripRichText(SteamFriends.GetPersonaName() ?? ""); if (!IsPlaceholderName(name, localSteamId)) { localDisplayName = name; } MaybeSyncRankedStateOnce(); return; } } catch { } try { Player localPlayer = PhotonNetwork.LocalPlayer; localSteamId = ((localPlayer != null) ? localPlayer.UserId : null) ?? "unknown"; Player localPlayer2 = PhotonNetwork.LocalPlayer; localDisplayName = StripRichText(((localPlayer2 != null) ? localPlayer2.NickName : null) ?? "Unknown"); MaybeSyncRankedStateOnce(); } catch { localSteamId = "unknown"; localDisplayName = "Unknown"; } } internal static bool IsPlaceholderName(string name, string steamId) { string text = (name ?? "").Trim(); if (text.Length == 0) { return true; } if (text == (steamId ?? "").Trim()) { return true; } if (text.Length == 17 && text.StartsWith("7656119")) { bool flag = true; string text2 = text; foreach (char c in text2) { if (c < '0' || c > '9') { flag = false; break; } } if (flag) { return true; } } return false; } private static void MaybeSyncRankedStateOnce() { if (_rankedSyncSent || string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown" || (IsPlaceholderName(localDisplayName, localSteamId) && Time.realtimeSinceStartup < 30f)) { return; } try { bool flag = Plugin.RankedEnabled != null && Plugin.RankedEnabled.Value; ApiClient.ToggleRanked(localSteamId, flag, 1, localDisplayName); _rankedSyncSent = true; Plugin.Log.LogInfo((object)$"[POLL] Initial ranked state synced to server: enabled={flag}"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POLL] Initial ranked sync failed: " + ex.Message)); } } private static void DetermineLocalTeam() { try { Player localPlayer = PhotonNetwork.LocalPlayer; Hashtable val = ((localPlayer != null) ? localPlayer.CustomProperties : null); if (val != null && ((Dictionary)(object)val).ContainsKey((object)"t_id")) { localTeamId = Convert.ToInt32(val[(object)"t_id"]); Plugin.Log.LogInfo((object)$"[POLL] Local team: {localTeamId} (from Photon t_id)"); CardChoiceEndPickPatch.FlushPendingPicks(localTeamId); return; } } catch { } try { PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null) { return; } foreach (Player player in instance.players) { if ((Object)(object)player == (Object)null) { continue; } PhotonView component = ((Component)player).GetComponent(); if (!((Object)(object)component != (Object)null) || !component.IsMine) { continue; } CharacterData component2 = ((Component)player).GetComponent(); if ((Object)(object)component2 != (Object)null) { FieldInfo field = typeof(CharacterData).GetField("teamID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { localTeamId = (int)field.GetValue(component2); Plugin.Log.LogInfo((object)$"[POLL] Local team: {localTeamId} (from CharacterData)"); CardChoiceEndPickPatch.FlushPendingPicks(localTeamId); break; } } for (int i = 0; i < instance.players.Count; i++) { Player obj2 = instance.players[i]; PhotonView val2 = ((obj2 != null) ? ((Component)obj2).GetComponent() : null); if ((Object)(object)val2 != (Object)null && val2.IsMine) { localTeamId = i; Plugin.Log.LogInfo((object)$"[POLL] Local team: {localTeamId} (from index)"); CardChoiceEndPickPatch.FlushPendingPicks(localTeamId); return; } } } } catch (Exception ex) { Plugin.Log.LogError((object)("[POLL] Team detection error: " + ex.Message)); } } private static void PollMatchState() { if (!PhotonNetwork.InRoom) { return; } GM_ArmsRace instance = GM_ArmsRace.instance; if ((Object)(object)instance == (Object)null) { return; } if (!fieldsResolved) { ResolveFields(instance); if (!fieldsResolved) { return; } } if (!pcolorRoomApplied) { try { PlayerManager instance2 = PlayerManager.instance; int num = (((Object)(object)instance2 != (Object)null && instance2.players != null) ? instance2.players.Count : 0); if (num >= 2) { pcolorRoomApplied = true; PlayerColorCosmetic.OnMatchStart(); try { TrailCosmetic.OnMatchStart(); } catch { } try { PlayerEffectCosmetic.OnMatchStart(); } catch { } } } catch { } } int fieldInt = GetFieldInt(instance, f_p1Points); int fieldInt2 = GetFieldInt(instance, f_p2Points); int fieldInt3 = GetFieldInt(instance, f_p1Rounds); int fieldInt4 = GetFieldInt(instance, f_p2Rounds); bool flag = fieldInt3 > 0 || fieldInt4 > 0 || fieldInt > 0 || fieldInt2 > 0; if (flag && !wasGameInProgress && !isTracking) { OnMatchStarted(); } if (isTracking) { if (fieldInt != lastP1Points || fieldInt2 != lastP2Points) { p1Points = fieldInt; p2Points = fieldInt2; if (TimelineAppend(fieldInt3, fieldInt, fieldInt4, fieldInt2)) { StampPointTime(); } if (matchIsRanked && fieldInt3 == 0 && fieldInt4 == 0 && !string.IsNullOrEmpty(ApiClient.ActiveRankedSeriesId) && !string.IsNullOrEmpty(LocalSteamId)) { ApiClient.PostLivePoints(ApiClient.ActiveRankedSeriesId, LocalSteamId, fieldInt, fieldInt2); } } if (fieldInt3 != lastP1Rounds || fieldInt4 != lastP2Rounds) { p1Rounds = fieldInt3; p2Rounds = fieldInt4; currentRound = p1Rounds + p2Rounds + 1; if (TimelineAppend(fieldInt3, fieldInt, fieldInt4, fieldInt2)) { StampPointTime(); } if (abyssalActivatedThisRound) { abyssalRoundsActivated++; abyssalActivatedThisRound = false; } if (fieldInt3 > lastP1Rounds) { Plugin.Log.LogInfo((object)$"[POLL] Round: P1! Rounds: {p1Rounds}-{p2Rounds}"); } if (fieldInt4 > lastP2Rounds) { Plugin.Log.LogInfo((object)$"[POLL] Round: P2! Rounds: {p1Rounds}-{p2Rounds}"); } try { PlayerColorCosmetic.OnRoundStart(); } catch { } try { PlayerEffectCosmetic.OnRoundStart(); } catch { } int num2 = ((localTeamId == 0) ? p1Rounds : p2Rounds); int num3 = ((localTeamId == 0) ? p2Rounds : p1Rounds); if (num3 > achMaxOpponentRounds) { achMaxOpponentRounds = num3; } if (num2 == 0 && num3 >= 4) { achWasDown04 = true; } if (!gameOverReported && (fieldInt3 >= roundsToWin || fieldInt4 >= roundsToWin)) { int winnerTeam = ((fieldInt3 <= fieldInt4) ? 1 : 0); OnGameOver(winnerTeam); } } PollCardPicks(); PollAchievementState(); } lastP1Points = fieldInt; lastP2Points = fieldInt2; lastP1Rounds = fieldInt3; lastP2Rounds = fieldInt4; wasGameInProgress = flag; } private static bool BothPlayersSupportSharedGameToken() { try { Player[] playerList = PhotonNetwork.PlayerList; Room currentRoom = PhotonNetwork.CurrentRoom; string text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; if (playerList == null || playerList.Length != 2 || string.IsNullOrEmpty(text)) { return false; } Player[] array = playerList; foreach (Player val in array) { if (val == null || val.CustomProperties == null) { return false; } string text2 = text + ":" + val.ActorNumber.ToString(CultureInfo.InvariantCulture); if (!((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_game_token_v") || (val.CustomProperties[(object)"cr_game_token_v"]?.ToString() ?? "") != text2) { return false; } } return true; } catch { return false; } } private static void TryPublishSharedGameToken() { //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown if (!oneVOneMatchAtStart || !string.IsNullOrEmpty(sharedGameToken) || matchStartServerTimestamp == 0 || !BothPlayersSupportSharedGameToken()) { return; } try { if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null) { string text = ""; Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (customProperties != null && ((Dictionary)(object)customProperties).ContainsKey((object)"cr_game_token")) { string text2 = customProperties[(object)"cr_game_token"]?.ToString() ?? ""; int num = text2.IndexOf(':'); text = ((num > 0) ? text2.Substring(0, num) : text2); } string text3; do { uint num2 = BitConverter.ToUInt32(Guid.NewGuid().ToByteArray(), 0); text3 = (num2 % 1000000).ToString("D6", CultureInfo.InvariantCulture); } while (text3 == text || text3 == previousGameToken); Hashtable val = new Hashtable(); val[(object)"cr_game_token"] = text3 + ":" + matchStartServerTimestamp.ToString(CultureInfo.InvariantCulture); if (PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null)) { sharedGameToken = text3; } } } catch { } } private static void BeginSharedGameToken() { if (!string.IsNullOrEmpty(sharedGameToken)) { previousGameToken = sharedGameToken; } sharedGameToken = ""; matchStartServerTimestamp = 0; if (oneVOneMatchAtStart) { try { matchStartServerTimestamp = PhotonNetwork.ServerTimestamp; } catch { return; } TryPublishSharedGameToken(); } } private static void TryRefreshSharedGameToken() { if (!oneVOneMatchAtStart || !string.IsNullOrEmpty(sharedGameToken)) { return; } try { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = ((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null); if (val != null && ((Dictionary)(object)val).ContainsKey((object)"cr_game_token")) { string text = val[(object)"cr_game_token"]?.ToString() ?? ""; string[] array = text.Split(':'); if (array.Length == 2 && Regex.IsMatch(array[0], "^\\d{6}$") && array[0] != previousGameToken && int.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var _)) { sharedGameToken = array[0]; return; } } } catch { } TryPublishSharedGameToken(); } private static string BuildReportRoomId(int reportP1Rounds = -1, int reportP2Rounds = -1) { TryRefreshSharedGameToken(); string arg = ((!string.IsNullOrEmpty(sharedGameToken)) ? sharedGameToken : matchStartTime.ToString("HHmmss", CultureInfo.InvariantCulture)); int num = ((reportP1Rounds >= 0 && reportP2Rounds >= 0) ? (reportP1Rounds + reportP2Rounds) : (p1Rounds + p2Rounds)); return $"{photonRoomId}_{arg}_r{num}"; } private static void TryDispatchMacroEvidence(string reportRoomId = null, int reportP1Rounds = -1, int reportP2Rounds = -1) { try { DispatchMacroEvidenceCore(reportRoomId, reportP1Rounds, reportP2Rounds); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MACRO-EVIDENCE] dispatch failed (match reporting unaffected): " + ex.Message)); } } private static void DispatchMacroEvidenceCore(string reportRoomId, int reportP1Rounds, int reportP2Rounds) { int num = ((reportP1Rounds >= 0) ? reportP1Rounds : p1Rounds); int num2 = ((reportP2Rounds >= 0) ? reportP2Rounds : p2Rounds); if (macroEvidenceDispatched || !oneVOneMatchAtStart || LocalMacroSuspectSeconds < 10 || num == num2 || (localTeamId != 0 && localTeamId != 1) || string.IsNullOrEmpty(localSteamId) || string.IsNullOrEmpty(opponentSteamId) || opponentSteamId.StartsWith("photon_") || (photonRoomId ?? "").IndexOf("offline", StringComparison.OrdinalIgnoreCase) >= 0) { return; } try { if (PhotonNetwork.OfflineMode) { return; } } catch { } string p1SteamId = ((localTeamId == 0) ? localSteamId : opponentSteamId); string p2SteamId = ((localTeamId == 0) ? opponentSteamId : localSteamId); int durationSeconds = Math.Max(0, (int)(DateTime.UtcNow - matchStartTime).TotalSeconds); string text = (string.IsNullOrEmpty(reportRoomId) ? BuildReportRoomId(num, num2) : reportRoomId); bool sharedGameTokenUsed = !string.IsNullOrEmpty(sharedGameToken); macroEvidenceDispatched = true; ApiClient.ReportMacroEvidence(p1SteamId, p2SteamId, num, num2, text, matchStartTime, durationSeconds, sharedGameTokenUsed, localSteamId, LocalMacroSuspectSeconds, LocalMacroPeakKeysPerSecond, LocalMacroPeakClicksPerSecond, LocalMacroPeakEventsPerSecond, LocalMacroTimeline); } private static void OnMatchStarted() { //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Expected O, but got Unknown //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Expected O, but got Unknown isTracking = true; gameOverReported = false; macroEvidenceDispatched = false; opponentDCReported = false; matchStartTime = DateTime.UtcNow; try { Room currentRoom = PhotonNetwork.CurrentRoom; string text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; Room currentRoom2 = PhotonNetwork.CurrentRoom; Hashtable val = ((currentRoom2 != null) ? ((RoomInfo)currentRoom2).CustomProperties : null); oneVOneMatchAtStart = !PhotonNetwork.OfflineMode && !text.StartsWith("ovt_", StringComparison.Ordinal) && !text.StartsWith("team_", StringComparison.Ordinal) && !text.StartsWith("ffa_", StringComparison.Ordinal) && (val == null || !((Dictionary)(object)val).ContainsKey((object)"cr_ff")) && PhotonNetwork.PlayerList != null && PhotonNetwork.PlayerList.Length == 2; } catch { oneVOneMatchAtStart = false; } BeginSharedGameToken(); try { Room currentRoom3 = PhotonNetwork.CurrentRoom; Hashtable val2 = ((currentRoom3 != null) ? ((RoomInfo)currentRoom3).CustomProperties : null); Room currentRoom4 = PhotonNetwork.CurrentRoom; string text2 = ((currentRoom4 != null) ? currentRoom4.Name : null) ?? ""; if ((val2 != null && ((Dictionary)(object)val2).ContainsKey((object)"cr_ff")) || text2.StartsWith("ranked_") || text2.StartsWith("team_") || text2.StartsWith("sct-") || text2.StartsWith("ovt_") || FfaMode.EngineActive()) { matchIsRanked = true; } else if (opponentRankChecked && opponentIsRanked && OpponentHasMod() && Plugin.RankedEnabled != null && Plugin.RankedEnabled.Value) { matchIsRanked = true; } bool flag = ((Dictionary)(object)val2)?.ContainsKey((object)"cr_ff") ?? false; if (matchIsRanked && !flag && seriesPreflightSent && string.IsNullOrEmpty(ApiClient.ActiveRankedSeriesId)) { seriesPreflightSent = false; Plugin.Log.LogInfo((object)"[POLL] Re-armed series preflight at game start (no live series id)"); } if (flag && string.IsNullOrEmpty(ApiClient.ActiveTeamSeriesId)) { TryRequestContinuationSeries(); } Room currentRoom5 = PhotonNetwork.CurrentRoom; if ((((currentRoom5 != null) ? currentRoom5.Name : null) ?? "").StartsWith("ovt_") && string.IsNullOrEmpty(ApiClient.ActiveOvt1v2SeriesId)) { TryRequestOvtContinuationSeries(); } } catch { } TrailCosmetic.OnMatchStart(); PlayerColorCosmetic.OnMatchStart(); try { PlayerEffectCosmetic.OnMatchStart(); } catch { } achTookDamage = false; achPhoenixUsed = false; achDied = false; achMaxOpponentRounds = 0; achWasDown04 = false; lastDeadState = false; lastRemainingRespawns = -1; achFiredShot = false; achMoved = false; achJumped = false; abyssalRoundsActivated = 0; abyssalActivatedThisRound = false; inPickPhase = false; pendingRegicideCheck = false; ResetPerMatchCombatCounters(); if (CardRarityLookup.Count == 0) { try { CardRarityLookup.ScanAll(); } catch { } } p1Points = 0; p2Points = 0; p1Rounds = 0; p2Rounds = 0; currentRound = 1; localCards.Clear(); opponentCards.Clear(); localOffers.Clear(); lastKnownP1CardCount = 0; lastKnownP2CardCount = 0; pickCountThisMatch = 0; broadcastCardNames.Clear(); try { if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) { Hashtable val3 = new Hashtable(); val3[(object)"cr_cards"] = ""; val3[(object)"cr_fps"] = 0; val3[(object)"cr_gstats"] = "0|0|0|0|0|0"; PhotonNetwork.LocalPlayer.SetCustomProperties(val3, (Hashtable)null, (WebFlags)null); } } catch { } matchPointTimeline.Clear(); OppStatBulletsFired = 0; OppStatBulletsHit = 0; OppStatBlocksActivated = 0; OppStatBlocksSuccessful = 0; OppStatKeysPressed = 0; OppStatActiveSeconds = 0f; OppStatMacroSuspectSeconds = 0; OppStatMacroPeakKeysPerSecond = 0; OppStatMacroPeakClicksPerSecond = 0; OppStatMacroPeakEventsPerSecond = 0; OppStatMacroTimeline = ""; if (preMatchCards.Count > 0) { Plugin.Log.LogInfo((object)$"[POLL] Recovering {preMatchCards.Count} pre-match card(s)"); foreach (MatchTracker.CardPickData preMatchCard in preMatchCards) { pickCountThisMatch++; preMatchCard.PickOrder = pickCountThisMatch; preMatchCard.RoundNumber = 1; localCards.Add(preMatchCard); broadcastCardNames.Add(preMatchCard.CardName); localOffers.Add(new MatchTracker.CardOfferData { CardName = preMatchCard.CardName, RoundNumber = 1, WasPicked = true }); Plugin.Log.LogInfo((object)$"[POLL] Card: Pre-match picked {preMatchCard.CardName} [#{pickCountThisMatch}] (+synth offer)"); } try { if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) { string text3 = string.Join("|", broadcastCardNames.ToArray()); Hashtable val4 = new Hashtable(); val4[(object)"cr_cards"] = text3; PhotonNetwork.LocalPlayer.SetCustomProperties(val4, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)("[POLL] Broadcast recovered cards: " + text3)); } } catch { } } preMatchCards.Clear(); preMatchPickCount = 0; if (preMatchOpponentCards.Count > 0) { Plugin.Log.LogInfo((object)$"[HARMONY-CARD] Recovering {preMatchOpponentCards.Count} pre-match opponent card(s)"); foreach (MatchTracker.CardPickData preMatchOpponentCard in preMatchOpponentCards) { preMatchOpponentCard.RoundNumber = 1; preMatchOpponentCard.PickOrder = opponentCards.Count + 1; opponentCards.Add(preMatchOpponentCard); opponentCardsViaHarmony = true; Plugin.Log.LogInfo((object)$"[HARMONY-CARD] Opp pre-match recovered: {preMatchOpponentCard.CardName} [#{preMatchOpponentCard.PickOrder}]"); } } preMatchOpponentCards.Clear(); lastKnownOpponentBroadcastCount = 0; try { Player[] playerList = PhotonNetwork.PlayerList; Player[] array = playerList; foreach (Player val5 in array) { if (val5 != null && !val5.IsLocal && val5.CustomProperties != null && ((Dictionary)(object)val5.CustomProperties).ContainsKey((object)"cr_cards")) { string text4 = val5.CustomProperties[(object)"cr_cards"].ToString(); if (!string.IsNullOrEmpty(text4)) { lastKnownOpponentBroadcastCount = text4.Split('|').Length; Plugin.Log.LogInfo((object)$"[POLL] Ignoring {lastKnownOpponentBroadcastCount} stale opponent cards from previous match"); } break; } } } catch { } IdentifyLocalPlayer(); TryResolveOpponent(); DetermineLocalTeam(); matchIsRanked = Plugin.RankedEnabled.Value && opponentIsRanked && OpponentHasMod(); string text5 = (matchIsRanked ? "RANKED" : "CASUAL"); Plugin.Log.LogInfo((object)("[POLL] === " + text5 + " Match Started ===")); Plugin.Log.LogInfo((object)$"[POLL] Me: {localDisplayName} ({localSteamId}) team {localTeamId}"); Plugin.Log.LogInfo((object)$"[POLL] Opp: {opponentDisplayName} ({opponentSteamId}) oppRanked={opponentIsRanked}"); } private static void OnGameOver(int winnerTeam) { if (!isTracking || gameOverReported) { return; } gameOverReported = true; sessionMatchCount++; BroadcastGstatsImmediate(); try { PhotonNetwork.SendAllOutgoingCommands(); } catch { } PollOpponentFps(); if (!opponentSteamIdResolved) { TryResolveOpponent(); } bool flag = winnerTeam == localTeamId; string arg = (matchIsRanked ? "RANKED" : "CASUAL"); Plugin.Log.LogInfo((object)$"[POLL] === {arg} Match Over === Winner: team {winnerTeam}"); string text = opponentDisplayName; try { Room currentRoom = PhotonNetwork.CurrentRoom; if ((((currentRoom != null) ? currentRoom.Name : null) ?? "").StartsWith("ovt_") && PhotonNetwork.PlayerList != null && PhotonNetwork.PlayerList.Length >= 3) { List list = new List(); Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if (val != null && !val.IsLocal) { list.Add(StripRichText(val.NickName ?? "?")); } } if (list.Count > 0) { text = string.Join(" + ", list); } } } catch { } Plugin.Log.LogInfo((object)(flag ? ("[POLL] YOU WON vs " + text + "!") : ("[POLL] You lost to " + text))); Plugin.Log.LogInfo((object)$"[POLL] Final: P1 {p1Rounds}r - P2 {p2Rounds}r"); List list2 = new List(); bool flag2 = false; Room currentRoom2 = PhotonNetwork.CurrentRoom; bool flag3 = (((currentRoom2 != null) ? currentRoom2.Name : null) ?? "").StartsWith("ovt_"); try { Room currentRoom3 = PhotonNetwork.CurrentRoom; flag2 = ((Dictionary)(object)((currentRoom3 != null) ? ((RoomInfo)currentRoom3).CustomProperties : null))?.ContainsKey((object)"cr_ff") ?? false; } catch { } if ((flag2 && PhotonNetwork.PlayerList != null && PhotonNetwork.PlayerList.Length >= 4) || (flag3 && PhotonNetwork.PlayerList != null && PhotonNetwork.PlayerList.Length >= 2)) { Player[] playerList2 = PhotonNetwork.PlayerList; foreach (Player val2 in playerList2) { if (val2 == null || (PhotonNetwork.LocalPlayer != null && val2.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber)) { continue; } string nickName = val2.NickName; if (string.IsNullOrEmpty(nickName)) { continue; } nickName = StripRichText(nickName); int num = -1; try { if (val2.CustomProperties != null && ((Dictionary)(object)val2.CustomProperties).ContainsKey((object)"t_id")) { num = Convert.ToInt32(val2.CustomProperties[(object)"t_id"]); } } catch { } string text2 = ((num >= 0 && localTeamId >= 0 && num == localTeamId) ? ("w/ " + nickName) : nickName); if (list2.Contains(text2)) { int k; for (k = 2; list2.Contains($"{text2} ({k})"); k++) { } text2 = $"{text2} ({k})"; } list2.Add(text2); } } if (list2.Count == 0) { list2.Add(opponentDisplayName ?? "Unknown"); } foreach (string item in list2) { if (!sessionWLByOpponent.TryGetValue(item, out var value) || value == null || value.Length < 6) { int[] array = new int[6]; if (value != null) { Array.Copy(value, array, Math.Min(value.Length, 6)); } value = (sessionWLByOpponent[item] = array); } int num2 = (flag3 ? 4 : ((!matchIsRanked) ? 2 : 0)); if (flag) { value[num2]++; } else { value[num2 + 1]++; } } if (flag3) { if (flag) { sessionOvtWins++; } else { sessionOvtLosses++; } } else if (matchIsRanked) { if (flag) { sessionRankedWins++; } else { sessionRankedLosses++; } if (currentSeriesGamesWon >= 2 || currentSeriesGamesLost >= 2) { currentSeriesGamesWon = 0; currentSeriesGamesLost = 0; sessionSeriesCounted = false; } if (flag) { currentSeriesGamesWon++; } else { currentSeriesGamesLost++; } if (currentSeriesGamesWon >= 2 || currentSeriesGamesLost >= 2) { bool flag4 = currentSeriesGamesWon >= 2; if (!sessionSeriesCounted) { sessionSeriesCounted = true; if (flag4) { sessionRankedSeriesWins++; } else { sessionRankedSeriesLosses++; } try { ApiClient.OnSeriesCompletedVsOpponent(opponentSteamId, flag4); } catch { } Plugin.Log.LogInfo((object)$"[SESSION] Ranked series tally (local BO3 decision): {sessionRankedSeriesWins}-{sessionRankedSeriesLosses}"); SaveSessionState(); } } } else if (flag) { sessionCasualWins++; } else { sessionCasualLosses++; } if (flag3) { try { if (ovtSoloWins >= 2 || ovtDuoWins >= 2) { ovtSoloWins = 0; ovtDuoWins = 0; } PlayerManager instance = PlayerManager.instance; int num3 = 0; int num4 = 0; if ((Object)(object)instance != (Object)null && instance.players != null) { foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null)) { if (player.TeamID == 0) { num3++; } else if (player.TeamID == 1) { num4++; } } } } int num5 = ((num3 != 1) ? ((num4 == 1) ? 1 : (-1)) : 0); if (num5 >= 0) { bool flag5 = p1Rounds > p2Rounds; if (num5 == 0 == flag5) { ovtSoloWins++; } else { ovtDuoWins++; } } } catch { } } AccumulateSessionTime(); SaveSessionState(); LastResult = new MatchTracker.MatchResult { Won = flag, MyRounds = ((localTeamId == 0) ? p1Rounds : p2Rounds), TheirRounds = ((localTeamId == 0) ? p2Rounds : p1Rounds), OpponentName = opponentDisplayName, Timestamp = DateTime.UtcNow }; HasPendingResult = true; string text3; string text4; string text5; string text6; if (localTeamId == 0) { text3 = localSteamId; text4 = localDisplayName; text5 = opponentSteamId; text6 = opponentDisplayName; } else { text3 = opponentSteamId; text4 = opponentDisplayName; text5 = localSteamId; text6 = localDisplayName; } int num6 = (int)(DateTime.UtcNow - matchStartTime).TotalSeconds; bool flag6 = true; if (opponentSteamIdResolved && !opponentSteamId.StartsWith("photon_")) { bool flag7 = false; try { Player[] playerList3 = PhotonNetwork.PlayerList; Player[] array3 = playerList3; foreach (Player val3 in array3) { if (val3 != null && !val3.IsLocal && val3.CustomProperties != null && ((Dictionary)(object)val3.CustomProperties).ContainsKey((object)"cr_cards")) { flag7 = true; break; } } } catch { } if (flag7) { long result = 0L; long result2 = 0L; long.TryParse(localSteamId, out result); long.TryParse(opponentSteamId, out result2); flag6 = result <= result2; if (!flag6) { Plugin.Log.LogInfo((object)"[POLL] Opponent will report this match (lower Steam ID)"); } } } string text7 = BuildReportRoomId(); bool flag8 = false; try { if (PhotonNetwork.OfflineMode) { flag8 = true; } if (!string.IsNullOrEmpty(photonRoomId) && photonRoomId.IndexOf("offline", StringComparison.OrdinalIgnoreCase) >= 0) { flag8 = true; } } catch { } if (flag8) { Plugin.Log.LogInfo((object)("[POLL] Skipping match report — offline/practice detected (room='" + photonRoomId + "')")); flag6 = false; } if (!flag8) { TryDispatchMacroEvidence(text7); } try { Room currentRoom4 = PhotonNetwork.CurrentRoom; string text8 = ((currentRoom4 != null) ? currentRoom4.Name : null) ?? ""; if (FfaMode.EngineActive()) { Plugin.Log.LogWarning((object)"[FFA-REPORT-ROUTE] polled OnGameOver fired in an ffa_ room — all non-FFA report paths banned"); EvaluateAchievements(flag); isTracking = false; matchIsRanked = false; return; } if (text8.StartsWith("ovt_") && flag6) { bool flag9 = false; if (PhotonNetwork.PlayerList != null && PhotonNetwork.PlayerList.Length == 3) { flag9 = TryReportOvtMatch(text7, num6); } if (!flag9) { ManualLogSource log = Plugin.Log; Player[] playerList4 = PhotonNetwork.PlayerList; log.LogWarning((object)$"[1v2-REPORT-ROUTE] ovt_ room, report not routed (players={((playerList4 != null) ? playerList4.Length : (-1))}) — 1v1 fallback banned"); } EvaluateAchievements(flag); isTracking = false; matchIsRanked = false; return; } } catch (Exception ex) { Plugin.Log.LogError((object)("[1v2] routing error: " + ex.Message)); } bool flag10 = false; try { Player[] playerList5 = PhotonNetwork.PlayerList; int num7 = ((playerList5 != null) ? playerList5.Length : (-1)); bool flag11 = !string.IsNullOrEmpty(ApiClient.ActiveTeamSeriesId); bool flag12 = false; try { Room currentRoom5 = PhotonNetwork.CurrentRoom; flag12 = ((Dictionary)(object)((currentRoom5 != null) ? ((RoomInfo)currentRoom5).CustomProperties : null))?.ContainsKey((object)"cr_ff") ?? false; } catch { } Plugin.Log.LogInfo((object)string.Format("[2v2-REPORT-ROUTE] shouldReport={0} ActiveTeamSeriesId={1} PlayerList.Length={2} cr_ff={3}", flag6, flag11 ? ApiClient.ActiveTeamSeriesId : "(null)", num7, flag12)); if (flag6 && flag11 && PhotonNetwork.PlayerList != null && PhotonNetwork.PlayerList.Length == 4 && TryReportTeamMatch(text7, num6)) { EvaluateAchievements(flag); isTracking = false; matchIsRanked = false; return; } if (flag12 || flag11) { if (flag6 && flag12 && !flag11 && num7 == 4) { Plugin.Log.LogWarning((object)"[2v2-REPORT-ROUTE] no team series at match end — requesting continuation and deferring report"); string deferredRoom = text7; int deferredDuration = num6; TryRequestContinuationSeries(delegate(bool ok) { if (ok && !string.IsNullOrEmpty(ApiClient.ActiveTeamSeriesId)) { bool flag15 = TryReportTeamMatch(deferredRoom, deferredDuration); Plugin.Log.LogInfo((object)$"[2v2-REPORT-ROUTE] deferred report after continuation: sent={flag15}"); } else { Plugin.Log.LogWarning((object)"[2v2-REPORT-ROUTE] continuation retry failed — game not recorded"); } }); } else { Plugin.Log.LogWarning((object)$"[2v2-REPORT-ROUTE] BLOCKING 1v1 fallback in 2v2 context: shouldReport={flag6} hasSeries={flag11} playerListLen={num7} cr_ff={flag12} — match will not be reported"); } EvaluateAchievements(flag); isTracking = false; matchIsRanked = false; return; } } catch (Exception ex2) { Plugin.Log.LogError((object)("[POLL] 2v2 routing error: " + ex2.Message)); } if (flag6 && !matchIsRanked && !string.IsNullOrEmpty(ApiClient.ActiveRankedSeriesId) && OpponentHasMod()) { Plugin.Log.LogInfo((object)("[REPORT-ROUTE] forcing isRanked=true: live series " + ApiClient.ActiveRankedSeriesId + " exists for this pairing (flag lost a race)")); matchIsRanked = true; } if (flag6) { try { Room currentRoom6 = PhotonNetwork.CurrentRoom; string text9 = ((currentRoom6 != null) ? currentRoom6.Name : null) ?? "(no room)"; bool flag13 = text9.StartsWith("sct-"); bool flag14 = text9.StartsWith("ranked_"); Plugin.Log.LogInfo((object)$"[REPORT-ROUTE] 1v1 path: room={text9} isRanked={matchIsRanked} tournament={flag13} ranked_queue={flag14} reporter={localSteamId} opponent={opponentSteamId}"); } catch { } ApiClient.ReportMatch(text3, text4, text5, text6, p1Rounds, p2Rounds, p1Points, p2Points, (localTeamId == 0) ? localCards : opponentCards, (localTeamId == 0) ? opponentCards : localCards, (localTeamId == 0) ? localOffers : emptyOffers, (localTeamId == 0) ? emptyOffers : localOffers, text7, photonRegion, num6, matchStartTime, localSteamId, matchIsRanked, LocalShotsThisMatch, LocalBlocksThisMatch, LocalBulletsFiredThisMatch, LocalBulletsHitThisMatch, LocalBlocksActivatedThisMatch, LocalBlocksSuccessfulThisMatch, LocalAvgFps, OpponentAvgFps, LocalKeysThisMatch, LocalActiveSecondsThisMatch, LocalMacroSuspectSeconds, LocalMacroPeakKeysPerSecond, LocalMacroPeakClicksPerSecond, LocalMacroPeakEventsPerSecond, LocalMacroTimeline, OppStatMacroSuspectSeconds, OppStatMacroPeakKeysPerSecond, OppStatMacroPeakClicksPerSecond, OppStatMacroPeakEventsPerSecond, OppStatMacroTimeline, OppStatBulletsFired, OppStatBulletsHit, OppStatBlocksActivated, OppStatBlocksSuccessful, OppStatKeysPressed, OppStatActiveSeconds, string.Join(",", matchPointTimeline.ToArray()), string.Join(",", localFpsTimeline), string.Join(",", oppFpsTimeline), localFreezeCount, localFreezeFocusedCount, localFreezeTotalSec, (pingSamples.Count > 0) ? ((int)Math.Round(pingSamples.Average())) : 0, (pingSamples.Count > 0) ? pingSamples.Max() : 0, localPingTimeline: string.Join(",", pingSamples), oppPingTimeline: string.Join(",", oppPingTimeline), oppPingAvg: (oppPingTimeline.Count > 0) ? ((int)Math.Round(oppPingTimeline.Average())) : 0, localRecvGapCount: localRecvGapCount, localRecvGapMaxMs: localRecvGapMaxMs, oppHbGapCount: oppHbGapCount, oppFreezeCount: oppFreezeCount, oppFreezeFocusedCount: oppFreezeFocusedCount, oppRecvGapCount: oppRecvGapCount, localHitTimeline: string.Join(",", localHitTimeline.ToArray()), oppHitTimeline: string.Join(",", oppHitTimeline.ToArray()), localBlockTimeline: string.Join(",", localBlockTimeline.ToArray()), oppBlockTimeline: string.Join(",", oppBlockTimeline.ToArray()), pointTimes: string.Join(",", pointTimes)); } EvaluateAchievements(flag); isTracking = false; matchIsRanked = false; } private static void TryRequestContinuationSeries(Action onDone = null) { try { if (Time.time - lastContinuationRequestTime < 8f || PhotonNetwork.PlayerList == null || PhotonNetwork.PlayerList.Length != 4) { return; } string[] array = new string[4]; int[] array2 = new int[4]; for (int i = 0; i < 4; i++) { Player val = PhotonNetwork.PlayerList[i]; if (val == null) { return; } string text = ResolvePhotonSteamId(val); if (string.IsNullOrEmpty(text) || text.StartsWith("photon_")) { return; } int num = -1; if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).ContainsKey((object)"t_id")) { try { num = Convert.ToInt32(val.CustomProperties[(object)"t_id"]); } catch { } } if (num != 0 && num != 1) { return; } array[i] = text; array2[i] = num; } List list = new List(); List list2 = new List(); for (int j = 0; j < 4; j++) { if (array2[j] == 0) { list.Add(array[j]); } else { list2.Add(array[j]); } } if (list.Count != 2 || list2.Count != 2) { return; } string text2 = null; long num2 = long.MaxValue; string[] array3 = array; foreach (string text3 in array3) { if (long.TryParse(text3, out var result) && result < num2) { num2 = result; text2 = text3; } } if (!(text2 != localSteamId)) { list.Sort(StringComparer.Ordinal); list2.Sort(StringComparer.Ordinal); Room currentRoom = PhotonNetwork.CurrentRoom; string roomId = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; lastContinuationRequestTime = Time.time; Plugin.Log.LogInfo((object)("[2v2-CONTINUATION] requesting continuation (t0=" + list[0] + "," + list[1] + " t1=" + list2[0] + "," + list2[1] + ")")); ApiClient.RequestContinuationSeries(localSteamId, roomId, photonRegion, list[0], list[1], list2[0], list2[1], onDone); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2-CONTINUATION] resolve error: " + ex.Message)); } } private static void TryRequestOvtContinuationSeries() { try { if (Time.time - lastOvtContinuationRequestTime < 8f || PhotonNetwork.PlayerList == null || PhotonNetwork.PlayerList.Length != 3) { return; } PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null) { return; } string[] array = new string[3]; int[] array2 = new int[3]; for (int i = 0; i < 3; i++) { Player val = PhotonNetwork.PlayerList[i]; if (val == null) { return; } string text = ResolvePhotonSteamId(val); if (string.IsNullOrEmpty(text) || text.StartsWith("photon_")) { return; } int num = -1; foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null)) { PhotonView component = ((Component)player).GetComponent(); if (!((Object)(object)component == (Object)null) && component.Owner != null && component.Owner.ActorNumber == val.ActorNumber) { num = player.TeamID; break; } } } if (num < 0) { return; } array[i] = text; array2[i] = num; } Dictionary> dictionary = new Dictionary>(); for (int j = 0; j < 3; j++) { if (!dictionary.ContainsKey(array2[j])) { dictionary[array2[j]] = new List(); } dictionary[array2[j]].Add(array[j]); } if (dictionary.Count != 2) { return; } string text2 = null; List list = new List(); foreach (KeyValuePair> item in dictionary) { if (item.Value.Count == 1) { text2 = item.Value[0]; } else { list = item.Value; } } if (text2 == null || list.Count != 2) { return; } list.Sort(StringComparer.Ordinal); string text3 = null; long num2 = long.MaxValue; string[] array3 = array; foreach (string text4 in array3) { if (long.TryParse(text4, out var result) && result < num2) { num2 = result; text3 = text4; } } if (!(text3 != localSteamId)) { Room currentRoom = PhotonNetwork.CurrentRoom; string roomId = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; lastOvtContinuationRequestTime = Time.time; Plugin.Log.LogInfo((object)("[1v2-CONTINUATION] requesting (solo=" + text2 + " duo=" + list[0] + "," + list[1] + ")")); ApiClient.RequestOvtContinuationSeries(localSteamId, roomId, photonRegion, text2, list[0], list[1]); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[1v2-CONTINUATION] resolve error: " + ex.Message)); } } private static bool TryReportOvtMatch(string reportRoomId, int duration) { if (PhotonNetwork.PlayerList == null || PhotonNetwork.PlayerList.Length != 3) { return false; } PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null) { return false; } if (string.IsNullOrEmpty(ApiClient.ActiveOvt1v2SeriesId)) { Plugin.Log.LogWarning((object)"[1v2-REPORT] no active series id — cannot report"); return false; } Dictionary, int)> dictionary = new Dictionary, int)>(); Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if (val == null) { continue; } string text = ResolvePhotonSteamId(val); if (string.IsNullOrEmpty(text) || text.StartsWith("photon_")) { Plugin.Log.LogWarning((object)$"[1v2-REPORT] couldn't resolve actor {val.ActorNumber}"); return false; } string text2 = StripRichText(val.NickName ?? text); if (string.IsNullOrEmpty(text2)) { text2 = text; } if (text2.Length > 60) { text2 = text2.Substring(0, 60); } int item = -1; foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null)) { PhotonView component = ((Component)player).GetComponent(); if (!((Object)(object)component == (Object)null) && component.Owner != null && component.Owner.ActorNumber == val.ActorNumber) { item = player.TeamID; break; } } } List list = new List(); if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_cards")) { string text3 = val.CustomProperties[(object)"cr_cards"]?.ToString() ?? ""; if (!string.IsNullOrEmpty(text3)) { int num = 1; string[] array = text3.Split('|'); foreach (string text4 in array) { string canonicalName = CardRarityLookup.GetCanonicalName(ToTitleCase(text4.Trim())); if (!string.IsNullOrEmpty(canonicalName)) { list.Add(new MatchTracker.CardPickData { CardName = canonicalName, CardRarity = CardRarityLookup.GetRarity(canonicalName), PickOrder = num++, RoundNumber = 1 }); } } } } int item2 = 0; if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_fps")) { try { item2 = Convert.ToInt32(val.CustomProperties[(object)"cr_fps"]); } catch { } } if (val.IsLocal) { if (localCards != null && localCards.Count > 0) { list = new List(localCards); } int localAvgFps = LocalAvgFps; if (localAvgFps > 0) { item2 = localAvgFps; } } dictionary[text] = (text2, item, list, item2); } if (dictionary.Count != 3) { Plugin.Log.LogWarning((object)$"[1v2-REPORT] resolved {dictionary.Count}/3 players"); return false; } Dictionary> dictionary2 = new Dictionary>(); foreach (KeyValuePair, int)> item3 in dictionary) { if (!dictionary2.ContainsKey(item3.Value.Item2)) { dictionary2[item3.Value.Item2] = new List(); } dictionary2[item3.Value.Item2].Add(item3.Key); } if (dictionary2.Count != 2) { Plugin.Log.LogWarning((object)$"[1v2-REPORT] expected 2 teams, got {dictionary2.Count}"); return false; } int num2 = -1; int num3 = -1; foreach (KeyValuePair> item4 in dictionary2) { if (item4.Value.Count == 1) { num2 = item4.Key; } else if (item4.Value.Count == 2) { num3 = item4.Key; } } if (num2 < 0 || num3 < 0) { Plugin.Log.LogWarning((object)"[1v2-REPORT] not a 1+2 split"); return false; } string text5 = dictionary2[num2][0]; List list2 = dictionary2[num3]; list2.Sort(StringComparer.Ordinal); string text6 = list2[0]; string text7 = list2[1]; string text8 = null; long num4 = long.MaxValue; foreach (string key in dictionary.Keys) { if (long.TryParse(key, out var result) && result < num4) { num4 = result; text8 = key; } } if (text8 == null) { text8 = localSteamId; } if (text8 != localSteamId) { Plugin.Log.LogInfo((object)("[1v2-REPORT] reporter is " + text8 + ", not me — skipping")); return true; } int num5 = ((num2 == 0) ? p1Rounds : p2Rounds); int num6 = ((num2 == 0) ? p2Rounds : p1Rounds); int soloPoints = ((num2 == 0) ? p1Points : p2Points); int duoPoints = ((num2 == 0) ? p2Points : p1Points); ApiClient.ReportOvtMatch(ApiClient.ActiveOvt1v2SeriesId, reportRoomId, photonRegion, duration, text5, dictionary[text5].Item1, dictionary[text5].Item3, text6, dictionary[text6].Item1, dictionary[text6].Item3, text7, dictionary[text7].Item1, dictionary[text7].Item3, num5, num6, soloPoints, duoPoints, localSteamId, dictionary[text5].Item4, dictionary[text6].Item4, dictionary[text7].Item4); Plugin.Log.LogInfo((object)$"[1v2-REPORT] submitted solo={text5} duo={text6},{text7} {num5}-{num6}"); return true; } private static void ResetPerMatchCombatCounters() { LocalShotsThisMatch = 0; LocalBlocksThisMatch = 0; LocalKeysThisMatch = 0; LocalMacroSuspectSeconds = 0; LocalMacroPeakKeysPerSecond = 0; LocalMacroPeakClicksPerSecond = 0; LocalMacroPeakEventsPerSecond = 0; inputSuspectWindows.Clear(); inputBucketTimer = 0f; inputBucketCount = 0; inputBucketKeyCount = 0; inputBucketClickCount = 0; inputBucketStartedAtMs = -1L; LocalActiveSecondsThisMatch = 0f; LocalBulletsFiredThisMatch = 0; LocalBulletsHitThisMatch = 0; LocalBlocksActivatedThisMatch = 0; LocalBlocksSuccessfulThisMatch = 0; LocalBlockRawAbsorbs = 0; LocalBlockDedupeDrops = 0; LastBlockActivatedTime = -999f; LastBlockSuccessfulTime = -999f; LastBlockAbsorbTime = -999f; LastLocalHitTime = -999f; LastBlockMissTime = -999f; LastBlockEventLabel = ""; fpsFrameCount = 0; fpsTimeAccum = 0f; fpsBroadcastTimer = 0f; opponentAvgFps = 0; localFpsTimeline.Clear(); tlFrames = 0; tlAccum = 0f; bcFrames = 0; bcAccum = 0f; lastBroadcastRecentFps = 0; oppFpsTimeline.Clear(); oppPingTimeline.Clear(); lastOppGstatsSeq = -1; lastOppSeqAdvanceTime = -1f; localFreezeCount = 0; localFreezeFocusedCount = 0; localFreezeTotalSec = 0f; pingSamples.Clear(); localRecvGapCount = 0; localRecvGapMaxMs = 0; _recvGapOpen = false; oppHbGapCount = 0; _oppHbGapOpen = false; oppFreezeCount = 0; oppFreezeFocusedCount = 0; oppRecvGapCount = 0; _lastTickStopwatchMs = -1L; _hitsRemaining = 0; _activationSuccessCredited = true; BlockChain.Reset(); _loggedFirstFire = (_loggedFirstHit = (_loggedFirstBlockAct = (_loggedFirstBlockOk = false))); _loggedHitBudgetDrop = false; localHitTimeline.Clear(); localBlockTimeline.Clear(); oppHitTimeline.Clear(); oppBlockTimeline.Clear(); localFps3sTimeline.Clear(); pointTimes.Clear(); LocalDamageTakenThisMatch = 0f; peerTele.Clear(); } public static void OnFfaMatchStarted() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown try { isTracking = true; gameOverReported = false; matchStartTime = DateTime.UtcNow; matchIsRanked = true; oneVOneMatchAtStart = false; macroEvidenceDispatched = false; opponentDCReported = false; inPickPhase = false; localCards.Clear(); localOffers.Clear(); broadcastCardNames.Clear(); preMatchCards.Clear(); preMatchPickCount = 0; pickCountThisMatch = 0; try { Hashtable val = new Hashtable(); val[(object)"cr_cards"] = ""; Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer != null) { localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch { } ResetPerMatchCombatCounters(); if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { IdentifyLocalPlayer(); } try { NativeUI.LogOverlayState($"ffa game {FfaMode.GameNumber} start (pre-close)"); } catch { } try { if (NativeUI.IsOpen) { NativeUI.Close(); } } catch { } Plugin.Log.LogInfo((object)$"[FFA] === Game {FfaMode.GameNumber} started === (tracking armed)"); } catch (Exception ex) { Plugin.Log.LogError((object)("[FFA] OnFfaMatchStarted: " + ex.Message)); } } private static void RecordFfaSession(int myPlace, bool localWon, int myTeam) { if (localWon) { sessionFfaWins++; } else { sessionFfaLosses++; } if (myPlace > 0 && sessionFfaPlacements.Count < 200) { sessionFfaPlacements.Add(myPlace); } List> list = new List>(); try { List names = new List(); PlayerManager instance = PlayerManager.instance; Player[] array = (Player[])(((object)PhotonNetwork.PlayerList) ?? ((object)new Player[0])); foreach (Player val in array) { if (val == null || val.IsLocal) { continue; } int num = -1; if (instance?.players != null) { foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null) && !((Object)(object)((Component)player).gameObject == (Object)null)) { PhotonView component = ((Component)player).GetComponent(); if (((component != null) ? component.Owner : null) != null && component.Owner.ActorNumber == val.ActorNumber) { num = player.TeamID; break; } } } } if (num < 0) { Plugin.Log.LogWarning((object)($"[SESSION] ffa: no team for actor {val.ActorNumber} " + "(" + val.NickName + ") — skipped")); continue; } string text = AddName(val.NickName); if (text != null) { list.Add(new KeyValuePair(text, num)); } } foreach (KeyValuePair leaver in FfaMode.Leavers) { if (leaver.Value.leftGameNumber == FfaMode.GameNumber) { string text2 = AddName(leaver.Value.displayName ?? ""); if (text2 != null) { list.Add(new KeyValuePair(text2, leaver.Value.slot)); } } } string AddName(string raw) { string text3 = StripRichText(raw ?? ""); if (string.IsNullOrEmpty(text3)) { return null; } if (names.Contains(text3)) { int j; for (j = 2; names.Contains($"{text3} ({j})"); j++) { } text3 = $"{text3} ({j})"; } names.Add(text3); return text3; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SESSION] ffa roster: " + ex.Message)); } if (myTeam >= 0) { foreach (KeyValuePair item in list) { int num2; try { num2 = FfaMode.ComparePlacement(item.Value, myTeam); } catch { continue; } if (num2 == 0) { continue; } if (!sessionWLByOpponent.TryGetValue(item.Key, out var value) || value == null || value.Length < 8) { int[] array2 = new int[8]; if (value != null) { Array.Copy(value, array2, Math.Min(value.Length, 8)); } value = (sessionWLByOpponent[item.Key] = array2); } if (num2 > 0) { value[6]++; } else { value[7]++; } } } SaveSessionState(); } public static void RecordFfaLocalPick(string cardName, int roundNumber) { try { string text = CardRarityLookup.GetCanonicalName(ToTitleCase(cardName)); if (string.IsNullOrEmpty(text)) { text = cardName; } localCards.Add(new MatchTracker.CardPickData { CardName = text, CardRarity = CardRarityLookup.GetRarity(text), PickOrder = localCards.Count + 1, RoundNumber = Math.Max(1, roundNumber) }); BroadcastCardPick(cardName); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FFA] RecordFfaLocalPick: " + ex.Message)); } } public static void OnFfaGameOver(int winnerTeam) { //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) if (gameOverReported) { return; } gameOverReported = true; isTracking = false; sessionMatchCount++; BroadcastGstatsImmediate(); try { PhotonNetwork.SendAllOutgoingCommands(); } catch { } int num = -1; try { PlayerManager instance = PlayerManager.instance; if (instance?.players != null) { foreach (Player player in instance.players) { if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null && (Object)(object)player.data?.view != (Object)null && player.data.view.IsMine) { num = player.TeamID; break; } } } } catch { } bool flag = num >= 0 && winnerTeam == num; int num2 = 1; try { HashSet hashSet = new HashSet { num }; PlayerManager instance2 = PlayerManager.instance; if (instance2?.players != null) { foreach (Player player2 in instance2.players) { if (!((Object)(object)player2 == (Object)null) && !((Object)(object)((Component)player2).gameObject == (Object)null) && player2.TeamID != num && hashSet.Add(player2.TeamID) && FfaMode.ComparePlacement(player2.TeamID, num) < 0) { num2++; } } } foreach (KeyValuePair leaver in FfaMode.Leavers) { if (hashSet.Add(leaver.Value.slot) && FfaMode.ComparePlacement(leaver.Value.slot, num) < 0) { num2++; } } } catch { } Plugin.Log.LogInfo((object)($"[POLL] === FFA Match Over === Winner: team {winnerTeam} " + string.Format("(you placed #{0}{1})", num2, flag ? " - VICTORY" : ""))); try { RecordFfaSession(num2, flag, num); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SESSION] ffa record failed: " + ex.Message)); } CompetitiveUI.ShowNotification(flag ? "FFA VICTORY!" : $"FFA over - you placed #{num2}", (Color)(flag ? Color.green : new Color(0.7f, 0.85f, 1f)), 6f); AccumulateSessionTime(); SaveSessionState(); int num3 = (int)(DateTime.UtcNow - matchStartTime).TotalSeconds; if (num3 <= 0 || num3 > 86400) { num3 = (int)Math.Max(1f, Time.realtimeSinceStartup - FfaMode.MatchStartRealtime); } string reportRoomId = $"{photonRoomId}_{matchStartTime:HHmmss}_r{FfaMode.GameNumber}"; try { if (!TryReportFfaMatch(reportRoomId, num3, winnerTeam)) { Plugin.Log.LogWarning((object)"[FFA-REPORT] report path did not run (see above)"); } } catch (Exception ex2) { Plugin.Log.LogError((object)("[FFA-REPORT] " + ex2.Message)); } } private static bool TryReportFfaMatch(string reportRoomId, int duration, int winnerTeam) { PlayerManager instance = PlayerManager.instance; if (instance?.players == null) { return false; } string activeFfaLobbyId = ApiClient.ActiveFfaLobbyId; if (string.IsNullOrEmpty(activeFfaLobbyId)) { Plugin.Log.LogWarning((object)"[FFA-REPORT] no active lobby id — cannot report"); return false; } List list = new List(); List list2 = new List(); string text = null; Player[] array = (Player[])(((object)PhotonNetwork.PlayerList) ?? ((object)new Player[0])); foreach (Player val in array) { if (val == null) { continue; } string text2 = ResolvePhotonSteamId(val); if (string.IsNullOrEmpty(text2) || text2.StartsWith("photon_")) { Plugin.Log.LogWarning((object)$"[FFA-REPORT] couldn't resolve actor {val.ActorNumber} — skipping them"); continue; } string text3 = StripRichText(val.NickName ?? text2); if (string.IsNullOrEmpty(text3)) { text3 = text2; } if (text3.Length > 60) { text3 = text3.Substring(0, 60); } int num = -1; foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null) && !((Object)(object)((Component)player).gameObject == (Object)null)) { PhotonView component = ((Component)player).GetComponent(); if (((component != null) ? component.Owner : null) != null && component.Owner.ActorNumber == val.ActorNumber) { num = player.TeamID; break; } } } if (num < 0) { Plugin.Log.LogWarning((object)$"[FFA-REPORT] no in-game player for actor {val.ActorNumber} — skipping"); continue; } int fps = 0; if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_fps")) { try { fps = Convert.ToInt32(val.CustomProperties[(object)"cr_fps"]); } catch { } } ApiClient.TeamTelemetry telemetry = null; string fpsTl; string pingTl; string hitTl; string blockTl; int[] counters; if (val.IsLocal) { if (LocalAvgFps > 0) { fps = LocalAvgFps; } telemetry = new ApiClient.TeamTelemetry { fpsTimeline = string.Join(",", localFps3sTimeline), pingTimeline = string.Join(",", pingSamples), pingAvg = ((pingSamples.Count > 0) ? ((int)Math.Round(pingSamples.Average())) : 0), hitTimeline = string.Join(",", localHitTimeline.ToArray()), blockTimeline = string.Join(",", localBlockTimeline.ToArray()), bulletsFired = LocalBulletsFiredThisMatch, bulletsHit = LocalBulletsHitThisMatch, blocksActivated = LocalBlocksActivatedThisMatch, blocksSuccessful = LocalBlocksSuccessfulThisMatch, keysPressed = LocalKeysThisMatch, activeSeconds = LocalActiveSecondsThisMatch }; } else if (TryGetPeerTelemetry(val.ActorNumber, out fpsTl, out pingTl, out hitTl, out blockTl, out counters)) { int pingAvg = 0; try { List list3 = new List(); string[] array2 = (pingTl ?? "").Split(','); foreach (string s in array2) { if (int.TryParse(s, out var result) && result > 0) { list3.Add(result); } } if (list3.Count > 0) { pingAvg = (int)Math.Round(list3.Average()); } } catch { } telemetry = new ApiClient.TeamTelemetry { fpsTimeline = fpsTl, pingTimeline = pingTl, pingAvg = pingAvg, hitTimeline = hitTl, blockTimeline = blockTl, bulletsFired = counters[0], bulletsHit = counters[1], blocksActivated = counters[2], blocksSuccessful = counters[3], keysPressed = counters[4], activeSeconds = counters[5] }; } list.Add(new ApiClient.FfaReportPlayer { steamId = text2, displayName = text3, slot = num, rounds = FfaMode.RoundsFor(num), points = FfaMode.PointsTotalFor(num), kills = FfaMode.KillsFor(num), leftEarly = false, fps = fps, cards = FfaMode.PickHistoryFor(num), telemetry = telemetry, damageDealt = FfaMode.DamageDealtFor(num), killTimeline = FfaMode.KillTimelineFor(num), damageTimeline = FfaMode.DamageTimelineFor(num) }); list2.Add(text2); if (num == winnerTeam) { text = text2; } } foreach (KeyValuePair leaver in FfaMode.Leavers) { if (!list2.Contains(leaver.Key)) { list.Add(new ApiClient.FfaReportPlayer { steamId = leaver.Key, displayName = leaver.Value.displayName, slot = leaver.Value.slot, rounds = leaver.Value.roundsWon, points = leaver.Value.pointsTotal, kills = leaver.Value.kills, leftEarly = true, fps = 0, absent = (leaver.Value.leftGameNumber != FfaMode.GameNumber), cards = FfaMode.PickHistoryFor(leaver.Value.slot), telemetry = null, damageDealt = FfaMode.DamageDealtFor(leaver.Value.slot), killTimeline = FfaMode.KillTimelineFor(leaver.Value.slot), damageTimeline = FfaMode.DamageTimelineFor(leaver.Value.slot) }); } } if (string.IsNullOrEmpty(text)) { foreach (ApiClient.FfaReportPlayer item in list) { if (item.slot == winnerTeam) { text = item.steamId; break; } } } if (list.Count < 2 || string.IsNullOrEmpty(text)) { Plugin.Log.LogWarning((object)string.Format("[FFA-REPORT] not reportable (entries={0}, winner={1})", list.Count, text ?? "unresolved")); return false; } string text4 = null; long num2 = long.MaxValue; foreach (string item2 in list2) { if (long.TryParse(item2, out var result2) && result2 < num2) { num2 = result2; text4 = item2; } } if (text4 == null) { text4 = localSteamId; } if (text4 != localSteamId) { Plugin.Log.LogInfo((object)("[FFA-REPORT] reporter is " + text4 + ", not me — skipping")); return true; } ApiClient.ReportFfaMatch(activeFfaLobbyId, reportRoomId, photonRegion, duration, list, text, localSteamId, FfaMode.TimelineString); Plugin.Log.LogInfo((object)$"[FFA-REPORT] submitted lobby={activeFfaLobbyId} n={list.Count} winner={text}"); return true; } private static bool TryReportTeamMatch(string reportRoomId, int duration) { if (PhotonNetwork.PlayerList == null || PhotonNetwork.PlayerList.Length != 4) { ManualLogSource log = Plugin.Log; Player[] playerList = PhotonNetwork.PlayerList; log.LogWarning((object)$"[2v2-REPORT] aborting: PlayerList.Length={((playerList != null) ? playerList.Length : (-1))} (expected 4)"); return false; } PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null) { Plugin.Log.LogWarning((object)("[2v2-REPORT] aborting: PlayerManager.instance=" + (((Object)(object)instance == (Object)null) ? "null" : "set") + " pm.players=" + ((instance?.players == null) ? "null" : "set"))); return false; } Player[] playerList2 = PhotonNetwork.PlayerList; Dictionary, int)> dictionary = new Dictionary, int)>(); Dictionary dictionary2 = new Dictionary(); Player[] array = playerList2; foreach (Player val in array) { if (val == null) { continue; } string text = ResolvePhotonSteamId(val); if (string.IsNullOrEmpty(text) || text.StartsWith("photon_")) { Plugin.Log.LogWarning((object)$"[2v2-REPORT] couldn't resolve Steam ID for actor {val.ActorNumber}"); return false; } string text2 = StripRichText(val.NickName ?? text); if (string.IsNullOrEmpty(text2)) { text2 = text; } if (text2.Length > 60) { text2 = text2.Substring(0, 60); } int item = -1; foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null)) { PhotonView component = ((Component)player).GetComponent(); if (!((Object)(object)component == (Object)null) && component.Owner != null && component.Owner.ActorNumber == val.ActorNumber) { item = player.TeamID; break; } } } List list = new List(); if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_cards")) { string text3 = val.CustomProperties[(object)"cr_cards"]?.ToString() ?? ""; if (!string.IsNullOrEmpty(text3)) { int num = 1; string[] array2 = text3.Split('|'); foreach (string text4 in array2) { string name = ToTitleCase(text4.Trim()); name = CardRarityLookup.GetCanonicalName(name); if (!string.IsNullOrEmpty(name)) { list.Add(new MatchTracker.CardPickData { CardName = name, CardRarity = CardRarityLookup.GetRarity(name), PickOrder = num++, RoundNumber = 1 }); } } } } int item2 = 0; if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_fps")) { try { item2 = Convert.ToInt32(val.CustomProperties[(object)"cr_fps"]); } catch { } } string fpsTl; string pingTl; string hitTl; string blockTl; int[] counters; if (val.IsLocal) { if (localCards != null && localCards.Count > 0) { list = new List(localCards); } int localAvgFps = LocalAvgFps; if (localAvgFps > 0) { item2 = localAvgFps; } dictionary2[text] = new ApiClient.TeamTelemetry { fpsTimeline = string.Join(",", localFps3sTimeline), pingTimeline = string.Join(",", pingSamples), pingAvg = ((pingSamples.Count > 0) ? ((int)Math.Round(pingSamples.Average())) : 0), hitTimeline = string.Join(",", localHitTimeline.ToArray()), blockTimeline = string.Join(",", localBlockTimeline.ToArray()), bulletsFired = LocalBulletsFiredThisMatch, bulletsHit = LocalBulletsHitThisMatch, blocksActivated = LocalBlocksActivatedThisMatch, blocksSuccessful = LocalBlocksSuccessfulThisMatch, keysPressed = LocalKeysThisMatch, activeSeconds = LocalActiveSecondsThisMatch }; } else if (TryGetPeerTelemetry(val.ActorNumber, out fpsTl, out pingTl, out hitTl, out blockTl, out counters)) { int pingAvg = 0; try { List list2 = new List(); string[] array3 = (pingTl ?? "").Split(','); foreach (string s in array3) { if (int.TryParse(s, out var result) && result > 0) { list2.Add(result); } } if (list2.Count > 0) { pingAvg = (int)Math.Round(list2.Average()); } } catch { } dictionary2[text] = new ApiClient.TeamTelemetry { fpsTimeline = fpsTl, pingTimeline = pingTl, pingAvg = pingAvg, hitTimeline = hitTl, blockTimeline = blockTl, bulletsFired = counters[0], bulletsHit = counters[1], blocksActivated = counters[2], blocksSuccessful = counters[3], keysPressed = counters[4], activeSeconds = counters[5] }; } dictionary[text] = (text2, item, list, item2); } if (dictionary.Count != 4) { Plugin.Log.LogWarning((object)$"[2v2-REPORT] resolved {dictionary.Count}/4 players, aborting"); return false; } string text5 = null; long num2 = long.MaxValue; foreach (string key in dictionary.Keys) { if (long.TryParse(key, out var result2) && result2 < num2) { num2 = result2; text5 = key; } } if (text5 == null) { text5 = localSteamId; } if (text5 != localSteamId) { Plugin.Log.LogInfo((object)("[2v2-REPORT] reporter is " + text5 + ", not me (" + localSteamId + ") — skipping")); return true; } List list3 = new List(); List list4 = new List(); foreach (KeyValuePair, int)> item3 in dictionary) { if (item3.Value.Item2 == 0) { list3.Add(item3.Key); } else if (item3.Value.Item2 == 1) { list4.Add(item3.Key); } } if (list3.Count != 2 || list4.Count != 2) { Plugin.Log.LogWarning((object)$"[2v2-REPORT] team split is {list3.Count}/{list4.Count}, aborting"); return false; } list3.Sort(StringComparer.Ordinal); list4.Sort(StringComparer.Ordinal); int num3 = p1Rounds; int num4 = p2Rounds; int t1Points = p1Points; int t2Points = p2Points; int num5 = ((num3 > num4) ? 1 : 2); string text6 = list3[0]; string text7 = list3[1]; string text8 = list4[0]; string text9 = list4[1]; ApiClient.ReportTeamMatch(ApiClient.ActiveTeamSeriesId, text6, dictionary[text6].Item1, dictionary[text6].Item3, text7, dictionary[text7].Item1, dictionary[text7].Item3, text8, dictionary[text8].Item1, dictionary[text8].Item3, text9, dictionary[text9].Item1, dictionary[text9].Item3, num3, num4, t1Points, t2Points, reportRoomId, photonRegion, duration, matchStartTime, localSteamId, matchIsRanked, num5, dictionary[text6].Item4, dictionary[text7].Item4, dictionary[text8].Item4, dictionary[text9].Item4, dictionary2.TryGetValue(text6, out var value) ? value : null, dictionary2.TryGetValue(text7, out var value2) ? value2 : null, dictionary2.TryGetValue(text8, out var value3) ? value3 : null, dictionary2.TryGetValue(text9, out var value4) ? value4 : null); Plugin.Log.LogInfo((object)$"[2v2-REPORT] submitted: t1={text6},{text7} t2={text8},{text9} winner=T{num5}"); return true; } private static string ResolvePhotonSteamId(Player pp) { try { Hashtable customProperties = pp.CustomProperties; long result; if (customProperties != null) { if (((Dictionary)(object)customProperties).ContainsKey((object)"u_id")) { string text = customProperties[(object)"u_id"]?.ToString(); if (!string.IsNullOrEmpty(text) && long.TryParse(text, out result)) { return text; } } if (((Dictionary)(object)customProperties).ContainsKey((object)"unity_id")) { string text2 = customProperties[(object)"unity_id"]?.ToString(); if (!string.IsNullOrEmpty(text2) && long.TryParse(text2, out result)) { return text2; } } } if (!string.IsNullOrEmpty(pp.UserId) && long.TryParse(pp.UserId, out result)) { return pp.UserId; } } catch { } return $"photon_{pp.ActorNumber}"; } private static void PollAchievementState() { if (!isTracking) { LocalAliveInCombatNow = false; return; } bool flag = false; try { PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null) { return; } foreach (Player player in instance.players) { if ((Object)(object)player == (Object)null) { continue; } PhotonView component = ((Component)player).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsMine) { continue; } CharacterData component2 = ((Component)player).GetComponent(); if ((Object)(object)component2 == (Object)null) { break; } if (!component2.dead && component2.health > 0f) { flag = true; } if (!component2.dead && component2.health > 0f && component2.health < component2.MaxHealth) { if (!achTookDamage) { Plugin.Log.LogInfo((object)"[ACH] Player took damage"); } achTookDamage = true; } if (component2.dead && !lastDeadState) { achDied = true; } lastDeadState = component2.dead; CharacterStatModifiers stats = component2.stats; if ((Object)(object)stats != (Object)null && stats.respawns > 0 && stats.remainingRespawns < stats.respawns) { if (!achPhoenixUsed) { Plugin.Log.LogInfo((object)"[ACH] Phoenix life consumed"); } achPhoenixUsed = true; } break; } } catch { } LocalAliveInCombatNow = flag && !inPickPhase; if (flag && !inPickPhase) { bool flag2 = false; try { flag2 = CompetitiveUI.AnyChatTyping || NativeUI.IsOpen; } catch { } if (!flag2 && !achFiredShot && Input.GetMouseButton(0)) { achFiredShot = true; Plugin.Log.LogInfo((object)"[ACH] Player fired a shot"); } if (!flag2 && !achMoved && (Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)97) || Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)100) || Input.GetKey((KeyCode)32) || Input.GetKey((KeyCode)273) || Input.GetKey((KeyCode)274) || Input.GetKey((KeyCode)276) || Input.GetKey((KeyCode)275))) { achMoved = true; Plugin.Log.LogInfo((object)"[ACH] Player moved"); } if (!flag2 && !achJumped && (Input.GetKey((KeyCode)32) || Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)273))) { achJumped = true; Plugin.Log.LogInfo((object)"[ACH] Player jumped"); } } } private static void EvaluateAchievements(bool localWon) { try { if (!CompetitiveRoomDetect.IsCompetitiveRoom()) { Plugin.Log.LogInfo((object)"[ACH] Skipping — not a competitive room (public/sandbox games award nothing)"); return; } int num = ((localTeamId == 0) ? p1Rounds : p2Rounds); int num2 = ((localTeamId == 0) ? p2Rounds : p1Rounds); if (num < roundsToWin && num2 < roundsToWin) { Plugin.Log.LogInfo((object)$"[ACH] Skipping — incomplete game ({num}-{num2}, need {roundsToWin})"); return; } bool flag = localWon && num2 == 0; string steamId = localSteamId; HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (MatchTracker.CardPickData localCard in localCards) { string text = localCard.CardName ?? ""; hashSet.Add(text); if (dictionary.ContainsKey(text)) { dictionary[text]++; } else { dictionary[text] = 1; } } foreach (MatchTracker.CardPickData preMatchCard in preMatchCards) { string text2 = preMatchCard.CardName ?? ""; hashSet.Add(text2); if (dictionary.ContainsKey(text2)) { dictionary[text2]++; } else { dictionary[text2] = 1; } } if (localWon && !achTookDamage) { Plugin.Log.LogInfo((object)"[ACH] Evaluating: Untouchable — PASSED"); ApiClient.UnlockAchievement(steamId, "untouchable"); } if (flag) { if (hashSet.Contains("Sneaky") || hashSet.Contains("Sneaky Bullets")) { ApiClient.UnlockAchievement(steamId, "silent_assassin"); } if (hashSet.Contains("Mayhem")) { ApiClient.UnlockAchievement(steamId, "total_mayhem"); } if (hashSet.Contains("Glass Cannon") || hashSet.Contains("Glasscannon")) { ApiClient.UnlockAchievement(steamId, "fragile_perfection"); } if (hashSet.Contains("Chase")) { ApiClient.UnlockAchievement(steamId, "no_escape"); } } bool flag2 = hashSet.Contains("Phoenix"); if (flag && flag2 && !achPhoenixUsed && !achDied) { Plugin.Log.LogInfo((object)"[ACH] Evaluating: Rise from the Ashes — PASSED"); ApiClient.UnlockAchievement(steamId, "rise_from_the_ashes"); } if (localWon && achWasDown04) { Plugin.Log.LogInfo((object)"[ACH] Evaluating: The Comeback Kid — PASSED"); ApiClient.UnlockAchievement(steamId, "the_comeback_kid"); } foreach (KeyValuePair item in dictionary) { if (item.Value >= 5) { Plugin.Log.LogInfo((object)$"[ACH] Evaluating: Stacked Deck — PASSED ({item.Key} x{item.Value})"); ApiClient.UnlockAchievement(steamId, "stacked_deck"); break; } } if (matchIsRanked && localWon && opponentSteamId == "76561198040410653") { pendingRegicideCheck = true; } if (localWon && !achFiredShot) { Plugin.Log.LogInfo((object)"[ACH] Evaluating: Pacifist — PASSED"); ApiClient.UnlockAchievement(steamId, "pacifist"); } if (localWon && !achMoved) { Plugin.Log.LogInfo((object)"[ACH] Evaluating: Immovable Object — PASSED"); ApiClient.UnlockAchievement(steamId, "immovable_object"); } if (localWon && !achJumped) { Plugin.Log.LogInfo((object)"[ACH] Evaluating: Grounded — PASSED"); ApiClient.UnlockAchievement(steamId, "grounded"); } if (localWon && !achLeftmostViolated && pickCountThisMatch >= 3) { Plugin.Log.LogInfo((object)$"[ACH] Evaluating: Instinct — PASSED ({pickCountThisMatch} untouched picks)"); ApiClient.UnlockAchievement(steamId, "instinct"); } achLeftmostViolated = false; if (localWon && (hashSet.Contains("Shields Up") || hashSet.Contains("ShieldsUp"))) { try { PlayerManager instance = PlayerManager.instance; Player val = null; if ((Object)(object)instance != (Object)null && instance.players != null) { foreach (Player player in instance.players) { if ((Object)(object)player != (Object)null && (Object)(object)player.data != (Object)null && (Object)(object)player.data.view != (Object)null && player.data.view.IsMine) { val = player; break; } } } GunAmmo val2 = (((Object)(object)val != (Object)null && (Object)(object)val.data.weaponHandler != (Object)null && (Object)(object)val.data.weaponHandler.gun != (Object)null) ? ((Component)val.data.weaponHandler.gun).GetComponentInChildren(true) : null); if ((Object)(object)val2 != (Object)null) { float num3 = (val2.reloadTime + val2.reloadTimeAdd) * val2.reloadTimeMultiplier; Plugin.Log.LogInfo((object)$"[ACH] God Build check: maxAmmo={val2.maxAmmo} reload={num3:F2}s"); if (val2.maxAmmo <= 1 && num3 <= 1f) { Plugin.Log.LogInfo((object)"[ACH] Evaluating: God Build — PASSED"); ApiClient.UnlockAchievement(steamId, "god_build"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ACH] God Build check failed: " + ex.Message)); } } if (!localWon) { return; } string text3 = ((preMatchCards.Count > 0) ? preMatchCards[0].CardName : ((localCards.Count > 0) ? localCards[0].CardName : "")); if (text3 == "Abyssal Countdown" || text3 == "AbyssalCountdown") { int num4 = abyssalRoundsActivated + (abyssalActivatedThisRound ? 1 : 0); int num5 = num + num2; Plugin.Log.LogInfo((object)$"[ACH] Deep End check: activated {num4}/{num5} rounds"); if (num5 > 0 && num4 >= num5) { Plugin.Log.LogInfo((object)"[ACH] Evaluating: Into the Deep End — PASSED"); ApiClient.UnlockAchievement(steamId, "deep_end"); } } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[ACH] Achievement evaluation error: " + ex2.Message)); } } public static void RegisterLogListener() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown if (!logListenerRegistered) { object obj = <>O.<0>__OnUnityLog; if (obj == null) { LogCallback val = OnUnityLog; <>O.<0>__OnUnityLog = val; obj = (object)val; } Application.logMessageReceived += (LogCallback)obj; logListenerRegistered = true; Plugin.Log.LogInfo((object)"[POLL] Unity log listener registered for card tracking"); } } public static void UnregisterLogListener() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if (logListenerRegistered) { object obj = <>O.<0>__OnUnityLog; if (obj == null) { LogCallback val = OnUnityLog; <>O.<0>__OnUnityLog = val; obj = (object)val; } Application.logMessageReceived -= (LogCallback)obj; logListenerRegistered = false; } } private static void OnUnityLog(string message, string stackTrace, LogType type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)type != 3) { return; } if (message.StartsWith("PICK PHASE")) { if (!inPickPhase) { Plugin.Log.LogInfo((object)"[ACH] Pick phase entered — input gating disabled"); } inPickPhase = true; } else if (message.StartsWith("MOVE PLAYERS END")) { if (inPickPhase) { Plugin.Log.LogInfo((object)"[ACH] Combat begins — input gating enabled"); } inPickPhase = false; if (!isTracking) { try { OnMatchStarted(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ACH] early start hook: " + ex.Message)); } } try { if (NativeUI.IsOpen) { NativeUI.Close(); } } catch { } } else if (message.StartsWith("Round over") || message.StartsWith("Point over")) { inPickPhase = false; } if (!message.StartsWith("Picking Card: ")) { return; } string text = message.Substring("Picking Card: ".Length); string name = ToTitleCase(text.Replace("(Clone)", "").Trim()); name = CardRarityLookup.GetCanonicalName(name); if (string.IsNullOrEmpty(name)) { return; } if (!isTracking) { preMatchPickCount++; preMatchCards.Add(new MatchTracker.CardPickData { CardName = name, CardRarity = CardRarityLookup.GetRarity(name), PickOrder = preMatchPickCount, RoundNumber = 1 }); Plugin.Log.LogInfo((object)$"[POLL] Card stored (pre-match): {name} [#{preMatchPickCount}]"); return; } pickCountThisMatch++; MatchTracker.CardPickData item = new MatchTracker.CardPickData { CardName = name, CardRarity = CardRarityLookup.GetRarity(name), PickOrder = pickCountThisMatch, RoundNumber = currentRound }; localCards.Add(item); _lastLocalPickedCardName = name; Plugin.Log.LogInfo((object)$"[POLL] Card: Local picked {name} [#{pickCountThisMatch}]"); bool flag = false; for (int i = 0; i < localOffers.Count; i++) { MatchTracker.CardOfferData cardOfferData = localOffers[i]; if (cardOfferData.WasPicked && cardOfferData.RoundNumber == currentRound && cardOfferData.CardName == name) { flag = true; break; } } if (!flag) { localOffers.Add(new MatchTracker.CardOfferData { CardName = name, RoundNumber = currentRound, WasPicked = true }); Plugin.Log.LogInfo((object)$"[POLL] Synthesized picked offer for {name} round={currentRound} (log intercept ran first; EndPick reconciles)"); } BroadcastCardPick(name); } private static void BroadcastCardPick(string cardName) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown try { if (PhotonNetwork.InRoom) { broadcastCardNames.Add(cardName); string text = string.Join("|", broadcastCardNames.ToArray()); Hashtable val = new Hashtable(); val[(object)"cr_cards"] = text; PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)("[POLL] Broadcast cards: " + text)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POLL] Card broadcast failed: " + ex.Message)); } } public static void OnOpponentCardPicked(string cardName, string rarity) { cardName = ToTitleCase(cardName); cardName = CardRarityLookup.GetCanonicalName(cardName); if (!isTracking) { preMatchOpponentCards.Add(new MatchTracker.CardPickData { CardName = cardName, CardRarity = rarity, PickOrder = preMatchOpponentCards.Count + 1, RoundNumber = 1 }); Plugin.Log.LogInfo((object)("[HARMONY-CARD] Opp card stored (pre-match): " + cardName)); } else { opponentCardsViaHarmony = true; MatchTracker.CardPickData cardPickData = new MatchTracker.CardPickData { CardName = cardName, CardRarity = rarity, PickOrder = opponentCards.Count + 1, RoundNumber = currentRound }; opponentCards.Add(cardPickData); Plugin.Log.LogInfo((object)$"[HARMONY-CARD] Opp card added: {cardName} [#{cardPickData.PickOrder}] (via Harmony)"); } } private static void PollCardPicks() { try { if (!PhotonNetwork.InRoom || opponentCardsViaHarmony) { return; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null) { return; } Player[] array = playerList; foreach (Player val in array) { if (val == null || val.IsLocal) { continue; } Hashtable customProperties = val.CustomProperties; if (customProperties == null || !((Dictionary)(object)customProperties).ContainsKey((object)"cr_cards")) { continue; } string text = customProperties[(object)"cr_cards"].ToString(); if (string.IsNullOrEmpty(text)) { continue; } string[] array2 = text.Split('|'); int num = array2.Length; if (num < lastKnownOpponentBroadcastCount) { Plugin.Log.LogInfo((object)$"[POLL] Opponent broadcast reset detected ({lastKnownOpponentBroadcastCount} -> {num}), re-syncing"); lastKnownOpponentBroadcastCount = 0; } if (num <= lastKnownOpponentBroadcastCount) { break; } for (int j = lastKnownOpponentBroadcastCount; j < num; j++) { string name = ToTitleCase(array2[j].Trim()); name = CardRarityLookup.GetCanonicalName(name); if (!string.IsNullOrEmpty(name)) { MatchTracker.CardPickData item = new MatchTracker.CardPickData { CardName = name, CardRarity = CardRarityLookup.GetRarity(name), PickOrder = j + 1, RoundNumber = currentRound }; opponentCards.Add(item); Plugin.Log.LogInfo((object)("[POLL] Card: Opp picked " + name + " [via mod sync]")); } } lastKnownOpponentBroadcastCount = num; break; } } catch { } } private static void ResolveFields(GM_ArmsRace gm) { try { Type type = ((object)gm).GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; f_p1Points = type.GetField("p1Points", bindingAttr); f_p2Points = type.GetField("p2Points", bindingAttr); f_p1Rounds = type.GetField("p1Rounds", bindingAttr); f_p2Rounds = type.GetField("p2Rounds", bindingAttr); f_roundsToWinGame = type.GetField("roundsToWinGame", bindingAttr); if (f_roundsToWinGame == null) { f_roundsToWinGame = type.GetField("roundsToWin", bindingAttr); } if (f_roundsToWinGame == null) { f_roundsToWinGame = type.GetField("m_roundsToWinGame", bindingAttr); } if (f_roundsToWinGame != null) { roundsToWin = GetFieldInt(gm, f_roundsToWinGame); if (roundsToWin <= 0) { roundsToWin = 5; } Plugin.Log.LogInfo((object)$"[POLL] Rounds to win: {roundsToWin}"); } else { roundsToWin = 5; Plugin.Log.LogInfo((object)$"[POLL] roundsToWinGame field not found, defaulting to {roundsToWin}"); } if (f_p1Points != null && f_p1Rounds != null) { fieldsResolved = true; Plugin.Log.LogInfo((object)"[POLL] GM_ArmsRace fields resolved"); } } catch (Exception ex) { Plugin.Log.LogError((object)("[POLL] Field resolution failed: " + ex.Message)); } } private static int GetFieldInt(object obj, FieldInfo field) { if (field == null || obj == null) { return 0; } try { return (int)field.GetValue(obj); } catch { return 0; } } public static bool OpponentHasMod() { try { if (!PhotonNetwork.InRoom) { return false; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null) { return false; } Player[] array = playerList; foreach (Player val in array) { if (val == null || val.IsLocal) { continue; } Hashtable customProperties = val.CustomProperties; if (customProperties == null) { continue; } foreach (object key in ((Dictionary)(object)customProperties).Keys) { if (key is string text && text.StartsWith("cr_", StringComparison.Ordinal)) { return true; } } } } catch { } return false; } internal static string StripRichText(string input) { if (string.IsNullOrEmpty(input)) { return input; } return Regex.Replace(input, "<.*?>", "").Trim(); } private static string ToTitleCase(string input) { if (string.IsNullOrEmpty(input)) { return input; } string[] array = input.ToLower().Split(' '); for (int i = 0; i < array.Length; i++) { if (array[i].Length > 0) { array[i] = char.ToUpper(array[i][0]) + array[i].Substring(1); } } return string.Join(" ", array); } private static void ResetMatchStateWithTrail() { TrailCosmetic.OnMatchEnd(); PlayerColorCosmetic.OnMatchEnd(); try { PlayerEffectCosmetic.OnMatchEnd(); } catch { } ResetMatchState(); } private static void ResetMatchState() { //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Expected O, but got Unknown isTracking = false; gameOverReported = false; oneVOneMatchAtStart = false; macroEvidenceDispatched = false; sharedGameToken = ""; previousGameToken = ""; matchStartServerTimestamp = 0; wasGameInProgress = false; pcolorRoomApplied = false; try { TabStatsOverlay.ClearCardBaselines(); } catch { } p1Points = 0; p2Points = 0; p1Rounds = 0; p2Rounds = 0; lastP1Points = 0; lastP2Points = 0; lastP1Rounds = 0; lastP2Rounds = 0; currentRound = 1; localTeamId = -1; playersIdentified = false; opponentSteamIdResolved = false; opponentRankChecked = false; opponentIsRanked = false; matchIsRanked = false; localCards.Clear(); opponentCards.Clear(); localOffers.Clear(); lastKnownP1CardCount = 0; lastKnownP2CardCount = 0; pickCountThisMatch = 0; broadcastCardNames.Clear(); lastKnownOpponentBroadcastCount = 0; preMatchCards.Clear(); preMatchPickCount = 0; opponentCardsViaHarmony = false; preMatchOpponentCards.Clear(); fieldsResolved = false; opponentWasPresent = false; opponentDCReported = false; achTookDamage = false; achPhoenixUsed = false; achDied = false; achMaxOpponentRounds = 0; achWasDown04 = false; lastDeadState = false; lastRemainingRespawns = -1; achFiredShot = false; achMoved = false; achJumped = false; achLeftmostViolated = false; abyssalRoundsActivated = 0; abyssalActivatedThisRound = false; inPickPhase = false; pendingRegicideCheck = false; LocalShotsThisMatch = 0; LocalBlocksThisMatch = 0; LocalKeysThisMatch = 0; LocalMacroSuspectSeconds = 0; LocalMacroPeakKeysPerSecond = 0; LocalMacroPeakClicksPerSecond = 0; LocalMacroPeakEventsPerSecond = 0; inputSuspectWindows.Clear(); inputBucketTimer = 0f; inputBucketCount = 0; inputBucketKeyCount = 0; inputBucketClickCount = 0; inputBucketStartedAtMs = -1L; LocalActiveSecondsThisMatch = 0f; LocalBulletsFiredThisMatch = 0; LocalBulletsHitThisMatch = 0; LocalBlocksActivatedThisMatch = 0; LocalBlocksSuccessfulThisMatch = 0; LocalBlockRawAbsorbs = 0; LocalBlockDedupeDrops = 0; LastBlockActivatedTime = -999f; LastBlockSuccessfulTime = -999f; LastBlockAbsorbTime = -999f; LastLocalHitTime = -999f; LastBlockMissTime = -999f; LastBlockEventLabel = ""; fpsFrameCount = 0; fpsTimeAccum = 0f; fpsBroadcastTimer = 0f; opponentAvgFps = 0; localFpsTimeline.Clear(); tlFrames = 0; tlAccum = 0f; bcFrames = 0; bcAccum = 0f; lastBroadcastRecentFps = 0; oppFpsTimeline.Clear(); oppPingTimeline.Clear(); lastOppGstatsSeq = -1; lastOppSeqAdvanceTime = -1f; localFreezeCount = 0; localFreezeFocusedCount = 0; localFreezeTotalSec = 0f; pingSamples.Clear(); localRecvGapCount = 0; localRecvGapMaxMs = 0; _recvGapOpen = false; oppHbGapCount = 0; _oppHbGapOpen = false; oppFreezeCount = 0; oppFreezeFocusedCount = 0; oppRecvGapCount = 0; _lastTickStopwatchMs = -1L; _hitsRemaining = 0; _activationSuccessCredited = true; BlockChain.Reset(); _loggedHitBudgetDrop = false; localHitTimeline.Clear(); localBlockTimeline.Clear(); oppHitTimeline.Clear(); oppBlockTimeline.Clear(); localFps3sTimeline.Clear(); pointTimes.Clear(); LocalDamageTakenThisMatch = 0f; peerTele.Clear(); OppStatMacroSuspectSeconds = 0; OppStatMacroPeakKeysPerSecond = 0; OppStatMacroPeakClicksPerSecond = 0; OppStatMacroPeakEventsPerSecond = 0; OppStatMacroTimeline = ""; try { if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) { Hashtable val = new Hashtable(); val[(object)"cr_cards"] = ""; PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch { } } public static void OnLocalCardOffered(string cardName, bool wasPicked, int round) { if (!string.IsNullOrEmpty(cardName)) { localOffers.Add(new MatchTracker.CardOfferData { CardName = cardName, RoundNumber = round, WasPicked = wasPicked }); if (wasPicked) { _lastLocalPickedCardName = cardName; } } } public static bool LocalOffersPickedIn(int fromIndex) { if (fromIndex < 0) { fromIndex = 0; } for (int i = fromIndex; i < localOffers.Count; i++) { if (localOffers[i].WasPicked) { return true; } } return false; } } public static class MatchTracker { public class CardPickData { public string CardName; public string CardRarity; public int PickOrder; public int RoundNumber; public bool Rolled; } public class CardOfferData { public string CardName; public int RoundNumber; public bool WasPicked; } public class MatchResult { public bool Won; public int MyRounds; public int TheirRounds; public string OpponentName; public DateTime Timestamp; } public static bool IsInMatch => GameStateWatcher.IsInMatch; public static bool IsInRoom => GameStateWatcher.IsInRoom; public static string LocalSteamId => GameStateWatcher.LocalSteamId; public static string LocalDisplayName => GameStateWatcher.LocalDisplayName; public static string OpponentDisplayName => GameStateWatcher.OpponentDisplayName; public static MatchResult LastResult => GameStateWatcher.LastResult; public static bool HasPendingResult => GameStateWatcher.HasPendingResult; public static int P1Rounds => GameStateWatcher.P1Rounds; public static int P2Rounds => GameStateWatcher.P2Rounds; public static int P1Points => GameStateWatcher.P1Points; public static int P2Points => GameStateWatcher.P2Points; public static int LocalTeamId => GameStateWatcher.LocalTeamId; public static void Initialize() { } } internal static class ModeInfoText { public const string TeamTitle = "2v2 - How It Works"; public const string Team = "Two teams of two play a best-of-3 series.\r\n\r\nHOW TO PLAY\r\n\r\n- Random queue uses an Elo band that widens as you wait.\r\n The server auto-balances the teams.\r\n- Custom lobbies have no Elo band.\r\n Joining the lobby is consent to play.\r\n- All 4 players have 120 seconds to ready up.\r\n If time expires, everyone returns to searching.\r\n- After an auto-queue game with a point margin of 3 or more,\r\n the weakest winner may swap with the strongest loser.\r\n\r\nSCORING\r\n\r\n- The first team to win 2 games wins the series.\r\n- 2v2 uses its own Glicko rating.\r\n It does not change your 1v1 rating.\r\n- Rating updates after the completed series.\r\n- W-L and WR count completed series, not individual games.\r\n\r\nREWARDS\r\n\r\n- Each game gives 600 base XP.\r\n A game win gets x1.5, for 900 base XP.\r\n- A series win gives 50 base Gold.\r\n A series loss gives 25 base Gold.\r\n- The opposing team's rating tier can multiply base rewards.\r\n- Game XP converts to Gold at 100 XP = 1 Gold.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\nRank - Position in the currently selected sort.\r\nPlayer - The player's display name.\r\nRating - The player's separate 2v2 Glicko rating.\r\nW-L - Completed series won and lost.\r\nWR - Series wins divided by completed series.\r\nAvg Mate Elo - Average rating of past teammates.\r\n A teammate uses 2v2 rating after 5 completed series.\r\n Before that, their 1v1 rating is used, or 1500 if absent.\r\nGold - Lifetime Gold earned from 2v2 only.\r\nXP - Lifetime XP earned from 2v2 only.\r\n Gold and XP do not affect your rating-based rank.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded."; public const string OvtTitle = "1v2 - How It Works"; public const string Ovt = "One solo player faces a duo in a best-of-3 series.\r\n\r\nHOW TO PLAY\r\n\r\n- This is a consent queue with no Elo band and no ready-up.\r\n- The server assigns one solo and two duo players.\r\n- Solo Extra Initial Pick is optional.\r\n If anyone enables it, the solo draws 2 cards on the\r\n opening pick.\r\n\r\nSCORING\r\n\r\n- The first side to win 2 games wins the series.\r\n- 1v2 is an UNRANKED beta. No rating is applied yet.\r\n- Games are recorded and will count when ranked play launches.\r\n\r\nREWARDS\r\n\r\n- Each game gives 500 XP.\r\n A game win gets x1.5, for 750 XP.\r\n- A series win gives each winner 40 Gold.\r\n A series loss gives each loser 20 Gold.\r\n- Game XP converts to Gold at 100 XP = 1 Gold.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\n- The tab has separate Solo and Duo boards.\r\n- You appear only on boards for roles you have played.\r\nRank - Activity order: wins, then WR, then games.\r\nPlayer - The player's display name.\r\nW-L - Games won and lost in that role only.\r\nWR - Win rate for games in that role.\r\n- These are activity boards. They are not sorted by Gold.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded."; public const string FfaTitle = "FFA - How It Works"; public const string Ffa = "Free-for-all for 3-10 players. Every player is their own team.\r\nStandard ROUNDS scoring - first to 5 points takes the game.\r\n\r\nHOW TO PLAY\r\n\r\n- There is no Elo band. Joining a lobby is consent to play.\r\n\r\n- Create a lobby, or join an open one from the browser.\r\n The HOST presses Start once at least 3 players are in\r\n (up to 10). Several lobbies can be open at once.\r\n\r\n- If the host leaves, the longest-waiting member becomes\r\n the new host automatically.\r\n\r\n- After each point, everyone except the point winner\r\n picks a card at the same time.\r\n\r\n- The pick timer is shown on screen. A pick landing\r\n near the end grants everyone a little extra time.\r\n When your timer hits zero, your highlighted card is\r\n picked for you automatically. You always get a\r\n card - skipping a pick is not possible.\r\n\r\n- You hold up to 5 cards.\r\n Picking a 6th replaces your oldest card.\r\n\r\nRATING\r\n\r\n- FFA is ranked with its own Glicko rating.\r\n\r\n- Placement uses points, then all round wins earned\r\n (spent ones included), then total kills.\r\n Ties share a place using competition order: 1, 2, 2, 4.\r\n\r\n- Your rating is scored against the players placed\r\n nearest to you (up to 4 of them), so one game can't\r\n swing your rating several times harder in a 10-player\r\n lobby than in a 3-player one.\r\n\r\n- A tied placement counts as a draw. New ratings move\r\n fast and settle down as you play more.\r\n\r\nREWARDS\r\n\r\n- Each game pays 600 base XP, plus 90 XP per player\r\n you placed above.\r\n\r\n- Placement multiplies that: up to x1.5 for winning a\r\n 3-player game, growing with lobby size to x5 for\r\n winning a full 10. Lower places scale down smoothly;\r\n last place keeps the base.\r\n\r\n- Placement Gold comes on top: 10-50 Gold by placement,\r\n scaled by lobby size.\r\n\r\n- A stronger opposing field multiplies the XP part\r\n (the same tier bonus as the other modes).\r\n\r\n- XP converts to Gold at 100 XP = 1 Gold, and level-ups\r\n pay their usual bonus Gold. A level-up landing during\r\n a game shows up inside that game's +g number - that is\r\n how a last place can occasionally out-earn the winner.\r\n\r\n- Spectators can bet Gold on FFA lobbies from this tab.\r\n\r\nREADING THE RECENT FFAS LIST\r\n\r\nDots + N(P) - Full points won.\r\nHalf dots + N(H) - Round wins that\r\n did not become one of that player's full points.\r\nNk - Kills.\r\n+xp +g - That game's XP and Gold\r\n (including any level-up bonus).\r\nGreen/red number - FFA rating change.\r\nCards - The hand held at game end.\r\n +N replaced counts picks that were\r\n pushed out by the 5-card cap - hover the line to see\r\n every pick in order.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\nRank - Position in the currently selected sort.\r\nPlayer - The player's display name.\r\nRating - The player's separate FFA Glicko rating.\r\nGames - Recorded FFA games played.\r\nWins - Games finished in 1st place.\r\nTop3 - Games finished in 1st, 2nd, or 3rd.\r\nAvgPl - Average finishing place. Lower is\r\n better - 1.0 means winning every game.\r\nWR - Share of games won outright.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded.\r\n A leaver keeps their tallies for placement."; } internal class NametagFontRenderer : MonoBehaviour { private class LabelState { public object OriginalFont; public string LastAppliedSku; } private const float POLL_INTERVAL = 0.5f; private static readonly Dictionary _skuToTmpFontName = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "nametag_typeface_caveat", "caveat" }, { "nametag_typeface_permanentmarker", "permanentmarker" }, { "nametag_typeface_courierprime", "courierprime" }, { "nametag_typeface_pacifico", "pacifico" }, { "nametag_typeface_playfairdisplay", "playfairdisplay" }, { "nametag_typeface_specialelite", "specialelite" }, { "nametag_typeface_vt323", "vt323" }, { "nametag_typeface_medievalsharp", "medievalsharp" }, { "nametag_typeface_smokum", "smokum" }, { "nametag_typeface_rye", "rye" }, { "nametag_typeface_orbitron", "orbitron" }, { "nametag_typeface_greatvibes", "greatvibes" }, { "nametag_typeface_cinzeldecorative", "cinzeldecorative" }, { "nametag_typeface_pressstart2p", "pressstart2p" }, { "nametag_typeface_audiowide", "audiowide" }, { "nametag_typeface_monoton", "monoton" }, { "nametag_typeface_bungeeshade", "bungeeshade" }, { "nametag_typeface_metalmania", "metalmania" }, { "nametag_typeface_unifrakturmaguntia", "unifrakturmaguntia" }, { "nametag_typeface_creepster", "creepster" }, { "nametag_typeface_rubikpuddles", "rubikpuddles" }, { "nametag_typeface_rubikmarkerhatch", "rubikmarkerhatch" } }; private static Dictionary _bundledFontsByName; private static bool _bundleLoadAttempted; private static object _fontBundle; private static Type _tTmpText; private static Type _tTmpFontAsset; private static PropertyInfo _pText; private static PropertyInfo _pFont; private static MethodInfo _mCreateFontAsset; private static MethodInfo _mSetAllDirty; private static MethodInfo _mUpdateMaterial; private static MethodInfo _mForceMeshUpdate; private static bool _reflectionReady; private readonly Dictionary _states = new Dictionary(); private static readonly Dictionary _fontAssetCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly HashSet _fontBuildFailed = new HashSet(StringComparer.OrdinalIgnoreCase); private static bool _reflectionLoggedMissing; private static bool _loggedFirstApply; private static bool TryBindReflection() { if (_reflectionReady) { return true; } try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (_tTmpText == null) { _tTmpText = assembly.GetType("TMPro.TMP_Text"); } if (_tTmpFontAsset == null) { _tTmpFontAsset = assembly.GetType("TMPro.TMP_FontAsset"); } if (_tTmpText != null && _tTmpFontAsset != null) { break; } } if (_tTmpText == null || _tTmpFontAsset == null) { if (!_reflectionLoggedMissing) { _reflectionLoggedMissing = true; Plugin.Log.LogWarning((object)$"[TYPEFACE] TMP types not found (tmpText={_tTmpText != null}, tmpFontAsset={_tTmpFontAsset != null}) — custom fonts disabled."); } return false; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; _pText = _tTmpText.GetProperty("text", bindingAttr); _pFont = _tTmpText.GetProperty("font", bindingAttr); _mCreateFontAsset = _tTmpFontAsset.GetMethod("CreateFontAsset", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Font) }, null); if (_mCreateFontAsset == null) { MethodInfo[] methods = _tTmpFontAsset.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "CreateFontAsset")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length >= 1 && parameters[0].ParameterType == typeof(Font)) { _mCreateFontAsset = methodInfo; break; } } } } BindingFlags bindingAttr2 = BindingFlags.Instance | BindingFlags.Public; _mSetAllDirty = _tTmpText.GetMethod("SetAllDirty", bindingAttr2); _mUpdateMaterial = _tTmpText.GetMethod("UpdateMaterial", bindingAttr2); _mForceMeshUpdate = _tTmpText.GetMethod("ForceMeshUpdate", bindingAttr2, null, new Type[2] { typeof(bool), typeof(bool) }, null); _reflectionReady = _pText != null && _pFont != null && _mCreateFontAsset != null; if (!_reflectionReady && !_reflectionLoggedMissing) { _reflectionLoggedMissing = true; Plugin.Log.LogWarning((object)$"[TYPEFACE] reflection incomplete (pText={_pText != null}, pFont={_pFont != null}, mCreateFontAsset={_mCreateFontAsset != null}) — custom fonts disabled."); } else if (_reflectionReady) { Plugin.Log.LogInfo((object)"[TYPEFACE] reflection bound OK — custom fonts enabled."); } return _reflectionReady; } catch { return false; } } private void OnEnable() { ((MonoBehaviour)this).StartCoroutine(PollLoop()); } private void OnDisable() { ((MonoBehaviour)this).StopAllCoroutines(); RestoreAllLabels(); } private IEnumerator PollLoop() { WaitForSeconds wait = new WaitForSeconds(0.5f); while (true) { try { ScanAndApply(); } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogWarning((object)("[TYPEFACE] scan error: " + ex2.Message)); } yield return wait; } } private void ScanAndApply() { if (!TryBindReflection()) { return; } if (!PhotonNetwork.InRoom) { if (_states.Count > 0) { RestoreAllLabels(); } return; } Dictionary dictionary = new Dictionary(StringComparer.Ordinal); Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if (val == null) { continue; } string text = NametagStyler.Clean(val.NickName ?? ""); if (string.IsNullOrEmpty(text)) { continue; } string value = ""; try { if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).TryGetValue((object)"cr_nametag_typeface", out object value2)) { value = value2?.ToString() ?? ""; } } catch { } dictionary[text] = value; } if (dictionary.Count == 0) { return; } Object[] array = Object.FindObjectsOfType(_tTmpText); HashSet hashSet = new HashSet(); Object[] array2 = array; foreach (Object val2 in array2) { Component val3 = (Component)(object)((val2 is Component) ? val2 : null); if (val3 != null) { hashSet.Add(val3); string name; try { name = (_pText.GetValue(val3) as string) ?? ""; } catch { continue; } string text2 = NametagStyler.Clean(name); string value3; if (string.IsNullOrEmpty(text2)) { RestoreLabel(val3); } else if (!dictionary.TryGetValue(text2, out value3)) { RestoreLabel(val3); } else { ApplyFont(val3, value3); } } } if (_states.Count <= 0) { return; } List list = null; foreach (KeyValuePair state in _states) { if (!hashSet.Contains(state.Key)) { if (list == null) { list = new List(); } list.Add(state.Key); } } if (list == null) { return; } foreach (Component item in list) { _states.Remove(item); } } private void ApplyFont(Component comp, string sku) { if (!_states.TryGetValue(comp, out var value)) { value = new LabelState(); try { value.OriginalFont = _pFont.GetValue(comp); } catch { return; } if (value.OriginalFont == null) { return; } _states[comp] = value; } if (string.IsNullOrEmpty(sku)) { if (value.LastAppliedSku != "") { try { _pFont.SetValue(comp, value.OriginalFont); } catch { } value.LastAppliedSku = ""; } } else { if (sku == value.LastAppliedSku) { return; } object orBuildFontAsset = GetOrBuildFontAsset(sku); if (orBuildFontAsset != null) { try { _pFont.SetValue(comp, orBuildFontAsset); } catch { return; } try { _mSetAllDirty?.Invoke(comp, null); } catch { } try { _mUpdateMaterial?.Invoke(comp, null); } catch { } try { _mForceMeshUpdate?.Invoke(comp, new object[2] { true, true }); } catch { } value.LastAppliedSku = sku; Plugin.Log.LogInfo((object)("[TYPEFACE] Applied " + sku + " to label '" + ((Object)comp).name + "'")); } } } public static object GetOrBuildFontAsset(string sku) { if (string.IsNullOrEmpty(sku)) { return null; } if (_fontAssetCache.TryGetValue(sku, out var value)) { return value; } if (_fontBuildFailed.Contains(sku)) { return null; } if (!TryBindReflection()) { return null; } if (!_skuToTmpFontName.TryGetValue(sku, out var value2)) { Plugin.Log.LogWarning((object)("[TYPEFACE] sku '" + sku + "' not in _skuToTmpFontName map — marking failed.")); _fontBuildFailed.Add(sku); return null; } EnsureBundleLoaded(); if (_bundledFontsByName != null && _bundledFontsByName.TryGetValue(value2, out var value3) && value3 != null) { _fontAssetCache[sku] = value3; Plugin.Log.LogInfo((object)("[TYPEFACE] Resolved " + sku + " → " + value2 + " (from bundle)")); return value3; } Plugin.Log.LogWarning((object)$"[TYPEFACE] TMP font '{value2}' for sku '{sku}' not in bundle — disabled. (Bundle present? {_bundledFontsByName != null})"); _fontBuildFailed.Add(sku); return null; } private static void EnsureBundleLoaded() { if (_bundleLoadAttempted) { return; } _bundleLoadAttempted = true; try { string location = Assembly.GetExecutingAssembly().Location; string directoryName = Path.GetDirectoryName(location); string text = Path.Combine(directoryName, "comp-rounds-fonts"); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("[TYPEFACE] Font bundle not found at " + text + " — typefaces disabled. Run the Unity Font Bundler to produce it.")); return; } AssetBundle val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("[TYPEFACE] AssetBundle.LoadFromFile returned null for " + text + " — corrupt or wrong Unity version.")); return; } _fontBundle = val; string[] allAssetNames = val.GetAllAssetNames(); _bundledFontsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); string[] array = allAssetNames; foreach (string text2 in array) { Object val2 = val.LoadAsset(text2, _tTmpFontAsset); if (!(val2 == (Object)null)) { string name = val2.name; if (!string.IsNullOrEmpty(name)) { _bundledFontsByName[name] = val2; } } } Plugin.Log.LogInfo((object)$"[TYPEFACE] Font bundle loaded: {_bundledFontsByName.Count} TMP_FontAssets available."); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TYPEFACE] Bundle load failed: " + ex.Message)); } } public static void LogAvailableTmpFonts() { if (!TryBindReflection()) { return; } try { Object[] array = Resources.FindObjectsOfTypeAll(_tTmpFontAsset); int num = ((array != null) ? array.Length : 0); Plugin.Log.LogInfo((object)$"[TYPEFACE] Available TMP_FontAssets in memory: {num}"); if (array == null) { return; } HashSet hashSet = new HashSet(); Object[] array2 = array; foreach (Object val in array2) { string text = ((val != null) ? val.name : null) ?? "(unnamed)"; if (hashSet.Add(text)) { Plugin.Log.LogInfo((object)("[TYPEFACE] - " + text)); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TYPEFACE] LogAvailableTmpFonts failed: " + ex.Message)); } } public static bool ApplyFontToLabel(object tmpLabel, string sku, Dictionary originalFontStore) { if (tmpLabel == null) { return false; } if (!TryBindReflection()) { return false; } if (!_loggedFirstApply) { _loggedFirstApply = true; ManualLogSource log = Plugin.Log; string[] obj = new string[5] { "[TYPEFACE] first ApplyFontToLabel call: sku='", sku, "' label='", null, null }; object obj2 = ((tmpLabel is Component) ? tmpLabel : null); obj[3] = ((obj2 != null) ? ((Object)obj2).name : null) ?? "(null)"; obj[4] = "'"; log.LogInfo((object)string.Concat(obj)); } try { object value = _pFont.GetValue(tmpLabel); if (originalFontStore != null && !originalFontStore.ContainsKey(tmpLabel) && value != null) { originalFontStore[tmpLabel] = value; } object value2; object obj3 = ((originalFontStore != null && originalFontStore.TryGetValue(tmpLabel, out value2)) ? value2 : value); object obj4 = (string.IsNullOrEmpty(sku) ? obj3 : GetOrBuildFontAsset(sku)); if (obj4 == null) { obj4 = obj3; } if (obj4 == null || value == obj4) { return false; } _pFont.SetValue(tmpLabel, obj4); try { _mSetAllDirty?.Invoke(tmpLabel, null); } catch { } try { _mUpdateMaterial?.Invoke(tmpLabel, null); } catch { } try { _mForceMeshUpdate?.Invoke(tmpLabel, new object[2] { true, true }); } catch { } return true; } catch { return false; } } private void RestoreLabel(Component comp) { if ((Object)(object)comp == (Object)null || !_states.TryGetValue(comp, out var value)) { return; } if (!string.IsNullOrEmpty(value.LastAppliedSku) && value.OriginalFont != null) { try { _pFont.SetValue(comp, value.OriginalFont); } catch { } } value.LastAppliedSku = ""; } private void RestoreAllLabels() { foreach (KeyValuePair state in _states) { if (!((Object)(object)state.Key == (Object)null) && !string.IsNullOrEmpty(state.Value.LastAppliedSku) && state.Value.OriginalFont != null) { try { _pFont.SetValue(state.Key, state.Value.OriginalFont); } catch { } state.Value.LastAppliedSku = ""; } } } } internal class NametagGlowRenderer : MonoBehaviour { private class LabelState { public Material OriginalMaterial; public string LastAppliedSku; public Material AppliedMaterial; } private class MaterialCacheKey : IEquatable { public Material BaseMaterial; public string Sku; public bool Equals(MaterialCacheKey other) { return other != null && BaseMaterial == other.BaseMaterial && Sku == other.Sku; } public override bool Equals(object obj) { return Equals(obj as MaterialCacheKey); } public override int GetHashCode() { Material baseMaterial = BaseMaterial; return ((baseMaterial != null) ? ((Object)baseMaterial).GetInstanceID() : 0) ^ (Sku?.GetHashCode() ?? 0); } } private const float POLL_INTERVAL = 0.5f; private static Type _tTmpText; private static PropertyInfo _pText; private static PropertyInfo _pFontSharedMaterial; private static PropertyInfo _pFontMaterial; private static MethodInfo _mSetMaterialDirty; private static MethodInfo _mSetVerticesDirty; private static MethodInfo _mSetLayoutDirty; private static MethodInfo _mUpdateMaterial; private static bool _reflectionReady; private readonly Dictionary _states = new Dictionary(); private readonly Dictionary _matCache = new Dictionary(); private static bool TryBindReflection() { if (_reflectionReady) { return true; } try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { _tTmpText = assembly.GetType("TMPro.TMP_Text"); if (_tTmpText != null) { break; } } if (_tTmpText == null) { return false; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; _pText = _tTmpText.GetProperty("text", bindingAttr); _pFontSharedMaterial = _tTmpText.GetProperty("fontSharedMaterial", bindingAttr); _pFontMaterial = _tTmpText.GetProperty("fontMaterial", bindingAttr); _mSetMaterialDirty = _tTmpText.GetMethod("SetMaterialDirty", bindingAttr); _mSetVerticesDirty = _tTmpText.GetMethod("SetVerticesDirty", bindingAttr); _mSetLayoutDirty = _tTmpText.GetMethod("SetLayoutDirty", bindingAttr); _mUpdateMaterial = _tTmpText.GetMethod("UpdateMaterial", bindingAttr); _reflectionReady = _pText != null && _pFontSharedMaterial != null; return _reflectionReady; } catch { return false; } } private void OnEnable() { ((MonoBehaviour)this).StartCoroutine(PollLoop()); } private void OnDisable() { ((MonoBehaviour)this).StopAllCoroutines(); RestoreAllLabels(); } private IEnumerator PollLoop() { WaitForSeconds wait = new WaitForSeconds(0.5f); while (true) { try { ScanAndApply(); } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogWarning((object)("[GLOW] scan error: " + ex2.Message)); } yield return wait; } } private void ScanAndApply() { if (!TryBindReflection()) { return; } if (!PhotonNetwork.InRoom) { if (_states.Count > 0) { RestoreAllLabels(); } return; } Dictionary dictionary = new Dictionary(StringComparer.Ordinal); Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if (val == null) { continue; } string text = NametagStyler.Clean(val.NickName ?? ""); if (string.IsNullOrEmpty(text)) { continue; } string value = ""; try { if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).TryGetValue((object)"cr_nametag_glow", out object value2)) { value = value2?.ToString() ?? ""; } } catch { } dictionary[text] = value; } if (dictionary.Count == 0) { return; } Object[] array = Object.FindObjectsOfType(_tTmpText); HashSet hashSet = new HashSet(); Object[] array2 = array; foreach (Object val2 in array2) { Component val3 = (Component)(object)((val2 is Component) ? val2 : null); if (val3 != null) { hashSet.Add(val3); string name; try { name = (_pText.GetValue(val3) as string) ?? ""; } catch { continue; } string text2 = NametagStyler.Clean(name); string value3; if (string.IsNullOrEmpty(text2)) { RestoreLabel(val3); } else if (!dictionary.TryGetValue(text2, out value3)) { RestoreLabel(val3); } else { ApplyGlow(val3, value3); } } } if (_states.Count <= 0) { return; } List list = null; foreach (KeyValuePair state in _states) { if (!hashSet.Contains(state.Key)) { if (list == null) { list = new List(); } list.Add(state.Key); } } if (list == null) { return; } foreach (Component item in list) { _states.Remove(item); } } private void ApplyGlow(Component comp, string sku) { if (!_states.TryGetValue(comp, out var value)) { value = new LabelState(); Material val; try { object? value2 = _pFontSharedMaterial.GetValue(comp); val = (Material)((value2 is Material) ? value2 : null); } catch { return; } if ((Object)(object)val == (Object)null) { return; } if (((Object)val).name != null && ((Object)val).name.Contains(" + nametag_")) { Material val2 = null; foreach (KeyValuePair item in _matCache) { if (item.Value == val) { val2 = item.Key.BaseMaterial; break; } } value.OriginalMaterial = val2 ?? val; } else { value.OriginalMaterial = val; } _states[comp] = value; } if (string.IsNullOrEmpty(sku)) { if (value.LastAppliedSku != "") { try { _pFontSharedMaterial.SetValue(comp, value.OriginalMaterial); } catch { } value.LastAppliedSku = ""; } } else { if (sku == value.LastAppliedSku) { return; } MaterialCacheKey key = new MaterialCacheKey { BaseMaterial = value.OriginalMaterial, Sku = sku }; if (!_matCache.TryGetValue(key, out var value3) || (Object)(object)value3 == (Object)null) { value3 = BuildGlowMaterial(value.OriginalMaterial, sku); if ((Object)(object)value3 == (Object)null) { return; } _matCache[key] = value3; } try { if (_pFontMaterial != null) { _pFontMaterial.SetValue(comp, value3); } else { _pFontSharedMaterial.SetValue(comp, value3); } } catch { return; } try { _mSetMaterialDirty?.Invoke(comp, null); } catch { } try { _mSetVerticesDirty?.Invoke(comp, null); } catch { } try { _mSetLayoutDirty?.Invoke(comp, null); } catch { } try { _mUpdateMaterial?.Invoke(comp, null); } catch { } value.LastAppliedSku = sku; value.AppliedMaterial = value3; Plugin.Log.LogInfo((object)("[GLOW] Applied " + sku + " to label '" + ((Object)comp).name + "'")); } } public static Material BuildGlowMaterial(Material baseMat, string sku) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)baseMat == (Object)null) { return null; } try { Material val = new Material(baseMat); ((Object)val).name = ((Object)baseMat).name + " + " + sku; ((Object)val).hideFlags = (HideFlags)61; Color glowColor = NametagStyler.GetGlowColor(sku); try { val.DisableKeyword("UNDERLAY_ON"); } catch { } try { val.DisableKeyword("GLOW_ON"); } catch { } if (val.HasProperty("_OutlineColor")) { val.SetColor("_OutlineColor", glowColor); } if (val.HasProperty("_OutlineWidth")) { val.SetFloat("_OutlineWidth", 0.15f); } if (val.HasProperty("_OutlineSoftness")) { val.SetFloat("_OutlineSoftness", 0.25f); } if (val.HasProperty("_FaceColor")) { val.SetColor("_FaceColor", Color.white); } if (val.HasProperty("_FaceDilate")) { val.SetFloat("_FaceDilate", 0f); } if (val.HasProperty("_UnderlayColor")) { val.SetColor("_UnderlayColor", Color.clear); } if (val.HasProperty("_UnderlayDilate")) { val.SetFloat("_UnderlayDilate", 0f); } if (val.HasProperty("_UnderlaySoftness")) { val.SetFloat("_UnderlaySoftness", 0f); } if (val.HasProperty("_GlowOuter")) { val.SetFloat("_GlowOuter", 0f); } if (val.HasProperty("_GlowPower")) { val.SetFloat("_GlowPower", 0f); } float num = (val.HasProperty("_OutlineWidth") ? val.GetFloat("_OutlineWidth") : (-1f)); float num2 = (val.HasProperty("_OutlineSoftness") ? val.GetFloat("_OutlineSoftness") : (-1f)); Color val2 = (val.HasProperty("_FaceColor") ? val.GetColor("_FaceColor") : Color.magenta); Color val3 = (val.HasProperty("_OutlineColor") ? val.GetColor("_OutlineColor") : Color.magenta); Plugin.Log.LogInfo((object)$"[GLOW] post-set props: outlineWidth={num} outlineSoftness={num2} faceColor=({val2.r:F2},{val2.g:F2},{val2.b:F2},{val2.a:F2}) outlineColor=({val3.r:F2},{val3.g:F2},{val3.b:F2},{val3.a:F2})"); string text = ""; try { text = string.Join(",", val.shaderKeywords); } catch { } ManualLogSource log = Plugin.Log; string[] obj4 = new string[9] { "[GLOW] Built material for ", sku, " (base=", ((Object)baseMat).name, ", shader=", null, null, null, null }; Shader shader = val.shader; obj4[5] = ((shader != null) ? ((Object)shader).name : null); obj4[6] = ", keywords=["; obj4[7] = text; obj4[8] = "])"; log.LogInfo((object)string.Concat(obj4)); return val; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[GLOW] BuildGlowMaterial(" + sku + ") failed: " + ex.Message)); return null; } } public static bool ApplyGlowToLabel(object tmpLabel, string sku, Dictionary originalMaterialStore, Dictionary glowMaterialCache) { if (tmpLabel == null) { return false; } if (!TryBindReflection()) { return false; } try { object? value = _pFontSharedMaterial.GetValue(tmpLabel); Material val = (Material)((value is Material) ? value : null); if (originalMaterialStore != null && !originalMaterialStore.ContainsKey(tmpLabel) && (Object)(object)val != (Object)null) { originalMaterialStore[tmpLabel] = val; } Material value2; Material val2 = ((originalMaterialStore != null && originalMaterialStore.TryGetValue(tmpLabel, out value2)) ? value2 : val); Material value3; if (string.IsNullOrEmpty(sku)) { value3 = val2; } else if (glowMaterialCache == null || !glowMaterialCache.TryGetValue(sku, out value3) || (Object)(object)value3 == (Object)null) { value3 = BuildGlowMaterial(val2, sku); if (glowMaterialCache != null && (Object)(object)value3 != (Object)null) { glowMaterialCache[sku] = value3; } } if ((Object)(object)value3 == (Object)null || val == value3) { return false; } if (_pFontMaterial != null) { _pFontMaterial.SetValue(tmpLabel, value3); } else { _pFontSharedMaterial.SetValue(tmpLabel, value3); } try { _mSetMaterialDirty?.Invoke(tmpLabel, null); } catch { } try { _mSetVerticesDirty?.Invoke(tmpLabel, null); } catch { } try { _mUpdateMaterial?.Invoke(tmpLabel, null); } catch { } return true; } catch { return false; } } public static Material BuildDarkOutlineMaterial(Material baseMat) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)baseMat == (Object)null) { return null; } try { Material val = new Material(baseMat); ((Object)val).name = ((Object)baseMat).name + " + podium-outline"; ((Object)val).hideFlags = (HideFlags)61; try { val.DisableKeyword("UNDERLAY_ON"); } catch { } try { val.DisableKeyword("GLOW_ON"); } catch { } if (val.HasProperty("_OutlineColor")) { val.SetColor("_OutlineColor", new Color(0f, 0f, 0f, 0.9f)); } if (val.HasProperty("_OutlineWidth")) { val.SetFloat("_OutlineWidth", 0.18f); } if (val.HasProperty("_OutlineSoftness")) { val.SetFloat("_OutlineSoftness", 0.1f); } return val; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[GLOW] BuildDarkOutlineMaterial failed: " + ex.Message)); return null; } } public static bool ApplyOutlineToLabel(object tmpLabel, bool on, Dictionary originalMaterialStore, Dictionary outlineMaterialCache) { if (tmpLabel == null) { return false; } if (!TryBindReflection()) { return false; } try { object? value = _pFontSharedMaterial.GetValue(tmpLabel); Material val = (Material)((value is Material) ? value : null); if (originalMaterialStore != null && !originalMaterialStore.ContainsKey(tmpLabel) && (Object)(object)val != (Object)null) { originalMaterialStore[tmpLabel] = val; } Material value2; Material val2 = ((originalMaterialStore != null && originalMaterialStore.TryGetValue(tmpLabel, out value2)) ? value2 : val); Material value3; if (!on) { value3 = val2; } else { if ((Object)(object)val2 == (Object)null) { return false; } if (outlineMaterialCache == null || !outlineMaterialCache.TryGetValue(val2, out value3) || (Object)(object)value3 == (Object)null) { value3 = BuildDarkOutlineMaterial(val2); if (outlineMaterialCache != null && (Object)(object)value3 != (Object)null) { outlineMaterialCache[val2] = value3; } } } if ((Object)(object)value3 == (Object)null || val == value3) { return false; } if (_pFontMaterial != null) { _pFontMaterial.SetValue(tmpLabel, value3); } else { _pFontSharedMaterial.SetValue(tmpLabel, value3); } try { _mSetMaterialDirty?.Invoke(tmpLabel, null); } catch { } try { _mSetVerticesDirty?.Invoke(tmpLabel, null); } catch { } try { _mUpdateMaterial?.Invoke(tmpLabel, null); } catch { } return true; } catch { return false; } } private void RestoreLabel(Component comp) { if ((Object)(object)comp == (Object)null || !_states.TryGetValue(comp, out var value)) { return; } if (!string.IsNullOrEmpty(value.LastAppliedSku) && (Object)(object)value.OriginalMaterial != (Object)null) { try { _pFontSharedMaterial.SetValue(comp, value.OriginalMaterial); } catch { } } value.LastAppliedSku = ""; } private void RestoreAllLabels() { foreach (KeyValuePair state in _states) { if (!((Object)(object)state.Key == (Object)null) && !string.IsNullOrEmpty(state.Value.LastAppliedSku) && !((Object)(object)state.Value.OriginalMaterial == (Object)null)) { try { _pFontSharedMaterial.SetValue(state.Key, state.Value.OriginalMaterial); } catch { } state.Value.LastAppliedSku = ""; } } } } internal static class NametagStyler { private static string _baseName; private static readonly Dictionary _tagsBySku = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "nametag_bold", ("", "") }, { "nametag_italic", ("", "") }, { "nametag_underline", ("", "") }, { "nametag_strike", ("", "") }, { "nametag_color_red", ("", "") }, { "nametag_color_cyan", ("", "") }, { "nametag_color_gold", ("", "") }, { "nametag_color_purple", ("", "") }, { "nametag_color_green", ("", "") }, { "nametag_color_pink", ("", "") }, { "nametag_neon_pink", ("", "") }, { "nametag_neon_cyan", ("", "") }, { "nametag_neon_lime", ("", "") }, { "nametag_neon_orange", ("", "") }, { "nametag_neon_violet", ("", "") }, { "nametag_neon_toxic", ("", "") }, { "nametag_neon_glowyellow", ("", "") }, { "nametag_font_caps", ("", "") }, { "nametag_font_smallcaps", ("", "") }, { "nametag_font_spaced", ("", "") }, { "nametag_size_smaller", ("", "") }, { "nametag_size_bigger", ("", "") }, { "nametag_size_huge", ("", "") }, { "nametag_size_xl", ("", "") }, { "nametag_color_emerald", ("", "") }, { "nametag_color_amber", ("", "") }, { "nametag_color_coral", ("", "") }, { "nametag_color_indigo", ("", "") }, { "nametag_float", ("", "") } }; private static readonly string[] _RAINBOW_COLORS = new string[6] { "#FF5566", "#FFB347", "#FFEE55", "#88FF99", "#55CCFF", "#BB88FF" }; private static readonly Dictionary _GRADIENT_PAIRS = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "nametag_gradient_sunset", (new Color(1f, 0.7f, 0.28f), new Color(0.9f, 0.3f, 0.54f)) }, { "nametag_gradient_aurora", (new Color(0.3f, 1f, 0.85f), new Color(0.65f, 0.4f, 1f)) }, { "nametag_gradient_ocean", (new Color(0.35f, 0.95f, 1f), new Color(0.15f, 0.2f, 0.65f)) }, { "nametag_gradient_ember", (new Color(1f, 0.95f, 0.3f), new Color(0.8f, 0.15f, 0.1f)) }, { "nametag_gradient_galaxy", (new Color(1f, 0.35f, 0.85f), new Color(0.35f, 0.65f, 1f)) } }; private static string _BuildRainbow(string clean) { if (string.IsNullOrEmpty(clean)) { return clean; } if (clean.IndexOf('<') >= 0) { return clean; } StringBuilder stringBuilder = new StringBuilder(clean.Length * 18); int num = 0; foreach (char c in clean) { if (char.IsWhiteSpace(c)) { stringBuilder.Append(c); continue; } stringBuilder.Append("') .Append(c) .Append(""); num++; } return stringBuilder.ToString(); } private static string _BuildGradientLerp(string clean, Color start, Color end) { //IL_0087: 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_009a: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(clean)) { return clean; } if (clean.IndexOf('<') >= 0) { return clean; } int num = 0; foreach (char c in clean) { if (!char.IsWhiteSpace(c)) { num++; } } switch (num) { case 0: return clean; case 1: return "" + clean + ""; default: { StringBuilder stringBuilder = new StringBuilder(clean.Length * 18); int num2 = 0; foreach (char c2 in clean) { if (char.IsWhiteSpace(c2)) { stringBuilder.Append(c2); continue; } float num3 = (float)num2 / (float)(num - 1); Color val = Color.Lerp(start, end, num3); stringBuilder.Append("') .Append(c2) .Append(""); num2++; } return stringBuilder.ToString(); } } } public static Color GetGlowColor(string sku) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(sku)) { return Color.clear; } return (Color)(sku switch { "nametag_glow_red" => new Color(1f, 0.27f, 0.33f, 1f), "nametag_glow_blue" => new Color(0.27f, 0.53f, 1f, 1f), "nametag_glow_gold" => new Color(1f, 0.8f, 0.27f, 1f), "nametag_glow_pink" => new Color(1f, 0.53f, 0.8f, 1f), "nametag_neon_pink" => new Color(1f, 0.12f, 0.55f, 1f), "nametag_neon_cyan" => new Color(0.12f, 0.94f, 1f, 1f), "nametag_neon_lime" => new Color(0.36f, 1f, 0.12f, 1f), "nametag_neon_orange" => new Color(1f, 0.48f, 0.12f, 1f), "nametag_neon_violet" => new Color(0.83f, 0.13f, 1f, 1f), "nametag_neon_toxic" => new Color(0.66f, 1f, 0.12f, 1f), "nametag_neon_glowyellow" => new Color(1f, 0.98f, 0.61f, 1f), _ => Color.clear, }); } public static string GetSubgroup(string sku) { if (string.IsNullOrEmpty(sku)) { return null; } if (sku.StartsWith("nametag_color_", StringComparison.OrdinalIgnoreCase)) { return "color"; } if (sku.StartsWith("nametag_neon_", StringComparison.OrdinalIgnoreCase)) { return "color"; } if (sku.StartsWith("nametag_glow_", StringComparison.OrdinalIgnoreCase)) { return "glow"; } if (sku.StartsWith("nametag_size_", StringComparison.OrdinalIgnoreCase)) { return "size"; } if (sku.StartsWith("nametag_typeface_", StringComparison.OrdinalIgnoreCase)) { return "typeface"; } if (sku.StartsWith("nametag_font_", StringComparison.OrdinalIgnoreCase)) { return "font"; } if (sku == "nametag_rainbow" || sku.StartsWith("nametag_gradient_", StringComparison.OrdinalIgnoreCase)) { return "color"; } return null; } public static string GetActiveTypefaceSku(List activeSkus) { if (activeSkus == null) { return ""; } foreach (string activeSku in activeSkus) { if (!string.IsNullOrEmpty(activeSku) && activeSku.StartsWith("nametag_typeface_", StringComparison.OrdinalIgnoreCase)) { return activeSku; } } return ""; } public static string Clean(string name) { if (string.IsNullOrEmpty(name)) { return name; } return Regex.Replace(name, "<.*?>", "").Trim(); } public static string WrapForSku(string name, string sku) { //IL_004c: 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) if (string.IsNullOrEmpty(name)) { return name; } if (sku == null) { return name; } if (sku == "nametag_rainbow") { return _BuildRainbow(name); } if (_GRADIENT_PAIRS.TryGetValue(sku, out (Color, Color) value)) { return _BuildGradientLerp(name, value.Item1, value.Item2); } if (_tagsBySku.TryGetValue(sku, out (string, string) value2)) { return value2.Item1 + name + value2.Item2; } return name; } public static string Wrap(string name, List activeSkus) { //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) string text = Clean(name); if (string.IsNullOrEmpty(text)) { return text; } if (activeSkus == null || activeSkus.Count == 0) { return text; } string[][] array = new string[8][] { new string[3] { "nametag_font_caps", "nametag_font_smallcaps", "nametag_font_spaced" }, new string[4] { "nametag_size_smaller", "nametag_size_bigger", "nametag_size_huge", "nametag_size_xl" }, new string[17] { "nametag_color_red", "nametag_color_cyan", "nametag_color_gold", "nametag_color_purple", "nametag_color_green", "nametag_color_pink", "nametag_color_emerald", "nametag_color_amber", "nametag_color_coral", "nametag_color_indigo", "nametag_neon_pink", "nametag_neon_cyan", "nametag_neon_lime", "nametag_neon_orange", "nametag_neon_violet", "nametag_neon_toxic", "nametag_neon_glowyellow" }, new string[1] { "nametag_strike" }, new string[1] { "nametag_underline" }, new string[1] { "nametag_italic" }, new string[1] { "nametag_bold" }, new string[1] { "nametag_float" } }; string text2 = text; foreach (string activeSku in activeSkus) { if (!string.IsNullOrEmpty(activeSku)) { if (activeSku == "nametag_rainbow") { text2 = _BuildRainbow(text2); break; } if (_GRADIENT_PAIRS.TryGetValue(activeSku, out (Color, Color) value)) { text2 = _BuildGradientLerp(text2, value.Item1, value.Item2); break; } } } string[][] array2 = array; foreach (string[] array3 in array2) { string[] array4 = array3; foreach (string text3 in array4) { if (activeSkus.Contains(text3) && _tagsBySku.TryGetValue(text3, out (string, string) value2)) { text2 = value2.Item1 + text2 + value2.Item2; break; } } } return text2; } public static string GetActiveGlowSku(List activeSkus) { if (activeSkus == null) { return ""; } foreach (string activeSku in activeSkus) { if (!string.IsNullOrEmpty(activeSku) && activeSku.StartsWith("nametag_glow_", StringComparison.OrdinalIgnoreCase)) { return activeSku; } } foreach (string activeSku2 in activeSkus) { if (!string.IsNullOrEmpty(activeSku2) && activeSku2.StartsWith("nametag_neon_", StringComparison.OrdinalIgnoreCase)) { return activeSku2; } } return ""; } public static void PublishToPhoton() { //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown try { if (!PhotonNetwork.IsConnected || PhotonNetwork.LocalPlayer == null) { return; } if (string.IsNullOrEmpty(_baseName)) { _baseName = Clean(PhotonNetwork.LocalPlayer.NickName); } string text = Clean(PhotonNetwork.LocalPlayer.NickName); if (!string.IsNullOrEmpty(text)) { _baseName = text; } if (string.IsNullOrEmpty(_baseName)) { return; } List list = ApiClient.CachedPlayerStats?.active_nametag_skus; string text2 = Wrap(_baseName, list); if (PhotonNetwork.LocalPlayer.NickName != text2) { PhotonNetwork.LocalPlayer.NickName = text2; Plugin.Log.LogInfo((object)$"[NAMETAG] Published '{text2}' ({list?.Count ?? 0} style(s))"); } string activeGlowSku = GetActiveGlowSku(list); string activeTypefaceSku = GetActiveTypefaceSku(list); try { Hashtable customProperties = PhotonNetwork.LocalPlayer.CustomProperties; object value; bool flag = !((Dictionary)(object)customProperties).TryGetValue((object)"cr_nametag_glow", out value) || (value?.ToString() ?? "") != activeGlowSku; object value2; bool flag2 = !((Dictionary)(object)customProperties).TryGetValue((object)"cr_nametag_typeface", out value2) || (value2?.ToString() ?? "") != activeTypefaceSku; if (flag || flag2) { Hashtable val = new Hashtable(); if (flag) { val[(object)"cr_nametag_glow"] = activeGlowSku; } if (flag2) { val[(object)"cr_nametag_typeface"] = activeTypefaceSku; } PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch { } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[NAMETAG] Publish failed: " + ex.Message)); } } } internal static class ClickGuard { private static readonly Dictionary _lastByKey = new Dictionary(); private static readonly object _legacyKey = new object(); public static bool Claim() { return Claim(null); } public static bool Claim(object key) { key = key ?? _legacyKey; float unscaledTime = Time.unscaledTime; if (_lastByKey.TryGetValue(key, out var value) && unscaledTime - value < 0.2f) { return false; } _lastByKey[key] = unscaledTime; if (_lastByKey.Count > 600) { _lastByKey.Clear(); } return true; } } internal static class UIFactory { public struct ScrollViewRefs { public GameObject scrollGO; public GameObject content; public RectTransform contentRT; } internal static Type tImage; internal static Type tButton; internal static Type tCanvas; internal static Type tLE; internal static Type tCanvasGroup; internal static Type tScrollRect; internal static Type tMask; internal static Type tRectMask2D; private static Type tVLG; private static Type tHLG; private static Type tCSF; internal static Type tGR; internal static Type tCanvasScaler; private static Type tTMP; private static bool typesReady; private static object tmpFont; private static bool fontReady; public static Type tListMenu; public static Type tListMenuPage; public static Type tGoBack; private static PropertyInfo pTmpText; private static PropertyInfo pTmpFontSize; private static PropertyInfo pTmpColor; private static PropertyInfo pTmpAlignment; private static PropertyInfo pTmpFont; private static PropertyInfo pTmpOverflow; private static PropertyInfo pTmpRichText; private static PropertyInfo pTmpFontStyle; private static PropertyInfo pTmpRaycastTarget; private static PropertyInfo pTmpCharSpacing; private static PropertyInfo pImgColor; private static PropertyInfo pImgRaycastTarget; private static PropertyInfo pBtnOnClick; private static MethodInfo mOnClickAdd; private static PropertyInfo pSRContent; private static PropertyInfo pSRViewport; private static PropertyInfo pSRVertical; private static PropertyInfo pSRHorizontal; private static PropertyInfo pSRMovementType; private static PropertyInfo pSRScrollSensitivity; private static PropertyInfo pVLGSpacing; private static PropertyInfo pVLGPadding; private static PropertyInfo pVLGChildForceW; private static PropertyInfo pVLGChildForceH; private static PropertyInfo pVLGChildControlW; private static PropertyInfo pVLGChildControlH; private static PropertyInfo pHLGSpacing; private static PropertyInfo pHLGPadding; private static PropertyInfo pHLGChildForceW; private static PropertyInfo pHLGChildForceH; private static PropertyInfo pHLGChildControlW; private static PropertyInfo pHLGChildControlH; private static PropertyInfo pCSFFit; private static PropertyInfo pLEMinW; private static PropertyInfo pLEMinH; private static PropertyInfo pLEPrefW; private static PropertyInfo pLEPrefH; private static PropertyInfo pLEFlexW; private static PropertyInfo pLEFlexH; private static PropertyInfo pLEIgnore; private static bool _unicodeFallbackInstalled; public const int AlignTopLeft = 257; public const int AlignTopCenter = 258; public const int AlignTopRight = 260; public const int AlignMidLeft = 513; public const int AlignMidCenter = 514; public const int AlignMidRight = 516; public static bool Ready => typesReady && fontReady; public static bool InitTypes() { if (typesReady) { return true; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (tImage == null) { tImage = assembly.GetType("UnityEngine.UI.Image"); } if (tButton == null) { tButton = assembly.GetType("UnityEngine.UI.Button"); } if (tScrollRect == null) { tScrollRect = assembly.GetType("UnityEngine.UI.ScrollRect"); } if (tMask == null) { tMask = assembly.GetType("UnityEngine.UI.Mask"); } if (tRectMask2D == null) { tRectMask2D = assembly.GetType("UnityEngine.UI.RectMask2D"); } if (tVLG == null) { tVLG = assembly.GetType("UnityEngine.UI.VerticalLayoutGroup"); } if (tHLG == null) { tHLG = assembly.GetType("UnityEngine.UI.HorizontalLayoutGroup"); } if (tCSF == null) { tCSF = assembly.GetType("UnityEngine.UI.ContentSizeFitter"); } if (tLE == null) { tLE = assembly.GetType("UnityEngine.UI.LayoutElement"); } if (tGR == null) { tGR = assembly.GetType("UnityEngine.UI.GraphicRaycaster"); } if (tTMP == null) { tTMP = assembly.GetType("TMPro.TextMeshProUGUI"); } if (tCanvas == null) { tCanvas = assembly.GetType("UnityEngine.Canvas"); } if (tCanvasScaler == null) { tCanvasScaler = assembly.GetType("UnityEngine.UI.CanvasScaler"); } if (tCanvasGroup == null) { tCanvasGroup = assembly.GetType("UnityEngine.CanvasGroup"); } if (tListMenu == null) { tListMenu = assembly.GetType("ListMenu"); } if (tListMenuPage == null) { tListMenuPage = assembly.GetType("ListMenuPage"); } if (tGoBack == null) { tGoBack = assembly.GetType("GoBack"); } } if (tImage == null || tTMP == null || tButton == null) { Plugin.Log.LogWarning((object)"[UI] Missing UI types"); return false; } if (tListMenu == null || tListMenuPage == null) { Plugin.Log.LogWarning((object)"[UI] Missing ROUNDS types"); return false; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; pTmpText = tTMP.GetProperty("text", bindingAttr); pTmpFontSize = tTMP.GetProperty("fontSize", bindingAttr); pTmpColor = tTMP.GetProperty("color", bindingAttr); pTmpAlignment = tTMP.GetProperty("alignment", bindingAttr); pTmpFont = tTMP.GetProperty("font", bindingAttr); pTmpOverflow = tTMP.GetProperty("overflowMode", bindingAttr); pTmpRichText = tTMP.GetProperty("richText", bindingAttr); pTmpFontStyle = tTMP.GetProperty("fontStyle", bindingAttr); pTmpRaycastTarget = tTMP.GetProperty("raycastTarget", bindingAttr); pTmpCharSpacing = tTMP.GetProperty("characterSpacing", bindingAttr); pImgColor = tImage.GetProperty("color", bindingAttr); pImgRaycastTarget = tImage.GetProperty("raycastTarget", bindingAttr); pBtnOnClick = tButton.GetProperty("onClick", bindingAttr); if (pBtnOnClick != null) { mOnClickAdd = pBtnOnClick.PropertyType.GetMethod("AddListener", new Type[1] { typeof(UnityAction) }); } pSRContent = tScrollRect?.GetProperty("content", bindingAttr); pSRViewport = tScrollRect?.GetProperty("viewport", bindingAttr); pSRVertical = tScrollRect?.GetProperty("vertical", bindingAttr); pSRHorizontal = tScrollRect?.GetProperty("horizontal", bindingAttr); pSRMovementType = tScrollRect?.GetProperty("movementType", bindingAttr); pSRScrollSensitivity = tScrollRect?.GetProperty("scrollSensitivity", bindingAttr); if (tVLG != null) { pVLGSpacing = tVLG.GetProperty("spacing", bindingAttr); pVLGPadding = tVLG.GetProperty("padding", bindingAttr); pVLGChildForceW = tVLG.GetProperty("childForceExpandWidth", bindingAttr); pVLGChildForceH = tVLG.GetProperty("childForceExpandHeight", bindingAttr); pVLGChildControlW = tVLG.GetProperty("childControlWidth", bindingAttr); pVLGChildControlH = tVLG.GetProperty("childControlHeight", bindingAttr); } if (tHLG != null) { pHLGSpacing = tHLG.GetProperty("spacing", bindingAttr); pHLGPadding = tHLG.GetProperty("padding", bindingAttr); pHLGChildForceW = tHLG.GetProperty("childForceExpandWidth", bindingAttr); pHLGChildForceH = tHLG.GetProperty("childForceExpandHeight", bindingAttr); pHLGChildControlW = tHLG.GetProperty("childControlWidth", bindingAttr); pHLGChildControlH = tHLG.GetProperty("childControlHeight", bindingAttr); } if (tCSF != null) { pCSFFit = tCSF.GetProperty("verticalFit", bindingAttr); } if (tLE != null) { pLEMinW = tLE.GetProperty("minWidth", bindingAttr); pLEMinH = tLE.GetProperty("minHeight", bindingAttr); pLEPrefW = tLE.GetProperty("preferredWidth", bindingAttr); pLEPrefH = tLE.GetProperty("preferredHeight", bindingAttr); pLEFlexW = tLE.GetProperty("flexibleWidth", bindingAttr); pLEFlexH = tLE.GetProperty("flexibleHeight", bindingAttr); pLEIgnore = tLE.GetProperty("ignoreLayout", bindingAttr); } typesReady = true; return true; } public static bool InitFont() { if (fontReady) { return true; } if (!typesReady) { return false; } Object[] array = Object.FindObjectsOfType(tTMP); foreach (Object obj in array) { try { object obj2 = pTmpFont?.GetValue(obj); if (obj2 != null) { tmpFont = obj2; fontReady = true; try { UnicodeFallback.Install(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FONT] UnicodeFallback.Install: " + ex.Message)); } return true; } } catch { } } return false; } public static void TryInstallUnicodeFallback() { if (_unicodeFallbackInstalled || tmpFont == null) { return; } try { Type type = tmpFont.GetType(); MethodInfo methodInfo = null; MethodInfo methodInfo2 = null; MethodInfo methodInfo3 = null; MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo4 in methods) { if (!(methodInfo4.Name != "CreateFontAsset")) { ParameterInfo[] parameters = methodInfo4.GetParameters(); if (parameters.Length == 3 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string) && parameters[2].ParameterType == typeof(int)) { methodInfo = methodInfo4; } else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Font)) { methodInfo2 = methodInfo4; } else if (parameters.Length >= 7 && parameters[0].ParameterType == typeof(Font) && parameters[1].ParameterType == typeof(int) && parameters[2].ParameterType == typeof(int) && parameters[3].ParameterType.IsEnum && parameters[4].ParameterType == typeof(int) && parameters[5].ParameterType == typeof(int) && parameters[6].ParameterType.IsEnum && (methodInfo3 == null || parameters.Length < methodInfo3.GetParameters().Length)) { methodInfo3 = methodInfo4; } } } if (methodInfo == null && methodInfo2 == null && methodInfo3 == null) { Plugin.Log.LogWarning((object)"[FONT] no usable TMP_FontAsset.CreateFontAsset overload found — unicode fallback disabled"); return; } string[] collection; try { collection = Font.GetOSInstalledFontNames(); } catch { collection = new string[0]; } HashSet hashSet = new HashSet(collection, StringComparer.OrdinalIgnoreCase); string[][] array = new string[4][] { new string[3] { "Segoe UI", "Arial", "Tahoma" }, new string[3] { "Microsoft YaHei", "SimHei", "SimSun" }, new string[3] { "Yu Gothic UI", "Meiryo", "MS Gothic" }, new string[2] { "Malgun Gothic", "Gulim" } }; List list = new List(); List list2 = new List(); string[][] array2 = array; foreach (string[] array3 in array2) { string[] array4 = array3; foreach (string text in array4) { if (!hashSet.Contains(text)) { continue; } list2.Add(text); bool flag = false; object obj2 = null; string text2 = null; if (methodInfo != null) { try { obj2 = methodInfo.Invoke(null, new object[3] { text, "Regular", 90 }); if (obj2 != null) { text2 = "CreateFontAsset(family,style,size)"; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FONT] by-name path failed for '" + text + "': " + ex.Message)); } } Font val = null; if (obj2 == null && (methodInfo2 != null || methodInfo3 != null)) { try { val = Font.CreateDynamicFontFromOSFont(text, 48); } catch { val = null; } if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("[FONT] fallback build failed for '" + text + "': CreateDynamicFontFromOSFont returned null")); continue; } } if (obj2 == null && methodInfo2 != null) { try { obj2 = methodInfo2.Invoke(null, new object[1] { val }); if (obj2 != null) { text2 = "CreateFontAsset(Font)"; } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[FONT] classic path failed for '" + text + "': " + ex2.Message)); } } if (obj2 == null && methodInfo3 != null) { try { ParameterInfo[] parameters2 = methodInfo3.GetParameters(); object[] array5 = new object[parameters2.Length]; array5[0] = val; array5[1] = 90; array5[2] = 9; array5[3] = Enum.ToObject(parameters2[3].ParameterType, 4165); array5[4] = 1024; array5[5] = 1024; array5[6] = Enum.ToObject(parameters2[6].ParameterType, 1); for (int l = 7; l < parameters2.Length; l++) { array5[l] = ((parameters2[l].ParameterType == typeof(bool)) ? ((object)true) : (parameters2[l].HasDefaultValue ? parameters2[l].DefaultValue : (parameters2[l].ParameterType.IsValueType ? Activator.CreateInstance(parameters2[l].ParameterType) : null))); } obj2 = methodInfo3.Invoke(null, array5); if (obj2 != null) { text2 = "CreateFontAsset(Font,size,pad,mode,w,h,population)"; } } catch (Exception ex3) { Plugin.Log.LogWarning((object)("[FONT] full path failed for '" + text + "': " + ex3.Message)); } } if (obj2 != null) { list.Add(obj2); flag = true; Plugin.Log.LogInfo((object)("[FONT] fallback built via " + text2 + " for '" + text + "'")); } else { Plugin.Log.LogWarning((object)("[FONT] fallback build failed for '" + text + "': all CreateFontAsset paths returned null")); } if (!flag) { continue; } break; } } if (list.Count == 0) { string text3 = ((list2.Count > 0) ? string.Join(", ", list2.ToArray()) : "(no candidates installed)"); Plugin.Log.LogWarning((object)("[FONT] no OS fallback fonts available; tried: " + text3)); return; } AppendToFontList(tmpFont, type, list, "fallbackFontAssetTable"); AppendToFontList(tmpFont, type, list, "fallbackFontAssets"); try { if ((type.Assembly.GetType("TMPro.TMP_Settings")?.GetProperty("fallbackFontAssets", BindingFlags.Static | BindingFlags.Public))?.GetValue(null) is IList list3) { foreach (object item in list) { list3.Add(item); } } } catch (Exception ex4) { Plugin.Log.LogWarning((object)("[FONT] TMP_Settings fallback append failed: " + ex4.Message)); } _unicodeFallbackInstalled = true; Plugin.Log.LogInfo((object)$"[FONT] unicode fallback installed ({list.Count} OS font asset(s)) — foreign names/chat now render"); } catch (Exception ex5) { Plugin.Log.LogWarning((object)("[FONT] unicode fallback install failed: " + ex5.Message)); } } private static void AppendToFontList(object fontAsset, Type fontAssetType, List assets, string memberName) { try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; IList list = null; PropertyInfo property = fontAssetType.GetProperty(memberName, bindingAttr); if (property != null) { list = property.GetValue(fontAsset) as IList; } if (list == null) { FieldInfo field = fontAssetType.GetField(memberName, bindingAttr); if (field != null) { list = field.GetValue(fontAsset) as IList; } if (list == null && field != null) { try { list = (IList)Activator.CreateInstance(field.FieldType); field.SetValue(fontAsset, list); } catch { } } if (list == null && property != null && property.CanWrite) { try { list = (IList)Activator.CreateInstance(property.PropertyType); property.SetValue(fontAsset, list); } catch { } } } if (list == null) { return; } foreach (object asset in assets) { if (!list.Contains(asset)) { list.Add(asset); } } } catch { } } public static GameObject CreatePanel(string name, Transform parent, Color bgColor, Vector2? sizeDelta = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0066: 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_0092: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; if (sizeDelta.HasValue) { val2.sizeDelta = sizeDelta.Value; } if (bgColor.a > 0f) { Component obj = val.AddComponent(tImage); pImgColor?.SetValue(obj, bgColor); pImgRaycastTarget?.SetValue(obj, true); } return val; } private static string _BoldWrap(string s) { if (string.IsNullOrEmpty(s)) { return s; } if (s.StartsWith("") && s.EndsWith("")) { return s; } return "" + s + ""; } public static object CreateText(string name, Transform parent, string text, float fontSize, Color color, int alignment = 257, Vector2? sizeDelta = null, bool richText = true, bool raycastTarget = false) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0101: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent(); Vector2 val3 = (val2.sizeDelta = (Vector2)(((??)sizeDelta) ?? new Vector2(200f, 24f))); if (val3.x > 0f && val3.y > 0f) { AddLE(val, -1f, -1f, val3.x, val3.y); } Component val5 = val.AddComponent(tTMP); try { UnicodeFallback.EnsureCharacters(text); } catch { } pTmpText?.SetValue(val5, richText ? _BoldWrap(text) : text); fontSize = Mathf.Max(fontSize, 12f); pTmpFontSize?.SetValue(val5, fontSize); pTmpColor?.SetValue(val5, color); pTmpRichText?.SetValue(val5, richText); pTmpRaycastTarget?.SetValue(val5, raycastTarget); if (tmpFont != null) { pTmpFont?.SetValue(val5, tmpFont); } pTmpCharSpacing?.SetValue(val5, 1f); try { pTmpFontStyle?.SetValue(val5, Enum.ToObject(pTmpFontStyle.PropertyType, 1)); } catch { } try { Type type = pTmpAlignment?.PropertyType; if (type != null) { pTmpAlignment.SetValue(val5, Enum.ToObject(type, alignment)); } } catch { } return val5; } public static GameObject CreateButton(string name, Transform parent, string label, float fontSize, Color textColor, Color bgColor, UnityAction onClick, Vector2? sizeDelta = null) { //IL_002f: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0071: 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_0091: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown Vector2 val = (Vector2)(((??)sizeDelta) ?? new Vector2(100f, 28f)); GameObject go = CreatePanel(name, parent, bgColor, val); RectTransform component = go.GetComponent(); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); component.anchorMax = val2; component.anchorMin = val2; component.sizeDelta = val; AddLE(go, -1f, -1f, val.x, val.y); CreateText(name + "_Txt", go.transform, label, fontSize, textColor, 514, Vector2.zero); RectTransform component2 = ((Component)go.transform.GetChild(0)).GetComponent(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; Component component3 = ((Component)go.transform.GetChild(0)).GetComponent(tLE); if ((Object)(object)component3 != (Object)null) { Object.Destroy((Object)(object)component3); } Component obj = go.AddComponent(tButton); try { PropertyInfo property = tButton.GetProperty("targetGraphic", BindingFlags.Instance | BindingFlags.Public); Component component4 = go.GetComponent(tImage); if (property != null && (Object)(object)component4 != (Object)null) { property.SetValue(obj, component4); } } catch { } if (pBtnOnClick != null && mOnClickAdd != null && onClick != null) { UnityAction val3 = (UnityAction)delegate { if (ClickGuard.Claim(go)) { onClick.Invoke(); } }; mOnClickAdd.Invoke(pBtnOnClick.GetValue(obj), new object[1] { val3 }); } if (onClick != null) { ClickHandler clickHandler = go.AddComponent(); clickHandler.onClick = delegate { if (ClickGuard.Claim(go)) { onClick.Invoke(); } }; } return go; } public static ScrollViewRefs CreateScrollView(string name, Transform parent, float spacing = 2f, bool childForceExpandWidth = true) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01db: 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) ScrollViewRefs result = default(ScrollViewRefs); GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; GameObject val3 = new GameObject("Viewport"); val3.transform.SetParent(val.transform, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; Component obj = val3.AddComponent(tImage); pImgColor?.SetValue(obj, (object)new Color(0f, 0f, 0f, 0.01f)); tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, true); if (tRectMask2D != null) { val3.AddComponent(tRectMask2D); } else if (tMask != null) { Component obj2 = val3.AddComponent(tMask); tMask.GetProperty("showMaskGraphic", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj2, false); } GameObject val5 = new GameObject("Content"); val5.transform.SetParent(val3.transform, false); RectTransform val6 = val5.AddComponent(); val6.anchorMin = new Vector2(0f, 1f); val6.anchorMax = new Vector2(1f, 1f); val6.pivot = new Vector2(0.5f, 1f); val6.sizeDelta = Vector2.zero; if (tVLG != null) { Component obj3 = val5.AddComponent(tVLG); pVLGSpacing?.SetValue(obj3, spacing); pVLGChildForceW?.SetValue(obj3, childForceExpandWidth); pVLGChildForceH?.SetValue(obj3, false); pVLGChildControlW?.SetValue(obj3, true); pVLGChildControlH?.SetValue(obj3, true); } if (tCSF != null) { Component obj4 = val5.AddComponent(tCSF); Type type = pCSFFit?.PropertyType; if (type != null) { pCSFFit.SetValue(obj4, Enum.ToObject(type, 2)); } } Component obj5 = val.AddComponent(tScrollRect); pSRContent?.SetValue(obj5, val6); pSRViewport?.SetValue(obj5, val4); pSRVertical?.SetValue(obj5, true); pSRHorizontal?.SetValue(obj5, false); pSRScrollSensitivity?.SetValue(obj5, 75f); Type type2 = pSRMovementType?.PropertyType; if (type2 != null) { pSRMovementType.SetValue(obj5, Enum.ToObject(type2, 1)); } result.scrollGO = val; result.content = val5; result.contentRT = val6; return result; } public static void AddVLG(GameObject go, float spacing = 2f, int padL = 0, int padR = 0, int padT = 0, int padB = 0, bool forceExpandW = true, bool forceExpandH = false) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown if (!(tVLG == null)) { Component obj = go.AddComponent(tVLG); pVLGSpacing?.SetValue(obj, spacing); pVLGPadding?.SetValue(obj, (object?)new RectOffset(padL, padR, padT, padB)); pVLGChildForceW?.SetValue(obj, forceExpandW); pVLGChildForceH?.SetValue(obj, forceExpandH); pVLGChildControlW?.SetValue(obj, true); pVLGChildControlH?.SetValue(obj, true); } } public static void AddHLG(GameObject go, float spacing = 4f, int padL = 0, int padR = 0, int padT = 0, int padB = 0, bool forceExpandW = false, bool forceExpandH = true) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown if (!(tHLG == null)) { Component obj = go.AddComponent(tHLG); pHLGSpacing?.SetValue(obj, spacing); pHLGPadding?.SetValue(obj, (object?)new RectOffset(padL, padR, padT, padB)); pHLGChildForceW?.SetValue(obj, forceExpandW); pHLGChildForceH?.SetValue(obj, forceExpandH); pHLGChildControlW?.SetValue(obj, true); pHLGChildControlH?.SetValue(obj, true); } } public static void AddLE(GameObject go, float minW = -1f, float minH = -1f, float prefW = -1f, float prefH = -1f, float flexW = -1f, float flexH = -1f) { if (!(tLE == null)) { Component obj = go.AddComponent(tLE); if (minW >= 0f) { pLEMinW?.SetValue(obj, minW); } if (minH >= 0f) { pLEMinH?.SetValue(obj, minH); } if (prefW >= 0f) { pLEPrefW?.SetValue(obj, prefW); } if (prefH >= 0f) { pLEPrefH?.SetValue(obj, prefH); } if (flexW >= 0f) { pLEFlexW?.SetValue(obj, flexW); } if (flexH >= 0f) { pLEFlexH?.SetValue(obj, flexH); } } } public static void SetPrefH(GameObject go, float prefH) { if (!(tLE == null) && !((Object)(object)go == (Object)null)) { Component component = go.GetComponent(tLE); if ((Object)(object)component != (Object)null) { pLEPrefH?.SetValue(component, prefH); } } } public static void SetPrefWH(GameObject go, float prefW, float prefH) { if (!(tLE == null) && !((Object)(object)go == (Object)null)) { Component component = go.GetComponent(tLE); if (!((Object)(object)component == (Object)null)) { pLEPrefW?.SetValue(component, prefW); pLEPrefH?.SetValue(component, prefH); } } } public static void AddClick(GameObject go, UnityAction onClick) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown if ((Object)(object)go == (Object)null || tButton == null || onClick == null) { return; } Component obj = go.AddComponent(tButton); try { PropertyInfo property = tButton.GetProperty("targetGraphic", BindingFlags.Instance | BindingFlags.Public); Component component = go.GetComponent(tImage); if (property != null && (Object)(object)component != (Object)null) { property.SetValue(obj, component); } } catch { } if (pBtnOnClick != null && mOnClickAdd != null) { UnityAction val = (UnityAction)delegate { if (ClickGuard.Claim(go)) { onClick.Invoke(); } }; mOnClickAdd.Invoke(pBtnOnClick.GetValue(obj), new object[1] { val }); } ClickHandler clickHandler = go.AddComponent(); clickHandler.onClick = delegate { if (ClickGuard.Claim(go)) { onClick.Invoke(); } }; } public static Component CreateFillBar(string name, Transform parent, Color bgColor, Color fillColor, float height = 8f) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name + "_BG"); val.transform.SetParent(parent, false); val.AddComponent(); AddLE(val, -1f, -1f, -1f, height, -1f, 0f); val.AddComponent(tImage); pImgColor?.SetValue(val.GetComponent(tImage), bgColor); GameObject val2 = new GameObject(name + "_Fill"); val2.transform.SetParent(val.transform, false); RectTransform val3 = val2.AddComponent(); val3.anchorMin = Vector2.zero; val3.anchorMax = new Vector2(0f, 1f); val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; val2.AddComponent(tImage); pImgColor?.SetValue(val2.GetComponent(tImage), fillColor); return (Component)(object)val3; } public static void SetFill(Component f, float a) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)f == (Object)null)) { RectTransform val = (RectTransform)(object)((f is RectTransform) ? f : null); if ((Object)(object)val != (Object)null) { val.anchorMax = new Vector2(Mathf.Clamp01(a), 1f); } } } public static void SetText(object t, string s) { if (t != null) { try { UnicodeFallback.EnsureCharacters(s); } catch { } pTmpText?.SetValue(t, _BoldWrap(s ?? "")); } } public static void SetColor(object t, Color c) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (t != null) { pTmpColor?.SetValue(t, c); } } public static void SetBold(object t, bool b) { if (t == null) { return; } try { Type type = pTmpFontStyle?.PropertyType; if (type != null) { pTmpFontStyle.SetValue(t, Enum.ToObject(type, b ? 1 : 0)); } } catch { } } public static void SetWordWrap(object t, bool on) { if (t == null || tTMP == null) { return; } try { tTMP.GetProperty("enableWordWrapping", BindingFlags.Instance | BindingFlags.Public)?.SetValue(t, on); } catch { } } public static void SetTextAutoHeight(object tmp, float minH = 0f) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (tmp == null || tLE == null) { return; } try { GameObject gameObject = ((Component)tmp).gameObject; Component val = gameObject.GetComponent(tLE); if ((Object)(object)val == (Object)null) { val = gameObject.AddComponent(tLE); } tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(val, -1f); tLE.GetProperty("preferredWidth", BindingFlags.Instance | BindingFlags.Public)?.SetValue(val, -1f); if (minH > 0f) { tLE.GetProperty("minHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(val, minH); } } catch { } } public static void SetOverflowMode(object t, int mode) { if (t == null || pTmpOverflow == null) { return; } try { pTmpOverflow.SetValue(t, Enum.ToObject(pTmpOverflow.PropertyType, mode)); } catch { } } public static void SetCharSpacing(object t, float spacing) { if (t != null) { pTmpCharSpacing?.SetValue(t, spacing); } } public static void SetImageColor(GameObject go, Color c) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)go == (Object)null)) { Component component = go.GetComponent(tImage); if ((Object)(object)component != (Object)null) { pImgColor?.SetValue(component, c); } } } public static object GetButtonText(GameObject btn) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown if ((Object)(object)btn == (Object)null) { return null; } foreach (Transform item in btn.transform) { Transform val = item; Component[] components = ((Component)val).GetComponents(); foreach (Component val2 in components) { if (((object)val2).GetType().Name == "TextMeshProUGUI") { return val2; } } } return null; } } public class ClickHandler : MonoBehaviour { public Action onClick; private RectTransform rt; private Camera canvasCamera; private bool cameraResolved; public static bool ModalBlockInput; public bool bypassModalBlock; private void Awake() { rt = ((Component)this).GetComponent(); } private void ResolveCamera() { cameraResolved = true; canvasCamera = null; Transform val = ((Component)this).transform; while ((Object)(object)val != (Object)null) { Component component = ((Component)val).GetComponent(UIFactory.tCanvas); if ((Object)(object)component != (Object)null) { try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; if ((int)UIFactory.tCanvas.GetProperty("renderMode", bindingAttr).GetValue(component) != 0) { ref Camera reference = ref canvasCamera; object? obj = UIFactory.tCanvas.GetProperty("worldCamera", bindingAttr)?.GetValue(component); reference = (Camera)((obj is Camera) ? obj : null); if ((Object)(object)canvasCamera == (Object)null) { canvasCamera = Camera.main; } } break; } catch { break; } } val = val.parent; } } private bool ContainsScreenPoint(RectTransform target, Vector3 point) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { return false; } Vector3[] array = (Vector3[])(object)new Vector3[4]; target.GetWorldCorners(array); float num = float.PositiveInfinity; float num2 = float.PositiveInfinity; float num3 = float.NegativeInfinity; float num4 = float.NegativeInfinity; for (int i = 0; i < array.Length; i++) { Vector3 val = (((Object)(object)canvasCamera != (Object)null) ? canvasCamera.WorldToScreenPoint(array[i]) : array[i]); num = Mathf.Min(num, val.x); num2 = Mathf.Min(num2, val.y); num3 = Mathf.Max(num3, val.x); num4 = Mathf.Max(num4, val.y); } return point.x >= num && point.x <= num3 && point.y >= num2 && point.y <= num4; } private bool IsInsideAncestorMasks(Vector3 point) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (UIFactory.tMask == null && UIFactory.tRectMask2D == null) { return true; } Transform parent = ((Component)this).transform.parent; while ((Object)(object)parent != (Object)null) { try { if (((UIFactory.tMask != null && (Object)(object)((Component)parent).GetComponent(UIFactory.tMask) != (Object)null) || (UIFactory.tRectMask2D != null && (Object)(object)((Component)parent).GetComponent(UIFactory.tRectMask2D) != (Object)null)) && !ContainsScreenPoint((RectTransform)(object)((parent is RectTransform) ? parent : null), point)) { return false; } } catch { } parent = parent.parent; } return true; } private void Update() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rt == (Object)null) && onClick != null && ((Component)this).gameObject.activeInHierarchy && (!ModalBlockInput || bypassModalBlock) && Input.GetMouseButtonDown(0)) { if (!cameraResolved) { ResolveCamera(); } Vector3 mousePosition = Input.mousePosition; if (ContainsScreenPoint(rt, mousePosition) && IsInsideAncestorMasks(mousePosition)) { onClick(); } } } } public static class NativeUI { public struct ChatEntry { public string Line; public DateTime AddedUtc; } private class HistoryRow { public GameObject root; public GameObject seriesGO; public GameObject btnId; public string currentMatchId; public object txtResult; public object txtOpp; public object txtFps; public object txtPing; public object txtXP; public object txtDate; public object txtCards; public object txtOppCards; public object txtSeriesHead; public object txtSeriesElo; public object txtStats; public object txtHitYou; public object txtBlockYou; public object txtKpsYou; public object txtHitOpp; public object txtBlockOpp; public object txtKpsOpp; } private class LBRow { public GameObject root; public GameObject hlWrap; public object txtRank; public object txtLv; public object txtName; public object txtRating; public object txtW; public object txtL; public object txtWL; public object txtGold; public string steamId; } private class CardRow { public GameObject root; public GameObject hl; public object txtName; public object txtRarity; public object txtPicks; public object txtWins; public object txtWR; public object txtPass; public object txtTier; public GameObject tierBtn; public string cardName; } private class AchRow { public GameObject root; public GameObject main; public object txtIcon; public object txtName; public object txtDesc; public object txtDate; public string key; } private sealed class FfaBrowserRow { public GameObject root; public GameObject joinBtn; public object txtInfo; public string lobbyId; } private class FfaLBRow { public GameObject root; public object txtRank; public object txtName; public object txtRating; public object txtGames; public object txtWins; public object txtTop3; public object txtAvgPl; public object txtWR; } private sealed class FfaRecentPlayerRow { public GameObject root; public GameObject cardsGO; public GameObject fullDotsGO; public GameObject halfDotsGO; public GameObject halfOverflowGO; public object txtPlacement; public object txtIdentity; public object txtPoints; public object txtHalfOverflow; public object txtHalves; public object txtKills; public object txtRewards; public object txtElo; public object txtCards; public string cardsHoverText; public readonly List fullDots = new List(); public readonly List halfDots = new List(); } private sealed class FfaTimelineGraph { public int eventCount; public float maxScore; public string title; public string eventLabel; public string maxLabel; public string[] names; public Color[] colors; public float[][] values; } private sealed class FfaRecentMatchRow { public GameObject root; public GameObject btnId; public RectTransform headerRect; public object txtHeader; public string currentMatchId; public string timelineSource; public string timelineMatchId; public FfaTimelineGraph graph; public readonly List players = new List(); } private sealed class FfaBetPlayerRow { public GameObject root; public GameObject betBtn; public object txtName; public object txtRating; public object txtOdds; public string lobbyId; public string steamId; public string displayName; public int gameNumber; } private sealed class FfaBetLobbyRow { public GameObject root; public object txtHeader; public readonly List players = new List(); } private sealed class FfaRecentGraphDrawer : MonoBehaviour { private void OnGUI() { DrawFfaRecentHoverGraph(); } } private class HomeCosRow { public GameObject root; public GameObject artGO; public object artImg; public object txt; } private struct CardStatTuple { public bool positive; public string amount; public string stat; } private class ArtistRow { public GameObject root; public object txtInfo; public GameObject priceBtn; public GameObject stockBtn; public GameObject giftBtn; public GameObject artImgGO; public object artImg; public string sku; public string name; public int price; public int stock; public bool catalogReady; } private class ArtistBlockRow { public GameObject root; public object txtInfo; public GameObject unblockBtn; public string steamId; public string name; } private class ShopRow { public GameObject root; public object txtName; public object txtDesc; public object txtPrice; public GameObject buyBtn; public GameObject setActiveBtn; public GameObject previewBtn; public object buyBtnTxt; public object previewBtnTxt; public long itemId; public string sku; public string previewColor; public int previewPrice; public string kind; public GameObject artImgGO; public object artImg; public GameObject swatchGO; public object[] swatchImgs = new object[3]; public GameObject artistBtn; } private sealed class MergedSeriesRow { public string ts; public ApiClient.RecentSeriesEntry oneVone; public ApiClient.MultimodeSeriesEntry multi; } private struct SGroup { public string series_id; public List matches; } private struct BracketRowPurpose { public bool isHeader; public string groupKey; } private class TeamLBRow { public GameObject root; public object txtRank; public object txtName; public object txtRating; public object txtWL; public object txtWR; public object txtMate; public object txtGold; public object txtXp; } private class TeamHistRow { public GameObject root; public object txtLine1; public object txtLine2; public GameObject btnId; public GameObject cardsRow; public object txtCardsLeft; public object txtCardsRight; public GameObject teleRow; public object txtTeleLA; public object txtTeleLB; public object txtTeleRA; public object txtTeleRB; public string seriesKey; public bool isHeader; public string matchKey; } [CompilerGenerated] private static class <>O { public static UnityAction <0>__ToggleHistoryCardMode; public static UnityAction <1>__StartCosmeticUpload; public static UnityAction <2>__StartCosmeticPlacementAdjustment; public static Action <3>__ValidateAndNameCosmetic; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__224_0; public static UnityAction <>9__224_1; public static UnityAction <>9__224_2; public static UnityAction <>9__224_3; public static UnityAction <>9__224_4; public static UnityAction <>9__239_0; public static UnityAction <>9__239_1; public static UnityAction <>9__239_2; public static UnityAction <>9__239_3; public static UnityAction <>9__239_4; public static UnityAction <>9__239_5; public static UnityAction <>9__239_6; public static UnityAction <>9__302_0; public static UnityAction <>9__302_1; public static UnityAction <>9__302_2; public static UnityAction <>9__302_3; public static UnityAction <>9__302_4; public static UnityAction <>9__302_5; public static Comparison <>9__321_0; public static Predicate <>9__339_0; public static UnityAction <>9__365_0; public static UnityAction <>9__365_1; public static UnityAction <>9__365_2; public static UnityAction <>9__365_3; public static UnityAction <>9__365_4; public static UnityAction <>9__365_5; public static UnityAction <>9__365_6; public static UnityAction <>9__390_0; public static Action <>9__390_1; public static UnityAction <>9__393_0; public static UnityAction <>9__393_1; public static UnityAction <>9__393_2; public static UnityAction <>9__393_3; public static UnityAction <>9__396_0; public static UnityAction <>9__396_1; public static UnityAction <>9__396_2; public static UnityAction <>9__396_3; public static UnityAction <>9__396_4; public static UnityAction <>9__396_5; public static UnityAction <>9__396_6; public static UnityAction <>9__396_7; public static UnityAction <>9__396_8; public static UnityAction <>9__396_9; public static Action <>9__397_1; public static UnityAction <>9__398_0; public static UnityAction <>9__398_1; public static Func <>9__407_3; public static Func <>9__407_4; public static Action <>9__407_2; public static UnityAction <>9__435_0; public static UnityAction <>9__435_1; public static UnityAction <>9__435_2; public static UnityAction <>9__435_3; public static UnityAction <>9__435_4; public static UnityAction <>9__435_5; public static Action <>9__450_2; public static UnityAction <>9__450_0; public static UnityAction <>9__450_1; public static Func <>9__455_0; public static Func <>9__455_1; public static Func <>9__455_2; public static Action <>9__460_6; public static Action <>9__460_8; public static Action <>9__533_5; public static Comparison <>9__534_0; public static Comparison <>9__534_1; public static Comparison <>9__534_2; public static Comparison <>9__534_3; public static Comparison <>9__534_4; public static Comparison <>9__534_5; public static Comparison <>9__534_6; public static Comparison <>9__534_7; public static Comparison <>9__534_8; public static Predicate <>9__534_10; public static UnityAction <>9__605_0; public static Action <>9__605_33; public static UnityAction <>9__605_1; public static Action <>9__605_34; public static UnityAction <>9__605_2; public static UnityAction <>9__605_3; public static UnityAction <>9__605_4; public static UnityAction <>9__605_5; public static UnityAction <>9__605_6; public static UnityAction <>9__605_7; public static UnityAction <>9__605_8; public static UnityAction <>9__605_9; public static UnityAction <>9__605_10; public static UnityAction <>9__605_11; public static UnityAction <>9__605_12; public static UnityAction <>9__605_13; public static UnityAction <>9__605_14; public static UnityAction <>9__605_15; public static UnityAction <>9__605_16; public static UnityAction <>9__605_17; public static UnityAction <>9__605_18; public static UnityAction <>9__605_20; public static UnityAction <>9__605_21; public static UnityAction <>9__605_22; public static UnityAction <>9__605_23; public static UnityAction <>9__605_24; public static UnityAction <>9__605_25; public static UnityAction <>9__605_26; public static UnityAction <>9__605_27; public static UnityAction <>9__605_28; public static UnityAction <>9__605_29; public static UnityAction <>9__605_30; public static Action <>9__605_35; public static UnityAction <>9__605_31; public static UnityAction <>9__605_32; public static Comparison <>9__610_0; public static Predicate <>9__612_0; public static Predicate <>9__612_1; public static Comparison <>9__628_1; public static Comparison <>9__628_2; public static Comparison <>9__628_3; public static Comparison <>9__628_4; public static Comparison <>9__628_5; public static Comparison <>9__628_6; public static Comparison <>9__628_7; public static Comparison <>9__628_8; public static UnityAction <>9__660_0; public static UnityAction <>9__660_1; public static UnityAction <>9__660_2; public static UnityAction <>9__660_3; public static UnityAction <>9__660_4; public static Func <>9__680_0; public static Func <>9__680_1; public static Func <>9__680_2; public static Func <>9__680_3; public static Func <>9__680_4; public static Func <>9__680_5; public static Func <>9__680_6; public static Func <>9__680_7; public static Func <>9__680_8; public static Func <>9__680_9; public static Func <>9__680_10; public static Func <>9__680_11; public static Func <>9__680_12; public static Func <>9__680_13; public static Func <>9__680_14; public static Func <>9__680_15; public static Func <>9__680_16; public static Func <>9__680_17; public static Comparison <>9__681_0; public static Predicate <>9__691_2; public static Predicate <>9__691_0; public static Comparison <>9__692_1; public static Comparison <>9__692_2; public static Comparison <>9__692_3; public static Comparison <>9__692_4; public static Comparison <>9__692_5; public static Comparison <>9__692_6; public static Comparison <>9__692_7; public static Comparison <>9__692_8; public static Func <>9__696_1; public static Func <>9__696_2; public static Comparison <>9__723_0; public static UnityAction <>9__747_0; public static UnityAction <>9__747_1; public static UnityAction <>9__747_2; public static UnityAction <>9__747_3; public static UnityAction <>9__747_4; public static Action <>9__747_9; public static UnityAction <>9__747_5; public static Action <>9__747_13; public static Action <>9__747_12; public static Action <>9__747_11; public static UnityAction <>9__747_6; public static UnityAction <>9__747_7; public static UnityAction <>9__747_8; public static Func <>9__751_0; public static UnityAction <>9__756_0; public static UnityAction <>9__758_0; public static UnityAction <>9__760_0; public static UnityAction <>9__760_1; public static UnityAction <>9__760_2; public static UnityAction <>9__819_0; public static UnityAction <>9__819_1; public static UnityAction <>9__819_2; public static UnityAction <>9__819_3; public static UnityAction <>9__819_4; public static UnityAction <>9__819_5; public static UnityAction <>9__819_6; public static UnityAction <>9__819_7; public static UnityAction <>9__819_8; public static UnityAction <>9__819_9; public static UnityAction <>9__819_10; public static UnityAction <>9__819_11; public static UnityAction <>9__819_12; public static Comparison<(string key, int sideIdx, int round, string sideLabel)> <>9__837_1; public static Predicate <>9__837_2; public static UnityAction <>9__855_0; public static UnityAction <>9__855_1; public static UnityAction <>9__855_2; public static UnityAction <>9__855_3; public static UnityAction <>9__855_4; public static UnityAction <>9__855_5; public static UnityAction <>9__855_6; public static UnityAction <>9__855_8; public static UnityAction <>9__855_9; internal void b__224_0() { Close(); } internal void b__224_1() { ApiClient.StartAutoUpdate(); } internal void b__224_2() { Application.OpenURL("https://discord.gg/comp-rounds"); } internal void b__224_3() { Application.OpenURL("https://github.com/SidNDeed/SidsCompetitiveRounds"); } internal void b__224_4() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime >= _nextManualRefreshAt) { _nextManualRefreshAt = Time.unscaledTime + 2f; RefreshData(); dirty = true; } else { CompetitiveUI.ShowNotification("Refreshing too fast - give it a sec", Color.yellow, 1.5f); } } internal void b__239_0() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.JoinQueue(localSteamId, MatchTracker.LocalDisplayName, null, rankedOnly: false); } } internal void b__239_1() { ApiClient.LeaveQueue(MatchTracker.LocalSteamId); } internal void b__239_2() { OnLfpButton(); } internal void b__239_3() { Plugin.RankedEnabled.Value = true; string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.ToggleRanked(localSteamId, enabled: true); } dirty = true; } internal void b__239_4() { Plugin.RankedEnabled.Value = false; string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.ToggleRanked(localSteamId, enabled: false); if (ApiClient.CurrentQueueState != ApiClient.QueueState.Idle) { ApiClient.LeaveQueue(localSteamId); } } dirty = true; } internal void b__239_5() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.ReadyUp(localSteamId); } } internal void b__239_6() { ApiClient.DeclineMatch(MatchTracker.LocalSteamId); } internal void b__302_0() { ShowInfoPopup("FFA - How It Works", "Free-for-all for 3-10 players. Every player is their own team.\r\nStandard ROUNDS scoring - first to 5 points takes the game.\r\n\r\nHOW TO PLAY\r\n\r\n- There is no Elo band. Joining a lobby is consent to play.\r\n\r\n- Create a lobby, or join an open one from the browser.\r\n The HOST presses Start once at least 3 players are in\r\n (up to 10). Several lobbies can be open at once.\r\n\r\n- If the host leaves, the longest-waiting member becomes\r\n the new host automatically.\r\n\r\n- After each point, everyone except the point winner\r\n picks a card at the same time.\r\n\r\n- The pick timer is shown on screen. A pick landing\r\n near the end grants everyone a little extra time.\r\n When your timer hits zero, your highlighted card is\r\n picked for you automatically. You always get a\r\n card - skipping a pick is not possible.\r\n\r\n- You hold up to 5 cards.\r\n Picking a 6th replaces your oldest card.\r\n\r\nRATING\r\n\r\n- FFA is ranked with its own Glicko rating.\r\n\r\n- Placement uses points, then all round wins earned\r\n (spent ones included), then total kills.\r\n Ties share a place using competition order: 1, 2, 2, 4.\r\n\r\n- Your rating is scored against the players placed\r\n nearest to you (up to 4 of them), so one game can't\r\n swing your rating several times harder in a 10-player\r\n lobby than in a 3-player one.\r\n\r\n- A tied placement counts as a draw. New ratings move\r\n fast and settle down as you play more.\r\n\r\nREWARDS\r\n\r\n- Each game pays 600 base XP, plus 90 XP per player\r\n you placed above.\r\n\r\n- Placement multiplies that: up to x1.5 for winning a\r\n 3-player game, growing with lobby size to x5 for\r\n winning a full 10. Lower places scale down smoothly;\r\n last place keeps the base.\r\n\r\n- Placement Gold comes on top: 10-50 Gold by placement,\r\n scaled by lobby size.\r\n\r\n- A stronger opposing field multiplies the XP part\r\n (the same tier bonus as the other modes).\r\n\r\n- XP converts to Gold at 100 XP = 1 Gold, and level-ups\r\n pay their usual bonus Gold. A level-up landing during\r\n a game shows up inside that game's +g number - that is\r\n how a last place can occasionally out-earn the winner.\r\n\r\n- Spectators can bet Gold on FFA lobbies from this tab.\r\n\r\nREADING THE RECENT FFAS LIST\r\n\r\nDots + N(P) - Full points won.\r\nHalf dots + N(H) - Round wins that\r\n did not become one of that player's full points.\r\nNk - Kills.\r\n+xp +g - That game's XP and Gold\r\n (including any level-up bonus).\r\nGreen/red number - FFA rating change.\r\nCards - The hand held at game end.\r\n +N replaced counts picks that were\r\n pushed out by the 5-card cap - hover the line to see\r\n every pick in order.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\nRank - Position in the currently selected sort.\r\nPlayer - The player's display name.\r\nRating - The player's separate FFA Glicko rating.\r\nGames - Recorded FFA games played.\r\nWins - Games finished in 1st place.\r\nTop3 - Games finished in 1st, 2nd, or 3rd.\r\nAvgPl - Average finishing place. Lower is\r\n better - 1.0 means winning every game.\r\nWR - Share of games won outright.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded.\r\n A leaver keeps their tallies for placement."); } internal void b__302_1() { ApiClient.FfaCreateLobby(); dirty = true; } internal void b__302_2() { ApiClient.FfaStartLobby(); dirty = true; } internal void b__302_3() { ApiClient.FfaLeaveQueue(); dirty = true; } internal void b__302_4() { ffaRecentPageReq = Math.Max(0, ffaRecentPageReq - 1); ApiClient.FetchFfaRecent(ffaRecentPageReq); } internal void b__302_5() { ffaRecentPageReq++; ApiClient.FetchFfaRecent(ffaRecentPageReq); } internal int b__321_0(ApiClient.FfaRecentPlayer a, ApiClient.FfaRecentPlayer b) { return ((a != null && a.placement > 0) ? a.placement : 99).CompareTo((b != null && b.placement > 0) ? b.placement : 99); } internal bool b__339_0(ApiClient.FfaLobbyMemberEntry m) { return m.is_host; } internal void b__365_0() { ShowInfoPopup("1v2 - How It Works", "One solo player faces a duo in a best-of-3 series.\r\n\r\nHOW TO PLAY\r\n\r\n- This is a consent queue with no Elo band and no ready-up.\r\n- The server assigns one solo and two duo players.\r\n- Solo Extra Initial Pick is optional.\r\n If anyone enables it, the solo draws 2 cards on the\r\n opening pick.\r\n\r\nSCORING\r\n\r\n- The first side to win 2 games wins the series.\r\n- 1v2 is an UNRANKED beta. No rating is applied yet.\r\n- Games are recorded and will count when ranked play launches.\r\n\r\nREWARDS\r\n\r\n- Each game gives 500 XP.\r\n A game win gets x1.5, for 750 XP.\r\n- A series win gives each winner 40 Gold.\r\n A series loss gives each loser 20 Gold.\r\n- Game XP converts to Gold at 100 XP = 1 Gold.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\n- The tab has separate Solo and Duo boards.\r\n- You appear only on boards for roles you have played.\r\nRank - Activity order: wins, then WR, then games.\r\nPlayer - The player's display name.\r\nW-L - Games won and lost in that role only.\r\nWR - Win rate for games in that role.\r\n- These are activity boards. They are not sorted by Gold.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded."); } internal void b__365_1() { ovtPreferredSide = (ovtPreferredSide + 1) % 3; dirty = true; } internal void b__365_2() { ovtSoloExtraPick = !ovtSoloExtraPick; dirty = true; } internal void b__365_3() { ApiClient.OvtJoinQueue(ovtPreferredSide, ovtSoloExtraPick); dirty = true; } internal void b__365_4() { ApiClient.OvtLeaveQueue(); dirty = true; } internal void b__365_5() { ovtRecentPageReq = Math.Max(0, ovtRecentPageReq - 1); ApiClient.FetchOvtRecent(ovtRecentPageReq); } internal void b__365_6() { ovtRecentPageReq++; ApiClient.FetchOvtRecent(ovtRecentPageReq); } internal void b__390_0() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.GenerateLinkCode(localSteamId); } } internal void b__390_1() { if (ClickGuard.Claim()) { discordRevealed = !discordRevealed; dirty = true; } } internal void b__393_0() { if (rankedPage > 0) { rankedPage--; dirty = true; } } internal void b__393_1() { rankedPage++; dirty = true; } internal void b__393_2() { if (casualPage > 0) { casualPage--; dirty = true; } } internal void b__393_3() { casualPage++; dirty = true; } internal void b__396_0() { if (liveSeriesPage > 0) { liveSeriesPage--; dirty = true; } } internal void b__396_1() { liveSeriesPage++; dirty = true; } internal void b__396_2() { if (recentSeriesPage > 0) { recentSeriesPage--; dirty = true; } } internal void b__396_3() { recentSeriesPage++; dirty = true; } internal void b__396_4() { lbSearch = ""; dirty = true; } internal void b__396_5() { if (lbPage > 0) { lbPage--; dirty = true; } } internal void b__396_6() { lbPage++; dirty = true; } internal void b__396_7() { if (h2hSeriesPage > 0) { h2hSeriesPage--; dirty = true; } } internal void b__396_8() { h2hSeriesPage++; dirty = true; } internal void b__396_9() { if (!string.IsNullOrEmpty(selectedSteamId) && !(selectedSteamId == MatchTracker.LocalSteamId)) { string localSteamId = MatchTracker.LocalSteamId; if (ApiClient.IsPlayerBlocked(selectedSteamId)) { ApiClient.UnblockPlayer(localSteamId, selectedSteamId); } else { ApiClient.BlockPlayer(localSteamId, selectedSteamId); } } } internal void b__397_1(ApiClient.PlayerStatsData d) { selectedStats = d; dirty = true; } internal void b__398_0() { ExportCardTierList(); } internal void b__398_1() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) try { string text; try { text = Path.GetFullPath(Path.Combine(Application.dataPath, "..", "CompetitiveRoundsTierLists")); Directory.CreateDirectory(text); } catch { text = Application.persistentDataPath; } Application.OpenURL("file:///" + text.Replace('\\', '/')); CompetitiveUI.ShowNotification("Tier lists live in " + text, new Color(0.6f, 0.8f, 1f), 8f); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TIER-EXPORT] open folder: " + ex.Message)); } } internal Type b__407_3(Assembly a) { return a.GetType("CardChoice"); } internal bool b__407_4(Type t) { return t != null; } internal void b__407_2() { if (ClickGuard.Claim()) { HideCardPreview(); } } internal void b__435_0() { achSort = "default"; achSortDesc = false; dirty = true; } internal void b__435_1() { if (achSort == "rarity") { achSortDesc = !achSortDesc; } else { achSort = "rarity"; achSortDesc = false; } dirty = true; } internal void b__435_2() { if (achSort == "gold") { achSortDesc = !achSortDesc; } else { achSort = "gold"; achSortDesc = false; } dirty = true; } internal void b__435_3() { if (achSort == "date") { achSortDesc = !achSortDesc; } else { achSort = "date"; achSortDesc = false; } dirty = true; } internal void b__435_4() { if (achEarnersPage > 0) { achEarnersPage--; dirty = true; } } internal void b__435_5() { achEarnersPage++; dirty = true; } internal void b__450_0() { CompetitiveUI.OpenPlayerSearch("Block a buyer - find the player", delegate(string sid, string pname) { <>c__DisplayClass450_0 CS$<>8__locals1 = new <>c__DisplayClass450_0 { pname = pname }; if (!string.IsNullOrEmpty(sid)) { string localSteamId = MatchTracker.LocalSteamId; ApiClient.ArtistBlock(localSteamId, sid, block: true, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Blocked " + CS$<>8__locals1.pname + ".") : resp); }); } }); } internal void b__450_2(string sid, string pname) { <>c__DisplayClass450_0 CS$<>8__locals1 = new <>c__DisplayClass450_0 { pname = pname }; if (!string.IsNullOrEmpty(sid)) { string localSteamId = MatchTracker.LocalSteamId; ApiClient.ArtistBlock(localSteamId, sid, block: true, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Blocked " + CS$<>8__locals1.pname + ".") : resp); }); } } internal void b__450_1() { try { string text = CosmeticUploadDir(); Application.OpenURL("file:///" + text.Replace('\\', '/')); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] open folder: " + ex.Message)); } } internal bool b__455_0(ApiClient.CosmeticSubmission s) { return s != null && (s.status == "pending" || s.status == "approved"); } internal bool b__455_1(ApiClient.CosmeticSubmission s) { return !string.IsNullOrEmpty(s.shop_sku); } internal string b__455_2(ApiClient.CosmeticSubmission s) { return s.shop_sku; } internal void b__460_6(bool ok, string resp) { ShowArtistResult(ok, ok ? "Renamed." : resp); } internal void b__460_8(bool ok, string resp) { ShowArtistResult(ok, ok ? "Description updated." : resp); } internal void b__533_5(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] purchase complete ok={ok}"); UIFactory.SetText(txtShopStatus, ok ? "Purchased!" : ("Purchase failed: " + resp + "")); dirty = true; } internal int b__534_0(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { return a.price.CompareTo(b.price); } internal int b__534_1(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { return a.price.CompareTo(b.price); } internal int b__534_2(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { bool flag = CustomMapColors.IsVanillaStyled(a.sku); bool flag2 = CustomMapColors.IsVanillaStyled(b.sku); if (flag != flag2) { return (!flag) ? 1 : (-1); } int num = a.price.CompareTo(b.price); if (num != 0) { return num; } return string.Compare(a.name, b.name, StringComparison.OrdinalIgnoreCase); } internal int b__534_3(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { int num = g__rank|534_9(a.sku).CompareTo(g__rank|534_9(b.sku)); if (num != 0) { return num; } int num2 = a.price.CompareTo(b.price); if (num2 != 0) { return num2; } return string.Compare(a.name, b.name, StringComparison.OrdinalIgnoreCase); } internal int b__534_4(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { return a.price.CompareTo(b.price); } internal int b__534_5(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { return a.price.CompareTo(b.price); } internal int b__534_6(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { return a.price.CompareTo(b.price); } internal int b__534_7(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { return a.price.CompareTo(b.price); } internal int b__534_8(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { return a.price.CompareTo(b.price); } internal bool b__534_10(ApiClient.ShopItemData f) { return (string.IsNullOrEmpty(f.artist_name) ? "House" : f.artist_name) == shopArtistFilter; } internal void b__605_0() { Plugin.Log.LogInfo((object)"[SETTINGS] Consent toggle clicked"); if (Plugin.DataConsentGranted) { Plugin.DataConsent.Value = "denied"; } else { Plugin.DataConsent.Value = "granted"; } ApiClient.OnConsentChanged(); dirty = true; } internal void b__605_1() { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; string localSteamId = MatchTracker.LocalSteamId; if (cachedPlayerStats == null || string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { return; } Plugin.Log.LogInfo((object)"[SETTINGS] appear-offline toggled"); cachedPlayerStats.appear_offline = !cachedPlayerStats.appear_offline; dirty = true; ApiClient.SetAppearOffline(localSteamId, cachedPlayerStats.appear_offline, delegate(bool ok, string resp) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!ok) { CompetitiveUI.ShowNotification("Appear-offline update failed - try again", Color.yellow, 3f); } dirty = true; }); } internal void b__605_33(bool ok, string resp) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!ok) { CompetitiveUI.ShowNotification("Appear-offline update failed - try again", Color.yellow, 3f); } dirty = true; } internal void b__605_2() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; string localSteamId = MatchTracker.LocalSteamId; if (cachedPlayerStats == null || string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { return; } if (string.IsNullOrEmpty(cachedPlayerStats.discord_username) && string.IsNullOrEmpty(cachedPlayerStats.discord_id)) { CompetitiveUI.ShowNotification("Link your Discord first (Home tab)", Color.yellow, 4f); return; } Plugin.Log.LogInfo((object)"[SETTINGS] show-discord toggled"); cachedPlayerStats.show_discord = !cachedPlayerStats.show_discord; dirty = true; ApiClient.SetShowDiscord(localSteamId, cachedPlayerStats.show_discord, delegate(bool ok, string resp) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!ok) { CompetitiveUI.ShowNotification("Show-Discord update failed - try again", Color.yellow, 3f); } dirty = true; }); } internal void b__605_34(bool ok, string resp) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!ok) { CompetitiveUI.ShowNotification("Show-Discord update failed - try again", Color.yellow, 3f); } dirty = true; } internal void b__605_3() { Plugin.Log.LogInfo((object)"[SETTINGS] FPS toggled"); Plugin.ShowFps.Value = !Plugin.ShowFps.Value; dirty = true; } internal void b__605_4() { Plugin.Log.LogInfo((object)"[SETTINGS] Ping/region toggled"); Plugin.ShowRegionPing.Value = !Plugin.ShowRegionPing.Value; dirty = true; } internal void b__605_5() { Plugin.Log.LogInfo((object)"[SETTINGS] In-game chat overlay toggled"); Plugin.ShowIngameChat.Value = !Plugin.ShowIngameChat.Value; dirty = true; } internal void b__605_6() { Plugin.Log.LogInfo((object)"[SETTINGS] Notifications toggled"); Plugin.ShowNotifications.Value = !Plugin.ShowNotifications.Value; dirty = true; } internal void b__605_7() { Plugin.Log.LogInfo((object)"[SETTINGS] Input overlay toggled"); Plugin.ShowInputOverlay.Value = !Plugin.ShowInputOverlay.Value; dirty = true; } internal void b__605_8() { Plugin.Log.LogInfo((object)"[SETTINGS] Block debug overlay toggled"); Plugin.ShowBlockDebug.Value = !Plugin.ShowBlockDebug.Value; dirty = true; } internal void b__605_9() { CursorColorCosmetic.CycleShape(); dirty = true; } internal void b__605_10() { Plugin.Log.LogInfo((object)"[SETTINGS] Trails toggled"); Plugin.ShowTrails.Value = !Plugin.ShowTrails.Value; if (Plugin.ShowTrails.Value) { if (GameStateWatcher.IsInMatch) { TrailCosmetic.OnMatchStart(); } } else { TrailCosmetic.OnMatchEnd(); } dirty = true; } internal void b__605_11() { Plugin.Log.LogInfo((object)"[SETTINGS] Custom player colors toggled"); Plugin.ShowPlayerColors.Value = !Plugin.ShowPlayerColors.Value; try { PlayerColorCosmetic.OnShowPlayerColorsToggled(); } catch { } try { PlayerEffectCosmetic.OnShowPlayerColorsToggled(); } catch { } dirty = true; } internal void b__605_12() { Plugin.Log.LogInfo((object)"[SETTINGS] Animated cosmetics toggled"); Plugin.AnimatedCosmetics.Value = !Plugin.AnimatedCosmetics.Value; try { PlayerEffectCosmetic.OnAnimatedCosmeticsToggled(); } catch { } dirty = true; } internal void b__605_13() { MapPhysicalColorPatch.BloomStrengthSetting.Cycle(); Plugin.Log.LogInfo((object)("[SETTINGS] Bloom strength -> " + MapPhysicalColorPatch.BloomStrengthSetting.Level)); dirty = true; } internal void b__605_14() { ScreenshakerDisablePatch.Cycle(); Plugin.Log.LogInfo((object)("[SETTINGS] Screen shake -> " + ScreenshakerDisablePatch.Level)); dirty = true; } internal void b__605_15() { Plugin.Log.LogInfo((object)"[SETTINGS] Chromatic aberration toggled"); Plugin.ChromaticAberrationEnabled.Value = !Plugin.ChromaticAberrationEnabled.Value; try { MapPhysicalColorPatch.ChromaticAberrationSetting.Apply(); } catch { } dirty = true; } internal void b__605_16() { Plugin.Log.LogInfo((object)"[SETTINGS] Map lighting toggled"); Plugin.MapLightingEnabled.Value = !Plugin.MapLightingEnabled.Value; try { MapPhysicalColorPatch.RenderPerfSettings.Apply(); MapPhysicalColorPatch.RenderPerfSettings.ApplyBackdrop(); } catch { } dirty = true; } internal void b__605_17() { Plugin.Log.LogInfo((object)"[SETTINGS] Map shadows toggled"); Plugin.MapShadowsEnabled.Value = !Plugin.MapShadowsEnabled.Value; try { MapPhysicalColorPatch.RenderPerfSettings.Apply(); MapPhysicalColorPatch.RenderPerfSettings.ApplyBackdrop(); } catch { } dirty = true; } internal void b__605_18() { _perfSectionOpen = !_perfSectionOpen; if ((Object)(object)_perfSectionBody != (Object)null) { _perfSectionBody.SetActive(_perfSectionOpen); } dirty = true; } internal void b__605_20() { if (Plugin.PerfOptimizations != null) { Plugin.PerfOptimizations.Value = !Plugin.PerfOptimizations.Value; dirty = true; } } internal void b__605_21() { if (Plugin.PerfStunPlayerNullGuard != null) { Plugin.PerfStunPlayerNullGuard.Value = !Plugin.PerfStunPlayerNullGuard.Value; dirty = true; } } internal void b__605_22() { if (Plugin.PerfDespawnOffscreenBullets != null) { Plugin.PerfDespawnOffscreenBullets.Value = !Plugin.PerfDespawnOffscreenBullets.Value; dirty = true; } } internal void b__605_23() { if (Plugin.PerfSwallowHitSoundNREs != null) { Plugin.PerfSwallowHitSoundNREs.Value = !Plugin.PerfSwallowHitSoundNREs.Value; dirty = true; } } internal void b__605_24() { if (Plugin.PerfSwallowEdgeBounceNREs != null) { Plugin.PerfSwallowEdgeBounceNREs.Value = !Plugin.PerfSwallowEdgeBounceNREs.Value; dirty = true; } } internal void b__605_25() { if (Plugin.PerfSkipMenuUpdateInMatch != null) { Plugin.PerfSkipMenuUpdateInMatch.Value = !Plugin.PerfSkipMenuUpdateInMatch.Value; dirty = true; } } internal void b__605_26() { if (Plugin.PerfBulletHitParticleCap != null) { Plugin.PerfBulletHitParticleCap.Value = !Plugin.PerfBulletHitParticleCap.Value; dirty = true; } } internal void b__605_27() { if (Plugin.PerfClampObjectPoolInit != null) { Plugin.PerfClampObjectPoolInit.Value = !Plugin.PerfClampObjectPoolInit.Value; dirty = true; } } internal void b__605_28() { CompetitiveUI.OpenBugReportModal(); } internal void b__605_29() { ApiClient.EscapeAllQueues(); dirty = true; } internal void b__605_30() { if (ClickGuard.Claim()) { deleteArmed = true; dirty = true; } } internal void b__605_31() { if (!ClickGuard.Claim()) { return; } string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { return; } deleteArmed = false; ApiClient.DeletePlayerData(localSteamId, delegate(bool ok, string msg) { Plugin.Log.LogInfo((object)$"[PRIVACY] Delete result: ok={ok} msg={msg}"); if (ok) { Plugin.DataConsent.Value = "denied"; ApiClient.OnConsentChanged(); if (txtDeleteStatus != null) { UIFactory.SetText(txtDeleteStatus, "Your data has been anonymized. Consent is now Denied."); } } else if (txtDeleteStatus != null) { UIFactory.SetText(txtDeleteStatus, "Deletion failed: " + msg + ""); } dirty = true; }); } internal void b__605_35(bool ok, string msg) { Plugin.Log.LogInfo((object)$"[PRIVACY] Delete result: ok={ok} msg={msg}"); if (ok) { Plugin.DataConsent.Value = "denied"; ApiClient.OnConsentChanged(); if (txtDeleteStatus != null) { UIFactory.SetText(txtDeleteStatus, "Your data has been anonymized. Consent is now Denied."); } } else if (txtDeleteStatus != null) { UIFactory.SetText(txtDeleteStatus, "Deletion failed: " + msg + ""); } dirty = true; } internal void b__605_32() { if (ClickGuard.Claim()) { deleteArmed = false; dirty = true; } } internal int b__610_0(MergedSeriesRow a, MergedSeriesRow b) { return string.CompareOrdinal(b.ts, a.ts); } internal bool b__612_0(ApiClient.MatchHistoryEntry m) { return m.is_ranked; } internal bool b__612_1(ApiClient.MatchHistoryEntry m) { return !m.is_ranked; } internal int b__628_1(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { return lbSortDesc ? b.rank.CompareTo(a.rank) : a.rank.CompareTo(b.rank); } internal int b__628_2(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { return lbSortDesc ? b.level.CompareTo(a.level) : a.level.CompareTo(b.level); } internal int b__628_3(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { return lbSortDesc ? string.Compare(b.display_name, a.display_name, StringComparison.OrdinalIgnoreCase) : string.Compare(a.display_name, b.display_name, StringComparison.OrdinalIgnoreCase); } internal int b__628_4(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { return lbSortDesc ? b.rating.CompareTo(a.rating) : a.rating.CompareTo(b.rating); } internal int b__628_5(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { return lbSortDesc ? b.wins.CompareTo(a.wins) : a.wins.CompareTo(b.wins); } internal int b__628_6(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { return lbSortDesc ? b.losses.CompareTo(a.losses) : a.losses.CompareTo(b.losses); } internal int b__628_7(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { float value = ((a.losses > 0) ? ((float)a.wins / (float)a.losses) : ((float)a.wins * 100f)); float value2 = ((b.losses > 0) ? ((float)b.wins / (float)b.losses) : ((float)b.wins * 100f)); return lbSortDesc ? value2.CompareTo(value) : value.CompareTo(value2); } internal int b__628_8(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { return lbSortDesc ? b.gold.CompareTo(a.gold) : a.gold.CompareTo(b.gold); } internal void b__660_0() { compareSelected.Clear(); dirty = true; } internal void b__660_1() { compareSearch = ""; dirty = true; } internal void b__660_2() { compareMetric = (compareMetric - 1 + COMPARE_METRICS.Length) % COMPARE_METRICS.Length; dirty = true; } internal void b__660_3() { compareMetric = (compareMetric + 1) % COMPARE_METRICS.Length; dirty = true; } internal void b__660_4() { compareMetric = (compareMetric + 1) % COMPARE_METRICS.Length; dirty = true; } internal float b__680_0(ApiClient.PlayerStatsData ps) { return (ps.bullets_fired > 0) ? ((float)ps.bullets_hit * 100f / (float)ps.bullets_fired) : 0f; } internal float b__680_1(ApiClient.PlayerStatsData ps) { return (ps.blocks_activated > 0) ? ((float)ps.blocks_successful * 100f / (float)ps.blocks_activated) : 0f; } internal float b__680_2(ApiClient.PlayerStatsData ps) { return ps.avg_cards_per_game; } internal float b__680_3(ApiClient.PlayerStatsData ps) { return ps.avg_fps; } internal float b__680_4(ApiClient.PlayerStatsData ps) { return ps.peak_rating; } internal float b__680_5(ApiClient.PlayerStatsData ps) { return ps.total_xp; } internal float b__680_6(ApiClient.PlayerStatsData ps) { return ps.achievements_unlocked; } internal float b__680_7(ApiClient.PlayerStatsData ps) { return ps.best_ranked_streak; } internal float b__680_8(ApiClient.PlayerStatsData ps) { return ps.best_casual_streak; } internal float b__680_9(ApiClient.PlayerStatsData ps) { return ps.sweeps_given; } internal float b__680_10(ApiClient.PlayerStatsData ps) { return ps.sweeps_taken; } internal float b__680_11(ApiClient.PlayerStatsData ps) { return ps.bets_won; } internal float b__680_12(ApiClient.PlayerStatsData ps) { return ps.bets_lost; } internal float b__680_13(ApiClient.PlayerStatsData ps) { return ps.avg_keys_per_sec; } internal float b__680_14(ApiClient.PlayerStatsData ps) { return ps.avg_keys_per_game; } internal float b__680_15(ApiClient.PlayerStatsData ps) { return (float)ps.avg_game_seconds / 60f; } internal float b__680_16(ApiClient.PlayerStatsData ps) { return ps.team_rating; } internal float b__680_17(ApiClient.PlayerStatsData ps) { return 0f; } internal int b__681_0(string a, string b) { return string.CompareOrdinal(AchName(a), AchName(b)); } internal bool b__691_2(SGroup g) { return g.matches == null || g.matches.Count == 0; } internal bool b__691_0(ApiClient.MatchHistoryEntry m) { return m.is_ranked && !string.IsNullOrEmpty(m.series_id) && m.series_id != "null"; } internal int b__692_1(ApiClient.CardStatData a, ApiClient.CardStatData b) { string value2; int value = g__TierRank|692_0(cardTierMap.TryGetValue(CardTierKey(cardFilter, a.card_name), out value2) ? value2 : ""); string value4; int value3 = g__TierRank|692_0(cardTierMap.TryGetValue(CardTierKey(cardFilter, b.card_name), out value4) ? value4 : ""); return cardSortDesc ? value.CompareTo(value3) : value3.CompareTo(value); } internal int b__692_2(ApiClient.CardStatData a, ApiClient.CardStatData b) { return cardSortDesc ? string.Compare(b.card_name, a.card_name, StringComparison.OrdinalIgnoreCase) : string.Compare(a.card_name, b.card_name, StringComparison.OrdinalIgnoreCase); } internal int b__692_3(ApiClient.CardStatData a, ApiClient.CardStatData b) { return cardSortDesc ? string.Compare(b.card_rarity, a.card_rarity, StringComparison.OrdinalIgnoreCase) : string.Compare(a.card_rarity, b.card_rarity, StringComparison.OrdinalIgnoreCase); } internal int b__692_4(ApiClient.CardStatData a, ApiClient.CardStatData b) { return cardSortDesc ? b.times_picked.CompareTo(a.times_picked) : a.times_picked.CompareTo(b.times_picked); } internal int b__692_5(ApiClient.CardStatData a, ApiClient.CardStatData b) { return cardSortDesc ? b.wins_with_card.CompareTo(a.wins_with_card) : a.wins_with_card.CompareTo(b.wins_with_card); } internal int b__692_6(ApiClient.CardStatData a, ApiClient.CardStatData b) { return cardSortDesc ? b.win_rate.CompareTo(a.win_rate) : a.win_rate.CompareTo(b.win_rate); } internal int b__692_7(ApiClient.CardStatData a, ApiClient.CardStatData b) { return cardSortDesc ? b.pass_rate.CompareTo(a.pass_rate) : a.pass_rate.CompareTo(b.pass_rate); } internal int b__692_8(ApiClient.CardStatData a, ApiClient.CardStatData b) { return cardSortDesc ? b.times_picked.CompareTo(a.times_picked) : a.times_picked.CompareTo(b.times_picked); } internal Type b__696_1(Assembly a) { return a.GetType("CardChoice"); } internal bool b__696_2(Type t) { return t != null; } internal int b__723_0(int a, int b) { return _lblParts[a].Length.CompareTo(_lblParts[b].Length); } internal void b__747_0() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.FetchFlaggedMatches(localSteamId); ApiClient.FetchBannedUsers(localSteamId); ApiClient.FetchAdminRecentSeries(localSteamId); ApiClient.FetchAdminQuarantine(localSteamId); } } internal void b__747_1() { CompetitiveUI.OpenAdminPrompt("ban"); } internal void b__747_2() { CompetitiveUI.OpenAdminPrompt("grant"); } internal void b__747_3() { CompetitiveUI.OpenAdminPrompt("reverse"); } internal void b__747_4() { CompetitiveUI.OpenBugReportAdminViewer(); } internal void b__747_5() { CompetitiveUI.OpenPlayerSearch("Grant the artist role - find the player", delegate(string sid, string pname) { <>c__DisplayClass747_0 CS$<>8__locals1 = new <>c__DisplayClass747_0 { pname = pname }; if (!string.IsNullOrEmpty(sid)) { ApiClient.AdminSetArtist(MatchTracker.LocalSteamId, sid, grant: true, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Artist role granted to " + CS$<>8__locals1.pname + ".") : resp); }); } }); } internal void b__747_9(string sid, string pname) { <>c__DisplayClass747_0 CS$<>8__locals1 = new <>c__DisplayClass747_0 { pname = pname }; if (!string.IsNullOrEmpty(sid)) { ApiClient.AdminSetArtist(MatchTracker.LocalSteamId, sid, grant: true, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Artist role granted to " + CS$<>8__locals1.pname + ".") : resp); }); } } internal void b__747_6() { ApiClient.FetchArtistsList(delegate { List cachedAllArtists = ApiClient.CachedAllArtists; if (cachedAllArtists == null || cachedAllArtists.Count == 0) { ShowArtistResult(ok: false, "{\"detail\":\"no artists defined\"}"); } else { string[] array = new string[cachedAllArtists.Count]; string[] array2 = new string[cachedAllArtists.Count]; for (int i = 0; i < cachedAllArtists.Count; i++) { array[i] = cachedAllArtists[i].display_name; array2[i] = cachedAllArtists[i].steam_id; } CompetitiveUI.OpenArtistPicker("Revoke which artist?", array, array2, delegate(string picked) { if (!string.IsNullOrEmpty(picked)) { ApiClient.AdminSetArtist(MatchTracker.LocalSteamId, picked, grant: false, delegate(bool flag, string resp) { ShowArtistResult(flag, flag ? "Artist revoked." : resp); }); } }, "Revoke", showClear: false); } }); } internal void b__747_11(bool ok) { List cachedAllArtists = ApiClient.CachedAllArtists; if (cachedAllArtists == null || cachedAllArtists.Count == 0) { ShowArtistResult(ok: false, "{\"detail\":\"no artists defined\"}"); return; } string[] array = new string[cachedAllArtists.Count]; string[] array2 = new string[cachedAllArtists.Count]; for (int i = 0; i < cachedAllArtists.Count; i++) { array[i] = cachedAllArtists[i].display_name; array2[i] = cachedAllArtists[i].steam_id; } CompetitiveUI.OpenArtistPicker("Revoke which artist?", array, array2, delegate(string picked) { if (!string.IsNullOrEmpty(picked)) { ApiClient.AdminSetArtist(MatchTracker.LocalSteamId, picked, grant: false, delegate(bool flag, string resp) { ShowArtistResult(flag, flag ? "Artist revoked." : resp); }); } }, "Revoke", showClear: false); } internal void b__747_12(string picked) { if (!string.IsNullOrEmpty(picked)) { ApiClient.AdminSetArtist(MatchTracker.LocalSteamId, picked, grant: false, delegate(bool ok2, string resp) { ShowArtistResult(ok2, ok2 ? "Artist revoked." : resp); }); } } internal void b__747_13(bool ok2, string resp) { ShowArtistResult(ok2, ok2 ? "Artist revoked." : resp); } internal void b__747_7() { CompetitiveUI.OpenCosmeticReview(); } internal void b__747_8() { CompetitiveUI.OpenCosmeticReleaseQueue(); } internal string b__751_0(string n) { return AdminDisplay(n, 24); } internal void b__756_0() { } internal void b__758_0() { } internal void b__760_0() { } internal void b__760_1() { } internal void b__760_2() { } internal void b__819_0() { if (!(ApiClient.TournamentKind == "sync")) { ApiClient.TournamentKind = "sync"; ApiClient.FetchTournamentCurrent(MatchTracker.LocalSteamId, force: true); dirty = true; } } internal void b__819_1() { if (!(ApiClient.TournamentKind == "async")) { ApiClient.TournamentKind = "async"; ApiClient.FetchTournamentCurrent(MatchTracker.LocalSteamId, force: true); dirty = true; } } internal void b__819_2() { ShowInfoPopup(_tInfoTitle, _tInfoInstructions); } internal void b__819_3() { ShowInfoPopup("Prizes", string.IsNullOrEmpty(_tInfoPrizes) ? "Prizes are announced when signups open." : _tInfoPrizes); } internal void b__819_4() { _CycleTz(); } internal void b__819_5() { _CycleDateFormat(); } internal void b__819_6() { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) string localSteamId = MatchTracker.LocalSteamId; ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament == null || string.IsNullOrEmpty(cachedTournament.tournament_id) || string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { return; } if (ApiClient.TournamentKind != "async") { List list = new List(); for (int i = 0; i < tSlotChecked.Count; i++) { int num = i; string[] time_slot_options = cachedTournament.time_slot_options; if (num >= ((time_slot_options != null) ? time_slot_options.Length : 0)) { break; } if (tSlotChecked[i]) { list.Add(cachedTournament.time_slot_options[i]); } } if (list.Count == 0) { CompetitiveUI.ShowNotification("Pick at least one start time below first", new Color(1f, 0.75f, 0.35f)); } else { ApiClient.TournamentSignup(cachedTournament.tournament_id, localSteamId, MatchTracker.LocalDisplayName, list.ToArray()); } } else { ApiClient.TournamentSignup(cachedTournament.tournament_id, localSteamId, MatchTracker.LocalDisplayName); } } internal void b__819_7() { string localSteamId = MatchTracker.LocalSteamId; ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id) && !string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.TournamentUnsignup(cachedTournament.tournament_id, localSteamId); } } internal void b__819_8() { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament == null || string.IsNullOrEmpty(cachedTournament.tournament_id)) { return; } List list = new List(); for (int i = 0; i < tSlotChecked.Count; i++) { int num = i; string[] time_slot_options = cachedTournament.time_slot_options; if (num >= ((time_slot_options != null) ? time_slot_options.Length : 0)) { break; } if (tSlotChecked[i]) { list.Add(cachedTournament.time_slot_options[i]); } } ApiClient.TournamentTimeVote(cachedTournament.tournament_id, MatchTracker.LocalSteamId, list.ToArray()); _tVoteLocalEdited = false; } internal void b__819_9() { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id)) { ApiClient.TournamentForceStartVote(cachedTournament.tournament_id, MatchTracker.LocalSteamId); } } internal void b__819_10() { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id)) { ApiClient.TournamentReady(cachedTournament.tournament_id, MatchTracker.LocalSteamId); } } internal void b__819_11() { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament == null || string.IsNullOrEmpty(cachedTournament.tournament_id) || cachedTournament.matches == null) { return; } ApiClient.TournamentMatchRow[] matches = cachedTournament.matches; foreach (ApiClient.TournamentMatchRow tournamentMatchRow in matches) { if (tournamentMatchRow.status == "scheduled" && (tournamentMatchRow.p1_signup_id == cachedTournament.my_signup_id || tournamentMatchRow.p2_signup_id == cachedTournament.my_signup_id) && !string.IsNullOrEmpty(tournamentMatchRow.match_id)) { ApiClient.TournamentPlayNow(cachedTournament.tournament_id, tournamentMatchRow.match_id, MatchTracker.LocalSteamId); break; } } } internal void b__819_12() { //IL_0148: Unknown result type (might be due to invalid IL or missing references) ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament == null || cachedTournament.matches == null) { return; } ApiClient.TournamentMatchRow[] matches = cachedTournament.matches; foreach (ApiClient.TournamentMatchRow tournamentMatchRow in matches) { if ((tournamentMatchRow.status == "ready" || tournamentMatchRow.status == "active") && (tournamentMatchRow.p1_signup_id == cachedTournament.my_signup_id || tournamentMatchRow.p2_signup_id == cachedTournament.my_signup_id) && !string.IsNullOrEmpty(tournamentMatchRow.match_id)) { string text = ((!string.IsNullOrEmpty(tournamentMatchRow.photon_room_name)) ? tournamentMatchRow.photon_room_name : ("sct-" + tournamentMatchRow.match_id.Replace("-", "").Substring(0, 12))); _tournamentDispatchedMatches.Remove(tournamentMatchRow.match_id); Plugin.SetPendingRoom(text, cachedTournament.photon_region); CompetitiveUI.ShowNotification("Reconnecting to " + text + " (region " + (cachedTournament.photon_region ?? "default") + ")", new Color(0.5f, 0.8f, 1f)); break; } } } internal int b__837_1((string key, int sideIdx, int round, string sideLabel) a, (string key, int sideIdx, int round, string sideLabel) b) { int num = a.sideIdx.CompareTo(b.sideIdx); if (num != 0) { return num; } return a.round.CompareTo(b.round); } internal bool b__837_2(ApiClient.TournamentMatchRow mm) { return mm.status == "ready" || mm.status == "active"; } internal void b__855_0() { ShowInfoPopup("2v2 - How It Works", "Two teams of two play a best-of-3 series.\r\n\r\nHOW TO PLAY\r\n\r\n- Random queue uses an Elo band that widens as you wait.\r\n The server auto-balances the teams.\r\n- Custom lobbies have no Elo band.\r\n Joining the lobby is consent to play.\r\n- All 4 players have 120 seconds to ready up.\r\n If time expires, everyone returns to searching.\r\n- After an auto-queue game with a point margin of 3 or more,\r\n the weakest winner may swap with the strongest loser.\r\n\r\nSCORING\r\n\r\n- The first team to win 2 games wins the series.\r\n- 2v2 uses its own Glicko rating.\r\n It does not change your 1v1 rating.\r\n- Rating updates after the completed series.\r\n- W-L and WR count completed series, not individual games.\r\n\r\nREWARDS\r\n\r\n- Each game gives 600 base XP.\r\n A game win gets x1.5, for 900 base XP.\r\n- A series win gives 50 base Gold.\r\n A series loss gives 25 base Gold.\r\n- The opposing team's rating tier can multiply base rewards.\r\n- Game XP converts to Gold at 100 XP = 1 Gold.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\nRank - Position in the currently selected sort.\r\nPlayer - The player's display name.\r\nRating - The player's separate 2v2 Glicko rating.\r\nW-L - Completed series won and lost.\r\nWR - Series wins divided by completed series.\r\nAvg Mate Elo - Average rating of past teammates.\r\n A teammate uses 2v2 rating after 5 completed series.\r\n Before that, their 1v1 rating is used, or 1500 if absent.\r\nGold - Lifetime Gold earned from 2v2 only.\r\nXP - Lifetime XP earned from 2v2 only.\r\n Gold and XP do not affect your rating-based rank.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded."); } internal void b__855_1() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)"[TEAM-QUEUE-UI] Search Random clicked"); string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { Plugin.Log.LogWarning((object)("[TEAM-QUEUE-UI] LocalSteamId='" + localSteamId + "' — Steam not ready yet, ignoring click")); CompetitiveUI.ShowNotification("Steam ID not ready yet — try again in a few seconds", new Color(1f, 0.6f, 0.2f), 4f); return; } string text = ""; try { text = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { } Plugin.Log.LogInfo((object)("[TEAM-QUEUE-UI] joining auto team queue sid=" + localSteamId + " region='" + text + "'")); ApiClient.JoinTeamQueue(localSteamId, MatchTracker.LocalDisplayName, text); } internal void b__855_2() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)"[TEAM-QUEUE-UI] Find Custom Lobby clicked"); string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { CompetitiveUI.ShowNotification("Steam ID not ready yet — try again in a few seconds", new Color(1f, 0.6f, 0.2f), 4f); return; } string text = ""; try { text = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { } Plugin.Log.LogInfo((object)("[TEAM-QUEUE-UI] joining manual team queue sid=" + localSteamId + " region='" + text + "'")); ApiClient.JoinTeamQueue(localSteamId, MatchTracker.LocalDisplayName, text, "manual"); } internal void b__855_3() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.LeaveTeamQueue(localSteamId); } } internal void b__855_4() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.ReadyUpTeam(localSteamId); } } internal void b__855_5() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.SetTeamPreferredTeam(localSteamId, 1); } } internal void b__855_6() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.SetTeamPreferredTeam(localSteamId, 2); } } internal void b__855_8() { teamSeriesPageReq = Math.Max(0, teamSeriesPageReq - 1); ApiClient.FetchAllSeriesPaged(teamSeriesPageReq, 10); } internal void b__855_9() { teamSeriesPageReq++; ApiClient.FetchAllSeriesPaged(teamSeriesPageReq, 10); } } [CompilerGenerated] private sealed class <>c__DisplayClass450_0 { public string pname; internal void b__3(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Blocked " + pname + ".") : resp); } } [CompilerGenerated] private sealed class <>c__DisplayClass747_0 { public string pname; internal void b__10(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Artist role granted to " + pname + ".") : resp); } } private static readonly Color C_BG = new Color(0.06f, 0.07f, 0.09f, 0.96f); private static readonly Color C_PANEL = new Color(0.1f, 0.11f, 0.14f, 0.92f); private static readonly Color C_WHITE = Color.white; private static readonly Color C_SUB = new Color(0.8f, 0.85f, 1f); private static readonly Color C_LABEL = new Color(0.7f, 0.7f, 0.75f); private static readonly Color C_GOLD = new Color(1f, 0.85f, 0.3f); private static readonly Color C_BLUE = new Color(0.4f, 0.8f, 1f); private static readonly Color C_GREEN = Color.green; private static readonly Color C_RED = new Color(1f, 0.4f, 0.4f); private static readonly Color C_DIM = new Color(0.5f, 0.5f, 0.55f); private static readonly Color C_TAB = new Color(0.16f, 0.17f, 0.22f, 0.9f); private static readonly Color C_TABACT = new Color(0.22f, 0.38f, 0.65f, 0.95f); private static readonly Color C_BTN = new Color(0.18f, 0.2f, 0.26f, 0.92f); private static readonly Color C_COMMON = new Color(0.9f, 0.9f, 0.9f); private static readonly Color C_UNCOMMON = new Color(0.3f, 0.6f, 1f); private static readonly Color C_RARE = new Color(0.95f, 0.35f, 0.65f); private static GameObject pageGO; private static GameObject overlayCanvasGO; private static GameObject mainMenuGroup; private static bool isOpen; private static bool pageBuilt; private static bool dirty = true; private static bool inGameMode; private static int currentTab; private static Component listMenu; private static GameObject[] tabPanels; private static GameObject[] groupButtons; private static GameObject[] subButtons; private static object[] groupTexts; private static object[] subTexts; private static GameObject subTabBar; private static GameObject[] subTabAnchors; private static object txtRating; private static object txtRD; private static object txtLevel; private static object txtXPProg; private static object txtTotalXP; private static object txtTopLeftName; private static Component xpFill; private static object txtRankedRec; private static object txtRankedStrk; private static object txtCasualRec; private static object txtCasualStrk; private static object txtSweeps; private static object txtTotalRec; private static object txtAccuracy; private static object txtSessionSum; private static object txtSessionSplit; private static object txtSessionSweeps; private static object txtOppSummary; private static object txtSessionOppLifetime; private static object txtTeam2v2Rec; private static object txtTeam2v2Strk; private static object txtOvtRec; private static object txtFfaRec; private static object txtFfaExtra; private static object sessionSplitLayoutTarget; private static GameObject sessionOppContainer; private static List sessionOppTexts = new List(); private static object txtLinkCode; private static GameObject linkCodeBtn; private static bool discordRevealed = false; private static object txtChatLog; private static Component chatScrollRect; private const int CHAT_LINE_MAX_CHARS = 500; private static object txtLiveSeries; private static object txtLiveHeader; private static object txtMyBets; private static bool liveHeaderPulseFilled = true; private static float liveHeaderNextPulseAt; private const float LIVE_HEADER_PULSE_INTERVAL = 2.5f; private static GameObject liveBetsContainer; private static List liveBetRowPool = new List(); private static GameObject liveBetsPager; private static GameObject liveBetsPrev; private static GameObject liveBetsNext; private static object txtLiveBetsPage; private static int liveSeriesPage = 0; private const int LIVE_SERIES_PER_PAGE = 5; private static GameObject srvStatusRow; private static object txtServerStatus; private static float liveSeriesAutoRefreshAt; private static float _nextManualRefreshAt; private static List chatLines = new List(); private static readonly object chatLinesLock = new object(); private const int CHAT_LOG_MAX = 60; private static GameObject rankedContainer; private static GameObject casualContainer; private static List rankedRows = new List(); private static List casualRows = new List(); private static object txtRankedPage; private static object txtCasualPage; private static GameObject rPrev; private static GameObject rNext; private static GameObject cPrev; private static GameObject cNext; private static int rankedPage; private static int casualPage; private const string PP_CARD_NAMES_FULL = "cr_history_card_names_full"; private static bool _historyCardsFull = PlayerPrefs.GetInt("cr_history_card_names_full", 0) != 0; private static GameObject rCardModeBtn; private static GameObject cCardModeBtn; private static object rCardModeTxt; private static object cCardModeTxt; private static List lbRows = new List(); private static object txtLBCount; private static object txtLBDetail; private static object txtLBDetailB; private static object txtLBAch; private static string selectedSteamId = ""; private static ApiClient.PlayerStatsData selectedStats; private static List selectedViewHistory; private static int h2hSeriesPage = 0; private const int H2H_SERIES_PER_PAGE = 2; private static int h2hSeriesTotalPages = 1; private static GameObject h2hPager; private static GameObject h2hPrev; private static GameObject h2hNext; private static object txtH2hPage; private static string lbSort = "rating"; private static bool lbSortDesc = true; private static object[] lbSortTexts; private static GameObject[] lbSortBtns; private static int lbPage = 0; private static object txtLBPage; private static GameObject lbPrev; private static GameObject lbNext; private static GameObject lbBlockBtn; private static GameObject lbBlockRow; private static object lbBlockTxt; private static object txtLBSteamId; private static GameObject lbGraphPanel; private static object txtRecentSeries; private static int recentSeriesPage = 0; private static object txtSeriesPage; private static GameObject seriesPrev; private static GameObject seriesNext; private static List cardRows = new List(); private static int cardFilter; private static string cardSort = "times_picked"; private static bool cardSortDesc = true; private static object[] cardSortTexts; private static GameObject[] cardSortBtns; private static GameObject[] cardFilterBtns; private static object[] cardFilterTexts; private static List achRows = new List(); private static object txtRankedStatus; private static object txtQueueInfo; private static object txtMatchFound; private static object txtConnectLabel; private static GameObject lfpBtn; private static object txtVersionStatus; private static GameObject updateBtn; private static GameObject qSearchBtn; private static GameObject qCancelBtn; private static GameObject qMatchPanel; private static GameObject readyBtn; private static GameObject declineBtn; private static GameObject connectLabel; private static GameObject rankOnBtn; private static GameObject rankOffBtn; private static object txtTournamentGame; private static GameObject tournamentIndRow; private static readonly float[] LB_COL_W = new float[8] { 40f, 40f, 300f, 92f, 56f, 56f, 80f, 90f }; private static readonly float[] CS_COL_W = new float[7] { 60f, 360f, 130f, 76f, 76f, 76f, 76f }; private static readonly string[] TIER_CYCLE = new string[8] { "", "S", "A", "B", "C", "D", "E", "F" }; private static Dictionary cardTierMap = new Dictionary(); private const float S = 1.25f; private static object menuFadeCG; private static GameObject clickBlocker; private static float dataCheckTimer; private static int lastMatchCount = -1; private static int lastLBCount = -1; private static int lastCardCount = -1; private static readonly Dictionary _animThumbs = new Dictionary(); private static PropertyInfo _pImgSprite; private static readonly Dictionary _animThumbLastIdx = new Dictionary(); private static float lbTabRefreshAt; private static uint _podiumTick = 0u; private static float _podiumTickAt = 0f; private static readonly List _podiumLbRows = new List(); private static readonly Dictionary _lbOutlineOrig = new Dictionary(); private static readonly Dictionary _lbOutlineCache = new Dictionary(); private static float teamTabRefreshAt; private static float teamSeriesRefreshAt; public static int teamSeriesPageReq = 0; public static string LfpMessageText = ""; public static int LfpExpiryIdx = 2; public static readonly int[] LfpExpiryMinutes = new int[4] { 15, 30, 60, 180 }; public static readonly string[] LfpExpiryLabels = new string[4] { "15m", "30m", "1h", "3h" }; private static float lfpCooldownUntil = -1f; private static object _lfpStatsRef; private static readonly string[] TAB_NAMES = new string[14] { "My Stats", "Leaderboard", "Card Stats", "Achievements", "Shop", "Settings", "Admin", "Tournaments", "2v2", "Compare", "Artist", "1v2", "FFA", "Home" }; private const int NUM_TABS = 14; private const int TAB_HOME = 13; private static readonly string[] GROUP_LABELS = new string[8] { "Home", "My Stats", "Leaderboard", "Tournaments", "Multiplayer", "Shop", "Admin", "Settings" }; private static readonly int[][] GROUP_MEMBERS = new int[8][] { new int[1] { 13 }, new int[3] { 0, 2, 3 }, new int[2] { 1, 9 }, new int[1] { 7 }, new int[3] { 8, 11, 12 }, new int[2] { 4, 10 }, new int[1] { 6 }, new int[1] { 5 } }; private const int GROUP_ADMIN = 6; private static object txtFfaStatus; private static object txtFfaLobbyHeader; private static object txtFfaLobbyBody; private static object txtFfaLbHeader; private static object txtFfaRecentHeader; private static object txtFfaRecentPage; private static GameObject ffaJoinBtn; private static GameObject ffaLeaveBtn; private static GameObject ffaStartBtn; private static GameObject ffaBetPanel; private static GameObject ffaBetContainer; private static GameObject ffaBrowserContainer; private static readonly List ffaBrowserRows = new List(); private static GameObject ffaLbContainer; private static GameObject ffaRecentContainer; private static GameObject ffaRecentPrevBtn; private static GameObject ffaRecentNextBtn; private static List ffaLbSortBtns; private static string[] ffaLbSortKeys; private static object[] ffaLbHeaderTexts; private static string ffaLbSortReq = "rating"; private static Component ffaLbScrollRect; private static Component ffaRecentScrollRect; private static Component ovtSoloScrollRect; private static Component ovtDuoScrollRect; private static Component ovtRecentScrollRect; private static readonly List ffaLbRows = new List(); private static readonly int[] FFA_LB_COL_W = new int[8] { 42, 220, 92, 80, 74, 74, 82, 70 }; private const int FFA_HALF_DOT_CAP = 8; private static readonly Color[] FFA_SLOT_PALETTE = (Color[])(object)new Color[10] { new Color(1f, 0.769f, 0.239f), new Color(0.31f, 0.659f, 1f), new Color(1f, 0.361f, 0.478f), new Color(0.863f, 0.89f, 0.925f), new Color(0.275f, 0.878f, 0.486f), new Color(0.769f, 0.549f, 1f), new Color(0.149f, 0.847f, 0.824f), new Color(1f, 0.482f, 0.878f), new Color(1f, 0.541f, 0.239f), new Color(0.784f, 1f, 0.4f) }; private static readonly List ffaBetLobbyRows = new List(); private static readonly List ffaRecentRows = new List(); private static RectTransform ffaRecentViewport; private static RectTransform ffaTabOuterViewport; private static Sprite ffaFullDotSprite; private static Sprite ffaHalfDotSprite; private static readonly Vector3[] ffaHoverCorners = (Vector3[])(object)new Vector3[4]; private static GUIStyle ffaGraphTitleStyle; private static GUIStyle ffaGraphLegendStyle; private static GUIStyle ffaGraphAxisStyle; private static Func ffaWorldToScreenPoint; private static bool ffaWorldToScreenPointResolved; public static int ffaRecentPageReq = 0; private static GUIStyle ffaCardsTipStyle; private static string ffaCardsTipCachedText; private static float ffaCardsTipCachedHeight; private static float ffaLbRefreshAt; private static float ffaRecentRefreshAt; private static float ffaBetRefreshAt; private static object txtOvtStatus; private static object txtOvtLobbyHeader; private static object txtOvtLobbyBody; private static object txtOvtSoloLbHeader; private static object txtOvtDuoLbHeader; private static object txtOvtRecentHeader; private static object txtOvtRecentPage; private static GameObject ovtJoinBtn; private static GameObject ovtLeaveBtn; private static GameObject ovtSideBtn; private static GameObject ovtExtraBtn; private static GameObject ovtSoloLbContainer; private static GameObject ovtDuoLbContainer; private static GameObject ovtRecentContainer; private static GameObject ovtRecentPrevBtn; private static GameObject ovtRecentNextBtn; private static int ovtPreferredSide = 0; private static bool ovtSoloExtraPick = false; private static readonly List ovtSoloLbRows = new List(); private static readonly List ovtDuoLbRows = new List(); private static readonly List ovtRecentRows = new List(); public static int ovtRecentPageReq = 0; private static float ovtTabRefreshAt; private static float ovtRecentRefreshAt; private static object txtHomeOnlineHdr; private static object txtHomeOnline; private static object txtHomeReleases; private static object txtHomeCosmetics; private static readonly List homeCosRows = new List(); private const int HOME_COS_ROWS = 12; private static float homeTabRefreshAt; private static Sprite _homeLogoSprite; private static bool _homeLogoTried; private static object txtLBPlayerName; private static readonly Dictionary CARD_DESC_FALLBACK = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "abyssalcountdown", "Stand still to summon dark powers." }, { "barrage", "Fire many bullets at the same time." }, { "bigbullet", "Bigger bullets." }, { "bigbullets", "Bigger bullets." }, { "bombsaway", "Spawn a bunch of small bombs around you when you block." }, { "brawler", "+200% HP for 3s after dealing damage." }, { "buckshot", "Adds a shotgun vibe to your attack." }, { "burst", "Multiple bullets are fired in a sequence." }, { "chase", "+60% movement when moving towards the opponent." }, { "chillingpresence", "Slightly slow nearby enemies." }, { "dazzle", "Bullets stun the opponent multiple times." }, { "decay", "Damage done to you is dealt over 4 seconds." }, { "demonicpact", "Shooting costs 10HP. Removes shooting cooldown." }, { "drillammo", "Bullets drill through walls." }, { "echo", "Blocking triggers another, delayed block." }, { "emp", "Blocking spawns a ring of slowing projectiles." }, { "empower", "Blocking increases the damage and speed of your next shot. The shot triggers any on-block abilities where it lands." }, { "explosivebullet", "Bullet explodes on impact." }, { "fastforward", "Bullets keep the default trajectory." }, { "frostslam", "Slows enemies around you when you block." }, { "grow", "Bullets get more damage over time when travelling." }, { "healingfield", "Blocking creates a healing field." }, { "homing", "Bullets home towards visible targets." }, { "implode", "Blocking pulls enemies towards you." }, { "lifestealer", "Steal HP from your opponent when near." }, { "overpower", "Deal 15% of your max HP to enemies around you when you block." }, { "parasite", "Bullets deal damage over 5 seconds." }, { "phoenix", "Respawn once on death." }, { "poison", "Bullets deal damage over 3 seconds." }, { "pristineperseverance", "+400% HP when above 90% HP." }, { "pristineperseverence", "+400% HP when above 90% HP." }, { "radarshot", "Blocking scans the area for enemies. You automatically shoot any enemy found." }, { "radiance", "Spawn damaging sun waves when reloading. The rate increases during the reload sequence." }, { "refresh", "You get block back when dealing damage." }, { "remote", "Steer bullet with right stick / mouse." }, { "ricochet", "Bullets lose half of their speed when they bounce." }, { "saw", "Blocking spawns a saw around you for a short while." }, { "scavenger", "Dealing damage reloads your weapon." }, { "shieldcharge", "Blocking launches you forward and gives you a second automatic block upon ending the charge." }, { "shieldsup", "Firing your last bullet triggers a block. Disables continuous reloading." }, { "shockwave", "Blocking pushes enemies away." }, { "silence", "Blocking silences enemies nearby." }, { "sneaky", "Bullets avoid the ground." }, { "staticfield", "Blocking creates a field that slows and deals damage." }, { "supernova", "Spawns a field that pulls enemies in and stuns after a while." }, { "tacticalreload", "Blocking reloads your weapon." }, { "targetbounce", "Bullets aim for visible targets when bouncing." }, { "tasteofblood", "+50% movement speed for 3s after dealing damage." }, { "teleport", "Blocking teleports you forward." }, { "thruster", "Bullets have thrusters that push targets." }, { "timeddetonation", "Bullets spawn bombs that explode after half a second." }, { "toxiccloud", "Bullets spawn a poison cloud on impact. Clouds deal damage and slow." }, { "trickster", "Bullets deal 80% more DMG per bounce (capped to your bounce count)." } }; private static readonly Dictionary CARD_STATS_FALLBACK = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "barrage", new CardStatTuple[4] { CST(p: true, "+4", "BULLETS"), CST(p: true, "+5", "AMMO"), CST(p: false, "-70%", "DAMAGE"), CST(p: false, "+0.25s", "RELOAD") } }, { "bigbullet", new CardStatTuple[1] { CST(p: false, "+0.25s", "RELOAD") } }, { "bigbullets", new CardStatTuple[1] { CST(p: false, "+0.25s", "RELOAD") } }, { "bombsaway", new CardStatTuple[2] { CST(p: true, "+30%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "bouncy", new CardStatTuple[3] { CST(p: true, "+2", "BULLET BOUNCES"), CST(p: true, "+25%", "DAMAGE"), CST(p: false, "+0.25s", "RELOAD") } }, { "buckshot", new CardStatTuple[4] { CST(p: true, "+4", "BULLETS"), CST(p: true, "+5", "AMMO"), CST(p: false, "-60%", "DAMAGE"), CST(p: false, "+0.25s", "RELOAD") } }, { "burst", new CardStatTuple[4] { CST(p: true, "+2", "BULLETS"), CST(p: true, "+3", "AMMO"), CST(p: false, "-60%", "DAMAGE"), CST(p: false, "+0.25s", "RELOAD") } }, { "carefulplanning", new CardStatTuple[3] { CST(p: true, "+100%", "DAMAGE"), CST(p: false, "-150%", "ATKSPD"), CST(p: false, "+0.5s", "RELOAD") } }, { "chase", new CardStatTuple[1] { CST(p: true, "+60%", "MOVE SPD (chasing)") } }, { "chillingpresence", new CardStatTuple[1] { CST(p: true, "+25%", "HP") } }, { "coldbullets", new CardStatTuple[2] { CST(p: true, "+70%", "BULLET SLOW"), CST(p: false, "+0.25s", "RELOAD") } }, { "combine", new CardStatTuple[3] { CST(p: true, "+100%", "DAMAGE"), CST(p: false, "-2", "AMMO"), CST(p: false, "+0.5s", "RELOAD") } }, { "dazzle", new CardStatTuple[1] { CST(p: false, "+0.25s", "RELOAD") } }, { "decay", new CardStatTuple[1] { CST(p: true, "+50%", "HP") } }, { "defender", new CardStatTuple[2] { CST(p: true, "-30%", "BLOCK CD"), CST(p: true, "+30%", "HP") } }, { "demonicpact", new CardStatTuple[3] { CST(p: true, "+9", "BULLETS"), CST(p: true, "+2", "SPLASH DMG"), CST(p: false, "+0.25s", "RELOAD") } }, { "drillammo", new CardStatTuple[2] { CST(p: true, "+7m", "DRILL"), CST(p: false, "+0.25s", "RELOAD") } }, { "echo", new CardStatTuple[2] { CST(p: true, "+30%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "emp", new CardStatTuple[2] { CST(p: true, "+30%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "empower", new CardStatTuple[1] { CST(p: false, "+0.25s", "BLOCK CD") } }, { "explosivebullet", new CardStatTuple[2] { CST(p: false, "-100%", "ATKSPD"), CST(p: false, "+0.25s", "RELOAD") } }, { "fastball", new CardStatTuple[3] { CST(p: true, "+250%", "BULLET SPEED"), CST(p: false, "-50%", "ATKSPD"), CST(p: false, "+0.25s", "RELOAD") } }, { "fastforward", new CardStatTuple[2] { CST(p: true, "+100%", "PROJ SPEED"), CST(p: true, "+30%", "RELOAD SPD") } }, { "frostslam", new CardStatTuple[2] { CST(p: true, "+30%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "glasscannon", new CardStatTuple[3] { CST(p: true, "+100%", "DAMAGE"), CST(p: false, "-100%", "HP"), CST(p: false, "+0.25s", "RELOAD") } }, { "grow", new CardStatTuple[1] { CST(p: false, "+0.25s", "RELOAD") } }, { "healingfield", new CardStatTuple[2] { CST(p: true, "+30%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "homing", new CardStatTuple[3] { CST(p: false, "-25%", "DAMAGE"), CST(p: false, "-50%", "ATKSPD"), CST(p: false, "+0.25s", "RELOAD") } }, { "huge", new CardStatTuple[1] { CST(p: true, "+80%", "HP") } }, { "implode", new CardStatTuple[2] { CST(p: true, "+50%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "leech", new CardStatTuple[2] { CST(p: true, "+75%", "LIFE STEAL"), CST(p: true, "+30%", "HP") } }, { "lifestealer", new CardStatTuple[1] { CST(p: true, "+25%", "HP") } }, { "mayhem", new CardStatTuple[3] { CST(p: true, "+5", "BULLET BOUNCES"), CST(p: false, "-15%", "DAMAGE"), CST(p: false, "+0.5s", "RELOAD") } }, { "overpower", new CardStatTuple[2] { CST(p: true, "+30%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "parasite", new CardStatTuple[4] { CST(p: true, "+50%", "LIFE STEAL"), CST(p: true, "+25%", "HP"), CST(p: true, "+25%", "DAMAGE"), CST(p: false, "+0.25s", "RELOAD") } }, { "phoenix", new CardStatTuple[1] { CST(p: false, "-35%", "HP") } }, { "poison", new CardStatTuple[3] { CST(p: true, "+70%", "DAMAGE"), CST(p: true, "+30%", "RELOAD SPD"), CST(p: false, "-1", "BULLET") } }, { "quickreload", new CardStatTuple[1] { CST(p: true, "-70%", "RELOAD") } }, { "quickshot", new CardStatTuple[2] { CST(p: true, "+150%", "BULLET SPEED"), CST(p: false, "+0.25s", "RELOAD") } }, { "radarshot", new CardStatTuple[2] { CST(p: true, "+30%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "radiance", new CardStatTuple[1] { CST(p: true, "+30%", "HP") } }, { "remote", new CardStatTuple[2] { CST(p: false, "-40%", "BULLET SPEED"), CST(p: false, "+0.25s", "RELOAD") } }, { "ricochet", new CardStatTuple[3] { CST(p: true, "+2", "BULLET BOUNCES"), CST(p: true, "+25%", "ATKSPD"), CST(p: false, "+0.25s", "RELOAD") } }, { "riccochet", new CardStatTuple[3] { CST(p: true, "+2", "BULLET BOUNCES"), CST(p: true, "+25%", "ATKSPD"), CST(p: false, "+0.25s", "RELOAD") } }, { "saw", new CardStatTuple[2] { CST(p: true, "+30%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "scavenger", new CardStatTuple[1] { CST(p: false, "+0.5s", "RELOAD") } }, { "shieldcharge", new CardStatTuple[1] { CST(p: false, "+0.25s", "BLOCK CD") } }, { "shieldsup", new CardStatTuple[2] { CST(p: false, "+0.5s", "RELOAD"), CST(p: false, "+0.5s", "BLOCK CD") } }, { "shockwave", new CardStatTuple[2] { CST(p: true, "+50%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "silence", new CardStatTuple[2] { CST(p: true, "+25%", "HP"), CST(p: false, "+0.25s", "BLOCK CD") } }, { "sneaky", new CardStatTuple[1] { CST(p: false, "+0.25s", "RELOAD") } }, { "spray", new CardStatTuple[4] { CST(p: true, "+1000%", "ATKSPD"), CST(p: true, "+12", "AMMO"), CST(p: false, "-75%", "DAMAGE"), CST(p: false, "+0.25s", "RELOAD") } }, { "staticfield", new CardStatTuple[1] { CST(p: false, "+0.25s", "BLOCK CD") } }, { "steadyshot", new CardStatTuple[3] { CST(p: true, "+40%", "HP"), CST(p: true, "+100%", "BULLET SPEED"), CST(p: false, "+0.25s", "RELOAD") } }, { "supernova", new CardStatTuple[2] { CST(p: true, "+50%", "HP"), CST(p: false, "+0.5s", "BLOCK CD") } }, { "tacticalreload", new CardStatTuple[1] { CST(p: false, "+0.25s", "BLOCK CD") } }, { "tank", new CardStatTuple[3] { CST(p: true, "+100%", "HP"), CST(p: false, "-25%", "ATKSPD"), CST(p: false, "+0.5s", "RELOAD") } }, { "targetbounce", new CardStatTuple[3] { CST(p: true, "+1", "BULLET BOUNCE"), CST(p: false, "-20%", "DAMAGE"), CST(p: false, "+0.25s", "RELOAD") } }, { "tasteofblood", new CardStatTuple[1] { CST(p: true, "+30%", "LIFE STEAL") } }, { "teleport", new CardStatTuple[1] { CST(p: true, "-30%", "BLOCK CD") } }, { "thruster", new CardStatTuple[1] { CST(p: false, "+0.25s", "RELOAD") } }, { "timeddetonation", new CardStatTuple[2] { CST(p: false, "-15%", "DAMAGE"), CST(p: false, "+0.25s", "RELOAD") } }, { "toxiccloud", new CardStatTuple[2] { CST(p: false, "-20%", "ATKSPD"), CST(p: false, "+0.5s", "RELOAD") } }, { "trickster", new CardStatTuple[3] { CST(p: true, "+2", "BULLET BOUNCES"), CST(p: false, "-20%", "DAMAGE"), CST(p: false, "+0.5s", "RELOAD") } }, { "windup", new CardStatTuple[4] { CST(p: true, "+100%", "BULLET SPEED"), CST(p: true, "+60%", "DAMAGE"), CST(p: false, "-100%", "ATKSPD"), CST(p: false, "+0.5s", "RELOAD") } } }; private static GameObject cardPreviewGO; private static GameObject infoPopupGO; private static readonly HashSet _tierFiltersLoaded = new HashSet(); private static float _tierAutoFetchAt = -999f; private static float _seriesAutoFetchAt = -999f; private static float _cardStatsAutoFetchAt = -999f; private static string achSort = "default"; private static bool achSortDesc = false; private static string achSelectedKey = null; private static int achEarnersPage = 0; private static GameObject achEarnPager; private static GameObject achEarnPrev; private static GameObject achEarnNext; private static object txtAchEarnPage; private static GameObject achSortDefBtn; private static GameObject achSortRarBtn; private static GameObject achSortGoldBtn; private static GameObject achSortDateBtn; private static object achEarnersHdr; private static object achEarnersBody; private static GameObject achEarnersPanel; private static GameObject achEarnersStash; private static object txtAchCount; private static readonly List artistRows = new List(); private static readonly List artistBlockRows = new List(); private static GameObject artistItemsContainer; private static GameObject artistBlocksContainer; private static object txtArtistStatus; private static object txtArtistSubs; private static object txtArtistSales; private static bool cosmeticPlacementLoading; private static int cosmeticPlacementLoadTicket; private static HashSet _autoEnabledRankedForMatches = new HashSet(); public static string CustomBetAmountText = ""; private static string customBetSeriesId; private static string customBetOnSteamId; private static int customBetTeam; private static bool customBetIsTeam; private static bool customBetIsFfa; private static int customBetFfaGameNumber; private static object txtShopBalance; private static object txtShopStatus; private static GameObject shopRowsContainer; private static GameObject shopTitlesHeader; private static GameObject shopTrailsHeader; private static GameObject shopColorsHeader; private static GameObject shopNametagsHeader; private static GameObject shopPColorsHeader; private static GameObject shopCursorHeader; private static GameObject shopEffectsHeader; private static GameObject shopFacesHeader; private static GameObject shopOtherHeader; private static string shopArtistFilter = null; private static GameObject shopArtistFilterRow; private static readonly List shopArtistBtns = new List(); private static readonly List shopArtistBtnTexts = new List(); private static readonly List shopArtistBtnNames = new List(); private const string SHOP_HOUSE_ARTIST = "House"; private static int shopCategoryFilter = 0; private static GameObject[] shopTabBtns; private static object[] shopTabTexts; private static object txtShopCategoryDesc; private static readonly string[] SHOP_TAB_NAMES = new string[10] { "All", "Cosmetics", "Name Styles", "Maps", "Titles", "Trails", "Body Color", "Cursor", "Effects", "Other" }; private static readonly string[] SHOP_TAB_DESCS = new string[10] { "All cosmetics - everything available, grouped by category.", "Character cosmetics - faces, eyes, and accessories, many made by community artists. Buy here, then equip them in ROUNDS' own character editor (F8 or main menu). Visible to all modded players.", "Bold, italic, underline, strikethrough, and color/size modifiers applied to your player nametag in lobbies and matches. Visible to every player, modded or not.", "Map color schemes. Equip as many as you like and cycle between your owned colors with Left Shift in-game.", "Flair text shown next to your name on the leaderboard, match history, and in chat.", "A glowing trail that follows your character body during combat. Only visible to modded players; the shop preview shows it following your cursor.", "Override the default orange/blue team color with a tint of your choice. Only visible to modded players. Premium tiers (Prismatic, Chrome) animate during combat.", "Mouse-cursor color tint (local-only). Pick the cursor SHAPE — arrow, dot, crosshair, circle — in Settings; the tint colors whichever shape you choose.", "In-combat particle aura around your character. Only visible to modded players.", "Utility unlocks (e.g. hide your gold total on the leaderboard)." }; private static List shopRowPool = new List(); private static readonly Dictionary shopPreviewOriginalMats = new Dictionary(); private static readonly Dictionary shopPreviewGlowMatCache = new Dictionary(); private static readonly Dictionary shopPreviewOriginalFonts = new Dictionary(); private static List shopRows = new List(); private static string shopSelectedSku = null; private static readonly Color C_ROWSEL = new Color(0.2f, 0.32f, 0.47f, 0.95f); private static object txtConsentStatus; private static object txtDeleteStatus; private static GameObject consentToggleBtn; private static GameObject deleteBtn; private static GameObject confirmDeleteBtn; private static GameObject cancelDelBtn; private static GameObject notifToggleBtn; private static GameObject fpsToggleBtn; private static GameObject pingToggleBtn; private static GameObject ingameChatToggleBtn; private static GameObject trailToggleBtn; private static GameObject blockDbgToggleBtn; private static GameObject playerColorToggleBtn; private static GameObject inputOverlayToggleBtn; private static GameObject cursorShapeBtn; private static GameObject appearOfflineBtn; private static object appearOfflineTxt; private static GameObject showDiscordBtn; private static object showDiscordTxt; private static GameObject screenShakeToggleBtn; private static GameObject mapLightingToggleBtn; private static GameObject mapShadowsToggleBtn; private static GameObject animCosToggleBtn; private static GameObject bloomToggleBtn; private static object screenShakeToggleTxt; private static object mapLightingToggleTxt; private static object mapShadowsToggleTxt; private static object animCosToggleTxt; private static object bloomToggleTxt; private static GameObject chromAbToggleBtn; private static object chromAbToggleTxt; private static object consentToggleTxt; private static object notifToggleTxt; private static object fpsToggleTxt; private static object pingToggleTxt; private static object ingameChatToggleTxt; private static object trailToggleTxt; private static object blockDbgToggleTxt; private static object playerColorToggleTxt; private static object inputOverlayToggleTxt; private static object cursorShapeTxt; private static GameObject perfMasterBtn; private static GameObject perfStunBtn; private static GameObject perfBulletsBtn; private static GameObject perfHitSndBtn; private static GameObject perfColorGhBtn; private static GameObject perfEdgeBnBtn; private static GameObject perfTagBtn; private static GameObject perfMenuBtn; private static object perfMasterTxt; private static object perfStunTxt; private static object perfBulletsTxt; private static object perfHitSndTxt; private static object perfColorGhTxt; private static object perfEdgeBnTxt; private static object perfTagTxt; private static object perfMenuTxt; private static GameObject perfBulletCapBtn; private static GameObject perfPoolBtn; private static object perfBulletCapTxt; private static object perfPoolTxt; private static bool _perfSectionOpen = false; private static object _perfSectionHeaderTxt; private static GameObject _perfSectionBody; private static bool deleteArmed = false; private static float _multiAutoFetchAt = -999f; private static GameObject comparePickerContent; private static GameObject compareGraphPanel; private static GameObject compareCardsScroll; private static GameObject compareCardsContent; private static object txtCompareStatus; private static object compareMetricBtnTxt; private static object txtCompareCards; private static GameObject compareMetricBtn; private static int compareMetric = 0; private static readonly string[] COMPARE_METRICS = new string[19] { "Elo over games", "Elo over time", "Top Cards", "Worst Cards", "Hit / Block %", "Avg Cards / Game", "Avg FPS", "Peak Elo", "Total XP", "Achievements", "Achievement Grid", "Region Time", "Top Streaks", "5-0s Given / Taken", "Bets Won / Lost", "Keys / Sec", "Keys / Game", "Avg Game Length", "2v2 Rating" }; private static string compareSearch = ""; private static object compareSearchField; private static string lbSearch = ""; private static string lbSearchLast = ""; private static object lbSearchField; private const int COMPARE_MAX = 12; private static readonly List compareSelected = new List(); private static readonly List comparePickerSteamIds = new List(); private static readonly List comparePickerRows = new List(); private static readonly List comparePickerTexts = new List(); private static readonly Dictionary compareStatsCache = new Dictionary(); private static readonly Color[] COMPARE_COLORS = (Color[])(object)new Color[12] { new Color(0.4f, 0.8f, 1f), new Color(1f, 0.5f, 0.4f), new Color(0.55f, 1f, 0.55f), new Color(1f, 0.85f, 0.3f), new Color(0.8f, 0.55f, 1f), new Color(0.4f, 0.95f, 0.9f), new Color(1f, 0.65f, 0.85f), new Color(0.7f, 0.9f, 0.45f), new Color(1f, 0.78f, 0.45f), new Color(0.6f, 0.7f, 1f), new Color(0.9f, 0.55f, 0.55f), new Color(0.65f, 0.85f, 0.75f) }; private static Sprite _pieCircleSprite; private static readonly Dictionary _bodyGlyphCache = new Dictionary(); private static GameObject tierExportPanel; private static int _lastChatIdSeen = 0; private static HashSet _mutedCache; private const string LBL_SEP = " + "; private const int LBL_MIN_VISIBLE = 6; private static readonly List _lblParts = new List(4); private static readonly List _lblOrder = new List(4); private static readonly int[] _lblGrant = new int[8]; private static GameObject adminFlagsContainer; private static GameObject adminBansContainer; private static object txtAdminFlagsHdr; private static object txtAdminBansHdr; private static List adminFlagRowPool = new List(); private static List adminBanRowPool = new List(); private static GameObject adminSeriesContainer; private static object txtAdminSeriesHdr; private static List adminSeriesRowPool = new List(); private static GameObject adminQuarantineContainer; private static object txtAdminQuarantineHdr; private static List adminQuarantineRowPool = new List(); private static List adminQuarantineRowBindings = new List(); private const int ADMIN_QUARANTINE_ROW_CAP = 20; private static object txtTState; private static object txtTWhen; private static object txtTPenalty; private static object txtTForceCount; private static object txtTMyMatch; private static object txtTDiscordGate; private static object txtTMyHistory; private static object txtTRoomCode; private static object txtTTzNow; private static string _tInfoTitle = "How It Works - Sync (weekly)"; private static string _tInfoInstructions = "HOW IT WORKS (Sync)\n 1. Pick every start time you can make, then sign up (Discord must be linked)\n 2. It locks when 8+ players agree on one time - decided 2 days before the default start, so you always get 24h+ notice; players who can't make the winning time are removed (no penalty)\n 3. Have ROUNDS open at start time (main menu is fine - no tab-sitting needed)\n 4. Mod auto-connects you to your opponent - no queue, no invites\n 5. Play BO3, bracket advances automatically - plan for a couple of hours total\n\nBETWEEN MATCHES\n * ~7 min breather before each of your matches after round 1\n * Both players press Play Now to skip the break and start early\n * Show up within 10 min of your match or forfeit\n * Bracket hidden until start (no scouting your first opponent)\n\nFORMAT\n * Double-elim BO3 (first to 2) - losing once drops you to the losers bracket\n * Matches run in parallel: your next match schedules the moment its players are known\n * Top seeds get byes when fewer than 16 sign up\n * Grand Final: WB champ vs LB champ (bracket reset if LB wins first BO3)\n * All matches count toward ranked Elo\n\nPENALTY %\n * Grows when you sign up but no-show at match time\n * Lower penalty = priority if more than 16 sign up"; private static string _tInfoPrizes = ""; private static GameObject txtTSignupBtn; private static GameObject txtTUnsignupBtn; private static GameObject txtTReadyBtn; private static GameObject txtTForceBtn; private static GameObject txtTTzButton; private static GameObject txtTDateFmtButton; private static GameObject txtTReconnectBtn; private static GameObject tSubTabSyncBtn; private static GameObject tSubTabAsyncBtn; private static GameObject tTimeVoteRow; private static GameObject tSignupList; private static GameObject tBracketList; private static GameObject tMyMatchPanel; private static GameObject tHistoryList; private static GameObject tVoteBoxPanel; private static GameObject tVoteSaveBtn; private static object txtTVoteHdr; private static GameObject tPlayNowBtn; private static List tHistoryRowPool = new List(); private static List tHistoryRowTexts = new List(); private static HashSet _tournamentDispatchedMatches = new HashSet(); private static List tSlotToggles = new List(); private static List tSlotChecked = new List(); private static List tSlotLabels = new List(); private static List tSignupRowPool = new List(); private static List tSignupRowTexts = new List(); private static List tBracketRowPool = new List(); private static List tBracketRowTexts = new List(); private static GameObject tBracketVisual; private static GameObject tTournBetsBox; private static GameObject tTournBetsContainer; private static object tTournBetsHeader; private static List tTournBetRowPool = new List(); private static List _tBracketRowPurposes = new List(); private static Dictionary _tBracketExpanded = new Dictionary(); private static string _tBracketSeededForTid = null; private static float tTournamentRefreshAt; private static float tReadyHeartbeatAt; private static readonly (string Label, string SystemId)[] _tzPresets = new(string, string)[12] { ("Local", ""), ("UTC", "UTC"), ("PT", "Pacific Standard Time"), ("MT", "Mountain Standard Time"), ("CT", "Central Standard Time"), ("ET", "Eastern Standard Time"), ("UK/GMT", "GMT Standard Time"), ("CET", "Central European Standard Time"), ("EET", "E. Europe Standard Time"), ("MSK", "Russian Standard Time"), ("JST", "Tokyo Standard Time"), ("AEST", "AUS Eastern Standard Time") }; private static readonly string[] _dateFormats = new string[3] { "ISO", "US", "EU" }; private static readonly CultureInfo _INV = CultureInfo.InvariantCulture; private static bool _tVoteLocalEdited = false; private static string _tVoteSlotSig = ""; private const string _SYNC_INSTRUCTIONS = "HOW IT WORKS (Sync)\n 1. Pick every start time you can make, then sign up (Discord must be linked)\n 2. It locks when 8+ players agree on one time - decided 2 days before the default start, so you always get 24h+ notice; players who can't make the winning time are removed (no penalty)\n 3. Have ROUNDS open at start time (main menu is fine - no tab-sitting needed)\n 4. Mod auto-connects you to your opponent - no queue, no invites\n 5. Play BO3, bracket advances automatically - plan for a couple of hours total\n\nBETWEEN MATCHES\n * ~7 min breather before each of your matches after round 1\n * Both players press Play Now to skip the break and start early\n * Show up within 10 min of your match or forfeit\n * Bracket hidden until start (no scouting your first opponent)\n\nFORMAT\n * Double-elim BO3 (first to 2) - losing once drops you to the losers bracket\n * Matches run in parallel: your next match schedules the moment its players are known\n * Top seeds get byes when fewer than 16 sign up\n * Grand Final: WB champ vs LB champ (bracket reset if LB wins first BO3)\n * All matches count toward ranked Elo\n\nPENALTY %\n * Grows when you sign up but no-show at match time\n * Lower penalty = priority if more than 16 sign up"; private const string _ASYNC_INSTRUCTIONS = "HOW IT WORKS (Async)\n 1. Sign up any time during the 7-day signup window (Discord must be linked)\n 2. On lock, bracket is built and first-round matches activate\n 3. Coordinate with your opponent via /dm-opponent on Discord\n 4. Both of you enable Ranked, join any private lobby in ROUNDS, play the BO3\n 5. Mod records the result automatically - no manual report, no room code needed\n 6. Winner advances in bracket; loser drops to LB (or is eliminated)\n\nAUTO-RECORDING REQUIREMENTS\n * Both players must have Ranked toggled ON in-game when playing\n * Any private ROUNDS lobby works - tournament doesn't force a specific room\n * Once you hit 2 BO3 wins, the mod advances the bracket and notifies you\n\nSCHEDULING\n * No fixed start time - self-paced, 7 days per match\n * Total tournament runs up to 6-9 weeks depending on how fast matches happen\n * Miss the deadline and you forfeit that match (tracked in penalty %)\n\nFORMAT\n * Double-elim BO3 - lose once, you drop to losers bracket\n * Grand Final: WB champ vs LB champ (bracket reset if LB wins first BO3)\n * All matches count toward ranked Elo\n\nPENALTY %\n * Grows when you sign up but forfeit a match by missing the 7-day deadline"; private static object txtTeamHeader; private static object txtTeamStatus; private static object txtTeamMembers; private static object txtTeamLBHeader; private static GameObject teamSearchBtn; private static GameObject teamSearchCustomBtn; private static GameObject teamLeaveBtn; private static GameObject teamReadyBtn; private static GameObject teamLBContainer; private static Component teamLBScrollRect; private static List teamLBRows = new List(); private static readonly int[] TLB_COL_W = new int[8] { 36, 200, 70, 80, 60, 92, 76, 88 }; private static List teamLBSortBtns; private static string[] teamLBSortKeys; private static object[] teamLBHeaderTexts; private static GameObject teamHistPrevBtn; private static GameObject teamHistNextBtn; private static object txtTeamHistPageIndicator; private static object txtTeamHistHeader; private static GameObject teamHistContainer; private static object teamHistScrollRect; private static List teamHistRows = new List(); private static Dictionary _teamSeriesExpanded = new Dictionary(); private static object txtTeamQueueListHeader; private static object txtTeamQueueListBody; private static object txtTeamQueueManualHeader; private static object txtTeamQueueManualBody; private static object txtTeamDcGrace; private static GameObject teamPickT1Btn; private static GameObject teamPickT2Btn; private static object txtPickStatus; private static GameObject teamLivePanel; private static object txtTeamLiveHeader; private static object txtTeamLiveBody; public static int CurrentTab => currentTab; public static bool IsOpen => isOpen; public static bool LfpPromptOpen { get; private set; } public static bool InfoPopupOpen => (Object)(object)infoPopupGO != (Object)null; public static bool CustomBetPromptOpen { get; private set; } public static string CustomBetTargetLabel { get; private set; } = ""; public static string CompareSearch { get { return compareSearch; } set { compareSearch = value ?? ""; } } public static string LeaderboardSearch { get { return lbSearch; } set { lbSearch = value ?? ""; } } internal static Type TImage => UIFactory.tImage; internal static Type TButton => UIFactory.tButton; private static GameObject MakeSubTabAnchor(int tabIdx, Transform parent, bool asFirst) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown GameObject val = new GameObject($"SubTabAnchor{tabIdx}"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddHLG(val, 0f); UIFactory.AddLE(val, -1f, 30f, -1f, 30f, -1f, 0f); if (asFirst) { val.transform.SetAsFirstSibling(); } if (subTabAnchors == null) { subTabAnchors = (GameObject[])(object)new GameObject[14]; } subTabAnchors[tabIdx] = val; val.SetActive(false); return val; } public static void MaybeRefreshLiveSeries() { if (currentTab != 1) { return; } if (Time.unscaledTime >= liveHeaderNextPulseAt) { liveHeaderNextPulseAt = Time.unscaledTime + 2.5f; liveHeaderPulseFilled = !liveHeaderPulseFilled; dirty = true; } if (!(Time.unscaledTime < liveSeriesAutoRefreshAt)) { liveSeriesAutoRefreshAt = Time.unscaledTime + 5f; ApiClient.FetchActiveSeries(); ApiClient.FetchActiveTeamSeries(); string localSteamId = MatchTracker.LocalSteamId; ApiClient.FetchFfaBettable(localSteamId); if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.FetchMyBets(localSteamId); } } } public static ChatEntry[] SnapshotChat(int tail) { lock (chatLinesLock) { int num = Math.Max(0, chatLines.Count - tail); ChatEntry[] array = new ChatEntry[chatLines.Count - num]; for (int i = 0; i < array.Length; i++) { array[i] = chatLines[num + i]; } return array; } } public static void CopyChatTail(List destination, int tail) { if (destination == null) { return; } lock (chatLinesLock) { destination.Clear(); int num = Math.Max(0, chatLines.Count - tail); for (int i = num; i < chatLines.Count; i++) { destination.Add(chatLines[i]); } } } private static void ToggleHistoryCardMode() { _historyCardsFull = !_historyCardsFull; PlayerPrefs.SetInt("cr_history_card_names_full", _historyCardsFull ? 1 : 0); PlayerPrefs.Save(); dirty = true; } private static string HistoryCardModeLabel() { return _historyCardsFull ? "Cards: FULL" : "Cards: chips"; } private static string GameCode(string matchId) { if (string.IsNullOrEmpty(matchId)) { return null; } string text = matchId.Replace("-", ""); return text.Substring(0, Math.Min(12, text.Length)).ToUpperInvariant(); } private static void CopyGameCode(string matchId) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(matchId)) { string text = (GUIUtility.systemCopyBuffer = GameCode(matchId)); CompetitiveUI.ShowNotification("Game ID " + text + " copied - paste into /game in Discord", new Color(0.6f, 0.9f, 1f)); } } private static string CardTierKey(int filterIdx, string cardName) { return string.Format("{0}|{1}", filterIdx, (cardName ?? "").ToLower()); } public static void Toggle() { if (isOpen) { Close(); } else { Open(); } } public static void MarkDirty() { dirty = true; } public static void SetLinkCode(string code) { if (txtLinkCode != null) { UIFactory.SetText(txtLinkCode, "" + code + " - type !link " + code + " in Discord"); } } public static void Open() { if (!UIFactory.Ready) { UIFactory.InitTypes(); UIFactory.InitFont(); } if (!UIFactory.Ready) { return; } bool isInOnlineRoom = GameStateWatcher.IsInOnlineRoom; inGameMode = isInOnlineRoom; EnsureOverlayCanvas(); bool flag = false; if (!pageBuilt || (Object)(object)pageGO == (Object)null || (Object)(object)pageGO.transform.parent != (Object)(object)overlayCanvasGO.transform) { if ((Object)(object)pageGO != (Object)null) { Object.Destroy((Object)(object)pageGO); } pageBuilt = false; BuildPage(overlayCanvasGO.transform); if (!pageBuilt) { return; } flag = true; } pageGO.SetActive(true); if (flag) { try { UIFactory.tCanvas?.GetMethod("ForceUpdateCanvases", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); } catch { } } isOpen = true; dirty = true; RefreshData(); ApiClient.ResetQueueCountTimer(); Plugin.Log.LogInfo((object)$"[NATIVE] Opened competitive page (inGame={inGameMode})"); } public static void Close() { if ((Object)(object)pageGO != (Object)null) { pageGO.SetActive(false); } isOpen = false; try { TrailPreview.Stop(); } catch { } try { PlayerEffectCosmetic.StopPreview(); } catch { } try { HideInfoPopup(); } catch { } try { HideCardPreview(); } catch { } SetClickBlocker(on: false); SetMenuFade(on: false); Plugin.Log.LogInfo((object)"[NATIVE] Closed competitive page"); } public static void LogOverlayState(string context) { //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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) try { bool flag = (Object)(object)pageGO != (Object)null && pageGO.activeInHierarchy; float num = -1f; try { PropertyInfo propertyInfo = menuFadeCG?.GetType().GetProperty("alpha", BindingFlags.Instance | BindingFlags.Public); if (propertyInfo != null) { num = (float)propertyInfo.GetValue(menuFadeCG); } } catch { } Vector2 val = Vector2.zero; try { GameObject obj2 = overlayCanvasGO; RectTransform val2 = ((obj2 != null) ? obj2.GetComponent() : null); if ((Object)(object)val2 != (Object)null) { Rect rect = val2.rect; val = ((Rect)(ref rect)).size; } } catch { } Plugin.Log.LogInfo((object)($"[OVERLAY-DIAG] {context}: window={Screen.width}x{Screen.height} " + $"canvas={val.x:0}x{val.y:0} pageActive={flag} " + $"isOpen={isOpen} fadeAlpha={num:0.00} fullscreen={Screen.fullScreen}")); } catch { } } public static void SetMenuFade(bool on) { try { if ((Object)(object)pageGO == (Object)null) { return; } if (menuFadeCG == null) { Type tCanvasGroup = UIFactory.tCanvasGroup; if (tCanvasGroup == null) { return; } menuFadeCG = pageGO.GetComponent(tCanvasGroup) ?? pageGO.AddComponent(tCanvasGroup); } menuFadeCG.GetType().GetProperty("alpha", BindingFlags.Instance | BindingFlags.Public)?.SetValue(menuFadeCG, on ? 0.16f : 1f); } catch { } } public static void SetClickBlocker(bool on) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_00ca: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)clickBlocker == (Object)null) { if ((Object)(object)overlayCanvasGO == (Object)null) { return; } clickBlocker = new GameObject("CR_ClickBlocker"); clickBlocker.transform.SetParent(overlayCanvasGO.transform, false); RectTransform val = clickBlocker.AddComponent(); val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.offsetMin = Vector2.zero; val.offsetMax = Vector2.zero; Component obj = clickBlocker.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, (object)new Color(0f, 0f, 0f, 0.001f)); UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, true); clickBlocker.SetActive(false); } if (on) { clickBlocker.transform.SetAsLastSibling(); } if (clickBlocker.activeSelf != on) { clickBlocker.SetActive(on); } } catch { } } public static void Tick() { if (!isOpen || !pageBuilt) { return; } if ((Object)(object)pageGO == (Object)null) { isOpen = false; pageBuilt = false; return; } if (Input.GetKeyDown((KeyCode)27)) { Close(); return; } dataCheckTimer += Time.deltaTime; if (dataCheckTimer >= 0.3f) { dataCheckTimer = 0f; int num = ApiClient.CachedMatchHistory?.Count ?? 0; int valueOrDefault = (ApiClient.CachedLeaderboard?.entries?.Length).GetValueOrDefault(); int num2 = ApiClient.CachedCardStats?.Count ?? 0; if (num != lastMatchCount || valueOrDefault != lastLBCount || num2 != lastCardCount) { lastMatchCount = num; lastLBCount = valueOrDefault; lastCardCount = num2; dirty = true; } } if (dirty) { dirty = false; RefreshCurrentTab(); } MaybeRefreshTournament(); MaybeRefreshTeamTab(); MaybeRefreshLeaderboardTab(); MaybeRefreshOvtTab(); MaybeRefreshFfaTab(); MaybeRefreshHomeTab(); TickAnimatedThumbnails(); } public static void TrackAnimatedThumb(object img, Sprite[] frames, float fps) { if (img != null) { if (frames == null || frames.Length < 2 || fps <= 0f) { _animThumbs.Remove(img); _animThumbLastIdx.Remove(img); } else { _animThumbs[img] = (frames, fps); _animThumbLastIdx.Remove(img); } } } private static void TickAnimatedThumbnails() { if (_animThumbs.Count == 0 || (currentTab != 4 && currentTab != 13)) { return; } try { if (_pImgSprite == null && UIFactory.tImage != null) { _pImgSprite = UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public); } if (_pImgSprite == null) { return; } bool flag = Plugin.AnimatedCosmetics != null && !Plugin.AnimatedCosmetics.Value; foreach (KeyValuePair animThumb in _animThumbs) { (Sprite[], float) value = animThumb.Value; Sprite[] item = value.Item1; float item2 = value.Item2; int num = ((!flag) ? ((int)(Time.unscaledTime * item2) % item.Length) : 0); if (!_animThumbLastIdx.TryGetValue(animThumb.Key, out var value2) || value2 != num) { _pImgSprite.SetValue(animThumb.Key, item[num]); _animThumbLastIdx[animThumb.Key] = num; } } } catch { } } private static void MaybeRefreshLeaderboardTab() { if (currentTab == 1) { TickPodiumSparkle(); if (!(Time.unscaledTime < lbTabRefreshAt)) { lbTabRefreshAt = Time.unscaledTime + 30f; ApiClient.FetchLeaderboard(); ApiClient.FetchRecentSeries(); ApiClient.FetchRecentMultimodeSeries(); } } } internal static bool IsPodiumTitle(string t) { return t == "1st Place" || t == "2nd Place" || t == "3rd Place"; } private static void SetLbRowOutline(LBRow row, bool on) { if (row != null) { NametagGlowRenderer.ApplyOutlineToLabel(row.txtRank, on, _lbOutlineOrig, _lbOutlineCache); NametagGlowRenderer.ApplyOutlineToLabel(row.txtLv, on, _lbOutlineOrig, _lbOutlineCache); NametagGlowRenderer.ApplyOutlineToLabel(row.txtName, on, _lbOutlineOrig, _lbOutlineCache); NametagGlowRenderer.ApplyOutlineToLabel(row.txtRating, on, _lbOutlineOrig, _lbOutlineCache); NametagGlowRenderer.ApplyOutlineToLabel(row.txtW, on, _lbOutlineOrig, _lbOutlineCache); NametagGlowRenderer.ApplyOutlineToLabel(row.txtL, on, _lbOutlineOrig, _lbOutlineCache); NametagGlowRenderer.ApplyOutlineToLabel(row.txtWL, on, _lbOutlineOrig, _lbOutlineCache); NametagGlowRenderer.ApplyOutlineToLabel(row.txtGold, on, _lbOutlineOrig, _lbOutlineCache); } } internal static string PodiumSparkleSpan(string title, string hex, uint tick) { StringBuilder stringBuilder = new StringBuilder(title.Length * 24 + 40); stringBuilder.Append("["); for (int i = 0; i < title.Length; i++) { bool flag = (i + (int)tick) % 3 == 0; stringBuilder.Append("") .Append(title[i]) .Append(""); } stringBuilder.Append("]"); return stringBuilder.ToString(); } private static void TickPodiumSparkle() { if (_podiumLbRows.Count == 0 || Time.unscaledTime < _podiumTickAt) { return; } _podiumTickAt = Time.unscaledTime + 0.7f; _podiumTick++; foreach (object[] podiumLbRow in _podiumLbRows) { if (podiumLbRow != null && podiumLbRow.Length >= 4 && podiumLbRow[0] != null) { UIFactory.SetText(podiumLbRow[0], (string)podiumLbRow[1] + " " + PodiumSparkleSpan((string)podiumLbRow[2], (string)podiumLbRow[3], _podiumTick)); } } } public static void MaybeRefreshTeamTab() { if (currentTab == 8 && !(Time.unscaledTime < teamTabRefreshAt)) { teamTabRefreshAt = Time.unscaledTime + 2f; ApiClient.UpdateTeamQueueList(force: true); ApiClient.UpdateTeamQueueCount(); ApiClient.FetchActiveTeamSeries(); if (Time.unscaledTime >= teamSeriesRefreshAt) { teamSeriesRefreshAt = Time.unscaledTime + 10f; ApiClient.FetchAllSeriesPaged(teamSeriesPageReq, 10); } } } private static void FindMainMenuGroup() { ListMenuButton[] array = Object.FindObjectsOfType(); Type type = null; PropertyInfo propertyInfo = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("TMPro.TMP_Text"); if (type != null) { break; } } if (type != null) { propertyInfo = type.GetProperty("text", BindingFlags.Instance | BindingFlags.Public); } ListMenuButton[] array2 = array; foreach (ListMenuButton val in array2) { if (propertyInfo == null) { break; } try { Component componentInChildren = ((Component)val).GetComponentInChildren(type, true); if ((Object)(object)componentInChildren == (Object)null || !(((propertyInfo.GetValue(componentInChildren) as string) ?? "").Trim().ToUpper() == "QUIT")) { continue; } mainMenuGroup = ((Component)((Component)val).transform.parent).gameObject; Plugin.Log.LogInfo((object)("[NATIVE] Found main menu group: " + ((Object)mainMenuGroup).name)); return; } catch { } } Plugin.Log.LogWarning((object)"[NATIVE] Could not find QUIT button"); } private static Transform FindCanvasAbove(Transform from) { Transform val = from; while ((Object)(object)val != (Object)null) { if (UIFactory.tCanvas != null && (Object)(object)((Component)val).GetComponent(UIFactory.tCanvas) != (Object)null) { Plugin.Log.LogInfo((object)("[NATIVE] Found Canvas: " + ((Object)((Component)val).gameObject).name)); return val; } val = val.parent; } return from.parent ?? from; } private static void EnsureOverlayCanvas() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)overlayCanvasGO != (Object)null) { return; } overlayCanvasGO = new GameObject("CR_OverlayCanvas"); ((Object)overlayCanvasGO).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)overlayCanvasGO); if (UIFactory.tCanvas != null) { Component obj = overlayCanvasGO.AddComponent(UIFactory.tCanvas); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; UIFactory.tCanvas.GetProperty("renderMode", bindingAttr)?.SetValue(obj, Enum.ToObject(UIFactory.tCanvas.GetProperty("renderMode", bindingAttr).PropertyType, 0)); UIFactory.tCanvas.GetProperty("sortingOrder", bindingAttr)?.SetValue(obj, 30000); } if (UIFactory.tCanvasScaler != null) { Component obj2 = overlayCanvasGO.AddComponent(UIFactory.tCanvasScaler); BindingFlags bindingAttr2 = BindingFlags.Instance | BindingFlags.Public; PropertyInfo property = UIFactory.tCanvasScaler.GetProperty("uiScaleMode", bindingAttr2); if (property != null) { property.SetValue(obj2, Enum.ToObject(property.PropertyType, 1)); } UIFactory.tCanvasScaler.GetProperty("referenceResolution", bindingAttr2)?.SetValue(obj2, (object)new Vector2(1920f, 1080f)); } if (UIFactory.tGR != null) { overlayCanvasGO.AddComponent(UIFactory.tGR); } Plugin.Log.LogInfo((object)"[NATIVE] Created persistent overlay Canvas"); } private static void BuildPage(Transform canvasParent) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_009d: 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_00b5: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Expected O, but got Unknown //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Expected O, but got Unknown //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_0498: Expected O, but got Unknown //IL_0512: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Unknown result type (might be due to invalid IL or missing references) //IL_067a: Unknown result type (might be due to invalid IL or missing references) //IL_0681: Expected O, but got Unknown //IL_06ec: Unknown result type (might be due to invalid IL or missing references) //IL_0700: Unknown result type (might be due to invalid IL or missing references) //IL_0728: Unknown result type (might be due to invalid IL or missing references) //IL_073c: Unknown result type (might be due to invalid IL or missing references) //IL_0768: Unknown result type (might be due to invalid IL or missing references) //IL_0781: Unknown result type (might be due to invalid IL or missing references) //IL_07af: Unknown result type (might be due to invalid IL or missing references) //IL_07e5: Unknown result type (might be due to invalid IL or missing references) //IL_07fe: Unknown result type (might be due to invalid IL or missing references) //IL_079a: Unknown result type (might be due to invalid IL or missing references) //IL_079f: Unknown result type (might be due to invalid IL or missing references) //IL_07a5: Expected O, but got Unknown //IL_082c: Unknown result type (might be due to invalid IL or missing references) //IL_0852: Unknown result type (might be due to invalid IL or missing references) //IL_086b: Unknown result type (might be due to invalid IL or missing references) //IL_0817: Unknown result type (might be due to invalid IL or missing references) //IL_081c: Unknown result type (might be due to invalid IL or missing references) //IL_0822: Expected O, but got Unknown //IL_0899: Unknown result type (might be due to invalid IL or missing references) //IL_08ae: Unknown result type (might be due to invalid IL or missing references) //IL_08b5: Expected O, but got Unknown //IL_090e: Unknown result type (might be due to invalid IL or missing references) //IL_0913: Unknown result type (might be due to invalid IL or missing references) //IL_0884: Unknown result type (might be due to invalid IL or missing references) //IL_0889: Unknown result type (might be due to invalid IL or missing references) //IL_088f: Expected O, but got Unknown //IL_0941: Unknown result type (might be due to invalid IL or missing references) //IL_092c: Unknown result type (might be due to invalid IL or missing references) //IL_0931: Unknown result type (might be due to invalid IL or missing references) //IL_0937: Expected O, but got Unknown try { rankedRows.Clear(); casualRows.Clear(); lbRows.Clear(); cardRows.Clear(); sessionOppTexts.Clear(); ovtSoloLbRows.Clear(); ovtDuoLbRows.Clear(); ovtRecentRows.Clear(); ffaLbRows.Clear(); ffaRecentRows.Clear(); pageGO = new GameObject("CompetitiveRoundsPage"); pageGO.transform.SetParent(canvasParent, false); RectTransform val = pageGO.AddComponent(); val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.offsetMin = Vector2.zero; val.offsetMax = Vector2.zero; pageGO.SetActive(false); GameObject val2 = UIFactory.CreatePanel("BG", pageGO.transform, C_BG); Component component = val2.GetComponent(UIFactory.tImage); if ((Object)(object)component != (Object)null) { UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, true); } GameObject val3 = new GameObject("Content"); val3.transform.SetParent(pageGO.transform, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.offsetMin = new Vector2(30f, 10f); val4.offsetMax = new Vector2(-30f, -10f); UIFactory.AddVLG(val3, 4f, 8, 8, 8, 8); GameObject val5 = new GameObject("TitleRow"); val5.transform.SetParent(val3.transform, false); val5.AddComponent(); UIFactory.AddHLG(val5, 8f); UIFactory.AddLE(val5, -1f, 30f, -1f, 30f, -1f, 0f); UIFactory.CreateText("Title", val5.transform, "SID'S COMPETITIVE ROUNDS", 24f, C_WHITE, 514, (Vector2?)new Vector2(0f, 30f), richText: true, raycastTarget: false); GameObject gameObject = ((Component)val5.transform.GetChild(0)).gameObject; if (UIFactory.tLE != null) { Component component2 = gameObject.GetComponent(UIFactory.tLE); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } } UIFactory.AddLE(gameObject, -1f, -1f, -1f, 42f, 1f); Transform transform = val5.transform; Color c_LABEL = C_LABEL; Color c_BTN = C_BTN; object obj = <>c.<>9__224_0; if (obj == null) { UnityAction val6 = delegate { Close(); }; <>c.<>9__224_0 = val6; obj = (object)val6; } UIFactory.CreateButton("BackBtn", transform, "< BACK", 16f, c_LABEL, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(85f, 34f)); GameObject val7 = new GameObject("SrvRow"); val7.transform.SetParent(val3.transform, false); val7.AddComponent(); UIFactory.AddHLG(val7, 6f); UIFactory.AddLE(val7, -1f, 22f, -1f, 22f, -1f, 0f); txtServerStatus = UIFactory.CreateText("SrvSt", val7.transform, "", 14f, new Color(1f, 0.7f, 0.6f), 514, (Vector2?)new Vector2(0f, 22f), richText: true, raycastTarget: false); object obj2 = txtServerStatus; object obj3 = ((obj2 is Component) ? obj2 : null); GameObject val8 = ((obj3 != null) ? ((Component)obj3).gameObject : null); if ((Object)(object)val8 != (Object)null && UIFactory.tLE != null) { Component component3 = val8.GetComponent(UIFactory.tLE); if ((Object)(object)component3 != (Object)null) { Object.Destroy((Object)(object)component3); } } if ((Object)(object)val8 != (Object)null) { UIFactory.AddLE(val8, -1f, -1f, -1f, 22f, 1f); } UIFactory.SetBold(txtServerStatus, b: true); val7.SetActive(false); srvStatusRow = val7; BuildRankedRow(val3.transform); GameObject val9 = new GameObject("TournIndRow"); val9.transform.SetParent(val3.transform, false); val9.AddComponent(); UIFactory.AddHLG(val9, 6f, 4); UIFactory.AddLE(val9, -1f, 22f, -1f, 22f, -1f, 0f); txtTournamentGame = UIFactory.CreateText("TGame", val9.transform, "", 15f, new Color(1f, 0.85f, 0.3f), 513, (Vector2?)new Vector2(700f, 22f), richText: true, raycastTarget: false); UIFactory.SetBold(txtTournamentGame, b: true); val9.SetActive(false); tournamentIndRow = val9; BuildTabBar(val3.transform); tabPanels = (GameObject[])(object)new GameObject[14]; tabPanels[0] = BuildMyStatsTab(val3.transform); tabPanels[1] = BuildLeaderboardTab(val3.transform); tabPanels[2] = BuildCardStatsTab(val3.transform); tabPanels[3] = BuildAchievementsTab(val3.transform); tabPanels[4] = BuildShopTab(val3.transform); tabPanels[5] = BuildSettingsTab(val3.transform); tabPanels[6] = BuildAdminTab(val3.transform); tabPanels[7] = BuildTournamentsTab(val3.transform); tabPanels[8] = BuildTeamTab(val3.transform); tabPanels[9] = BuildCompareTab(val3.transform); tabPanels[10] = BuildArtistTab(val3.transform); tabPanels[11] = BuildOneVTwoTab(val3.transform, 11); tabPanels[12] = BuildFfaTab(val3.transform, 12); tabPanels[13] = BuildHomeTab(val3.transform); GameObject val10 = new GameObject("Bottom"); val10.transform.SetParent(val3.transform, false); val10.AddComponent(); UIFactory.AddHLG(val10, 8f); UIFactory.AddLE(val10, -1f, 26f, -1f, 26f, -1f, 0f); UIFactory.CreateText("Ver", val10.transform, "v1.35.5", 13f, C_DIM, 513, (Vector2?)new Vector2(90f, 22f), richText: true, raycastTarget: false); txtVersionStatus = UIFactory.CreateText("VerStatus", val10.transform, "", 12f, C_DIM, 513, (Vector2?)new Vector2(130f, 22f), richText: true, raycastTarget: false); Transform transform2 = val10.transform; Color c_WHITE = C_WHITE; Color bgColor = new Color(0.6f, 0.4f, 0.1f, 0.9f); object obj4 = <>c.<>9__224_1; if (obj4 == null) { UnityAction val11 = delegate { ApiClient.StartAutoUpdate(); }; <>c.<>9__224_1 = val11; obj4 = (object)val11; } updateBtn = UIFactory.CreateButton("UpdateBtn", transform2, "Update", 14f, c_WHITE, bgColor, (UnityAction)obj4, (Vector2?)new Vector2(75f, 26f)); updateBtn.SetActive(false); Transform transform3 = val10.transform; Color white = Color.white; Color bgColor2 = new Color(0.345f, 0.396f, 0.949f, 0.9f); object obj5 = <>c.<>9__224_2; if (obj5 == null) { UnityAction val12 = delegate { Application.OpenURL("https://discord.gg/comp-rounds"); }; <>c.<>9__224_2 = val12; obj5 = (object)val12; } UIFactory.CreateButton("Discord", transform3, "Discord", 14f, white, bgColor2, (UnityAction)obj5, (Vector2?)new Vector2(80f, 26f)); Transform transform4 = val10.transform; Color white2 = Color.white; Color bgColor3 = new Color(0.2f, 0.2f, 0.2f, 0.9f); object obj6 = <>c.<>9__224_3; if (obj6 == null) { UnityAction val13 = delegate { Application.OpenURL("https://github.com/SidNDeed/SidsCompetitiveRounds"); }; <>c.<>9__224_3 = val13; obj6 = (object)val13; } UIFactory.CreateButton("GitHub", transform4, "GitHub", 14f, white2, bgColor3, (UnityAction)obj6, (Vector2?)new Vector2(75f, 26f)); GameObject val14 = new GameObject("S"); val14.transform.SetParent(val10.transform, false); val14.AddComponent(); UIFactory.AddLE(val14, -1f, -1f, -1f, -1f, 1f); Transform transform5 = val10.transform; Color c_WHITE2 = C_WHITE; Color c_BTN2 = C_BTN; object obj7 = <>c.<>9__224_4; if (obj7 == null) { UnityAction val15 = delegate { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime >= _nextManualRefreshAt) { _nextManualRefreshAt = Time.unscaledTime + 2f; RefreshData(); dirty = true; } else { CompetitiveUI.ShowNotification("Refreshing too fast - give it a sec", Color.yellow, 1.5f); } }; <>c.<>9__224_4 = val15; obj7 = (object)val15; } UIFactory.CreateButton("RefreshBtn", transform5, "Refresh", 15f, c_WHITE2, c_BTN2, (UnityAction)obj7, (Vector2?)new Vector2(85f, 26f)); SwitchTab(13); pageBuilt = true; Plugin.Log.LogInfo((object)"[NATIVE] Competitive page built"); } catch (Exception arg) { Plugin.Log.LogError((object)$"[NATIVE] BuildPage failed: {arg}"); pageBuilt = false; } } private static void OnLfpButton() { //IL_0015: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; if (cachedPlayerStats == null) { CompetitiveUI.ShowNotification("Stats still loading - try again in a moment.", C_DIM); return; } if (string.IsNullOrEmpty(cachedPlayerStats.discord_id)) { CompetitiveUI.ShowNotification("Link your Discord account first (Home tab) to use RLFP pings.", new Color(1f, 0.8f, 0.3f), 7f); return; } if (Plugin.RankedEnabled == null || !Plugin.RankedEnabled.Value) { CompetitiveUI.ShowNotification("Enable Ranked first - the RLFP ping is for ranked matches.", new Color(1f, 0.8f, 0.3f), 6f); return; } float num = lfpCooldownUntil - Time.realtimeSinceStartup; if (num > 0f) { CompetitiveUI.ShowNotification($"RLFP ping available in {(int)(num / 60f)}m {(int)(num % 60f)}s (1 per hour).", C_DIM, 6f); return; } LfpMessageText = ""; LfpExpiryIdx = 2; LfpPromptOpen = true; } public static void SubmitLfpPing() { LfpPromptOpen = false; int expiresMinutes = LfpExpiryMinutes[Mathf.Clamp(LfpExpiryIdx, 0, LfpExpiryMinutes.Length - 1)]; ApiClient.SendLfpPing(MatchTracker.LocalSteamId, LfpMessageText ?? "", expiresMinutes); } public static void CancelLfpPing() { LfpPromptOpen = false; } public static void LfpArmCooldown(int seconds) { if (seconds > 0) { lfpCooldownUntil = Time.realtimeSinceStartup + (float)seconds; dirty = true; } } private static void BuildRankedRow(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0152: 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_0180: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Expected O, but got Unknown //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Expected O, but got Unknown //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Expected O, but got Unknown //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Expected O, but got Unknown //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Expected O, but got Unknown //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Expected O, but got Unknown //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_050a: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Expected O, but got Unknown //IL_0581: Unknown result type (might be due to invalid IL or missing references) //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_05b4: Unknown result type (might be due to invalid IL or missing references) //IL_059f: Unknown result type (might be due to invalid IL or missing references) //IL_05a4: Unknown result type (might be due to invalid IL or missing references) //IL_05aa: Expected O, but got Unknown GameObject val = new GameObject("RankedRow"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddHLG(val, 10f, 4, 4); UIFactory.AddLE(val, -1f, 26f, -1f, 26f, -1f, 0f); object t = UIFactory.CreateText("PName", val.transform, ApiClient.CachedPlayerStats?.display_name ?? MatchTracker.LocalDisplayName ?? "", 20f, C_SUB, 513, (Vector2?)new Vector2(110f, 28f), richText: true, raycastTarget: false); UIFactory.SetBold(t, b: true); txtTopLeftName = t; txtRankedStatus = UIFactory.CreateText("RS", val.transform, "RANKED: OFF", 18f, Color.gray, 513, (Vector2?)new Vector2(140f, 28f), richText: true, raycastTarget: false); UIFactory.SetBold(txtRankedStatus, b: true); Transform transform = val.transform; Color c_WHITE = C_WHITE; Color c_BTN = C_BTN; object obj = <>c.<>9__239_0; if (obj == null) { UnityAction val2 = delegate { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.JoinQueue(localSteamId, MatchTracker.LocalDisplayName, null, rankedOnly: false); } }; <>c.<>9__239_0 = val2; obj = (object)val2; } qSearchBtn = UIFactory.CreateButton("Search", transform, "Search Ranked", 15f, c_WHITE, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(130f, 26f)); Transform transform2 = val.transform; Color c_WHITE2 = C_WHITE; Color c_BTN2 = C_BTN; object obj2 = <>c.<>9__239_1; if (obj2 == null) { UnityAction val3 = delegate { ApiClient.LeaveQueue(MatchTracker.LocalSteamId); }; <>c.<>9__239_1 = val3; obj2 = (object)val3; } qCancelBtn = UIFactory.CreateButton("Cancel", transform2, "Cancel", 15f, c_WHITE2, c_BTN2, (UnityAction)obj2, (Vector2?)new Vector2(70f, 26f)); Transform transform3 = val.transform; Color c_WHITE3 = C_WHITE; Color c_BTN3 = C_BTN; object obj3 = <>c.<>9__239_2; if (obj3 == null) { UnityAction val4 = delegate { OnLfpButton(); }; <>c.<>9__239_2 = val4; obj3 = (object)val4; } lfpBtn = UIFactory.CreateButton("LfpPing", transform3, "RLFP Ping", 15f, c_WHITE3, c_BTN3, (UnityAction)obj3, (Vector2?)new Vector2(95f, 26f)); Transform transform4 = val.transform; Color c_GREEN = C_GREEN; Color c_BTN4 = C_BTN; object obj4 = <>c.<>9__239_3; if (obj4 == null) { UnityAction val5 = delegate { Plugin.RankedEnabled.Value = true; string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.ToggleRanked(localSteamId, enabled: true); } dirty = true; }; <>c.<>9__239_3 = val5; obj4 = (object)val5; } rankOnBtn = UIFactory.CreateButton("RankOn", transform4, "Enable", 15f, c_GREEN, c_BTN4, (UnityAction)obj4, (Vector2?)new Vector2(70f, 26f)); Transform transform5 = val.transform; Color c_RED = C_RED; Color c_BTN5 = C_BTN; object obj5 = <>c.<>9__239_4; if (obj5 == null) { UnityAction val6 = delegate { Plugin.RankedEnabled.Value = false; string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.ToggleRanked(localSteamId, enabled: false); if (ApiClient.CurrentQueueState != ApiClient.QueueState.Idle) { ApiClient.LeaveQueue(localSteamId); } } dirty = true; }; <>c.<>9__239_4 = val6; obj5 = (object)val6; } rankOffBtn = UIFactory.CreateButton("RankOff", transform5, "Disable", 15f, c_RED, c_BTN5, (UnityAction)obj5, (Vector2?)new Vector2(70f, 26f)); txtQueueInfo = UIFactory.CreateText("QI", val.transform, "", 18f, C_BLUE, 513, (Vector2?)new Vector2(340f, 28f), richText: true, raycastTarget: false); UIFactory.SetBold(txtQueueInfo, b: true); GameObject val7 = new GameObject("S"); val7.transform.SetParent(val.transform, false); val7.AddComponent(); UIFactory.AddLE(val7, -1f, -1f, -1f, -1f, 1f); qMatchPanel = new GameObject("MatchPanel"); qMatchPanel.transform.SetParent(parent, false); qMatchPanel.AddComponent(); UIFactory.AddVLG(qMatchPanel, 4f, 8); UIFactory.AddLE(qMatchPanel, -1f, 50f, -1f, 50f, -1f, 0f); txtMatchFound = UIFactory.CreateText("MF", qMatchPanel.transform, "MATCH FOUND!", 18f, C_GREEN, 513, (Vector2?)new Vector2(700f, 24f), richText: true, raycastTarget: false); UIFactory.SetBold(txtMatchFound, b: true); GameObject val8 = new GameObject("MBR"); val8.transform.SetParent(qMatchPanel.transform, false); val8.AddComponent(); UIFactory.AddHLG(val8, 8f, 0, 0, 0, 0, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(val8, -1f, 26f, -1f, 26f, -1f, 0f); Transform transform6 = val8.transform; Color c_WHITE4 = C_WHITE; Color bgColor = new Color(0.2f, 0.5f, 0.2f, 0.9f); object obj6 = <>c.<>9__239_5; if (obj6 == null) { UnityAction val9 = delegate { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.ReadyUp(localSteamId); } }; <>c.<>9__239_5 = val9; obj6 = (object)val9; } readyBtn = UIFactory.CreateButton("Ready", transform6, "Ready Up", 15f, c_WHITE4, bgColor, (UnityAction)obj6, (Vector2?)new Vector2(90f, 24f)); txtConnectLabel = UIFactory.CreateText("CT", val8.transform, "Waiting for opponent...", 15f, C_BLUE, 513, (Vector2?)new Vector2(320f, 24f), richText: true, raycastTarget: false); object obj7 = txtConnectLabel; object obj8 = ((obj7 is Component) ? obj7 : null); connectLabel = ((obj8 != null) ? ((Component)obj8).gameObject : null); if ((Object)(object)connectLabel != (Object)null) { connectLabel.SetActive(false); } Transform transform7 = val8.transform; Color c_WHITE5 = C_WHITE; Color c_BTN6 = C_BTN; object obj9 = <>c.<>9__239_6; if (obj9 == null) { UnityAction val10 = delegate { ApiClient.DeclineMatch(MatchTracker.LocalSteamId); }; <>c.<>9__239_6 = val10; obj9 = (object)val10; } declineBtn = UIFactory.CreateButton("Decline", transform7, "Decline", 15f, c_WHITE5, c_BTN6, (UnityAction)obj9, (Vector2?)new Vector2(70f, 24f)); qMatchPanel.SetActive(false); } private static int GroupOf(int tabIdx) { for (int i = 0; i < GROUP_MEMBERS.Length; i++) { for (int j = 0; j < GROUP_MEMBERS[i].Length; j++) { if (GROUP_MEMBERS[i][j] == tabIdx) { return i; } } } return 0; } private static bool TabVisible(int i) { return i != 10 || ApiClient.IsArtist; } private static void BuildTabBar(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Expected O, but got Unknown //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Expected O, but got Unknown GameObject val = new GameObject("TabBar"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddHLG(val); UIFactory.AddLE(val, -1f, 28f, -1f, 28f, -1f, 0f); groupButtons = (GameObject[])(object)new GameObject[GROUP_LABELS.Length]; groupTexts = new object[GROUP_LABELS.Length]; for (int i = 0; i < GROUP_LABELS.Length; i++) { int gi = i; GameObject val2 = UIFactory.CreateButton($"TabG{i}", val.transform, GROUP_LABELS[i], 13f, C_LABEL, C_TAB, (UnityAction)delegate { SwitchTab(GROUP_MEMBERS[gi][0]); }, (Vector2?)new Vector2(0f, 26f)); if (UIFactory.tLE != null) { Component component = val2.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } UIFactory.AddLE(val2, -1f, 26f, -1f, 26f, 1f, 0f); groupButtons[i] = val2; groupTexts[i] = UIFactory.GetButtonText(val2); } subTabBar = new GameObject("SubTabBar"); subTabBar.transform.SetParent(parent, false); subTabBar.AddComponent(); UIFactory.AddHLG(subTabBar, 8f, 0, 0, 0, 0, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(subTabBar, -1f, 28f, -1f, 28f, 1f, 0f); GameObject val3 = new GameObject("S"); val3.transform.SetParent(subTabBar.transform, false); val3.AddComponent(); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, 1f); subButtons = (GameObject[])(object)new GameObject[14]; subTexts = new object[14]; for (int num = 0; num < GROUP_MEMBERS.Length; num++) { if (GROUP_MEMBERS[num].Length < 2) { continue; } for (int num2 = 0; num2 < GROUP_MEMBERS[num].Length; num2++) { int idx = GROUP_MEMBERS[num][num2]; GameObject val4 = UIFactory.CreateButton($"SubTab{idx}", subTabBar.transform, TAB_NAMES[idx], 14f, C_LABEL, C_TAB, (UnityAction)delegate { SwitchTab(idx); }, (Vector2?)new Vector2(360f, 26f)); subButtons[idx] = val4; subTexts[idx] = UIFactory.GetButtonText(val4); val4.SetActive(false); } } GameObject val5 = new GameObject("S"); val5.transform.SetParent(subTabBar.transform, false); val5.AddComponent(); UIFactory.AddLE(val5, -1f, -1f, -1f, -1f, 1f); UpdateTabBarVisual(); } private static void UpdateTabBarVisual() { //IL_0073: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) if (groupButtons == null) { return; } int num = GroupOf(currentTab); for (int i = 0; i < GROUP_LABELS.Length; i++) { if (!((Object)(object)groupButtons[i] == (Object)null)) { if (i == 6) { groupButtons[i].SetActive(ApiClient.IsAdmin); } UIFactory.SetImageColor(groupButtons[i], (i == num) ? C_TABACT : C_TAB); if (groupTexts[i] != null) { UIFactory.SetColor(groupTexts[i], (i == num) ? C_WHITE : C_LABEL); UIFactory.SetBold(groupTexts[i], i == num); } } } int[] array = GROUP_MEMBERS[num]; int num2 = 0; for (int j = 0; j < array.Length; j++) { if (TabVisible(array[j])) { num2++; } } bool flag = num2 > 1; GameObject val = ((subTabAnchors != null && currentTab >= 0 && currentTab < subTabAnchors.Length) ? subTabAnchors[currentTab] : null); if (subTabAnchors != null) { for (int k = 0; k < subTabAnchors.Length; k++) { if ((Object)(object)subTabAnchors[k] != (Object)null && (Object)(object)subTabAnchors[k] != (Object)(object)val) { subTabAnchors[k].SetActive(false); } } } bool flag2 = flag && (Object)(object)val != (Object)null; if ((Object)(object)val != (Object)null) { val.SetActive(flag2); } if ((Object)(object)subTabBar != (Object)null) { if (flag2 && (Object)(object)subTabBar.transform.parent != (Object)(object)val.transform) { subTabBar.transform.SetParent(val.transform, false); } subTabBar.SetActive(flag2); } if (subButtons == null) { return; } for (int l = 0; l < subButtons.Length; l++) { if ((Object)(object)subButtons[l] == (Object)null) { continue; } bool flag3 = false; for (int m = 0; m < array.Length; m++) { if (array[m] == l) { flag3 = true; break; } } bool flag4 = flag && flag3 && TabVisible(l); subButtons[l].SetActive(flag4); if (flag4) { UIFactory.SetImageColor(subButtons[l], (l == currentTab) ? C_TABACT : C_TAB); if (subTexts[l] != null) { UIFactory.SetColor(subTexts[l], (l == currentTab) ? C_WHITE : C_LABEL); UIFactory.SetBold(subTexts[l], l == currentTab); } } } } private static void ToggleInnerScroll(Component scrollRect, float contentH) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) try { Behaviour val = (Behaviour)(object)((scrollRect is Behaviour) ? scrollRect : null); if (!((Object)(object)val == (Object)null)) { Transform transform = ((Component)val).transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); float num; if (!((Object)(object)val2 != (Object)null)) { num = 0f; } else { Rect rect = val2.rect; num = ((Rect)(ref rect)).height; } float num2 = num; bool flag = num2 > 1f && contentH > num2; if (val.enabled != flag) { val.enabled = flag; } } } catch { } } private static GameObject BuildFfaTab(Transform parent, int tabIdx) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Expected O, but got Unknown //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Expected O, but got Unknown //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Expected O, but got Unknown //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Expected O, but got Unknown //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_04f7: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Expected O, but got Unknown //IL_057f: Unknown result type (might be due to invalid IL or missing references) //IL_0593: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Expected O, but got Unknown //IL_0605: Unknown result type (might be due to invalid IL or missing references) //IL_0678: Unknown result type (might be due to invalid IL or missing references) //IL_068c: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Unknown result type (might be due to invalid IL or missing references) //IL_06ad: Expected O, but got Unknown //IL_06fa: Unknown result type (might be due to invalid IL or missing references) //IL_0701: Expected O, but got Unknown //IL_075b: Unknown result type (might be due to invalid IL or missing references) //IL_0762: Expected O, but got Unknown //IL_07ce: Unknown result type (might be due to invalid IL or missing references) //IL_07e2: Unknown result type (might be due to invalid IL or missing references) //IL_07fd: Unknown result type (might be due to invalid IL or missing references) //IL_0804: Expected O, but got Unknown //IL_09cf: Unknown result type (might be due to invalid IL or missing references) //IL_09e8: Unknown result type (might be due to invalid IL or missing references) //IL_09f5: Unknown result type (might be due to invalid IL or missing references) //IL_0a08: Unknown result type (might be due to invalid IL or missing references) //IL_0a17: Expected O, but got Unknown //IL_095d: Unknown result type (might be due to invalid IL or missing references) //IL_0975: Unknown result type (might be due to invalid IL or missing references) //IL_0afb: Unknown result type (might be due to invalid IL or missing references) //IL_0b02: Expected O, but got Unknown //IL_0b5d: Unknown result type (might be due to invalid IL or missing references) //IL_0b64: Expected O, but got Unknown //IL_0bd0: Unknown result type (might be due to invalid IL or missing references) //IL_0be4: Unknown result type (might be due to invalid IL or missing references) //IL_0bff: Unknown result type (might be due to invalid IL or missing references) //IL_0c06: Expected O, but got Unknown //IL_0c5f: Unknown result type (might be due to invalid IL or missing references) //IL_0c78: Unknown result type (might be due to invalid IL or missing references) //IL_0ca6: Unknown result type (might be due to invalid IL or missing references) //IL_0cd0: Unknown result type (might be due to invalid IL or missing references) //IL_0ce4: Unknown result type (might be due to invalid IL or missing references) //IL_0d10: Unknown result type (might be due to invalid IL or missing references) //IL_0d29: Unknown result type (might be due to invalid IL or missing references) //IL_0c91: Unknown result type (might be due to invalid IL or missing references) //IL_0c96: Unknown result type (might be due to invalid IL or missing references) //IL_0c9c: Expected O, but got Unknown //IL_0d57: Unknown result type (might be due to invalid IL or missing references) //IL_0d42: Unknown result type (might be due to invalid IL or missing references) //IL_0d47: Unknown result type (might be due to invalid IL or missing references) //IL_0d4d: Expected O, but got Unknown GameObject val = new GameObject("FfaOuter"); val.transform.SetParent(parent, false); val.AddComponent(); val.AddComponent(); EnsureFfaWorldToScreenPoint(); UIFactory.AddVLG(val, 0f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(tabIdx, val.transform, asFirst: true); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("FfaScroll", val.transform, 6f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); Transform parent2 = scrollViewRefs.content.transform.parent; ffaTabOuterViewport = (RectTransform)(object)((parent2 is RectTransform) ? parent2 : null); GameObject val2 = new GameObject("FfaInner"); val2.transform.SetParent(scrollViewRefs.content.transform, false); val2.AddComponent(); UIFactory.AddVLG(val2, 8f, 10, 10, 8, 8); GameObject val3 = new GameObject("FfaHdrRow"); val3.transform.SetParent(val2.transform, false); val3.AddComponent(); UIFactory.AddHLG(val3, 10f); UIFactory.AddLE(val3, -1f, -1f, -1f, 38f, -1f, 0f); UIFactory.CreateText("FfaH", val3.transform, "FREE-FOR-ALL (3-10 players) - RANKED", 26f, C_GOLD, 513, (Vector2?)new Vector2(700f, 36f), richText: true, raycastTarget: false); GameObject val4 = new GameObject("FfaHdrSp"); val4.transform.SetParent(val3.transform, false); val4.AddComponent(); UIFactory.AddLE(val4, -1f, -1f, -1f, -1f, 1f); Transform transform = val3.transform; Color c_WHITE = C_WHITE; Color c_BTN = C_BTN; object obj = <>c.<>9__302_0; if (obj == null) { UnityAction val5 = delegate { ShowInfoPopup("FFA - How It Works", "Free-for-all for 3-10 players. Every player is their own team.\r\nStandard ROUNDS scoring - first to 5 points takes the game.\r\n\r\nHOW TO PLAY\r\n\r\n- There is no Elo band. Joining a lobby is consent to play.\r\n\r\n- Create a lobby, or join an open one from the browser.\r\n The HOST presses Start once at least 3 players are in\r\n (up to 10). Several lobbies can be open at once.\r\n\r\n- If the host leaves, the longest-waiting member becomes\r\n the new host automatically.\r\n\r\n- After each point, everyone except the point winner\r\n picks a card at the same time.\r\n\r\n- The pick timer is shown on screen. A pick landing\r\n near the end grants everyone a little extra time.\r\n When your timer hits zero, your highlighted card is\r\n picked for you automatically. You always get a\r\n card - skipping a pick is not possible.\r\n\r\n- You hold up to 5 cards.\r\n Picking a 6th replaces your oldest card.\r\n\r\nRATING\r\n\r\n- FFA is ranked with its own Glicko rating.\r\n\r\n- Placement uses points, then all round wins earned\r\n (spent ones included), then total kills.\r\n Ties share a place using competition order: 1, 2, 2, 4.\r\n\r\n- Your rating is scored against the players placed\r\n nearest to you (up to 4 of them), so one game can't\r\n swing your rating several times harder in a 10-player\r\n lobby than in a 3-player one.\r\n\r\n- A tied placement counts as a draw. New ratings move\r\n fast and settle down as you play more.\r\n\r\nREWARDS\r\n\r\n- Each game pays 600 base XP, plus 90 XP per player\r\n you placed above.\r\n\r\n- Placement multiplies that: up to x1.5 for winning a\r\n 3-player game, growing with lobby size to x5 for\r\n winning a full 10. Lower places scale down smoothly;\r\n last place keeps the base.\r\n\r\n- Placement Gold comes on top: 10-50 Gold by placement,\r\n scaled by lobby size.\r\n\r\n- A stronger opposing field multiplies the XP part\r\n (the same tier bonus as the other modes).\r\n\r\n- XP converts to Gold at 100 XP = 1 Gold, and level-ups\r\n pay their usual bonus Gold. A level-up landing during\r\n a game shows up inside that game's +g number - that is\r\n how a last place can occasionally out-earn the winner.\r\n\r\n- Spectators can bet Gold on FFA lobbies from this tab.\r\n\r\nREADING THE RECENT FFAS LIST\r\n\r\nDots + N(P) - Full points won.\r\nHalf dots + N(H) - Round wins that\r\n did not become one of that player's full points.\r\nNk - Kills.\r\n+xp +g - That game's XP and Gold\r\n (including any level-up bonus).\r\nGreen/red number - FFA rating change.\r\nCards - The hand held at game end.\r\n +N replaced counts picks that were\r\n pushed out by the 5-card cap - hover the line to see\r\n every pick in order.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\nRank - Position in the currently selected sort.\r\nPlayer - The player's display name.\r\nRating - The player's separate FFA Glicko rating.\r\nGames - Recorded FFA games played.\r\nWins - Games finished in 1st place.\r\nTop3 - Games finished in 1st, 2nd, or 3rd.\r\nAvgPl - Average finishing place. Lower is\r\n better - 1.0 means winning every game.\r\nWR - Share of games won outright.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded.\r\n A leaver keeps their tallies for placement."); }; <>c.<>9__302_0 = val5; obj = (object)val5; } UIFactory.CreateButton("FfaInfo", transform, "Info", 18f, c_WHITE, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(110f, 34f)); UIFactory.CreateText("FfaNote", val2.transform, "New mode - first playtest build. Games are ranked from day one.", 18f, C_DIM, 513, (Vector2?)new Vector2(1035f, 29f), richText: true, raycastTarget: false); GameObject val6 = new GameObject("FfaCtl"); val6.transform.SetParent(val2.transform, false); val6.AddComponent(); UIFactory.AddHLG(val6, 8f); UIFactory.AddLE(val6, -1f, -1f, -1f, 44f, -1f, 0f); Transform transform2 = val6.transform; Color c_WHITE2 = C_WHITE; Color bgColor = new Color(0.25f, 0.45f, 0.18f, 0.9f); object obj2 = <>c.<>9__302_1; if (obj2 == null) { UnityAction val7 = delegate { ApiClient.FfaCreateLobby(); dirty = true; }; <>c.<>9__302_1 = val7; obj2 = (object)val7; } ffaJoinBtn = UIFactory.CreateButton("FfaCreate", transform2, "Create Lobby", 18f, c_WHITE2, bgColor, (UnityAction)obj2, (Vector2?)new Vector2(184f, 36f)); Transform transform3 = val6.transform; Color c_WHITE3 = C_WHITE; Color bgColor2 = new Color(0.55f, 0.42f, 0.1f, 0.95f); object obj3 = <>c.<>9__302_2; if (obj3 == null) { UnityAction val8 = delegate { ApiClient.FfaStartLobby(); dirty = true; }; <>c.<>9__302_2 = val8; obj3 = (object)val8; } ffaStartBtn = UIFactory.CreateButton("FfaStart", transform3, "Start Game", 18f, c_WHITE3, bgColor2, (UnityAction)obj3, (Vector2?)new Vector2(158f, 36f)); Transform transform4 = val6.transform; Color c_WHITE4 = C_WHITE; Color bgColor3 = new Color(0.5f, 0.2f, 0.2f, 0.9f); object obj4 = <>c.<>9__302_3; if (obj4 == null) { UnityAction val9 = delegate { ApiClient.FfaLeaveQueue(); dirty = true; }; <>c.<>9__302_3 = val9; obj4 = (object)val9; } ffaLeaveBtn = UIFactory.CreateButton("FfaLeave", transform4, "Leave", 18f, c_WHITE4, bgColor3, (UnityAction)obj4, (Vector2?)new Vector2(103f, 36f)); txtFfaStatus = UIFactory.CreateText("FfaSt", val2.transform, "Browse open lobbies below, or create your own.", 20f, C_LABEL, 513, (Vector2?)new Vector2(1035f, 31f), richText: true, raycastTarget: false); GameObject val10 = UIFactory.CreatePanel("FfaQL", val2.transform, C_PANEL); UIFactory.AddVLG(val10, 2f, 10, 10, 6, 6); UIFactory.AddLE(val10, -1f, -1f, -1f, -1f, -1f, 0f); txtFfaLobbyHeader = UIFactory.CreateText("FfaQLH", val10.transform, "Open FFA Lobbies", 21f, C_SUB, 513, (Vector2?)new Vector2(1035f, 29f), richText: true, raycastTarget: false); ffaBrowserContainer = new GameObject("FfaBrowser"); ffaBrowserContainer.transform.SetParent(val10.transform, false); ffaBrowserContainer.AddComponent(); UIFactory.AddVLG(ffaBrowserContainer, 3f); txtFfaLobbyBody = UIFactory.CreateText("FfaQLB", val10.transform, "Loading...", 18f, C_LABEL, 257, (Vector2?)new Vector2(1035f, 29f), richText: true, raycastTarget: false); object obj5 = txtFfaLobbyBody; Component val11 = (Component)((obj5 is Component) ? obj5 : null); if ((Object)(object)val11 != (Object)null) { UIFactory.AddLE(val11.gameObject, -1f, 29f, -1f, 29f, -1f, 0f); } UIFactory.SetWordWrap(txtFfaLobbyBody, on: true); ffaBetPanel = UIFactory.CreatePanel("FfaBetPanel", val2.transform, C_PANEL); UIFactory.AddVLG(ffaBetPanel, 3f, 10, 10, 6, 7); UIFactory.AddLE(ffaBetPanel, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("FfaBetHeader", ffaBetPanel.transform, "Live FFA Lobbies - Betting", 21f, C_SUB, 513, (Vector2?)new Vector2(1035f, 29f), richText: true, raycastTarget: false); ffaBetContainer = new GameObject("FfaBetLobbies"); ffaBetContainer.transform.SetParent(ffaBetPanel.transform, false); ffaBetContainer.AddComponent(); UIFactory.AddVLG(ffaBetContainer, 4f); ffaBetPanel.SetActive(false); GameObject val12 = new GameObject("FfaBot"); val12.transform.SetParent(val2.transform, false); val12.AddComponent(); UIFactory.AddHLG(val12, 8f); UIFactory.AddLE(val12, -1f, 520f, -1f, 936f, -1f, 0f); GameObject val13 = new GameObject("FfaLBCol"); val13.transform.SetParent(val12.transform, false); val13.AddComponent(); UIFactory.AddVLG(val13, 4f); UIFactory.AddLE(val13, 736f, -1f, 793f, -1f, 0f, 1f); txtFfaLbHeader = UIFactory.CreateText("FfaLBH", val13.transform, "FFA Leaderboard", 23f, C_SUB, 513, (Vector2?)new Vector2(575f, 31f), richText: true, raycastTarget: false); GameObject val14 = new GameObject("FfaLBHR"); val14.transform.SetParent(val13.transform, false); val14.AddComponent(); UIFactory.AddHLG(val14, 4f, 8, 8); UIFactory.AddLE(val14, -1f, 31f, -1f, 31f, -1f, 0f); string[] array = new string[8] { "#", "Player", "Rating", "Games", "Wins", "Top3", "AvgPl", "WR" }; string[] hdrSortKey = new string[8] { null, null, "rating", "games", "wins", "top3", "avg_placement", "win_rate" }; ffaLbSortBtns = new List(); ffaLbSortKeys = hdrSortKey; ffaLbHeaderTexts = new object[array.Length]; for (int num = 0; num < array.Length; num++) { int idx = num; if (hdrSortKey[num] == null) { object obj6 = UIFactory.CreateText($"FfaLBH_{num}", val14.transform, array[num], 17f, C_LABEL, 513, (Vector2?)new Vector2((float)FFA_LB_COL_W[num], 24f), richText: true, raycastTarget: false); ffaLbHeaderTexts[num] = obj6; ffaLbSortBtns.Add(null); continue; } GameObject val15 = UIFactory.CreateButton("FfaLBS_" + hdrSortKey[num], val14.transform, array[num], 17f, C_LABEL, new Color(0.18f, 0.2f, 0.24f, 0.85f), (UnityAction)delegate { ffaLbSortReq = hdrSortKey[idx]; dirty = true; ApiClient.FetchFfaLeaderboard(200, hdrSortKey[idx]); }, (Vector2?)new Vector2((float)FFA_LB_COL_W[num], 24f)); ffaLbSortBtns.Add(val15); ffaLbHeaderTexts[num] = UIFactory.GetButtonText(val15); } UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("FfaLBSV", val13.transform, 1f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); ffaLbContainer = scrollViewRefs2.content; ffaLbScrollRect = scrollViewRefs2.scrollGO.GetComponent(UIFactory.tScrollRect); for (int num2 = 0; num2 < 100; num2++) { ffaLbRows.Add(CreateFfaLBRow(ffaLbContainer.transform, $"flb{num2}")); } GameObject val16 = new GameObject("FfaRCol"); val16.transform.SetParent(val12.transform, false); val16.AddComponent(); UIFactory.AddVLG(val16, 4f); UIFactory.AddLE(val16, -1f, -1f, -1f, -1f, 1f, 1f); GameObject val17 = new GameObject("FfaRHR"); val17.transform.SetParent(val16.transform, false); val17.AddComponent(); UIFactory.AddHLG(val17, 6f); UIFactory.AddLE(val17, -1f, 34f, -1f, 34f, -1f, 0f); txtFfaRecentHeader = UIFactory.CreateText("FfaRH", val17.transform, "Recent Ranked FFAs", 23f, C_SUB, 513, (Vector2?)new Vector2(345f, 34f), richText: true, raycastTarget: false); GameObject val18 = new GameObject("FfaRSp"); val18.transform.SetParent(val17.transform, false); val18.AddComponent(); UIFactory.AddLE(val18, -1f, -1f, -1f, -1f, 1f); Transform transform5 = val17.transform; Color c_WHITE5 = C_WHITE; Color bgColor4 = new Color(0.22f, 0.25f, 0.3f, 0.95f); object obj7 = <>c.<>9__302_4; if (obj7 == null) { UnityAction val19 = delegate { ffaRecentPageReq = Math.Max(0, ffaRecentPageReq - 1); ApiClient.FetchFfaRecent(ffaRecentPageReq); }; <>c.<>9__302_4 = val19; obj7 = (object)val19; } ffaRecentPrevBtn = UIFactory.CreateButton("FfaRP", transform5, "<", 17f, c_WHITE5, bgColor4, (UnityAction)obj7, (Vector2?)new Vector2(32f, 29f)); txtFfaRecentPage = UIFactory.CreateText("FfaRPI", val17.transform, "1/1", 17f, C_LABEL, 514, (Vector2?)new Vector2(55f, 29f), richText: true, raycastTarget: false); Transform transform6 = val17.transform; Color c_WHITE6 = C_WHITE; Color bgColor5 = new Color(0.22f, 0.25f, 0.3f, 0.95f); object obj8 = <>c.<>9__302_5; if (obj8 == null) { UnityAction val20 = delegate { ffaRecentPageReq++; ApiClient.FetchFfaRecent(ffaRecentPageReq); }; <>c.<>9__302_5 = val20; obj8 = (object)val20; } ffaRecentNextBtn = UIFactory.CreateButton("FfaRN", transform6, ">", 17f, c_WHITE6, bgColor5, (UnityAction)obj8, (Vector2?)new Vector2(32f, 29f)); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("FfaRSV", val16.transform); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); ffaRecentContainer = scrollViewRefs3.content; Transform parent3 = scrollViewRefs3.content.transform.parent; ffaRecentViewport = (RectTransform)(object)((parent3 is RectTransform) ? parent3 : null); ffaRecentScrollRect = scrollViewRefs3.scrollGO.GetComponent(UIFactory.tScrollRect); return val; } private static FfaLBRow CreateFfaLBRow(Transform parent, string name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) FfaLBRow ffaLBRow = new FfaLBRow(); ffaLBRow.root = new GameObject(name); ffaLBRow.root.transform.SetParent(parent, false); ffaLBRow.root.AddComponent(); UIFactory.AddHLG(ffaLBRow.root, 4f, 8, 8); UIFactory.AddLE(ffaLBRow.root, -1f, 29f, -1f, 29f, -1f, 0f); ffaLBRow.txtRank = UIFactory.CreateText("r", ffaLBRow.root.transform, "", 20f, C_GOLD, 513, (Vector2?)new Vector2((float)FFA_LB_COL_W[0], 22f), richText: true, raycastTarget: false); ffaLBRow.txtName = UIFactory.CreateText("n", ffaLBRow.root.transform, "", 20f, C_WHITE, 513, (Vector2?)new Vector2((float)FFA_LB_COL_W[1], 22f), richText: true, raycastTarget: false); UIFactory.SetOverflowMode(ffaLBRow.txtName, 3); ffaLBRow.txtRating = UIFactory.CreateText("rt", ffaLBRow.root.transform, "", 20f, C_WHITE, 514, (Vector2?)new Vector2((float)FFA_LB_COL_W[2], 22f), richText: true, raycastTarget: false); UIFactory.SetBold(ffaLBRow.txtRating, b: true); ffaLBRow.txtGames = UIFactory.CreateText("g", ffaLBRow.root.transform, "", 18f, C_LABEL, 514, (Vector2?)new Vector2((float)FFA_LB_COL_W[3], 22f), richText: true, raycastTarget: false); ffaLBRow.txtWins = UIFactory.CreateText("w", ffaLBRow.root.transform, "", 18f, C_LABEL, 514, (Vector2?)new Vector2((float)FFA_LB_COL_W[4], 22f), richText: true, raycastTarget: false); ffaLBRow.txtTop3 = UIFactory.CreateText("t3", ffaLBRow.root.transform, "", 18f, C_LABEL, 514, (Vector2?)new Vector2((float)FFA_LB_COL_W[5], 22f), richText: true, raycastTarget: false); ffaLBRow.txtAvgPl = UIFactory.CreateText("ap", ffaLBRow.root.transform, "", 18f, C_LABEL, 514, (Vector2?)new Vector2((float)FFA_LB_COL_W[6], 22f), richText: true, raycastTarget: false); ffaLBRow.txtWR = UIFactory.CreateText("wr", ffaLBRow.root.transform, "", 18f, C_LABEL, 514, (Vector2?)new Vector2((float)FFA_LB_COL_W[7], 22f), richText: true, raycastTarget: false); ffaLBRow.root.SetActive(false); return ffaLBRow; } private static void SetFfaLayoutWidth(GameObject go, float preferred, float flexible, float minimum = -1f) { if ((Object)(object)go == (Object)null || UIFactory.tLE == null) { return; } try { Component component = go.GetComponent(UIFactory.tLE); if ((Object)(object)component == (Object)null) { UIFactory.AddLE(go, -1f, -1f, preferred, -1f, flexible); component = go.GetComponent(UIFactory.tLE); } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; UIFactory.tLE.GetProperty("preferredWidth", bindingAttr)?.SetValue(component, preferred); UIFactory.tLE.GetProperty("flexibleWidth", bindingAttr)?.SetValue(component, flexible); if (minimum >= 0f) { UIFactory.tLE.GetProperty("minWidth", bindingAttr)?.SetValue(component, minimum); } } catch { } } private static object CreateFfaTextCell(string name, Transform parent, float width, int align, float fontSize, Color color, bool flexible = false, float minWidth = -1f) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) object obj = UIFactory.CreateText(name, parent, "", fontSize, color, align, (Vector2?)new Vector2(width, 25f), richText: true, raycastTarget: false); Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null) { SetFfaLayoutWidth(val.gameObject, width, flexible ? 1f : 0f, minWidth); } return obj; } private static FfaBetPlayerRow CreateFfaBetPlayerRow(Transform parent, string name) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown FfaBetPlayerRow row = new FfaBetPlayerRow(); row.root = new GameObject(name); row.root.transform.SetParent(parent, false); row.root.AddComponent(); UIFactory.AddHLG(row.root, 6f, 6, 6, 0, 0, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(row.root, -1f, 27f, -1f, 27f, -1f, 0f); row.txtName = CreateFfaTextCell("Name", row.root.transform, 420f, 513, 17f, C_WHITE, flexible: true, 180f); row.txtRating = CreateFfaTextCell("Rating", row.root.transform, 100f, 516, 16f, C_LABEL); row.txtOdds = CreateFfaTextCell("Odds", row.root.transform, 82f, 516, 16f, C_GOLD); row.betBtn = UIFactory.CreateButton("Bet", row.root.transform, "Bet", 15f, C_WHITE, new Color(0.42f, 0.31f, 0.08f, 0.95f), (UnityAction)delegate { OpenCustomFfaBetPrompt(row.lobbyId, row.steamId, row.displayName, row.gameNumber); }, (Vector2?)new Vector2(64f, 23f)); SetFfaLayoutWidth(row.betBtn, 64f, 0f, 64f); row.root.SetActive(false); return row; } private static FfaBetLobbyRow CreateFfaBetLobbyRow(Transform parent, string name) { //IL_001e: 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_00a6: Unknown result type (might be due to invalid IL or missing references) FfaBetLobbyRow ffaBetLobbyRow = new FfaBetLobbyRow(); ffaBetLobbyRow.root = UIFactory.CreatePanel(name, parent, new Color(0.13f, 0.14f, 0.18f, 0.88f)); UIFactory.AddVLG(ffaBetLobbyRow.root, 1f, 4, 4, 3, 4); UIFactory.AddLE(ffaBetLobbyRow.root, -1f, 34f, -1f, 34f, -1f, 0f); ffaBetLobbyRow.txtHeader = UIFactory.CreateText("Header", ffaBetLobbyRow.root.transform, "", 18f, C_WHITE, 513, (Vector2?)new Vector2(1000f, 27f), richText: true, raycastTarget: false); ffaBetLobbyRow.root.SetActive(false); return ffaBetLobbyRow; } private static void SetFfaBetLobbyHeight(FfaBetLobbyRow row, int playerCount) { if (!((Object)(object)row?.root == (Object)null)) { float num = 34f + (float)Math.Max(0, playerCount) * 28f; Component val = ((UIFactory.tLE != null) ? row.root.GetComponent(UIFactory.tLE) : null); if (!((Object)(object)val == (Object)null)) { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; UIFactory.tLE.GetProperty("preferredHeight", bindingAttr)?.SetValue(val, num); UIFactory.tLE.GetProperty("minHeight", bindingAttr)?.SetValue(val, num); } } } private static Sprite CreateFfaDotSprite(bool half) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(32, 32, (TextureFormat)5, false); ((Object)val).name = (half ? "CR_FfaHalfDot" : "CR_FfaFullDot"); ((Object)val).hideFlags = (HideFlags)61; ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; Color[] array = (Color[])(object)new Color[1024]; float num = 15.5f; float num2 = num - 1f; float num3 = num2 * num2; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num4 = (float)j - num; float num5 = (float)i - num; bool flag = num4 * num4 + num5 * num5 <= num3 && (!half || (float)j <= num); array[i * 32 + j] = (Color)(flag ? Color.white : new Color(0f, 0f, 0f, 0f)); } } val.SetPixels(array); val.Apply(false, true); Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 32f); ((Object)val2).name = ((Object)val).name; ((Object)val2).hideFlags = (HideFlags)61; return val2; } private static void EnsureFfaDotSprites() { if ((Object)(object)ffaFullDotSprite == (Object)null) { ffaFullDotSprite = CreateFfaDotSprite(half: false); } if ((Object)(object)ffaHalfDotSprite == (Object)null) { ffaHalfDotSprite = CreateFfaDotSprite(half: true); } } private static GameObject CreateFfaDot(Transform parent, string name, Sprite sprite) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddLE(val, -1f, -1f, 10f, 10f, 0f, 0f); Component obj = val.AddComponent(UIFactory.tImage); try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; UIFactory.tImage.GetProperty("sprite", bindingAttr)?.SetValue(obj, sprite); UIFactory.tImage.GetProperty("preserveAspect", bindingAttr)?.SetValue(obj, true); UIFactory.tImage.GetProperty("raycastTarget", bindingAttr)?.SetValue(obj, false); } catch { } return val; } private static FfaRecentPlayerRow CreateFfaRecentPlayerRow(Transform parent, string name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_00c5: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) FfaRecentPlayerRow ffaRecentPlayerRow = new FfaRecentPlayerRow(); ffaRecentPlayerRow.root = new GameObject(name); ffaRecentPlayerRow.root.transform.SetParent(parent, false); ffaRecentPlayerRow.root.AddComponent(); UIFactory.AddVLG(ffaRecentPlayerRow.root, 0f, 4, 4); GameObject val = new GameObject("Line"); val.transform.SetParent(ffaRecentPlayerRow.root.transform, false); val.AddComponent(); UIFactory.AddHLG(val, 4f, 0, 0, 0, 0, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(val, -1f, 25f, -1f, 25f, -1f, 0f); ffaRecentPlayerRow.txtPlacement = CreateFfaTextCell("Place", val.transform, 36f, 513, 16f, C_DIM); ffaRecentPlayerRow.txtIdentity = CreateFfaTextCell("Identity", val.transform, 260f, 513, 16f, C_WHITE, flexible: true, 150f); UIFactory.SetOverflowMode(ffaRecentPlayerRow.txtIdentity, 3); ffaRecentPlayerRow.fullDotsGO = new GameObject("PointDots"); ffaRecentPlayerRow.fullDotsGO.transform.SetParent(val.transform, false); ffaRecentPlayerRow.fullDotsGO.AddComponent(); UIFactory.AddHLG(ffaRecentPlayerRow.fullDotsGO, 2f, 0, 0, 7, 7, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(ffaRecentPlayerRow.fullDotsGO, -1f, -1f, 0f, 25f, 0f, 0f); ffaRecentPlayerRow.txtPoints = CreateFfaTextCell("Points", val.transform, 48f, 513, 15f, C_LABEL); ffaRecentPlayerRow.halfDotsGO = new GameObject("HalfDots"); ffaRecentPlayerRow.halfDotsGO.transform.SetParent(val.transform, false); ffaRecentPlayerRow.halfDotsGO.AddComponent(); UIFactory.AddHLG(ffaRecentPlayerRow.halfDotsGO, 2f, 0, 0, 7, 7, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(ffaRecentPlayerRow.halfDotsGO, -1f, -1f, 0f, 25f, 0f, 0f); ffaRecentPlayerRow.txtHalfOverflow = CreateFfaTextCell("HalfMore", val.transform, 32f, 513, 14f, C_DIM); object txtHalfOverflow = ffaRecentPlayerRow.txtHalfOverflow; object obj = ((txtHalfOverflow is Component) ? txtHalfOverflow : null); ffaRecentPlayerRow.halfOverflowGO = ((obj != null) ? ((Component)obj).gameObject : null); ffaRecentPlayerRow.txtHalves = CreateFfaTextCell("Halves", val.transform, 50f, 513, 15f, C_LABEL); ffaRecentPlayerRow.txtKills = CreateFfaTextCell("Kills", val.transform, 42f, 513, 15f, C_LABEL); ffaRecentPlayerRow.txtRewards = CreateFfaTextCell("Rewards", val.transform, 128f, 516, 15f, C_BLUE); ffaRecentPlayerRow.txtElo = CreateFfaTextCell("Elo", val.transform, 62f, 516, 15f, C_LABEL); ffaRecentPlayerRow.txtCards = UIFactory.CreateText("Cards", ffaRecentPlayerRow.root.transform, "", 15f, new Color(0.4f, 0.47f, 0.55f), 257, (Vector2?)new Vector2(0f, 20f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(ffaRecentPlayerRow.txtCards, on: true); UIFactory.SetTextAutoHeight(ffaRecentPlayerRow.txtCards, 20f); object txtCards = ffaRecentPlayerRow.txtCards; object obj2 = ((txtCards is Component) ? txtCards : null); ffaRecentPlayerRow.cardsGO = ((obj2 != null) ? ((Component)obj2).gameObject : null); if ((Object)(object)ffaRecentPlayerRow.cardsGO != (Object)null) { ffaRecentPlayerRow.cardsGO.SetActive(false); } ffaRecentPlayerRow.root.SetActive(false); return ffaRecentPlayerRow; } private static FfaRecentMatchRow CreateFfaRecentMatchRow(Transform parent, string name) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown FfaRecentMatchRow row = new FfaRecentMatchRow(); row.root = UIFactory.CreatePanel(name, parent, new Color(0.13f, 0.14f, 0.18f, 0.88f)); UIFactory.AddVLG(row.root, 2f, 6, 6, 4, 5); UIFactory.AddLE(row.root, -1f, 38f, -1f, -1f, -1f, 0f); GameObject val = new GameObject("Header"); val.transform.SetParent(row.root.transform, false); row.headerRect = val.AddComponent(); UIFactory.AddHLG(val, 6f, 0, 0, 0, 0, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(val, -1f, 29f, -1f, 29f, -1f, 0f); row.txtHeader = CreateFfaTextCell("HeaderText", val.transform, 520f, 513, 17f, C_WHITE, flexible: true, 260f); row.btnId = UIFactory.CreateButton("ID", val.transform, "ID", 12f, C_DIM, C_BTN, (UnityAction)delegate { CopyGameCode(row.currentMatchId); }, (Vector2?)new Vector2(30f, 21f)); SetFfaLayoutWidth(row.btnId, 30f, 0f, 30f); row.root.SetActive(false); return row; } private static Color FfaPlayerColor(int slot) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) int num = FFA_SLOT_PALETTE.Length; return FFA_SLOT_PALETTE[(slot % num + num) % num]; } private static string FfaSafeRich(string value) { if (string.IsNullOrEmpty(value)) { return ""; } StringBuilder stringBuilder = new StringBuilder(value.Length); foreach (char c in value) { stringBuilder.Append((c < ' ' || (c >= '\u007f' && c <= '\u009f') || c == '\u2028' || c == '\u2029') ? ' ' : c); } return stringBuilder.ToString().Replace("&", "&").Replace("<", "<") .Replace(">", ">"); } private static string FfaTitleHex(string value) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(value)) { return "#FFD94D"; } try { Color val = default(Color); if (ColorUtility.TryParseHtmlString(value, ref val)) { return "#" + ColorUtility.ToHtmlStringRGB(val); } } catch { } return "#FFD94D"; } private static int FfaGameNumber(string room) { if (string.IsNullOrEmpty(room)) { return -1; } int num = room.LastIndexOf("_r", StringComparison.Ordinal); if (num < 0 || num + 2 >= room.Length) { return -1; } if (int.TryParse(room.Substring(num + 2), NumberStyles.None, CultureInfo.InvariantCulture, out var result) && result > 0) { return result; } return -1; } private static string BuildFfaCardsText(ApiClient.FfaRecentPlayer player, out string hoverText) { hoverText = null; if (player?.cards == null || player.cards.Count == 0) { return ""; } int num = 0; StringBuilder stringBuilder = new StringBuilder(" Cards: "); bool flag = true; for (int i = 0; i < player.cards.Count; i++) { ApiClient.FfaRecentCard ffaRecentCard = player.cards[i]; if (ffaRecentCard != null && ffaRecentCard.rolled) { num++; continue; } if (!flag) { stringBuilder.Append(", "); } flag = false; stringBuilder.Append("").Append(FfaSafeRich(ffaRecentCard?.name ?? "?")).Append(""); } if (flag) { stringBuilder.Append("none held"); } if (num > 0) { stringBuilder.Append(" +").Append(num).Append(" replaced (hover)"); StringBuilder stringBuilder2 = new StringBuilder("All picks (oldest first) - red = replaced:\n"); int num2 = 0; for (int j = 0; j < player.cards.Count; j++) { ApiClient.FfaRecentCard ffaRecentCard2 = player.cards[j]; if (num2 > 0) { stringBuilder2.Append(", "); } string value = ((ffaRecentCard2 != null && ffaRecentCard2.rolled) ? "#FF7777" : "#DDDDDD"); stringBuilder2.Append("") .Append(FfaSafeRich(ffaRecentCard2?.name ?? "?")) .Append(""); if (++num2 >= 4 && j < player.cards.Count - 1) { stringBuilder2.Append('\n'); num2 = 0; } } hoverText = stringBuilder2.ToString(); } return stringBuilder.ToString(); } private static void FillFfaDotPool(List pool, GameObject group, int count, Sprite sprite, Color color, string prefix) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) count = Math.Max(0, count); while (pool.Count < count) { pool.Add(CreateFfaDot(group.transform, prefix + pool.Count, sprite)); } for (int i = 0; i < pool.Count; i++) { bool flag = i < count; pool[i].SetActive(flag); if (flag) { UIFactory.SetImageColor(pool[i], color); } } float preferred = ((count > 0) ? ((float)count * 10f + (float)(count - 1) * 2f) : 0f); SetFfaLayoutWidth(group, preferred, 0f); } private static FfaTimelineGraph ParseFfaTimeline(ApiClient.FfaRecentMatch match, List players) { //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if (match == null || string.IsNullOrEmpty(match.timeline) || players == null || players.Count == 0) { return null; } string[] array = match.timeline.Split(','); int count = players.Count; FfaTimelineGraph ffaTimelineGraph = new FfaTimelineGraph(); ffaTimelineGraph.names = new string[count]; ffaTimelineGraph.colors = (Color[])(object)new Color[count]; ffaTimelineGraph.values = new float[count][]; FfaTimelineGraph ffaTimelineGraph2 = ffaTimelineGraph; int[] array2 = new int[count]; int[] array3 = new int[count]; for (int i = 0; i < count; i++) { ffaTimelineGraph2.names[i] = Trunc(players[i]?.display_name ?? "?", 18); int num = ((players[i] != null) ? players[i].slot : (-1)); if (num < 0) { num = i; } ffaTimelineGraph2.colors[i] = FfaPlayerColor(num); ffaTimelineGraph2.values[i] = new float[array.Length + 1]; } int num2 = 0; foreach (string text in array) { int k; for (k = 0; k < text.Length && (text[k] == ' ' || text[k] == '\t'); k++) { } int num3 = k; int num4 = 0; for (; k < text.Length && char.IsDigit(text[k]); k++) { num4 = num4 * 10 + (text[k] - 48); } if (k == num3) { continue; } int num5 = -1; for (int l = 0; l < count; l++) { if (players[l] != null && players[l].slot == num4) { num5 = l; break; } } if (num5 < 0) { continue; } bool flag = false; for (int m = k; m < text.Length; m++) { if (text[m] == 'R') { flag = true; break; } } array3[num5]++; if (flag) { array2[num5]++; Array.Clear(array3, 0, array3.Length); } num2++; for (int n = 0; n < count; n++) { float num6 = (float)array2[n] + (float)array3[n] * 0.5f; ffaTimelineGraph2.values[n][num2] = num6; if (num6 > ffaTimelineGraph2.maxScore) { ffaTimelineGraph2.maxScore = num6; } } } if (num2 == 0) { return null; } ffaTimelineGraph2.eventCount = num2; ffaTimelineGraph2.maxScore = Mathf.Max(1f, Mathf.Ceil(ffaTimelineGraph2.maxScore * 2f) * 0.5f); int num7 = FfaGameNumber(match.photon_room_id); ffaTimelineGraph2.title = ((num7 > 0) ? $"Game {num7} score progression" : "Score progression"); ffaTimelineGraph2.eventLabel = $"{num2} half-point events"; ffaTimelineGraph2.maxLabel = ffaTimelineGraph2.maxScore.ToString("0.#", CultureInfo.InvariantCulture); return ffaTimelineGraph2; } private static void BuildFfaRecentRowText(ApiClient.FfaRecentMatch match, FfaRecentMatchRow row) { //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) if (match == null || row == null) { return; } row.currentMatchId = match.match_id; if ((Object)(object)row.btnId != (Object)null) { row.btnId.SetActive(!string.IsNullOrEmpty(match.match_id)); } string arg = ""; if (!string.IsNullOrEmpty(match.ended_at) && DateTime.TryParse(match.ended_at, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var result)) { arg = result.ToString("M/d", CultureInfo.InvariantCulture); } string text = ((match.duration_seconds > 0) ? $"{match.duration_seconds / 60}m{match.duration_seconds % 60:00}s" : "?"); int num = FfaGameNumber(match.photon_room_id); int num2 = ((match.player_count > 0) ? match.player_count : (match.players?.Count ?? 0)); string text2 = ((num > 0) ? $"Game {num}" : "Game ?"); string text3 = ((!string.IsNullOrEmpty(match.timeline)) ? " (hover for score graph)" : ""); UIFactory.SetText(row.txtHeader, $"{arg} - {num2} players" + " - " + text + " - " + text2 + text3); List list = new List(match.players ?? new List()); list.Sort((ApiClient.FfaRecentPlayer a, ApiClient.FfaRecentPlayer b) => ((a != null && a.placement > 0) ? a.placement : 99).CompareTo((b != null && b.placement > 0) ? b.placement : 99)); while (row.players.Count < list.Count) { row.players.Add(CreateFfaRecentPlayerRow(row.root.transform, "Player" + row.players.Count)); } EnsureFfaDotSprites(); for (int num3 = 0; num3 < row.players.Count; num3++) { FfaRecentPlayerRow ffaRecentPlayerRow = row.players[num3]; if (num3 >= list.Count) { ffaRecentPlayerRow.root.SetActive(false); continue; } ApiClient.FfaRecentPlayer ffaRecentPlayer = list[num3]; if (ffaRecentPlayer == null) { ffaRecentPlayerRow.root.SetActive(false); continue; } int placement = ffaRecentPlayer.placement; bool flag = (!string.IsNullOrEmpty(match.winner_steam_id) && ffaRecentPlayer.steam_id == match.winner_steam_id) || (string.IsNullOrEmpty(match.winner_steam_id) && placement == 1); Color color = FfaPlayerColor(ffaRecentPlayer.slot); UIFactory.SetText(ffaRecentPlayerRow.txtPlacement, (placement > 0) ? $"#{placement}" : "#?"); string text4 = (string.IsNullOrEmpty(ffaRecentPlayer.title) ? "" : (" [" + FfaSafeRich(Trunc(ffaRecentPlayer.title, 14)) + "]")); string text5 = (flag ? "#FFD700" : "#FFFFFF"); string text6 = (ffaRecentPlayer.left_early ? " (left)" : ""); UIFactory.SetText(ffaRecentPlayerRow.txtIdentity, "" + FfaSafeRich(Trunc(ffaRecentPlayer.display_name ?? "?", 18)) + "" + text4 + text6); int num4 = Math.Max(0, ffaRecentPlayer.rounds_won); int num5 = Math.Max(0, ffaRecentPlayer.points_total - num4 * 2); int num6 = Math.Min(8, num5); FillFfaDotPool(ffaRecentPlayerRow.fullDots, ffaRecentPlayerRow.fullDotsGO, num4, ffaFullDotSprite, color, "P"); FillFfaDotPool(ffaRecentPlayerRow.halfDots, ffaRecentPlayerRow.halfDotsGO, num6, ffaHalfDotSprite, color, "H"); UIFactory.SetText(ffaRecentPlayerRow.txtPoints, $"{num4}(P)"); int num7 = num5 - num6; if ((Object)(object)ffaRecentPlayerRow.halfOverflowGO != (Object)null) { ffaRecentPlayerRow.halfOverflowGO.SetActive(num7 > 0); } if (num7 > 0) { UIFactory.SetText(ffaRecentPlayerRow.txtHalfOverflow, $"+{num7}"); } UIFactory.SetText(ffaRecentPlayerRow.txtHalves, $"{num5}(H)"); UIFactory.SetText(ffaRecentPlayerRow.txtKills, $"{Math.Max(0, ffaRecentPlayer.kills)}k"); UIFactory.SetText(ffaRecentPlayerRow.txtRewards, (ffaRecentPlayer.xp_gained == 0 && ffaRecentPlayer.gold_gained == 0) ? "" : $"+{ffaRecentPlayer.xp_gained}xp +{ffaRecentPlayer.gold_gained}g"); if (ffaRecentPlayer.has_rating_change) { string text7 = ffaRecentPlayer.rating_change.ToString("+0;-0;0", CultureInfo.InvariantCulture); UIFactory.SetText(ffaRecentPlayerRow.txtElo, "= 0f) ? "#00FF00" : "#FF6666") + ">" + text7 + ""); } else { UIFactory.SetText(ffaRecentPlayerRow.txtElo, ""); } string hoverText; string text8 = BuildFfaCardsText(ffaRecentPlayer, out hoverText); ffaRecentPlayerRow.cardsHoverText = hoverText; if ((Object)(object)ffaRecentPlayerRow.cardsGO != (Object)null) { ffaRecentPlayerRow.cardsGO.SetActive(!string.IsNullOrEmpty(text8)); } if (!string.IsNullOrEmpty(text8)) { UIFactory.SetText(ffaRecentPlayerRow.txtCards, text8); } ffaRecentPlayerRow.root.SetActive(true); } if (row.timelineMatchId != match.match_id || row.timelineSource != match.timeline) { row.timelineMatchId = match.match_id; row.timelineSource = match.timeline; row.graph = ParseFfaTimeline(match, list); } row.root.SetActive(true); } private static float EstimateFfaRecentHeight(ApiClient.FfaRecentMatch match) { float num = 38f; if (match?.players == null) { return num; } foreach (ApiClient.FfaRecentPlayer player in match.players) { num += 27f; if (player?.cards == null || player.cards.Count == 0) { continue; } int num2 = 11; int num3 = 0; foreach (ApiClient.FfaRecentCard card in player.cards) { if (card != null && card.rolled) { num3++; } else { num2 += (card?.name?.Length ?? 1) + 2; } } if (num3 > 0) { num2 += 22; } num += (float)Math.Max(1, (num2 + 89) / 90) * 20f; } return num + 8f; } private static void EnsureFfaWorldToScreenPoint() { if (ffaWorldToScreenPointResolved) { return; } ffaWorldToScreenPointResolved = true; try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = assembly.GetType("UnityEngine.RectTransformUtility"); if (!(type == null)) { MethodInfo method = type.GetMethod("WorldToScreenPoint", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Camera), typeof(Vector3) }, null); if (!(method == null)) { ffaWorldToScreenPoint = (Func)Delegate.CreateDelegate(typeof(Func), method); break; } } } } catch { ffaWorldToScreenPoint = null; } } private static bool TryGetFfaScreenRect(RectTransform target, out Rect rect) { //IL_0002: 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_0086: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); if ((Object)(object)target == (Object)null || !((Component)target).gameObject.activeInHierarchy) { return false; } target.GetWorldCorners(ffaHoverCorners); float num = float.PositiveInfinity; float num2 = float.PositiveInfinity; float num3 = float.NegativeInfinity; float num4 = float.NegativeInfinity; for (int i = 0; i < 4; i++) { Vector2 val = (Vector2)((ffaWorldToScreenPoint != null) ? ffaWorldToScreenPoint(null, ffaHoverCorners[i]) : new Vector2(ffaHoverCorners[i].x, ffaHoverCorners[i].y)); num = Mathf.Min(num, val.x); num3 = Mathf.Max(num3, val.x); num2 = Mathf.Min(num2, val.y); num4 = Mathf.Max(num4, val.y); } if (num3 <= num || num4 <= num2) { return false; } rect = new Rect(num, (float)Screen.height - num4, num3 - num, num4 - num2); return true; } private static bool TryGetFfaViewportClippedRect(RectTransform target, out Rect rect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); if (!TryGetFfaScreenRect(target, out var rect2)) { return false; } if ((Object)(object)ffaRecentViewport != (Object)null && TryGetFfaScreenRect(ffaRecentViewport, out var rect3)) { float num = Mathf.Max(((Rect)(ref rect2)).xMin, ((Rect)(ref rect3)).xMin); float num2 = Mathf.Min(((Rect)(ref rect2)).xMax, ((Rect)(ref rect3)).xMax); float num3 = Mathf.Max(((Rect)(ref rect2)).yMin, ((Rect)(ref rect3)).yMin); float num4 = Mathf.Min(((Rect)(ref rect2)).yMax, ((Rect)(ref rect3)).yMax); if (num2 <= num || num4 <= num3) { return false; } ((Rect)(ref rect2))..ctor(num, num3, num2 - num, num4 - num3); } if ((Object)(object)ffaTabOuterViewport != (Object)null && TryGetFfaScreenRect(ffaTabOuterViewport, out var rect4)) { float num5 = Mathf.Max(((Rect)(ref rect2)).xMin, ((Rect)(ref rect4)).xMin); float num6 = Mathf.Min(((Rect)(ref rect2)).xMax, ((Rect)(ref rect4)).xMax); float num7 = Mathf.Max(((Rect)(ref rect2)).yMin, ((Rect)(ref rect4)).yMin); float num8 = Mathf.Min(((Rect)(ref rect2)).yMax, ((Rect)(ref rect4)).yMax); if (num6 <= num5 || num8 <= num7) { return false; } ((Rect)(ref rect2))..ctor(num5, num7, num6 - num5, num8 - num7); } rect = rect2; return true; } private static bool TryGetFfaHeaderHoverRect(FfaRecentMatchRow row, out Rect rect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); if (row == null || row.graph == null) { return false; } return TryGetFfaViewportClippedRect(row.headerRect, out rect); } private static void EnsureFfaGraphStyles() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00db: Expected O, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if (ffaGraphTitleStyle == null) { ffaGraphTitleStyle = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, clipping = (TextClipping)0 }; ffaGraphTitleStyle.normal.textColor = Color.white; ffaGraphLegendStyle = new GUIStyle(GUI.skin.label) { fontSize = 12, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, clipping = (TextClipping)0 }; ffaGraphLegendStyle.normal.textColor = Color.white; ffaGraphAxisStyle = new GUIStyle(GUI.skin.label) { fontSize = 11, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, clipping = (TextClipping)0 }; ffaGraphAxisStyle.normal.textColor = new Color(0.65f, 0.68f, 0.74f); } } private static void DrawFfaGraphSegment(Vector2 start, Vector2 end, Color color, float thickness) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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) float num = end.x - start.x; float num2 = end.y - start.y; float num3 = Mathf.Sqrt(num * num + num2 * num2); if (!(num3 < 0.1f)) { Matrix4x4 matrix = GUI.matrix; Color color2 = GUI.color; GUI.color = color; GUIUtility.RotateAroundPivot(Mathf.Atan2(num2, num) * 57.29578f, start); GUI.DrawTexture(new Rect(start.x, start.y - thickness * 0.5f, num3, thickness), (Texture)(object)Texture2D.whiteTexture); GUI.matrix = matrix; GUI.color = color2; } } private static void DrawFfaTimelineGraph(FfaTimelineGraph graph, Vector2 mouse) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) if (graph == null || graph.eventCount <= 0 || graph.values == null) { return; } EnsureFfaGraphStyles(); int num = (graph.names.Length + 1) / 2; float num2 = 470f; float num3 = 218f + (float)num * 18f; float num4 = mouse.x + 18f; float num5 = mouse.y + 18f; if (num4 + num2 > (float)Screen.width - 6f) { num4 = mouse.x - num2 - 18f; } if (num5 + num3 > (float)Screen.height - 6f) { num5 = mouse.y - num3 - 18f; } num4 = Mathf.Clamp(num4, 6f, Mathf.Max(6f, (float)Screen.width - num2 - 6f)); num5 = Mathf.Clamp(num5, 6f, Mathf.Max(6f, (float)Screen.height - num3 - 6f)); Rect val = default(Rect); ((Rect)(ref val))..ctor(num4, num5, num2, num3); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.025f, 0.03f, 0.045f, 0.97f), 0f, 0f); GUI.Label(new Rect(num4 + 14f, num5 + 8f, num2 - 28f, 24f), graph.title, ffaGraphTitleStyle); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(num4 + 42f, num5 + 38f, num2 - 60f, 142f); Color color = default(Color); ((Color)(ref color))..ctor(0.35f, 0.38f, 0.45f, 0.42f); DrawFfaGraphSegment(new Vector2(((Rect)(ref val2)).x, ((Rect)(ref val2)).y), new Vector2(((Rect)(ref val2)).x, ((Rect)(ref val2)).yMax), color, 1f); DrawFfaGraphSegment(new Vector2(((Rect)(ref val2)).x, ((Rect)(ref val2)).yMax), new Vector2(((Rect)(ref val2)).xMax, ((Rect)(ref val2)).yMax), color, 1f); DrawFfaGraphSegment(new Vector2(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + ((Rect)(ref val2)).height * 0.5f), new Vector2(((Rect)(ref val2)).xMax, ((Rect)(ref val2)).y + ((Rect)(ref val2)).height * 0.5f), color, 1f); GUI.Label(new Rect(num4 + 8f, ((Rect)(ref val2)).y - 8f, 32f, 22f), graph.maxLabel, ffaGraphAxisStyle); GUI.Label(new Rect(num4 + 22f, ((Rect)(ref val2)).yMax - 12f, 18f, 22f), "0", ffaGraphAxisStyle); GUI.Label(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).yMax + 3f, ((Rect)(ref val2)).width, 20f), graph.eventLabel, ffaGraphAxisStyle); float num6 = ((graph.eventCount > 0) ? (((Rect)(ref val2)).width / (float)graph.eventCount) : ((Rect)(ref val2)).width); Vector2 start = default(Vector2); Vector2 end = default(Vector2); for (int i = 0; i < graph.values.Length; i++) { float[] array = graph.values[i]; if (array != null) { Color color2 = graph.colors[i]; for (int j = 0; j < graph.eventCount; j++) { float num7 = array[j]; float num8 = array[j + 1]; ((Vector2)(ref start))..ctor(((Rect)(ref val2)).x + (float)j * num6, ((Rect)(ref val2)).yMax - num7 / graph.maxScore * ((Rect)(ref val2)).height); ((Vector2)(ref end))..ctor(((Rect)(ref val2)).x + (float)(j + 1) * num6, ((Rect)(ref val2)).yMax - num8 / graph.maxScore * ((Rect)(ref val2)).height); DrawFfaGraphSegment(start, end, color2, 2f); } } } float num9 = ((Rect)(ref val2)).yMax + 28f; float num10 = (num2 - 28f) * 0.5f; for (int k = 0; k < graph.names.Length; k++) { int num11 = k & 1; int num12 = k / 2; float num13 = num4 + 14f + (float)num11 * num10; float num14 = num9 + (float)num12 * 18f; GUI.DrawTexture(new Rect(num13, num14 + 7f, 20f, 3f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, graph.colors[k], 0f, 0f); GUI.Label(new Rect(num13 + 26f, num14, num10 - 30f, 19f), graph.names[k], ffaGraphLegendStyle); } } private static void DrawFfaRecentHoverGraph() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_004d: 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_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) try { if (Event.current == null || (int)Event.current.type != 7 || !isOpen || currentTab != 12) { return; } Vector2 mousePosition = Event.current.mousePosition; string text = null; FfaTimelineGraph ffaTimelineGraph = null; for (int i = 0; i < ffaRecentRows.Count; i++) { if (text != null) { break; } FfaRecentMatchRow ffaRecentMatchRow = ffaRecentRows[i]; if ((Object)(object)ffaRecentMatchRow?.root == (Object)null || !ffaRecentMatchRow.root.activeInHierarchy) { continue; } for (int j = 0; j < ffaRecentMatchRow.players.Count; j++) { FfaRecentPlayerRow ffaRecentPlayerRow = ffaRecentMatchRow.players[j]; if (!((Object)(object)ffaRecentPlayerRow?.cardsGO == (Object)null) && ffaRecentPlayerRow.cardsGO.activeInHierarchy && !string.IsNullOrEmpty(ffaRecentPlayerRow.cardsHoverText)) { RectTransform component = ffaRecentPlayerRow.cardsGO.GetComponent(); if (!((Object)(object)component == (Object)null) && TryGetFfaViewportClippedRect(component, out var rect) && ((Rect)(ref rect)).Contains(mousePosition)) { text = ffaRecentPlayerRow.cardsHoverText; break; } } } if (text == null && ffaTimelineGraph == null && TryGetFfaHeaderHoverRect(ffaRecentMatchRow, out var rect2) && ((Rect)(ref rect2)).Contains(mousePosition)) { ffaTimelineGraph = ffaRecentMatchRow.graph; } } if (text == null && ffaTimelineGraph == null) { return; } int depth = GUI.depth; try { GUI.depth = -20000; if (text != null) { DrawFfaCardsTooltip(text, mousePosition); } else { DrawFfaTimelineGraph(ffaTimelineGraph, mousePosition); } } finally { GUI.depth = depth; } } catch { } } private static void DrawFfaCardsTooltip(string tip, Vector2 mouse) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown if (ffaCardsTipStyle == null) { ffaCardsTipStyle = new GUIStyle(GUI.skin.label) { fontSize = 13, fontStyle = (FontStyle)1, alignment = (TextAnchor)0, richText = true, wordWrap = true, clipping = (TextClipping)0 }; ffaCardsTipStyle.normal.textColor = Color.white; } if ((object)tip != ffaCardsTipCachedText) { ffaCardsTipCachedText = tip; ffaCardsTipCachedHeight = ffaCardsTipStyle.CalcHeight(new GUIContent(tip), 450f); } float num = ffaCardsTipCachedHeight + 20f; float num2 = Mathf.Max(8f, Mathf.Min(mouse.x + 18f, (float)Screen.width - 470f - 8f)); float num3 = Mathf.Max(8f, Mathf.Min(mouse.y + 14f, (float)Screen.height - num - 8f)); Rect val = default(Rect); ((Rect)(ref val))..ctor(num2, num3, 470f, num); Color color = GUI.color; GUI.color = new Color(0.07f, 0.08f, 0.1f, 0.96f); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture); GUI.color = color; GUI.Label(new Rect(((Rect)(ref val)).x + 10f, ((Rect)(ref val)).y + 10f, 450f, ffaCardsTipCachedHeight), tip, ffaCardsTipStyle); } private static void MaybeRefreshFfaTab() { if (currentTab == 12) { ApiClient.FfaProbeServerState(); ApiClient.UpdateFfaQueuePoll(force: false); ApiClient.FetchFfaLobbies(); if (Time.unscaledTime >= ffaRecentRefreshAt) { ffaRecentRefreshAt = Time.unscaledTime + 10f; ApiClient.FetchFfaRecent(ffaRecentPageReq); } if (Time.unscaledTime >= ffaBetRefreshAt) { ffaBetRefreshAt = Time.unscaledTime + 10f; ApiClient.FetchFfaBettable(MatchTracker.LocalSteamId); } if (Time.unscaledTime >= ffaLbRefreshAt) { ffaLbRefreshAt = Time.unscaledTime + 30f; ApiClient.FetchFfaLeaderboard(200, ffaLbSortReq); } } } private static void RefreshFfaTab() { //IL_0552: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Unknown result type (might be due to invalid IL or missing references) //IL_0631: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) bool isFfaQueuePolling = ApiClient.IsFfaQueuePolling; string ffaQueueStatus = ApiClient.FfaQueueStatus; bool flag = !string.IsNullOrEmpty(ApiClient.OpenFfaLobbyId); bool flag2 = Plugin.PendingFfaSlot >= 0; bool flag3 = false; try { int num; if (PhotonNetwork.InRoom) { Room currentRoom = PhotonNetwork.CurrentRoom; num = ((((currentRoom != null) ? currentRoom.Name : null) ?? "").StartsWith("ffa_") ? 1 : 0); } else { num = 0; } flag3 = (byte)num != 0; } catch { } if ((Object)(object)ffaJoinBtn != (Object)null) { ffaJoinBtn.SetActive(!isFfaQueuePolling && !flag2 && !flag3 && !flag && ffaQueueStatus != "leaving"); } if ((Object)(object)ffaStartBtn != (Object)null) { bool flag4 = flag && ApiClient.FfaLobbyIsHost && !flag2 && !flag3 && ffaQueueStatus != "leaving"; ffaStartBtn.SetActive(flag4); if (flag4) { UIFactory.SetText(UIFactory.GetButtonText(ffaStartBtn), ApiClient.FfaLobbyCanStart ? $"Start Game ({ApiClient.FfaLobbyMemberCount}/{ApiClient.FfaLobbyMaxPlayers})" : $"Start (need {ApiClient.FfaLobbyMinPlayers}+)"); } } if ((Object)(object)ffaLeaveBtn != (Object)null) { ffaLeaveBtn.SetActive((isFfaQueuePolling || flag2 || flag) && !flag3); } if (txtFfaStatus != null) { string s; if (flag3) { s = "In FFA match."; } else if (ffaQueueStatus == "leaving") { s = "Leaving..."; } else if (ffaQueueStatus == "ready_join" || flag2) { int num2 = ((Plugin.PendingFfaSlot >= 0) ? Plugin.PendingFfaSlot : ApiClient.FfaMySlot); int num3 = Math.Max(ApiClient.FfaLobbyPlayerCount, num2 + 1); s = $"Game starting! Joining as player {num2 + 1} of {num3}..."; } else if (flag) { if (ApiClient.FfaLobbyIsHost) { s = (ApiClient.FfaLobbyCanStart ? $"Your lobby is ready. {ApiClient.FfaLobbyMemberCount} in - press Start, or wait for more (up to {ApiClient.FfaLobbyMaxPlayers})." : $"You are the host. Waiting for players - {ApiClient.FfaLobbyMemberCount}/{ApiClient.FfaLobbyMinPlayers} needed to start."); } else { string text = null; try { text = ApiClient.FfaLobbyMembers?.Find((ApiClient.FfaLobbyMemberEntry m) => m.is_host)?.display_name; } catch { } s = string.Format("In {0}'s lobby - waiting for the host to start ({1} in).", FfaSafeRich(Trunc(text ?? "the host", 16)), ApiClient.FfaLobbyMemberCount); } } else { s = "Browse open lobbies below, or create your own."; } UIFactory.SetText(txtFfaStatus, s); } RenderFfaLobbySection(); RenderFfaBettingSection(); List list = ApiClient.CachedFfaLeaderboard ?? new List(); if (ffaLbSortKeys != null && ffaLbHeaderTexts != null && ffaLbSortBtns != null) { string[] array = new string[8] { "#", "Player", "Rating", "Games", "Wins", "Top3", "AvgPl", "WR" }; for (int num4 = 0; num4 < ffaLbSortKeys.Length && num4 < array.Length; num4++) { bool flag5 = ffaLbSortKeys[num4] != null && ffaLbSortKeys[num4] == ffaLbSortReq; UIFactory.SetText(ffaLbHeaderTexts[num4], flag5 ? (array[num4] + " v") : array[num4]); UIFactory.SetColor(ffaLbHeaderTexts[num4], flag5 ? C_GOLD : C_LABEL); if ((Object)(object)ffaLbSortBtns[num4] != (Object)null) { UIFactory.SetImageColor(ffaLbSortBtns[num4], flag5 ? new Color(0.38f, 0.3f, 0.1f, 0.98f) : new Color(0.18f, 0.2f, 0.24f, 0.85f)); } } } for (int num5 = 0; num5 < ffaLbRows.Count; num5++) { FfaLBRow ffaLBRow = ffaLbRows[num5]; if (num5 >= list.Count) { ffaLBRow.root.SetActive(false); continue; } ApiClient.FfaLeaderboardEntry ffaLeaderboardEntry = list[num5]; bool flag6 = ffaLeaderboardEntry.steam_id == MatchTracker.LocalSteamId; UIFactory.SetText(ffaLBRow.txtRank, $"#{ffaLeaderboardEntry.rank}"); UIFactory.SetColor(ffaLBRow.txtRank, (Color)((ffaLeaderboardEntry.rank == 1) ? new Color(1f, 0.84f, 0f) : ((ffaLeaderboardEntry.rank == 2) ? new Color(0.75f, 0.75f, 0.75f) : ((ffaLeaderboardEntry.rank == 3) ? new Color(0.8f, 0.5f, 0.2f) : C_GOLD)))); string text2 = Trunc(ffaLeaderboardEntry.display_name, 14); if (!string.IsNullOrEmpty(ffaLeaderboardEntry.title)) { string text3 = (string.IsNullOrEmpty(ffaLeaderboardEntry.title_color) ? "#FFD94D" : ffaLeaderboardEntry.title_color); text2 = (IsPodiumTitle(ffaLeaderboardEntry.title) ? (text2 + " " + PodiumSparkleSpan(ffaLeaderboardEntry.title, text3, 0u)) : (text2 + " [" + Trunc(ffaLeaderboardEntry.title, 12) + "]")); } UIFactory.SetText(ffaLBRow.txtName, text2); UIFactory.SetColor(ffaLBRow.txtName, flag6 ? C_GREEN : C_WHITE); if (ffaLeaderboardEntry.rd > 0) { UIFactory.SetText(ffaLBRow.txtRating, $"{ffaLeaderboardEntry.rating} ~{ffaLeaderboardEntry.rd}"); } else { UIFactory.SetText(ffaLBRow.txtRating, $"{ffaLeaderboardEntry.rating}"); } UIFactory.SetText(ffaLBRow.txtGames, $"{ffaLeaderboardEntry.games_played}"); UIFactory.SetText(ffaLBRow.txtWins, $"{ffaLeaderboardEntry.wins}"); UIFactory.SetText(ffaLBRow.txtTop3, $"{ffaLeaderboardEntry.top3}"); UIFactory.SetText(ffaLBRow.txtAvgPl, (ffaLeaderboardEntry.avg_placement > 0f) ? $"{ffaLeaderboardEntry.avg_placement:F1}" : "-"); UIFactory.SetText(ffaLBRow.txtWR, $"{ffaLeaderboardEntry.win_rate * 100f:F0}%"); ffaLBRow.root.SetActive(true); } if (txtFfaLbHeader != null) { UIFactory.SetText(txtFfaLbHeader, (list.Count == 0) ? "FFA Leaderboard - no ranked FFAs yet" : $"FFA Leaderboard ({list.Count} ranked)"); } ToggleInnerScroll(ffaLbScrollRect, (float)Math.Min(list.Count, ffaLbRows.Count) * 30f); if (!((Object)(object)ffaRecentContainer != (Object)null)) { return; } List list2 = ApiClient.CachedFfaRecent ?? new List(); while (ffaRecentRows.Count < Math.Min(list2.Count, 10)) { ffaRecentRows.Add(CreateFfaRecentMatchRow(ffaRecentContainer.transform, $"FfaRR{ffaRecentRows.Count}")); } float num6 = 0f; for (int num7 = 0; num7 < ffaRecentRows.Count; num7++) { FfaRecentMatchRow ffaRecentMatchRow = ffaRecentRows[num7]; if (num7 >= list2.Count) { ffaRecentMatchRow.root.SetActive(false); continue; } BuildFfaRecentRowText(list2[num7], ffaRecentMatchRow); num6 += EstimateFfaRecentHeight(list2[num7]) + 2f; } ToggleInnerScroll(ffaRecentScrollRect, num6); if (txtFfaRecentHeader != null) { UIFactory.SetText(txtFfaRecentHeader, (ApiClient.CachedFfaRecentTotal == 0) ? "Recent Ranked FFAs - none yet" : $"Recent Ranked FFAs ({ApiClient.CachedFfaRecentTotal} total)"); } int num8 = Math.Max(1, ApiClient.CachedFfaRecentPages); if (txtFfaRecentPage != null) { UIFactory.SetText(txtFfaRecentPage, $"{ffaRecentPageReq + 1}/{num8}"); } if ((Object)(object)ffaRecentPrevBtn != (Object)null) { ffaRecentPrevBtn.SetActive(ffaRecentPageReq > 0); } if ((Object)(object)ffaRecentNextBtn != (Object)null) { ffaRecentNextBtn.SetActive(ffaRecentPageReq + 1 < num8); } } private static void RenderFfaBettingSection() { //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ffaBetPanel == (Object)null || (Object)(object)ffaBetContainer == (Object)null) { return; } List cachedFfaBettable = ApiClient.CachedFfaBettable; bool flag = cachedFfaBettable != null && cachedFfaBettable.Count > 0; ffaBetPanel.SetActive(flag); if (!flag) { for (int i = 0; i < ffaBetLobbyRows.Count; i++) { ffaBetLobbyRows[i].root.SetActive(false); } return; } while (ffaBetLobbyRows.Count < cachedFfaBettable.Count) { ffaBetLobbyRows.Add(CreateFfaBetLobbyRow(ffaBetContainer.transform, $"FfaBetLobby{ffaBetLobbyRows.Count}")); } for (int j = 0; j < ffaBetLobbyRows.Count; j++) { FfaBetLobbyRow ffaBetLobbyRow = ffaBetLobbyRows[j]; if (j >= cachedFfaBettable.Count) { ffaBetLobbyRow.root.SetActive(false); continue; } ApiClient.FfaBettableLobby ffaBettableLobby = cachedFfaBettable[j]; List players = ffaBettableLobby.players; int num = players?.Count ?? 0; int num2 = ((ffaBettableLobby.player_count > 0) ? ffaBettableLobby.player_count : num); string arg = (ffaBettableLobby.is_member ? " (your lobby)" : (ffaBettableLobby.already_bet ? " (bet placed)" : "")); UIFactory.SetText(ffaBetLobbyRow.txtHeader, $"Game {ffaBettableLobby.game_number} - {num2} players{arg}"); while (ffaBetLobbyRow.players.Count < num) { ffaBetLobbyRow.players.Add(CreateFfaBetPlayerRow(ffaBetLobbyRow.root.transform, $"Player{ffaBetLobbyRow.players.Count}")); } for (int k = 0; k < ffaBetLobbyRow.players.Count; k++) { FfaBetPlayerRow ffaBetPlayerRow = ffaBetLobbyRow.players[k]; if (k >= num) { ffaBetPlayerRow.root.SetActive(false); continue; } ApiClient.FfaBettablePlayer ffaBettablePlayer = players[k]; ffaBetPlayerRow.lobbyId = ffaBettableLobby.lobby_id; ffaBetPlayerRow.steamId = ffaBettablePlayer.steam_id; ffaBetPlayerRow.displayName = ffaBettablePlayer.display_name ?? "Player"; ffaBetPlayerRow.gameNumber = ffaBettableLobby.game_number; UIFactory.SetText(ffaBetPlayerRow.txtName, FfaSafeRich(Trunc(ffaBetPlayerRow.displayName, 28))); UIFactory.SetText(ffaBetPlayerRow.txtRating, $"{ffaBettablePlayer.rating}"); UIFactory.SetText(ffaBetPlayerRow.txtOdds, "x" + ffaBettablePlayer.odds_multiplier.ToString("0.00", CultureInfo.InvariantCulture)); UIFactory.SetColor(ffaBetPlayerRow.txtOdds, ffaBettablePlayer.bettable ? C_GOLD : C_DIM); ffaBetPlayerRow.betBtn.SetActive(ffaBettablePlayer.bettable && !ffaBettableLobby.is_member && !ffaBettableLobby.already_bet); ffaBetPlayerRow.root.SetActive(true); } SetFfaBetLobbyHeight(ffaBetLobbyRow, num); ffaBetLobbyRow.root.SetActive(true); } } private static FfaBrowserRow CreateFfaBrowserRow(Transform parent, string name) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown FfaBrowserRow row = new FfaBrowserRow(); row.root = new GameObject(name); row.root.transform.SetParent(parent, false); row.root.AddComponent(); UIFactory.AddHLG(row.root, 8f, 6, 6, 0, 0, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(row.root, -1f, 31f, -1f, 31f, -1f, 0f); row.txtInfo = CreateFfaTextCell("Info", row.root.transform, 760f, 513, 17f, C_WHITE, flexible: true, 300f); UIFactory.SetOverflowMode(row.txtInfo, 3); row.joinBtn = UIFactory.CreateButton("Join", row.root.transform, "Join", 16f, C_WHITE, new Color(0.25f, 0.42f, 0.2f, 0.95f), (UnityAction)delegate { if (!string.IsNullOrEmpty(row.lobbyId)) { ApiClient.FfaJoinLobby(row.lobbyId); } dirty = true; }, (Vector2?)new Vector2(88f, 26f)); SetFfaLayoutWidth(row.joinBtn, 88f, 0f, 88f); row.root.SetActive(false); return row; } private static void RenderFfaLobbySection() { //IL_054d: Unknown result type (might be due to invalid IL or missing references) //IL_0559: Unknown result type (might be due to invalid IL or missing references) if (txtFfaLobbyHeader == null || txtFfaLobbyBody == null) { return; } int num2; if (!string.IsNullOrEmpty(ApiClient.OpenFfaLobbyId)) { for (int i = 0; i < ffaBrowserRows.Count; i++) { ffaBrowserRows[i].root.SetActive(false); } List ffaLobbyMembers = ApiClient.FfaLobbyMembers; int num = ffaLobbyMembers?.Count ?? 0; UIFactory.SetText(txtFfaLobbyHeader, $"Your Lobby ({Math.Max(num, ApiClient.FfaLobbyMemberCount)}/{ApiClient.FfaLobbyMaxPlayers} - host starts at {ApiClient.FfaLobbyMinPlayers}+)"); if (num == 0) { UIFactory.SetText(txtFfaLobbyBody, "Loading members..."); num2 = 29; } else { StringBuilder stringBuilder = new StringBuilder(); foreach (ApiClient.FfaLobbyMemberEntry item in ffaLobbyMembers) { string text = ((item.steam_id == MatchTracker.LocalSteamId) ? "" : ""); string text2 = ((item.rating > 0) ? $"FFA {item.rating}" : $"1v1 {item.rating_1v1}"); string text3 = (item.is_host ? " HOST" : ""); int num3 = item.wait_seconds / 60; int num4 = item.wait_seconds % 60; string text4 = ((num3 > 0) ? $"{num3}m{num4:D2}s" : $"{num4}s"); stringBuilder.Append(" " + text + FfaSafeRich(Trunc(item.display_name, 18)) + " " + text2 + text3 + " " + text4 + "\n"); } UIFactory.SetText(txtFfaLobbyBody, stringBuilder.ToString()); num2 = (int)((float)num * 23f + 6f); } } else { List cachedFfaLobbies = ApiClient.CachedFfaLobbies; int num5 = cachedFfaLobbies?.Count ?? 0; UIFactory.SetText(txtFfaLobbyHeader, (num5 == 0) ? "Open FFA Lobbies (none right now)" : $"Open FFA Lobbies ({num5})"); while (ffaBrowserRows.Count < Math.Min(num5, 20)) { ffaBrowserRows.Add(CreateFfaBrowserRow(ffaBrowserContainer.transform, $"FfaBrow{ffaBrowserRows.Count}")); } for (int j = 0; j < ffaBrowserRows.Count; j++) { FfaBrowserRow ffaBrowserRow = ffaBrowserRows[j]; if (cachedFfaLobbies == null || j >= cachedFfaLobbies.Count) { ffaBrowserRow.root.SetActive(false); continue; } ApiClient.FfaOpenLobbyEntry ffaOpenLobbyEntry = cachedFfaLobbies[j]; ffaBrowserRow.lobbyId = ffaOpenLobbyEntry.lobby_id; int num6 = ffaOpenLobbyEntry.age_seconds / 60; string text5 = ((num6 > 0) ? $"{num6}m" : $"{ffaOpenLobbyEntry.age_seconds}s"); UIFactory.SetText(ffaBrowserRow.txtInfo, "" + FfaSafeRich(Trunc(ffaOpenLobbyEntry.host_name, 18)) + "'s lobby" + $" {ffaOpenLobbyEntry.player_count}/{ffaOpenLobbyEntry.max_players}" + " open " + text5 + ""); bool active = ffaOpenLobbyEntry.player_count < ffaOpenLobbyEntry.max_players && ApiClient.FfaQueueStatus != "leaving"; ffaBrowserRow.joinBtn.SetActive(active); ffaBrowserRow.root.SetActive(true); } UIFactory.SetText(txtFfaLobbyBody, (num5 != 0) ? "" : (ApiClient.FfaLobbiesUnavailable ? "Lobby browser unavailable right now - the server may be updating." : ((cachedFfaLobbies == null) ? "Loading..." : "No open lobbies - create one and rally the Discord!"))); num2 = ((num5 == 0) ? 29 : 2); } object obj = txtFfaLobbyBody; Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null) { Component component = val.gameObject.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)num2); UIFactory.tLE.GetProperty("minHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)num2); } RectTransform component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sizeDelta = new Vector2(component2.sizeDelta.x, (float)num2); } } } private static GameObject BuildOneVTwoTab(Transform parent, int tabIdx) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_0157: 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_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Expected O, but got Unknown //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Expected O, but got Unknown //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Expected O, but got Unknown //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Expected O, but got Unknown //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_0400: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Expected O, but got Unknown //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_0470: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Unknown result type (might be due to invalid IL or missing references) //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Expected O, but got Unknown //IL_0611: Unknown result type (might be due to invalid IL or missing references) //IL_0618: Expected O, but got Unknown //IL_0672: Unknown result type (might be due to invalid IL or missing references) //IL_0679: Expected O, but got Unknown //IL_06e5: Unknown result type (might be due to invalid IL or missing references) //IL_06f9: Unknown result type (might be due to invalid IL or missing references) //IL_078b: Unknown result type (might be due to invalid IL or missing references) //IL_079f: Unknown result type (might be due to invalid IL or missing references) //IL_0820: Unknown result type (might be due to invalid IL or missing references) //IL_0827: Expected O, but got Unknown //IL_0882: Unknown result type (might be due to invalid IL or missing references) //IL_0889: Expected O, but got Unknown //IL_08f5: Unknown result type (might be due to invalid IL or missing references) //IL_0909: Unknown result type (might be due to invalid IL or missing references) //IL_0924: Unknown result type (might be due to invalid IL or missing references) //IL_092b: Expected O, but got Unknown //IL_0984: Unknown result type (might be due to invalid IL or missing references) //IL_099d: Unknown result type (might be due to invalid IL or missing references) //IL_09cb: Unknown result type (might be due to invalid IL or missing references) //IL_09f5: Unknown result type (might be due to invalid IL or missing references) //IL_0a09: Unknown result type (might be due to invalid IL or missing references) //IL_0a35: Unknown result type (might be due to invalid IL or missing references) //IL_0a4e: Unknown result type (might be due to invalid IL or missing references) //IL_09b6: Unknown result type (might be due to invalid IL or missing references) //IL_09bb: Unknown result type (might be due to invalid IL or missing references) //IL_09c1: Expected O, but got Unknown //IL_0a7c: Unknown result type (might be due to invalid IL or missing references) //IL_0a67: Unknown result type (might be due to invalid IL or missing references) //IL_0a6c: Unknown result type (might be due to invalid IL or missing references) //IL_0a72: Expected O, but got Unknown GameObject val = new GameObject("OneVTwoOuter"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 0f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(tabIdx, val.transform, asFirst: true); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("OneVTwoScroll", val.transform, 6f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val2 = new GameObject("OneVTwo"); val2.transform.SetParent(scrollViewRefs.content.transform, false); val2.AddComponent(); UIFactory.AddVLG(val2, 8f, 20, 10, 8, 14); GameObject val3 = new GameObject("O1HdrRow"); val3.transform.SetParent(val2.transform, false); val3.AddComponent(); UIFactory.AddHLG(val3, 10f); UIFactory.AddLE(val3, -1f, -1f, -1f, 45f, -1f, 0f); UIFactory.CreateText("O1H", val3.transform, "1v2 — Solo vs Duo", 32f, C_GOLD, 257, (Vector2?)new Vector2(500f, 43f), richText: true, raycastTarget: false); GameObject val4 = new GameObject("O1HdrSp"); val4.transform.SetParent(val3.transform, false); val4.AddComponent(); UIFactory.AddLE(val4, -1f, -1f, -1f, -1f, 1f); Transform transform = val3.transform; Color c_WHITE = C_WHITE; Color c_BTN = C_BTN; object obj = <>c.<>9__365_0; if (obj == null) { UnityAction val5 = delegate { ShowInfoPopup("1v2 - How It Works", "One solo player faces a duo in a best-of-3 series.\r\n\r\nHOW TO PLAY\r\n\r\n- This is a consent queue with no Elo band and no ready-up.\r\n- The server assigns one solo and two duo players.\r\n- Solo Extra Initial Pick is optional.\r\n If anyone enables it, the solo draws 2 cards on the\r\n opening pick.\r\n\r\nSCORING\r\n\r\n- The first side to win 2 games wins the series.\r\n- 1v2 is an UNRANKED beta. No rating is applied yet.\r\n- Games are recorded and will count when ranked play launches.\r\n\r\nREWARDS\r\n\r\n- Each game gives 500 XP.\r\n A game win gets x1.5, for 750 XP.\r\n- A series win gives each winner 40 Gold.\r\n A series loss gives each loser 20 Gold.\r\n- Game XP converts to Gold at 100 XP = 1 Gold.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\n- The tab has separate Solo and Duo boards.\r\n- You appear only on boards for roles you have played.\r\nRank - Activity order: wins, then WR, then games.\r\nPlayer - The player's display name.\r\nW-L - Games won and lost in that role only.\r\nWR - Win rate for games in that role.\r\n- These are activity boards. They are not sorted by Gold.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded."); }; <>c.<>9__365_0 = val5; obj = (object)val5; } UIFactory.CreateButton("O1Info", transform, "Info", 18f, c_WHITE, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(110f, 34f)); UIFactory.CreateText("O1Beta", val2.transform, "UNRANKED BETA — single games, no series rating yet. Stats are tracked and will count once ranked launches.", 19f, C_DIM, 257, (Vector2?)new Vector2(915f, 29f), richText: true, raycastTarget: false); GameObject val6 = new GameObject("O1Ctl"); val6.transform.SetParent(val2.transform, false); val6.AddComponent(); UIFactory.AddHLG(val6, 8f); UIFactory.AddLE(val6, -1f, -1f, -1f, 46f, -1f, 0f); Transform transform2 = val6.transform; Color c_WHITE2 = C_WHITE; Color c_BTN2 = C_BTN; object obj2 = <>c.<>9__365_1; if (obj2 == null) { UnityAction val7 = delegate { ovtPreferredSide = (ovtPreferredSide + 1) % 3; dirty = true; }; <>c.<>9__365_1 = val7; obj2 = (object)val7; } ovtSideBtn = UIFactory.CreateButton("O1Side", transform2, "Side: Any", 18f, c_WHITE2, c_BTN2, (UnityAction)obj2, (Vector2?)new Vector2(144f, 37f)); Transform transform3 = val6.transform; Color c_WHITE3 = C_WHITE; Color c_BTN3 = C_BTN; object obj3 = <>c.<>9__365_2; if (obj3 == null) { UnityAction val8 = delegate { ovtSoloExtraPick = !ovtSoloExtraPick; dirty = true; }; <>c.<>9__365_2 = val8; obj3 = (object)val8; } ovtExtraBtn = UIFactory.CreateButton("O1Extra", transform3, "Solo Extra Initial Pick: OFF", 18f, c_WHITE3, c_BTN3, (UnityAction)obj3, (Vector2?)new Vector2(283f, 37f)); Transform transform4 = val6.transform; Color c_WHITE4 = C_WHITE; Color bgColor = new Color(0.25f, 0.45f, 0.18f, 0.9f); object obj4 = <>c.<>9__365_3; if (obj4 == null) { UnityAction val9 = delegate { ApiClient.OvtJoinQueue(ovtPreferredSide, ovtSoloExtraPick); dirty = true; }; <>c.<>9__365_3 = val9; obj4 = (object)val9; } ovtJoinBtn = UIFactory.CreateButton("O1Join", transform4, "Join 1v2 Lobby", 19f, c_WHITE4, bgColor, (UnityAction)obj4, (Vector2?)new Vector2(181f, 37f)); Transform transform5 = val6.transform; Color c_WHITE5 = C_WHITE; Color bgColor2 = new Color(0.5f, 0.2f, 0.2f, 0.9f); object obj5 = <>c.<>9__365_4; if (obj5 == null) { UnityAction val10 = delegate { ApiClient.OvtLeaveQueue(); dirty = true; }; <>c.<>9__365_4 = val10; obj5 = (object)val10; } ovtLeaveBtn = UIFactory.CreateButton("O1Leave", transform5, "Leave", 19f, c_WHITE5, bgColor2, (UnityAction)obj5, (Vector2?)new Vector2(108f, 37f)); object t = UIFactory.CreateText("O1Note", val2.transform, "Solo Extra Initial Pick: the solo gets one extra card in the game's FIRST draw only. It's ON for the match if ANY of the three lobby members turned it on. Active in-game — the solo's first pick screen deals twice.", 16f, C_DIM, 257, (Vector2?)new Vector2(915f, 46f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t, on: true); txtOvtStatus = UIFactory.CreateText("O1St", val2.transform, "Not in queue.", 20f, C_LABEL, 257, (Vector2?)new Vector2(915f, 32f), richText: true, raycastTarget: false); GameObject val11 = UIFactory.CreatePanel("O1QL", val2.transform, C_PANEL); UIFactory.AddVLG(val11, 2f, 10, 10, 6, 6); UIFactory.AddLE(val11, -1f, -1f, -1f, -1f, -1f, 0f); txtOvtLobbyHeader = UIFactory.CreateText("O1QLH", val11.transform, "1v2 Lobby", 21f, C_SUB, 513, (Vector2?)new Vector2(891f, 29f), richText: true, raycastTarget: false); txtOvtLobbyBody = UIFactory.CreateText("O1QLB", val11.transform, "Loading…", 19f, C_LABEL, 257, (Vector2?)new Vector2(891f, 29f), richText: true, raycastTarget: false); object obj6 = txtOvtLobbyBody; Component val12 = (Component)((obj6 is Component) ? obj6 : null); if ((Object)(object)val12 != (Object)null) { UIFactory.AddLE(val12.gameObject, -1f, 29f, -1f, 29f, -1f, 0f); } UIFactory.SetWordWrap(txtOvtLobbyBody, on: true); GameObject val13 = new GameObject("O1Bot"); val13.transform.SetParent(val2.transform, false); val13.AddComponent(); UIFactory.AddHLG(val13, 8f); UIFactory.AddLE(val13, -1f, 532f, -1f, 931f, -1f, 0f); GameObject val14 = new GameObject("O1LCol"); val14.transform.SetParent(val13.transform, false); val14.AddComponent(); UIFactory.AddVLG(val14, 4f); UIFactory.AddLE(val14, 505f, -1f, 554f, -1f, 0f, 1f); txtOvtSoloLbHeader = UIFactory.CreateText("O1SLH", val14.transform, "Solo Leaderboard (unranked beta)", 21f, C_SUB, 513, (Vector2?)new Vector2(530f, 29f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("O1SLSV", val14.transform, 1f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, 200f, -1f, 399f, -1f, 0f); ovtSoloLbContainer = scrollViewRefs2.content; ovtSoloScrollRect = scrollViewRefs2.scrollGO.GetComponent(UIFactory.tScrollRect); txtOvtDuoLbHeader = UIFactory.CreateText("O1DLH", val14.transform, "Duo Leaderboard (unranked beta)", 21f, C_SUB, 513, (Vector2?)new Vector2(530f, 29f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("O1DLSV", val14.transform, 1f); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, 200f, -1f, 399f, -1f, 0f); ovtDuoLbContainer = scrollViewRefs3.content; ovtDuoScrollRect = scrollViewRefs3.scrollGO.GetComponent(UIFactory.tScrollRect); GameObject val15 = new GameObject("O1RCol"); val15.transform.SetParent(val13.transform, false); val15.AddComponent(); UIFactory.AddVLG(val15, 4f); UIFactory.AddLE(val15, -1f, -1f, -1f, -1f, 1f, 1f); GameObject val16 = new GameObject("O1RHR"); val16.transform.SetParent(val15.transform, false); val16.AddComponent(); UIFactory.AddHLG(val16, 6f); UIFactory.AddLE(val16, -1f, 34f, -1f, 34f, -1f, 0f); txtOvtRecentHeader = UIFactory.CreateText("O1RH", val16.transform, "Recent 1v2 Games", 24f, C_SUB, 513, (Vector2?)new Vector2(337f, 34f), richText: true, raycastTarget: false); GameObject val17 = new GameObject("O1RSp"); val17.transform.SetParent(val16.transform, false); val17.AddComponent(); UIFactory.AddLE(val17, -1f, -1f, -1f, -1f, 1f); Transform transform6 = val16.transform; Color c_WHITE6 = C_WHITE; Color bgColor3 = new Color(0.22f, 0.25f, 0.3f, 0.95f); object obj7 = <>c.<>9__365_5; if (obj7 == null) { UnityAction val18 = delegate { ovtRecentPageReq = Math.Max(0, ovtRecentPageReq - 1); ApiClient.FetchOvtRecent(ovtRecentPageReq); }; <>c.<>9__365_5 = val18; obj7 = (object)val18; } ovtRecentPrevBtn = UIFactory.CreateButton("O1RP", transform6, "<", 18f, c_WHITE6, bgColor3, (UnityAction)obj7, (Vector2?)new Vector2(34f, 29f)); txtOvtRecentPage = UIFactory.CreateText("O1RPI", val16.transform, "1/1", 18f, C_LABEL, 514, (Vector2?)new Vector2(58f, 29f), richText: true, raycastTarget: false); Transform transform7 = val16.transform; Color c_WHITE7 = C_WHITE; Color bgColor4 = new Color(0.22f, 0.25f, 0.3f, 0.95f); object obj8 = <>c.<>9__365_6; if (obj8 == null) { UnityAction val19 = delegate { ovtRecentPageReq++; ApiClient.FetchOvtRecent(ovtRecentPageReq); }; <>c.<>9__365_6 = val19; obj8 = (object)val19; } ovtRecentNextBtn = UIFactory.CreateButton("O1RN", transform7, ">", 18f, c_WHITE7, bgColor4, (UnityAction)obj8, (Vector2?)new Vector2(34f, 29f)); UIFactory.ScrollViewRefs scrollViewRefs4 = UIFactory.CreateScrollView("O1RSV", val15.transform); UIFactory.AddLE(scrollViewRefs4.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); ovtRecentContainer = scrollViewRefs4.content; ovtRecentScrollRect = scrollViewRefs4.scrollGO.GetComponent(UIFactory.tScrollRect); return val; } private static void MaybeRefreshOvtTab() { if (currentTab == 11) { ApiClient.UpdateOvtQueuePoll(force: false); ApiClient.UpdateOvtQueueList(); if (Time.unscaledTime >= ovtRecentRefreshAt) { ovtRecentRefreshAt = Time.unscaledTime + 10f; ApiClient.FetchOvtRecent(ovtRecentPageReq); } if (Time.unscaledTime >= ovtTabRefreshAt) { ovtTabRefreshAt = Time.unscaledTime + 30f; ApiClient.FetchOvtLeaderboard(); ApiClient.FetchOvtLeaderboard(200, "solo"); ApiClient.FetchOvtLeaderboard(200, "duo"); } } } private static void RefreshOneVTwoTab() { if ((Object)(object)ovtSideBtn != (Object)null) { UIFactory.SetText(UIFactory.GetButtonText(ovtSideBtn), (ovtPreferredSide == 1) ? "Side: Solo" : ((ovtPreferredSide == 2) ? "Side: Duo" : "Side: Any")); } if ((Object)(object)ovtExtraBtn != (Object)null) { UIFactory.SetText(UIFactory.GetButtonText(ovtExtraBtn), ovtSoloExtraPick ? "Solo Extra Initial Pick: ON" : "Solo Extra Initial Pick: OFF"); } bool isOvtQueuePolling = ApiClient.IsOvtQueuePolling; bool flag = Plugin.PendingOvtSlot >= 0 || !string.IsNullOrEmpty(ApiClient.ActiveOvt1v2SeriesId); bool flag2 = false; try { int num; if (PhotonNetwork.InRoom) { Room currentRoom = PhotonNetwork.CurrentRoom; num = ((((currentRoom != null) ? currentRoom.Name : null) ?? "").StartsWith("ovt_") ? 1 : 0); } else { num = 0; } flag2 = (byte)num != 0; } catch { } if ((Object)(object)ovtJoinBtn != (Object)null) { ovtJoinBtn.SetActive(!isOvtQueuePolling && !flag && !flag2 && ApiClient.OvtQueueStatus != "leaving"); } if ((Object)(object)ovtLeaveBtn != (Object)null) { ovtLeaveBtn.SetActive((isOvtQueuePolling || flag) && !flag2); } if (txtOvtStatus != null) { string ovtQueueStatus = ApiClient.OvtQueueStatus; string s; if (flag2) { s = "In a 1v2 match."; } else { switch (ovtQueueStatus) { case "searching": s = $"Searching… {ApiClient.OvtQueueCount} in lobby (locks at 3)"; break; case "ready_join": { string text = Trunc(ApiClient.OvtLockedSoloName ?? "?", 14); List ovtLockedDuo = ApiClient.OvtLockedDuo; string text2 = ((ovtLockedDuo != null && ovtLockedDuo.Count >= 2) ? (Trunc(ovtLockedDuo[0].display_name, 14) + " + " + Trunc(ovtLockedDuo[1].display_name, 14)) : "duo"); s = "Match found! Joining… " + text + " vs " + text2 + "" + (ApiClient.OvtSoloExtraPick ? " (solo extra pick)" : ""); break; } case "leaving": s = "Leaving queue…"; break; default: s = ((!flag) ? "Not in queue." : "1v2 lobby pending — Leave to dissolve it if nothing happens."); break; } } UIFactory.SetText(txtOvtStatus, s); } RenderOvtLobbySection(); FillOvtRoleBoard(ovtSoloLbContainer, ovtSoloLbRows, ApiClient.CachedOvtLeaderboardSolo, txtOvtSoloLbHeader, "Solo Leaderboard", "#FFB347"); FillOvtRoleBoard(ovtDuoLbContainer, ovtDuoLbRows, ApiClient.CachedOvtLeaderboardDuo, txtOvtDuoLbHeader, "Duo Leaderboard", "#88AAFF"); ToggleInnerScroll(ovtSoloScrollRect, (float)(ApiClient.CachedOvtLeaderboardSolo?.Count ?? 0) * 25f); ToggleInnerScroll(ovtDuoScrollRect, (float)(ApiClient.CachedOvtLeaderboardDuo?.Count ?? 0) * 25f); RefreshOvtRecent(); } private static void FillOvtRoleBoard(GameObject container, List pool, List lb, object headerTxt, string label, string accent) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null) { return; } if (lb == null) { if (headerTxt != null) { UIFactory.SetText(headerTxt, "" + label + " (unranked beta - loading...)"); } return; } if (headerTxt != null) { UIFactory.SetText(headerTxt, (lb.Count == 0) ? ("" + label + " (unranked beta - no games yet)") : $"{label} (unranked beta - {lb.Count} players)"); } while (pool.Count < lb.Count && pool.Count < 100) { object item = UIFactory.CreateText($"{((Object)container).name}R{pool.Count}", container.transform, "", 18f, C_WHITE, 513, (Vector2?)new Vector2(518f, 24f), richText: true, raycastTarget: false); pool.Add(item); } for (int i = 0; i < pool.Count; i++) { object obj = pool[i]; Component val = (Component)((obj is Component) ? obj : null); if (!((Object)(object)val == (Object)null)) { if (i >= lb.Count) { val.gameObject.SetActive(false); continue; } ApiClient.OvtLeaderboardEntry ovtLeaderboardEntry = lb[i]; val.gameObject.SetActive(true); bool flag = ovtLeaderboardEntry.steam_id == MatchTracker.LocalSteamId; string text = ((!string.IsNullOrEmpty(ovtLeaderboardEntry.title_color)) ? ovtLeaderboardEntry.title_color : (flag ? "#88FF88" : "#FFFFFF")); string text2 = ((ovtLeaderboardEntry.rank == 1) ? "#FFD700" : ((ovtLeaderboardEntry.rank == 2) ? "#C0C0C0" : ((ovtLeaderboardEntry.rank == 3) ? "#CD7F32" : "#FFD94D"))); UIFactory.SetText(pool[i], $"#{ovtLeaderboardEntry.rank} {Trunc(ovtLeaderboardEntry.display_name, 14)} {ovtLeaderboardEntry.wins}-{ovtLeaderboardEntry.losses} ({ovtLeaderboardEntry.win_rate:F0}%) Lv{ovtLeaderboardEntry.level}"); } } } private static void RefreshOvtRecent() { //IL_0054: 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_0166: 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) if ((Object)(object)ovtRecentContainer == (Object)null) { return; } List list = ApiClient.CachedOvtRecent ?? new List(); while (ovtRecentRows.Count < Math.Min(list.Count, 10)) { object obj = UIFactory.CreateText($"O1RR{ovtRecentRows.Count}", ovtRecentContainer.transform, "", 18f, C_WHITE, 257, (Vector2?)new Vector2(896f, 27f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(obj, on: false); ovtRecentRows.Add(obj); } float num = 0f; for (int i = 0; i < ovtRecentRows.Count; i++) { object obj2 = ovtRecentRows[i]; Component val = (Component)((obj2 is Component) ? obj2 : null); if ((Object)(object)val == (Object)null) { continue; } if (i >= list.Count) { val.gameObject.SetActive(false); continue; } UIFactory.SetText(ovtRecentRows[i], BuildOvtRecentRowText(list[i], out var lines)); int num2 = lines * 24 + 10; UIFactory.SetPrefH(val.gameObject, num2); RectTransform component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(component.sizeDelta.x, (float)num2); } val.gameObject.SetActive(true); num += (float)(num2 + 2); } ToggleInnerScroll(ovtRecentScrollRect, num); if (txtOvtRecentHeader != null) { UIFactory.SetText(txtOvtRecentHeader, (ApiClient.CachedOvtRecentTotal == 0) ? "Recent 1v2 Games - none yet" : $"Recent 1v2 Games ({ApiClient.CachedOvtRecentTotal} series)"); } int num3 = Math.Max(1, ApiClient.CachedOvtRecentPages); if (txtOvtRecentPage != null) { UIFactory.SetText(txtOvtRecentPage, $"{ovtRecentPageReq + 1}/{num3}"); } if ((Object)(object)ovtRecentPrevBtn != (Object)null) { ovtRecentPrevBtn.SetActive(ovtRecentPageReq > 0); } if ((Object)(object)ovtRecentNextBtn != (Object)null) { ovtRecentNextBtn.SetActive(ovtRecentPageReq + 1 < num3); } } private static string BuildOvtRecentRowText(ApiClient.OvtRecentSeries s, out int lines) { StringBuilder stringBuilder = new StringBuilder(); lines = 1; string text = ""; try { string text2 = ((!string.IsNullOrEmpty(s.completed_at)) ? s.completed_at : s.created_at); if (!string.IsNullOrEmpty(text2) && text2.Length >= 10) { text = DateTime.Parse(text2).ToString("M/d"); } } catch { } string text3 = ((s.status == "completed") ? "" : " (in progress)"); string text4 = (s.solo_extra_pick ? " +pick" : ""); stringBuilder.Append(string.Format("{0} vs {1} + {2} {3}-{4} {5}{6}{7}\n", Trunc(s.solo_name ?? "?", 14), Trunc(s.duo_a_name ?? "?", 14), Trunc(s.duo_b_name ?? "?", 14), s.solo_wins, s.duo_wins, text, text3, text4)); foreach (ApiClient.OvtRecentMatch match in s.matches) { string text5 = ((match.winner_side == 1) ? "solo won" : ((match.winner_side == 2) ? "duo won" : "")); string text6 = ((match.duration_seconds > 0) ? $"{match.duration_seconds / 60}:{match.duration_seconds % 60:00}" : ""); stringBuilder.Append($" - {match.solo_rounds}-{match.duo_rounds} {text5} {text6}\n"); lines++; if (match.cards_by_steam == null || match.cards_by_steam.Count <= 0) { continue; } string[][] array = new string[3][] { new string[3] { s.solo_steam, s.solo_name, "#FFB347" }, new string[3] { s.duo_a_steam, s.duo_a_name, "#88AAFF" }, new string[3] { s.duo_b_steam, s.duo_b_name, "#88AAFF" } }; string[][] array2 = array; foreach (string[] array3 in array2) { if (!string.IsNullOrEmpty(array3[0]) && match.cards_by_steam.TryGetValue(array3[0], out var value) && value != null && value.Count != 0) { string text7 = string.Join(", ", value.ToArray()); if (text7.Length > 90) { text7 = text7.Substring(0, 90) + "..."; } stringBuilder.Append(" " + Trunc(array3[1] ?? "?", 12) + ": " + text7 + "\n"); lines++; } } } if (s.xp_by_steam != null || s.gold_by_steam != null) { string[][] array4 = new string[3][] { new string[3] { s.solo_steam, s.solo_name, "#FFB347" }, new string[3] { s.duo_a_steam, s.duo_a_name, "#88AAFF" }, new string[3] { s.duo_b_steam, s.duo_b_name, "#88AAFF" } }; List list = new List(); string[][] array5 = array4; foreach (string[] array6 in array5) { if (!string.IsNullOrEmpty(array6[0])) { int value2 = 0; int value3 = 0; if (s.xp_by_steam != null) { s.xp_by_steam.TryGetValue(array6[0], out value2); } if (s.gold_by_steam != null) { s.gold_by_steam.TryGetValue(array6[0], out value3); } if (value2 > 0 || value3 > 0) { list.Add(string.Format("{1} +{2}xp", array6[2], Trunc(array6[1] ?? "?", 12), value2) + ((value3 > 0) ? $" +{value3}g" : "")); } } } if (list.Count > 0) { stringBuilder.Append(" series: " + string.Join(" ", list.ToArray()) + "\n"); lines++; } } return stringBuilder.ToString(); } private static void RenderOvtLobbySection() { //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Unknown result type (might be due to invalid IL or missing references) if (txtOvtLobbyHeader == null || txtOvtLobbyBody == null) { return; } List cachedOvtQueueList = ApiClient.CachedOvtQueueList; int num = cachedOvtQueueList?.Count ?? 0; float num2 = 24f; int num3; if (num == 0) { UIFactory.SetText(txtOvtLobbyHeader, "1v2 Lobby (empty)"); UIFactory.SetText(txtOvtLobbyBody, (cachedOvtQueueList == null) ? "Loading…" : "No one in the 1v2 lobby right now."); num3 = 29; } else { UIFactory.SetText(txtOvtLobbyHeader, $"1v2 Lobby ({num} — locks at 3)"); StringBuilder stringBuilder = new StringBuilder(); foreach (ApiClient.OvtQueueListEntry item in cachedOvtQueueList) { string text = ((item.steam_id == MatchTracker.LocalSteamId) ? "" : ""); string text2 = $"{item.rating_1v1} 1v1"; if (item.rating_2v2 > 0) { text2 += $" {item.rating_2v2} 2v2"; } string text3 = ((item.side_assigned != 1) ? ((item.side_assigned != 2) ? ((item.preferred_side != 1) ? ((item.preferred_side != 2) ? "any side" : "wants duo") : "wants solo") : "DUO") : "SOLO"); string text4 = ((item.status == "searching") ? "searching" : ((item.status == "ready_join") ? "locked" : ("" + item.status + ""))); int num4 = item.wait_seconds / 60; int num5 = item.wait_seconds % 60; string text5 = ((num4 > 0) ? $"{num4}m{num5:D2}s" : $"{num5}s"); string text6 = (item.solo_extra_pick ? " +pick" : ""); stringBuilder.Append(" " + text + Trunc(item.display_name, 18) + " " + text2 + " " + text3 + " " + text4 + " " + text5 + "" + text6 + "\n"); } UIFactory.SetText(txtOvtLobbyBody, stringBuilder.ToString()); num3 = (int)((float)num * num2 + 6f); } object obj = txtOvtLobbyBody; Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null) { Component component = val.gameObject.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)num3); UIFactory.tLE.GetProperty("minHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)num3); } RectTransform component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sizeDelta = new Vector2(component2.sizeDelta.x, (float)num3); } } } private static void SwitchTab(int idx) { currentTab = idx; CompetitiveUI.ClearCardHoverRegions(); for (int i = 0; i < 14; i++) { if ((Object)(object)tabPanels[i] != (Object)null) { tabPanels[i].SetActive(i == idx); } } UpdateTabBarVisual(); if (idx == 1) { lbTabRefreshAt = Time.unscaledTime + 30f; ApiClient.FetchLeaderboard(); ApiClient.FetchRecentSeries(); ApiClient.FetchRecentMultimodeSeries(); ApiClient.FetchActiveSeries(); ApiClient.FetchRankTiers(); string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.FetchMyBets(localSteamId); } } if (idx == 2 && ApiClient.CachedCardStats == null) { ApiClient.FetchCardStats(200, MatchTracker.LocalSteamId); } if (idx == 3 && ApiClient.CachedAchievements == null) { string localSteamId2 = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId2) && localSteamId2 != "unknown") { ApiClient.FetchAchievements(localSteamId2); } } if (idx == 4) { string localSteamId3 = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId3) && localSteamId3 != "unknown") { ApiClient.FetchShopItems(localSteamId3); ApiClient.FetchInventory(localSteamId3); } else { ApiClient.FetchShopItems(); } } if (idx == 6) { string localSteamId4 = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId4) && ApiClient.IsAdmin) { ApiClient.FetchFlaggedMatches(localSteamId4); ApiClient.FetchBannedUsers(localSteamId4); ApiClient.FetchAdminRecentSeries(localSteamId4); ApiClient.FetchAdminQuarantine(localSteamId4); } } if (idx == 7) { ApiClient.FetchTournamentCurrent(MatchTracker.LocalSteamId, force: true); ApiClient.FetchSiteTournamentHistory(); ApiClient.FetchActiveSeries(); string localSteamId5 = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId5) && localSteamId5 != "unknown") { ApiClient.FetchPlayerTournaments(localSteamId5); ApiClient.FetchMyBets(localSteamId5); } } if (idx == 8) { if (ApiClient.CachedTeamLeaderboard == null || ApiClient.CachedTeamLeaderboard.Count == 0) { ApiClient.FetchTeamLeaderboard(); } string localSteamId6 = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId6) && localSteamId6 != "unknown") { ApiClient.FetchTeamMatchHistory(localSteamId6); } } if (idx == 9 && ApiClient.CachedLeaderboard == null) { ApiClient.FetchLeaderboard(); } if (idx == 10) { string localSteamId7 = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId7) && localSteamId7 != "unknown" && ApiClient.IsArtist) { ApiClient.FetchArtistItems(localSteamId7); ApiClient.FetchMySubmissions(localSteamId7); ApiClient.FetchArtistSales(localSteamId7); } } if (idx == 11) { ovtTabRefreshAt = Time.unscaledTime + 30f; ovtRecentRefreshAt = Time.unscaledTime + 10f; ApiClient.FetchOvtLeaderboard(); ApiClient.FetchOvtLeaderboard(200, "solo"); ApiClient.FetchOvtLeaderboard(200, "duo"); ApiClient.FetchOvtRecent(ovtRecentPageReq); ApiClient.UpdateOvtQueueList(force: true); } if (idx == 12) { ffaLbRefreshAt = Time.unscaledTime + 30f; ffaRecentRefreshAt = Time.unscaledTime + 10f; ffaBetRefreshAt = Time.unscaledTime + 10f; ApiClient.FetchFfaLeaderboard(200, ffaLbSortReq); ApiClient.FetchFfaRecent(ffaRecentPageReq); ApiClient.FetchFfaBettable(MatchTracker.LocalSteamId); ApiClient.UpdateFfaQueueList(force: true); } if (idx == 13) { homeTabRefreshAt = Time.unscaledTime + 15f; ApiClient.FetchOnlinePlayers(); ApiClient.FetchNewestCosmetics(); ApiClient.FetchReleaseNotes(); } dirty = true; } private static HomeCosRow CreateHomeCosRow(Transform parent, int idx) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) HomeCosRow homeCosRow = new HomeCosRow(); homeCosRow.root = new GameObject($"hcos{idx}"); homeCosRow.root.transform.SetParent(parent, false); homeCosRow.root.AddComponent(); UIFactory.AddHLG(homeCosRow.root, 8f, 2, 2); UIFactory.AddLE(homeCosRow.root, -1f, 80f, -1f, 80f, -1f, 0f); homeCosRow.artGO = new GameObject("art"); homeCosRow.artGO.transform.SetParent(homeCosRow.root.transform, false); homeCosRow.artGO.AddComponent(); UIFactory.AddLE(homeCosRow.artGO, 76f, -1f, 76f, 76f, 0f, 0f); if (UIFactory.tImage != null) { homeCosRow.artImg = homeCosRow.artGO.AddComponent(UIFactory.tImage); try { UIFactory.tImage.GetProperty("preserveAspect", BindingFlags.Instance | BindingFlags.Public)?.SetValue(homeCosRow.artImg, true); } catch { } try { UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(homeCosRow.artImg, false); } catch { } } homeCosRow.txt = UIFactory.CreateText("t", homeCosRow.root.transform, "", 17f, C_WHITE, 513, (Vector2?)new Vector2(310f, 76f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(homeCosRow.txt, on: false); homeCosRow.root.SetActive(false); return homeCosRow; } private static Sprite GetHomeLogoSprite() { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) if (_homeLogoTried) { return _homeLogoSprite; } _homeLogoTried = true; try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = null; string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith("logo.png", StringComparison.OrdinalIgnoreCase)) { text = text2; break; } } if (text == null) { Plugin.Log.LogWarning((object)"[HOME] embedded logo resource not found"); return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int j = 0; j < array.Length; j += num) { num = stream.Read(array, j, array.Length - j); if (num <= 0) { break; } } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { return null; } ((Object)val).hideFlags = (HideFlags)61; _homeLogoSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)_homeLogoSprite).hideFlags = (HideFlags)61; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[HOME] logo load failed: " + ex.Message)); } return _homeLogoSprite; } private static string HomeSan(string s) { return string.IsNullOrEmpty(s) ? "" : s.Replace("<", "[").Replace(">", "]"); } private static string FmtAgo(int minutes) { if (minutes < 60) { return "recently online"; } return $"{minutes / 60}h ago"; } private static string HomeTitleSpan(ApiClient.OnlinePlayerEntry p) { if (string.IsNullOrEmpty(p.title)) { return ""; } string text = (string.IsNullOrEmpty(p.titleColor) ? "#FFFFFF" : p.titleColor); return " [" + HomeSan(p.title) + "]"; } private static GameObject BuildHomeTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Expected O, but got Unknown //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Expected O, but got Unknown //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Expected O, but got Unknown //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_0498: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_05d1: Unknown result type (might be due to invalid IL or missing references) //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_05fc: Unknown result type (might be due to invalid IL or missing references) //IL_0603: Expected O, but got Unknown //IL_066f: Unknown result type (might be due to invalid IL or missing references) //IL_0674: Unknown result type (might be due to invalid IL or missing references) //IL_06a2: Unknown result type (might be due to invalid IL or missing references) //IL_06cc: Unknown result type (might be due to invalid IL or missing references) //IL_06e0: Unknown result type (might be due to invalid IL or missing references) //IL_068d: Unknown result type (might be due to invalid IL or missing references) //IL_0692: Unknown result type (might be due to invalid IL or missing references) //IL_0698: Expected O, but got Unknown //IL_0754: Unknown result type (might be due to invalid IL or missing references) //IL_07ca: Unknown result type (might be due to invalid IL or missing references) //IL_07de: Unknown result type (might be due to invalid IL or missing references) //IL_0806: Unknown result type (might be due to invalid IL or missing references) //IL_081a: Unknown result type (might be due to invalid IL or missing references) //IL_08b9: Unknown result type (might be due to invalid IL or missing references) //IL_08c0: Expected O, but got Unknown //IL_0922: Unknown result type (might be due to invalid IL or missing references) //IL_0989: Unknown result type (might be due to invalid IL or missing references) //IL_099d: Unknown result type (might be due to invalid IL or missing references) //IL_0a0e: Unknown result type (might be due to invalid IL or missing references) //IL_0a22: Unknown result type (might be due to invalid IL or missing references) //IL_0a60: Unknown result type (might be due to invalid IL or missing references) //IL_0ad6: Unknown result type (might be due to invalid IL or missing references) //IL_0aea: Unknown result type (might be due to invalid IL or missing references) //IL_0b71: Unknown result type (might be due to invalid IL or missing references) //IL_0b85: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Home"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 6f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val2 = new GameObject("HomeHdr"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddHLG(val2, 16f, 0, 0, 0, 0, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(val2, -1f, 112f, -1f, 112f, -1f, 0f); GameObject val3 = new GameObject("S"); val3.transform.SetParent(val2.transform, false); val3.AddComponent(); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, 1f); GameObject val4 = new GameObject("HomeLogo"); val4.transform.SetParent(val2.transform, false); val4.AddComponent(); UIFactory.AddLE(val4, 104f, 104f, 104f, 104f, 0f, 0f); Sprite homeLogoSprite = GetHomeLogoSprite(); if ((Object)(object)homeLogoSprite != (Object)null && UIFactory.tImage != null) { Component obj = val4.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, homeLogoSprite); UIFactory.tImage.GetProperty("preserveAspect", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, true); UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, false); } GameObject val5 = new GameObject("HomeHdrTxt"); val5.transform.SetParent(val2.transform, false); val5.AddComponent(); UIFactory.AddVLG(val5); UIFactory.AddLE(val5, -1f, -1f, 460f, -1f, 0f, 0f); UIFactory.CreateText("HT", val5.transform, "SID'S COMPETITIVE ROUNDS", 30f, C_WHITE, 513, (Vector2?)new Vector2(460f, 40f), richText: true, raycastTarget: false); UIFactory.CreateText("HS", val5.transform, "Ranked 1v1 - 2v2 - tournaments - cosmetics v1.35.5", 15f, C_LABEL, 513, (Vector2?)new Vector2(460f, 22f), richText: true, raycastTarget: false); txtHomeOnlineHdr = UIFactory.CreateText("HO", val5.transform, "", 17f, C_GREEN, 513, (Vector2?)new Vector2(460f, 26f), richText: true, raycastTarget: false); GameObject val6 = new GameObject("S"); val6.transform.SetParent(val2.transform, false); val6.AddComponent(); UIFactory.AddLE(val6, -1f, -1f, -1f, -1f, 1f); GameObject val7 = new GameObject("HomeCols"); val7.transform.SetParent(val.transform, false); val7.AddComponent(); UIFactory.AddHLG(val7, 8f); UIFactory.AddLE(val7, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val8 = new GameObject("HLeft"); val8.transform.SetParent(val7.transform, false); val8.AddComponent(); UIFactory.AddVLG(val8, 4f); UIFactory.AddLE(val8, 360f, -1f, 420f, -1f, 0f, 1f); GameObject val9 = UIFactory.CreatePanel("HOn", val8.transform, C_PANEL); UIFactory.AddVLG(val9, 2f, 10, 10, 6, 6); UIFactory.AddLE(val9, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.CreateText("HOnH", val9.transform, "Players", 19f, C_SUB, 257, (Vector2?)new Vector2(380f, 28f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("HOnSV", val9.transform, 0f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); txtHomeOnline = UIFactory.CreateText("HOnT", scrollViewRefs.content.transform, "Loading...", 15f, C_WHITE, 257, (Vector2?)new Vector2(380f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtHomeOnline, on: true); UIFactory.SetTextAutoHeight(txtHomeOnline); GameObject val10 = UIFactory.CreatePanel("LkB", val8.transform, C_PANEL); UIFactory.AddVLG(val10, 4f, 10, 10, 6, 6); UIFactory.AddLE(val10, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("LkL", val10.transform, "Discord Link", 19f, new Color(0.55f, 0.55f, 0.95f), 257, (Vector2?)new Vector2(340f, 28f), richText: true, raycastTarget: false); GameObject val11 = new GameObject("LkR"); val11.transform.SetParent(val10.transform, false); val11.AddComponent(); UIFactory.AddHLG(val11, 8f); UIFactory.AddLE(val11, -1f, -1f, -1f, 28f); Transform transform = val11.transform; Color c_WHITE = C_WHITE; Color c_BTN = C_BTN; object obj2 = <>c.<>9__390_0; if (obj2 == null) { UnityAction val12 = delegate { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.GenerateLinkCode(localSteamId); } }; <>c.<>9__390_0 = val12; obj2 = (object)val12; } linkCodeBtn = UIFactory.CreateButton("LkBtn", transform, "Get Link Code", 15f, c_WHITE, c_BTN, (UnityAction)obj2, (Vector2?)new Vector2(130f, 26f)); txtLinkCode = UIFactory.CreateText("LkC", val11.transform, "Type !link CODE in Discord", 15f, C_DIM, 257, (Vector2?)new Vector2(240f, 26f), richText: true, raycastTarget: true); object obj3 = txtLinkCode; Component val13 = (Component)((obj3 is Component) ? obj3 : null); if ((Object)(object)val13 != (Object)null) { ClickHandler clickHandler = val13.gameObject.AddComponent(); clickHandler.onClick = delegate { if (ClickGuard.Claim()) { discordRevealed = !discordRevealed; dirty = true; } }; } GameObject val14 = UIFactory.CreatePanel("HCos", val8.transform, C_PANEL); UIFactory.AddVLG(val14, 3f, 10, 10, 6, 6); UIFactory.AddLE(val14, -1f, 280f, -1f, 340f, -1f, 0f); UIFactory.CreateText("HCosH", val14.transform, "Newest Cosmetics", 22f, new Color(0.85f, 0.6f, 1f), 257, (Vector2?)new Vector2(380f, 30f), richText: true, raycastTarget: false); txtHomeCosmetics = UIFactory.CreateText("HCosT", val14.transform, "Loading...", 15f, C_DIM, 257, (Vector2?)new Vector2(380f, 22f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("HCosSV", val14.transform); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); homeCosRows.Clear(); for (int num = 0; num < 12; num++) { homeCosRows.Add(CreateHomeCosRow(scrollViewRefs2.content.transform, num)); } GameObject val15 = new GameObject("HRight"); val15.transform.SetParent(val7.transform, false); val15.AddComponent(); UIFactory.AddVLG(val15, 4f); UIFactory.AddLE(val15, -1f, -1f, -1f, -1f, 1f, 1f); GameObject val16 = UIFactory.CreatePanel("HRel", val15.transform, C_PANEL); UIFactory.AddVLG(val16, 2f, 10, 10, 6, 6); UIFactory.AddLE(val16, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.CreateText("HRelH", val16.transform, "Latest Releases", 19f, C_GOLD, 257, (Vector2?)new Vector2(400f, 28f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("HRelSV", val16.transform, 0f); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); txtHomeReleases = UIFactory.CreateText("HRelT", scrollViewRefs3.content.transform, "Loading release notes...", 14f, C_WHITE, 257, (Vector2?)new Vector2(560f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtHomeReleases, on: true); UIFactory.SetTextAutoHeight(txtHomeReleases); GameObject val17 = UIFactory.CreatePanel("CB", val15.transform, C_PANEL); UIFactory.AddVLG(val17, 4f, 10, 10, 6, 6); UIFactory.AddLE(val17, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("CH", val17.transform, "Chat (press T to send)", 17f, new Color(0.7f, 0.85f, 1f), 257, (Vector2?)new Vector2(340f, 26f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs4 = UIFactory.CreateScrollView("ChSV", val17.transform, 0f); UIFactory.AddLE(scrollViewRefs4.scrollGO, -1f, 240f, -1f, 240f, -1f, 0f); chatScrollRect = scrollViewRefs4.scrollGO.GetComponent(UIFactory.tScrollRect); txtChatLog = UIFactory.CreateText("ChLog", scrollViewRefs4.content.transform, "No messages yet. Anyone chatting here or in #scr-discussion on Discord will appear.", 14f, C_WHITE, 257, (Vector2?)new Vector2(560f, 400f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtChatLog, on: true); object obj4 = txtChatLog; object obj5 = ((obj4 is Component) ? obj4 : null); Component val18 = ((obj5 != null) ? ((Component)obj5).gameObject.GetComponent(UIFactory.tLE) : null); if ((Object)(object)val18 != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(val18, -1f); } return val; } private static void RefreshHomeTab() { //IL_0849: Unknown result type (might be due to invalid IL or missing references) //IL_08e3: Unknown result type (might be due to invalid IL or missing references) ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; if ((Object)(object)linkCodeBtn != (Object)null && txtLinkCode != null) { bool flag = cachedPlayerStats != null && !string.IsNullOrEmpty(cachedPlayerStats.discord_id); linkCodeBtn.SetActive(!flag); if (flag) { string text = ((!string.IsNullOrEmpty(cachedPlayerStats.discord_username)) ? ("@" + cachedPlayerStats.discord_username) : ("ID " + cachedPlayerStats.discord_id)); string text2 = (discordRevealed ? text : "***** (click to show)"); UIFactory.SetText(txtLinkCode, "Linked to Discord (" + text2 + ")"); } } int num = ((ApiClient.CachedOnlineListCount > 0) ? ApiClient.CachedOnlineListCount : ApiClient.CachedOnlineCount); if (txtHomeOnlineHdr != null) { UIFactory.SetText(txtHomeOnlineHdr, (num > 0) ? string.Format("{0} player{1} online now", num, (num == 1) ? "" : "s") : ""); } if (txtHomeOnline != null) { StringBuilder stringBuilder = new StringBuilder(); List cachedOnlinePlayers = ApiClient.CachedOnlinePlayers; List cachedRecentPlayers = ApiClient.CachedRecentPlayers; stringBuilder.Append("Online now\n"); if (cachedOnlinePlayers == null) { stringBuilder.Append("Loading...\n"); } else if (cachedOnlinePlayers.Count == 0) { stringBuilder.Append("Nobody visible right now.\n"); } else { foreach (ApiClient.OnlinePlayerEntry item in cachedOnlinePlayers) { stringBuilder.Append($"* {HomeSan(item.name)}{HomeTitleSpan(item)} {item.rating}\n"); } } stringBuilder.Append("\nRecently online\n"); if (cachedRecentPlayers == null || cachedRecentPlayers.Count == 0) { stringBuilder.Append("-\n"); } else { foreach (ApiClient.OnlinePlayerEntry item2 in cachedRecentPlayers) { stringBuilder.Append($"{HomeSan(item2.name)}{HomeTitleSpan(item2)} {item2.rating} {FmtAgo(item2.minutesAgo)}\n"); } } stringBuilder.Append("\nHide yourself here: Settings -> Appear offline."); UIFactory.SetText(txtHomeOnline, stringBuilder.ToString()); } if (txtHomeReleases != null) { List cachedReleaseNotes = ApiClient.CachedReleaseNotes; if (cachedReleaseNotes == null) { UIFactory.SetText(txtHomeReleases, "Loading release notes..."); } else if (cachedReleaseNotes.Count == 0) { UIFactory.SetText(txtHomeReleases, "Release notes unavailable right now."); } else { StringBuilder stringBuilder2 = new StringBuilder(); foreach (ApiClient.ReleaseNoteEntry item3 in cachedReleaseNotes) { stringBuilder2.Append("" + HomeSan(item3.tag) + ""); if (!string.IsNullOrEmpty(item3.title) && item3.title != item3.tag) { stringBuilder2.Append(" " + HomeSan(item3.title) + ""); } if (!string.IsNullOrEmpty(item3.date)) { stringBuilder2.Append(" " + item3.date + ""); } stringBuilder2.Append('\n'); if (!string.IsNullOrEmpty(item3.body)) { stringBuilder2.Append("" + item3.body + "\n"); } stringBuilder2.Append('\n'); } UIFactory.SetText(txtHomeReleases, stringBuilder2.ToString()); } } List cachedNewestCosmetics = ApiClient.CachedNewestCosmetics; string text3 = "Grab them in the Shop tab."; if (cachedNewestCosmetics != null && cachedNewestCosmetics.Count > 0) { List list = new List(); foreach (ApiClient.NewestCosmeticEntry item4 in cachedNewestCosmetics) { if (!string.IsNullOrEmpty(item4.added) && !list.Contains(item4.added)) { list.Add(item4.added); } } if (list.Count >= 2) { text3 = "Updates of " + list[0] + " & " + list[1] + " - grab them in the Shop tab."; } else if (list.Count == 1) { text3 = "Update of " + list[0] + " - grab them in the Shop tab."; } } if (txtHomeCosmetics != null) { UIFactory.SetText(txtHomeCosmetics, (cachedNewestCosmetics == null) ? "Loading..." : ((cachedNewestCosmetics.Count == 0) ? "None yet." : text3)); } Color val = default(Color); for (int i = 0; i < homeCosRows.Count; i++) { HomeCosRow homeCosRow = homeCosRows[i]; if (cachedNewestCosmetics == null || i >= cachedNewestCosmetics.Count) { if (homeCosRow.artImg != null) { TrackAnimatedThumb(homeCosRow.artImg, null, 0f); } homeCosRow.root.SetActive(false); continue; } ApiClient.NewestCosmeticEntry newestCosmeticEntry = cachedNewestCosmetics[i]; if ((newestCosmeticEntry.kind ?? "") == "face" && (Object)(object)CustomCosmetics.GetShopSprite(newestCosmeticEntry.sku) == (Object)null) { if (homeCosRow.artImg != null) { TrackAnimatedThumb(homeCosRow.artImg, null, 0f); } homeCosRow.root.SetActive(false); continue; } string text4 = ((!string.IsNullOrEmpty(newestCosmeticEntry.previewColor) && newestCosmeticEntry.previewColor.StartsWith("#")) ? newestCosmeticEntry.previewColor : "#FFFFFF"); string s = (newestCosmeticEntry.kind ?? "").Replace('_', ' '); string text5 = ((!string.IsNullOrEmpty(newestCosmeticEntry.artistName)) ? (" by " + HomeSan(newestCosmeticEntry.artistName) + "") : ""); string text6 = ((!string.IsNullOrEmpty(newestCosmeticEntry.added)) ? (" " + newestCosmeticEntry.added + "") : ""); string text7 = (newestCosmeticEntry.onSale ? $"{newestCosmeticEntry.price}g" : "coming soon!"); UIFactory.SetText(homeCosRow.txt, "" + HomeSan(newestCosmeticEntry.name) + " " + text7 + "\n(" + HomeSan(s) + ", " + HomeSan(newestCosmeticEntry.rarity) + ")" + text5 + text6); if (homeCosRow.artImg != null) { PropertyInfo property = UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property2 = UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public); Sprite shopSprite = CustomCosmetics.GetShopSprite(newestCosmeticEntry.sku); if ((Object)(object)shopSprite != (Object)null) { try { property?.SetValue(homeCosRow.artImg, shopSprite); property2?.SetValue(homeCosRow.artImg, Color.white); } catch { } float fps; Sprite[] shopFrames = CustomCosmetics.GetShopFrames(newestCosmeticEntry.sku, out fps); TrackAnimatedThumb(homeCosRow.artImg, shopFrames, fps); } else { if (!ColorUtility.TryParseHtmlString(text4, ref val)) { ((Color)(ref val))..ctor(0.4f, 0.42f, 0.5f); } val.a = 1f; try { property?.SetValue(homeCosRow.artImg, null); property2?.SetValue(homeCosRow.artImg, val); } catch { } TrackAnimatedThumb(homeCosRow.artImg, null, 0f); } } homeCosRow.root.SetActive(true); } RefreshChatLog(); } private static void MaybeRefreshHomeTab() { if (currentTab == 13 && !(Time.unscaledTime < homeTabRefreshAt)) { homeTabRefreshAt = Time.unscaledTime + 15f; ApiClient.FetchOnlinePlayers(); } } private static GameObject BuildMyStatsTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Expected O, but got Unknown //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Expected O, but got Unknown //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Expected O, but got Unknown //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_0486: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04d5: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_056f: Unknown result type (might be due to invalid IL or missing references) //IL_0597: Unknown result type (might be due to invalid IL or missing references) //IL_05ab: Unknown result type (might be due to invalid IL or missing references) //IL_05d7: Unknown result type (might be due to invalid IL or missing references) //IL_05eb: Unknown result type (might be due to invalid IL or missing references) //IL_0617: Unknown result type (might be due to invalid IL or missing references) //IL_062b: Unknown result type (might be due to invalid IL or missing references) //IL_0657: Unknown result type (might be due to invalid IL or missing references) //IL_066b: Unknown result type (might be due to invalid IL or missing references) //IL_0697: Unknown result type (might be due to invalid IL or missing references) //IL_06ab: Unknown result type (might be due to invalid IL or missing references) //IL_06d7: Unknown result type (might be due to invalid IL or missing references) //IL_06eb: Unknown result type (might be due to invalid IL or missing references) //IL_0717: Unknown result type (might be due to invalid IL or missing references) //IL_072b: Unknown result type (might be due to invalid IL or missing references) //IL_0757: Unknown result type (might be due to invalid IL or missing references) //IL_076b: Unknown result type (might be due to invalid IL or missing references) //IL_0797: Unknown result type (might be due to invalid IL or missing references) //IL_07ab: Unknown result type (might be due to invalid IL or missing references) //IL_07d7: Unknown result type (might be due to invalid IL or missing references) //IL_07eb: Unknown result type (might be due to invalid IL or missing references) //IL_0817: Unknown result type (might be due to invalid IL or missing references) //IL_082b: Unknown result type (might be due to invalid IL or missing references) //IL_0857: Unknown result type (might be due to invalid IL or missing references) //IL_086b: Unknown result type (might be due to invalid IL or missing references) //IL_088c: Unknown result type (might be due to invalid IL or missing references) //IL_0902: Unknown result type (might be due to invalid IL or missing references) //IL_0916: Unknown result type (might be due to invalid IL or missing references) //IL_093e: Unknown result type (might be due to invalid IL or missing references) //IL_0952: Unknown result type (might be due to invalid IL or missing references) //IL_097e: Unknown result type (might be due to invalid IL or missing references) //IL_0992: Unknown result type (might be due to invalid IL or missing references) //IL_09be: Unknown result type (might be due to invalid IL or missing references) //IL_09d2: Unknown result type (might be due to invalid IL or missing references) //IL_0a0d: Unknown result type (might be due to invalid IL or missing references) //IL_0a21: Unknown result type (might be due to invalid IL or missing references) //IL_0a3c: Unknown result type (might be due to invalid IL or missing references) //IL_0a46: Expected O, but got Unknown //IL_0a84: Unknown result type (might be due to invalid IL or missing references) //IL_0a8b: Expected O, but got Unknown //IL_0aec: Unknown result type (might be due to invalid IL or missing references) //IL_0b51: Unknown result type (might be due to invalid IL or missing references) //IL_0b65: Unknown result type (might be due to invalid IL or missing references) //IL_0b9c: Unknown result type (might be due to invalid IL or missing references) //IL_0bb0: Unknown result type (might be due to invalid IL or missing references) //IL_0c5d: Unknown result type (might be due to invalid IL or missing references) //IL_0c64: Expected O, but got Unknown //IL_0cbf: Unknown result type (might be due to invalid IL or missing references) //IL_0cc6: Expected O, but got Unknown //IL_0d1f: Unknown result type (might be due to invalid IL or missing references) //IL_0d24: Unknown result type (might be due to invalid IL or missing references) //IL_0d52: Unknown result type (might be due to invalid IL or missing references) //IL_0d7c: Unknown result type (might be due to invalid IL or missing references) //IL_0d90: Unknown result type (might be due to invalid IL or missing references) //IL_0dbc: Unknown result type (might be due to invalid IL or missing references) //IL_0dc1: Unknown result type (might be due to invalid IL or missing references) //IL_0d3d: Unknown result type (might be due to invalid IL or missing references) //IL_0d42: Unknown result type (might be due to invalid IL or missing references) //IL_0d48: Expected O, but got Unknown //IL_0def: Unknown result type (might be due to invalid IL or missing references) //IL_0e08: Unknown result type (might be due to invalid IL or missing references) //IL_0e0f: Expected O, but got Unknown //IL_0e68: Unknown result type (might be due to invalid IL or missing references) //IL_0e6d: Unknown result type (might be due to invalid IL or missing references) //IL_0dda: Unknown result type (might be due to invalid IL or missing references) //IL_0ddf: Unknown result type (might be due to invalid IL or missing references) //IL_0de5: Expected O, but got Unknown //IL_0e97: Unknown result type (might be due to invalid IL or missing references) //IL_0ec6: Unknown result type (might be due to invalid IL or missing references) //IL_0f2b: Unknown result type (might be due to invalid IL or missing references) //IL_0f3f: Unknown result type (might be due to invalid IL or missing references) //IL_0e82: Unknown result type (might be due to invalid IL or missing references) //IL_0e87: Unknown result type (might be due to invalid IL or missing references) //IL_0e8d: Expected O, but got Unknown //IL_0fe8: Unknown result type (might be due to invalid IL or missing references) //IL_0fef: Expected O, but got Unknown //IL_104a: Unknown result type (might be due to invalid IL or missing references) //IL_1051: Expected O, but got Unknown //IL_10aa: Unknown result type (might be due to invalid IL or missing references) //IL_10af: Unknown result type (might be due to invalid IL or missing references) //IL_10dd: Unknown result type (might be due to invalid IL or missing references) //IL_1107: Unknown result type (might be due to invalid IL or missing references) //IL_111b: Unknown result type (might be due to invalid IL or missing references) //IL_1147: Unknown result type (might be due to invalid IL or missing references) //IL_114c: Unknown result type (might be due to invalid IL or missing references) //IL_10c8: Unknown result type (might be due to invalid IL or missing references) //IL_10cd: Unknown result type (might be due to invalid IL or missing references) //IL_10d3: Expected O, but got Unknown //IL_117a: Unknown result type (might be due to invalid IL or missing references) //IL_1193: Unknown result type (might be due to invalid IL or missing references) //IL_119a: Expected O, but got Unknown //IL_11f3: Unknown result type (might be due to invalid IL or missing references) //IL_11f8: Unknown result type (might be due to invalid IL or missing references) //IL_1165: Unknown result type (might be due to invalid IL or missing references) //IL_116a: Unknown result type (might be due to invalid IL or missing references) //IL_1170: Expected O, but got Unknown //IL_1222: Unknown result type (might be due to invalid IL or missing references) //IL_120d: Unknown result type (might be due to invalid IL or missing references) //IL_1212: Unknown result type (might be due to invalid IL or missing references) //IL_1218: Expected O, but got Unknown GameObject val = new GameObject("MyStatsOuter"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(0, val.transform, asFirst: true); GameObject val2 = new GameObject("MyStats"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddHLG(val2, 8f); UIFactory.AddLE(val2, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("MSLeftSV", val2.transform, 4f); UIFactory.AddLE(scrollViewRefs.scrollGO, 340f, -1f, 380f, -1f, 1f, 1f); GameObject content = scrollViewRefs.content; UIFactory.AddLE(content, -1f, -1f, -1f, -1f, -1f, 0f); GameObject val3 = UIFactory.CreatePanel("RB", content.transform, C_PANEL); UIFactory.AddVLG(val3, 2f, 10, 10, 6, 6); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, -1f, 0f); object t = UIFactory.CreateText("RL", val3.transform, "Glicko-2 Rating", 19f, C_SUB, 257, (Vector2?)new Vector2(250f, 28f), richText: true, raycastTarget: false); UIFactory.SetCharSpacing(t, 1f); GameObject val4 = new GameObject("RR"); val4.transform.SetParent(val3.transform, false); val4.AddComponent(); UIFactory.AddHLG(val4, 12f); UIFactory.AddLE(val4, -1f, -1f, -1f, 38f); txtRating = UIFactory.CreateText("Rat", val4.transform, "1500", 30f, C_WHITE, 513, (Vector2?)new Vector2(110f, 38f), richText: true, raycastTarget: false); UIFactory.SetBold(txtRating, b: true); txtRD = UIFactory.CreateText("RD", val4.transform, "RD: 350", 18f, C_LABEL, 513, (Vector2?)new Vector2(240f, 38f), richText: true, raycastTarget: false); GameObject val5 = UIFactory.CreatePanel("XB", content.transform, C_PANEL); UIFactory.AddVLG(val5, 2f, 10, 10, 6, 6); UIFactory.AddLE(val5, -1f, -1f, -1f, -1f, -1f, 0f); GameObject val6 = new GameObject("LR"); val6.transform.SetParent(val5.transform, false); val6.AddComponent(); UIFactory.AddHLG(val6, 8f); UIFactory.AddLE(val6, -1f, -1f, -1f, 28f); txtLevel = UIFactory.CreateText("Lv", val6.transform, "Level 1", 19f, C_BLUE, 513, (Vector2?)new Vector2(100f, 28f), richText: true, raycastTarget: false); UIFactory.SetBold(txtLevel, b: true); txtXPProg = UIFactory.CreateText("XPP", val6.transform, "", 16f, C_LABEL, 513, (Vector2?)new Vector2(130f, 28f), richText: true, raycastTarget: false); GameObject val7 = new GameObject("S"); val7.transform.SetParent(val6.transform, false); val7.AddComponent(); UIFactory.AddLE(val7, -1f, -1f, -1f, -1f, 1f); txtTotalXP = UIFactory.CreateText("TXP", val6.transform, "0 XP", 16f, C_LABEL, 516, (Vector2?)new Vector2(110f, 28f), richText: true, raycastTarget: false); xpFill = UIFactory.CreateFillBar("XP", val5.transform, new Color(0.2f, 0.2f, 0.25f, 0.8f), new Color(0.3f, 0.7f, 1f, 0.9f), 10f); GameObject val8 = UIFactory.CreatePanel("RecB", content.transform, C_PANEL); UIFactory.AddVLG(val8, 1f, 10, 10, 6, 6); UIFactory.AddLE(val8, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("RecL", val8.transform, "Record", 19f, C_SUB, 257, (Vector2?)new Vector2(340f, 28f), richText: true, raycastTarget: false); txtRankedRec = UIFactory.CreateText("RR", val8.transform, "", 16f, C_WHITE, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); txtRankedStrk = UIFactory.CreateText("RS", val8.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(340f, 44f), richText: true, raycastTarget: false); txtTeam2v2Rec = UIFactory.CreateText("T2", val8.transform, "", 16f, C_WHITE, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); txtTeam2v2Strk = UIFactory.CreateText("T2S", val8.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(340f, 22f), richText: true, raycastTarget: false); txtOvtRec = UIFactory.CreateText("O12", val8.transform, "", 16f, C_WHITE, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); txtFfaRec = UIFactory.CreateText("FFR", val8.transform, "", 16f, C_WHITE, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); txtFfaExtra = UIFactory.CreateText("FFX", val8.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(340f, 22f), richText: true, raycastTarget: false); txtCasualRec = UIFactory.CreateText("CR", val8.transform, "", 16f, C_WHITE, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); txtCasualStrk = UIFactory.CreateText("CS", val8.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(340f, 22f), richText: true, raycastTarget: false); txtSweeps = UIFactory.CreateText("SW", val8.transform, "", 16f, C_WHITE, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); txtTotalRec = UIFactory.CreateText("TR", val8.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(340f, 22f), richText: true, raycastTarget: false); txtAccuracy = UIFactory.CreateText("AC", val8.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(340f, 44f), richText: true, raycastTarget: false); GameObject val9 = UIFactory.CreatePanel("SB", content.transform, C_PANEL); UIFactory.AddVLG(val9, 3f, 10, 10, 8, 8); UIFactory.AddLE(val9, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("SL", val9.transform, "Session Info", 19f, new Color(0.7f, 0.8f, 1f), 257, (Vector2?)new Vector2(340f, 28f), richText: true, raycastTarget: false); txtSessionSum = UIFactory.CreateText("SS", val9.transform, "No games this session", 17f, C_DIM, 257, (Vector2?)new Vector2(340f, 26f), richText: true, raycastTarget: false); txtSessionSplit = UIFactory.CreateText("SSp", val9.transform, "", 16f, C_LABEL, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); txtSessionSweeps = UIFactory.CreateText("SSw", val9.transform, "", 16f, C_WHITE, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); txtSessionOppLifetime = UIFactory.CreateText("SOL", val9.transform, "", 15f, new Color(0.6f, 0.75f, 1f), 257, (Vector2?)new Vector2(340f, 22f), richText: true, raycastTarget: false); sessionOppContainer = new GameObject("SOC"); sessionOppContainer.transform.SetParent(val9.transform, false); sessionOppContainer.AddComponent(); UIFactory.AddVLG(sessionOppContainer, 1f); GameObject val10 = new GameObject("Right"); val10.transform.SetParent(val2.transform, false); val10.AddComponent(); UIFactory.AddVLG(val10, 4f); UIFactory.AddLE(val10, -1f, -1f, -1f, -1f, 1f, 1f); GameObject val11 = UIFactory.CreatePanel("RkB", val10.transform, C_PANEL); UIFactory.AddVLG(val11, 1f, 8, 8, 6, 6); UIFactory.AddLE(val11, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.CreateText("RkH", val11.transform, "Ranked History", 21f, C_GOLD, 257, (Vector2?)new Vector2(250f, 30f), richText: true, raycastTarget: false); txtOppSummary = UIFactory.CreateText("OS", val11.transform, "", 15f, new Color(0.7f, 0.8f, 1f), 257, (Vector2?)new Vector2(500f, 22f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("RkSV", val11.transform, 1f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); rankedContainer = scrollViewRefs2.content; for (int i = 0; i < 15; i++) { rankedRows.Add(CreateHistoryRow(rankedContainer.transform, $"rr{i}")); } GameObject val12 = new GameObject("RPg"); val12.transform.SetParent(val11.transform, false); val12.AddComponent(); UIFactory.AddHLG(val12, 6f); UIFactory.AddLE(val12, -1f, -1f, -1f, 20f, -1f, 0f); GameObject val13 = new GameObject("S"); val13.transform.SetParent(val12.transform, false); val13.AddComponent(); UIFactory.AddLE(val13, -1f, -1f, -1f, -1f, 1f); Transform transform = val12.transform; Color c_LABEL = C_LABEL; Color c_BTN = C_BTN; object obj = <>c.<>9__393_0; if (obj == null) { UnityAction val14 = delegate { if (rankedPage > 0) { rankedPage--; dirty = true; } }; <>c.<>9__393_0 = val14; obj = (object)val14; } rPrev = UIFactory.CreateButton("rP", transform, "< Prev", 10f, c_LABEL, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(50f, 18f)); txtRankedPage = UIFactory.CreateText("rPI", val12.transform, "", 10f, C_LABEL, 514, (Vector2?)new Vector2(35f, 18f), richText: true, raycastTarget: false); Transform transform2 = val12.transform; Color c_LABEL2 = C_LABEL; Color c_BTN2 = C_BTN; object obj2 = <>c.<>9__393_1; if (obj2 == null) { UnityAction val15 = delegate { rankedPage++; dirty = true; }; <>c.<>9__393_1 = val15; obj2 = (object)val15; } rNext = UIFactory.CreateButton("rN", transform2, "Next >", 10f, c_LABEL2, c_BTN2, (UnityAction)obj2, (Vector2?)new Vector2(50f, 18f)); GameObject val16 = new GameObject("S"); val16.transform.SetParent(val12.transform, false); val16.AddComponent(); UIFactory.AddLE(val16, -1f, -1f, -1f, -1f, 1f); Transform transform3 = val12.transform; Color c_LABEL3 = C_LABEL; Color c_BTN3 = C_BTN; object obj3 = <>O.<0>__ToggleHistoryCardMode; if (obj3 == null) { UnityAction val17 = ToggleHistoryCardMode; <>O.<0>__ToggleHistoryCardMode = val17; obj3 = (object)val17; } rCardModeBtn = UIFactory.CreateButton("rCm", transform3, "", 10f, c_LABEL3, c_BTN3, (UnityAction)obj3, (Vector2?)new Vector2(100f, 18f)); rCardModeTxt = UIFactory.GetButtonText(rCardModeBtn); GameObject val18 = UIFactory.CreatePanel("CsB", val10.transform, C_PANEL); UIFactory.AddVLG(val18, 1f, 8, 8, 6, 6); UIFactory.AddLE(val18, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.CreateText("CsH", val18.transform, "Casual History", 21f, C_SUB, 257, (Vector2?)new Vector2(250f, 30f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("CsSV", val18.transform, 1f); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); casualContainer = scrollViewRefs3.content; for (int num = 0; num < 12; num++) { casualRows.Add(CreateHistoryRow(casualContainer.transform, $"cr{num}")); } GameObject val19 = new GameObject("CPg"); val19.transform.SetParent(val18.transform, false); val19.AddComponent(); UIFactory.AddHLG(val19, 6f); UIFactory.AddLE(val19, -1f, -1f, -1f, 20f, -1f, 0f); GameObject val20 = new GameObject("S"); val20.transform.SetParent(val19.transform, false); val20.AddComponent(); UIFactory.AddLE(val20, -1f, -1f, -1f, -1f, 1f); Transform transform4 = val19.transform; Color c_LABEL4 = C_LABEL; Color c_BTN4 = C_BTN; object obj4 = <>c.<>9__393_2; if (obj4 == null) { UnityAction val21 = delegate { if (casualPage > 0) { casualPage--; dirty = true; } }; <>c.<>9__393_2 = val21; obj4 = (object)val21; } cPrev = UIFactory.CreateButton("cP", transform4, "< Prev", 10f, c_LABEL4, c_BTN4, (UnityAction)obj4, (Vector2?)new Vector2(50f, 18f)); txtCasualPage = UIFactory.CreateText("cPI", val19.transform, "", 10f, C_LABEL, 514, (Vector2?)new Vector2(35f, 18f), richText: true, raycastTarget: false); Transform transform5 = val19.transform; Color c_LABEL5 = C_LABEL; Color c_BTN5 = C_BTN; object obj5 = <>c.<>9__393_3; if (obj5 == null) { UnityAction val22 = delegate { casualPage++; dirty = true; }; <>c.<>9__393_3 = val22; obj5 = (object)val22; } cNext = UIFactory.CreateButton("cN", transform5, "Next >", 10f, c_LABEL5, c_BTN5, (UnityAction)obj5, (Vector2?)new Vector2(50f, 18f)); GameObject val23 = new GameObject("S"); val23.transform.SetParent(val19.transform, false); val23.AddComponent(); UIFactory.AddLE(val23, -1f, -1f, -1f, -1f, 1f); Transform transform6 = val19.transform; Color c_LABEL6 = C_LABEL; Color c_BTN6 = C_BTN; object obj6 = <>O.<0>__ToggleHistoryCardMode; if (obj6 == null) { UnityAction val24 = ToggleHistoryCardMode; <>O.<0>__ToggleHistoryCardMode = val24; obj6 = (object)val24; } cCardModeBtn = UIFactory.CreateButton("cCm", transform6, "", 10f, c_LABEL6, c_BTN6, (UnityAction)obj6, (Vector2?)new Vector2(100f, 18f)); cCardModeTxt = UIFactory.GetButtonText(cCardModeBtn); return val; } private static HistoryRow CreateHistoryRow(Transform parent, string name) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Expected O, but got Unknown //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Expected O, but got Unknown //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_045c: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_04a1: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Expected O, but got Unknown //IL_0554: Unknown result type (might be due to invalid IL or missing references) //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_0597: Unknown result type (might be due to invalid IL or missing references) //IL_05a8: Unknown result type (might be due to invalid IL or missing references) //IL_05da: Unknown result type (might be due to invalid IL or missing references) //IL_05eb: Unknown result type (might be due to invalid IL or missing references) //IL_061d: Unknown result type (might be due to invalid IL or missing references) //IL_062e: Unknown result type (might be due to invalid IL or missing references) //IL_0660: Unknown result type (might be due to invalid IL or missing references) //IL_0671: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Unknown result type (might be due to invalid IL or missing references) //IL_06b4: Unknown result type (might be due to invalid IL or missing references) //IL_06e6: Unknown result type (might be due to invalid IL or missing references) //IL_06f7: Unknown result type (might be due to invalid IL or missing references) //IL_0741: Unknown result type (might be due to invalid IL or missing references) //IL_0755: Unknown result type (might be due to invalid IL or missing references) //IL_07b5: Unknown result type (might be due to invalid IL or missing references) //IL_07c9: Unknown result type (might be due to invalid IL or missing references) HistoryRow row = new HistoryRow(); row.seriesGO = new GameObject(name + "s"); row.seriesGO.transform.SetParent(parent, false); row.seriesGO.AddComponent(); UIFactory.AddHLG(row.seriesGO, 4f, 4); UIFactory.AddLE(row.seriesGO, -1f, -1f, -1f, 25f); row.txtSeriesHead = UIFactory.CreateText("sh", row.seriesGO.transform, "", 19f, C_GREEN, 257, (Vector2?)new Vector2(500f, 25f), richText: true, raycastTarget: false); row.txtSeriesElo = UIFactory.CreateText("se", row.seriesGO.transform, "", 19f, C_GREEN, 516, (Vector2?)new Vector2(160f, 25f), richText: true, raycastTarget: false); row.seriesGO.SetActive(false); row.root = new GameObject(name); row.root.transform.SetParent(parent, false); row.root.AddComponent(); UIFactory.AddVLG(row.root, 0f, 4); GameObject val = new GameObject("m"); val.transform.SetParent(row.root.transform, false); val.AddComponent(); UIFactory.AddHLG(val); UIFactory.AddLE(val, -1f, -1f, -1f, 25f); row.txtResult = UIFactory.CreateText("r", val.transform, "", 19f, C_GREEN, 513, (Vector2?)new Vector2(132f, 25f), richText: true, raycastTarget: false); row.btnId = UIFactory.CreateButton("id", val.transform, "ID", 9f, C_DIM, C_BTN, (UnityAction)delegate { CopyGameCode(row.currentMatchId); }, (Vector2?)new Vector2(24f, 17f)); row.btnId.transform.SetSiblingIndex(0); row.btnId.SetActive(false); row.txtOpp = UIFactory.CreateText("o", val.transform, "", 18f, C_WHITE, 513, (Vector2?)new Vector2(240f, 25f), richText: true, raycastTarget: false); row.txtFps = UIFactory.CreateText("fp", val.transform, "", 14f, C_LABEL, 513, (Vector2?)new Vector2(120f, 25f), richText: true, raycastTarget: false); GameObject val2 = new GameObject("Sfp"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddLE(val2, -1f, -1f, 22f, -1f, 0f); row.txtPing = UIFactory.CreateText("pg", val.transform, "", 14f, C_LABEL, 513, (Vector2?)new Vector2(150f, 25f), richText: true, raycastTarget: false); GameObject val3 = new GameObject("S"); val3.transform.SetParent(val.transform, false); val3.AddComponent(); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, 1f); row.txtXP = UIFactory.CreateText("x", val.transform, "", 16f, C_BLUE, 516, (Vector2?)new Vector2(65f, 25f), richText: true, raycastTarget: false); row.txtDate = UIFactory.CreateText("d", val.transform, "", 15f, C_DIM, 516, (Vector2?)new Vector2(45f, 25f), richText: true, raycastTarget: false); GameObject val4 = new GameObject("st"); val4.transform.SetParent(row.root.transform, false); val4.AddComponent(); UIFactory.AddHLG(val4, 2f); UIFactory.AddLE(val4, -1f, -1f, -1f, 20f); Color color = default(Color); ((Color)(ref color))..ctor(0.65f, 0.7f, 0.78f); row.txtStats = UIFactory.CreateText("st0", val4.transform, "", 14f, color, 513, (Vector2?)new Vector2(70f, 20f), richText: true, raycastTarget: false); row.txtHitYou = UIFactory.CreateText("hy", val4.transform, "", 14f, color, 513, (Vector2?)new Vector2(110f, 20f), richText: true, raycastTarget: false); row.txtBlockYou = UIFactory.CreateText("by", val4.transform, "", 14f, color, 513, (Vector2?)new Vector2(88f, 20f), richText: true, raycastTarget: false); row.txtKpsYou = UIFactory.CreateText("ky", val4.transform, "", 14f, color, 513, (Vector2?)new Vector2(96f, 20f), richText: true, raycastTarget: false); row.txtHitOpp = UIFactory.CreateText("ho", val4.transform, "", 14f, color, 513, (Vector2?)new Vector2(110f, 20f), richText: true, raycastTarget: false); row.txtBlockOpp = UIFactory.CreateText("bo", val4.transform, "", 14f, color, 513, (Vector2?)new Vector2(88f, 20f), richText: true, raycastTarget: false); row.txtKpsOpp = UIFactory.CreateText("ko", val4.transform, "", 14f, color, 513, (Vector2?)new Vector2(96f, 20f), richText: true, raycastTarget: false); row.txtCards = UIFactory.CreateText("c", row.root.transform, "", 19f, new Color(0.6f, 0.7f, 0.9f), 257, (Vector2?)new Vector2(900f, 25f), richText: true, raycastTarget: false); UIFactory.SetCharSpacing(row.txtCards, 1.5f); row.txtOppCards = UIFactory.CreateText("oc", row.root.transform, "", 19f, new Color(0.9f, 0.6f, 0.5f), 257, (Vector2?)new Vector2(900f, 25f), richText: true, raycastTarget: false); UIFactory.SetCharSpacing(row.txtOppCards, 1.5f); row.root.SetActive(false); return row; } private static GameObject BuildLeaderboardTab(Transform parent) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0069: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Expected O, but got Unknown //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Expected O, but got Unknown //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Expected O, but got Unknown //IL_055e: Unknown result type (might be due to invalid IL or missing references) //IL_0563: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Expected O, but got Unknown //IL_0f6d: Unknown result type (might be due to invalid IL or missing references) //IL_0f81: Unknown result type (might be due to invalid IL or missing references) //IL_0fac: Unknown result type (might be due to invalid IL or missing references) //IL_0fb6: Expected O, but got Unknown //IL_1022: Unknown result type (might be due to invalid IL or missing references) //IL_1029: Expected O, but got Unknown //IL_1088: Unknown result type (might be due to invalid IL or missing references) //IL_108d: Unknown result type (might be due to invalid IL or missing references) //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_05bb: Unknown result type (might be due to invalid IL or missing references) //IL_05cf: Unknown result type (might be due to invalid IL or missing references) //IL_05fb: Unknown result type (might be due to invalid IL or missing references) //IL_0600: Unknown result type (might be due to invalid IL or missing references) //IL_057c: Unknown result type (might be due to invalid IL or missing references) //IL_0581: Unknown result type (might be due to invalid IL or missing references) //IL_0587: Expected O, but got Unknown //IL_10bb: Unknown result type (might be due to invalid IL or missing references) //IL_10f9: Unknown result type (might be due to invalid IL or missing references) //IL_110d: Unknown result type (might be due to invalid IL or missing references) //IL_1148: Unknown result type (might be due to invalid IL or missing references) //IL_114d: Unknown result type (might be due to invalid IL or missing references) //IL_10a6: Unknown result type (might be due to invalid IL or missing references) //IL_10ab: Unknown result type (might be due to invalid IL or missing references) //IL_10b1: Expected O, but got Unknown //IL_062e: Unknown result type (might be due to invalid IL or missing references) //IL_0647: Unknown result type (might be due to invalid IL or missing references) //IL_064e: Expected O, but got Unknown //IL_0696: Unknown result type (might be due to invalid IL or missing references) //IL_069d: Expected O, but got Unknown //IL_0706: Unknown result type (might be due to invalid IL or missing references) //IL_070d: Expected O, but got Unknown //IL_0779: Unknown result type (might be due to invalid IL or missing references) //IL_078d: Unknown result type (might be due to invalid IL or missing references) //IL_07b5: Unknown result type (might be due to invalid IL or missing references) //IL_07c9: Unknown result type (might be due to invalid IL or missing references) //IL_07f5: Unknown result type (might be due to invalid IL or missing references) //IL_080e: Unknown result type (might be due to invalid IL or missing references) //IL_0619: Unknown result type (might be due to invalid IL or missing references) //IL_061e: Unknown result type (might be due to invalid IL or missing references) //IL_0624: Expected O, but got Unknown //IL_117b: Unknown result type (might be due to invalid IL or missing references) //IL_11a5: Unknown result type (might be due to invalid IL or missing references) //IL_11ac: Expected O, but got Unknown //IL_1219: Unknown result type (might be due to invalid IL or missing references) //IL_122d: Unknown result type (might be due to invalid IL or missing references) //IL_127a: Unknown result type (might be due to invalid IL or missing references) //IL_128e: Unknown result type (might be due to invalid IL or missing references) //IL_12e2: Unknown result type (might be due to invalid IL or missing references) //IL_12f6: Unknown result type (might be due to invalid IL or missing references) //IL_130d: Unknown result type (might be due to invalid IL or missing references) //IL_1317: Expected O, but got Unknown //IL_1392: Unknown result type (might be due to invalid IL or missing references) //IL_13ab: Unknown result type (might be due to invalid IL or missing references) //IL_1166: Unknown result type (might be due to invalid IL or missing references) //IL_116b: Unknown result type (might be due to invalid IL or missing references) //IL_1171: Expected O, but got Unknown //IL_083c: Unknown result type (might be due to invalid IL or missing references) //IL_08e5: Unknown result type (might be due to invalid IL or missing references) //IL_08ec: Expected O, but got Unknown //IL_0827: Unknown result type (might be due to invalid IL or missing references) //IL_082c: Unknown result type (might be due to invalid IL or missing references) //IL_0832: Expected O, but got Unknown //IL_13d9: Unknown result type (might be due to invalid IL or missing references) //IL_13f2: Unknown result type (might be due to invalid IL or missing references) //IL_13f9: Expected O, but got Unknown //IL_147c: Unknown result type (might be due to invalid IL or missing references) //IL_1490: Unknown result type (might be due to invalid IL or missing references) //IL_13c4: Unknown result type (might be due to invalid IL or missing references) //IL_13c9: Unknown result type (might be due to invalid IL or missing references) //IL_13cf: Expected O, but got Unknown //IL_1501: Unknown result type (might be due to invalid IL or missing references) //IL_0b78: Unknown result type (might be due to invalid IL or missing references) //IL_0b7f: Expected O, but got Unknown //IL_0beb: Unknown result type (might be due to invalid IL or missing references) //IL_0bff: Unknown result type (might be due to invalid IL or missing references) //IL_0c1a: Unknown result type (might be due to invalid IL or missing references) //IL_0c21: Expected O, but got Unknown //IL_0c7a: Unknown result type (might be due to invalid IL or missing references) //IL_0c7f: Unknown result type (might be due to invalid IL or missing references) //IL_0a01: Unknown result type (might be due to invalid IL or missing references) //IL_09fa: Unknown result type (might be due to invalid IL or missing references) //IL_0cad: Unknown result type (might be due to invalid IL or missing references) //IL_0cd7: Unknown result type (might be due to invalid IL or missing references) //IL_0ceb: Unknown result type (might be due to invalid IL or missing references) //IL_0d17: Unknown result type (might be due to invalid IL or missing references) //IL_0d1c: Unknown result type (might be due to invalid IL or missing references) //IL_0c98: Unknown result type (might be due to invalid IL or missing references) //IL_0c9d: Unknown result type (might be due to invalid IL or missing references) //IL_0ca3: Expected O, but got Unknown //IL_0d4a: Unknown result type (might be due to invalid IL or missing references) //IL_0d69: Unknown result type (might be due to invalid IL or missing references) //IL_0dd0: Unknown result type (might be due to invalid IL or missing references) //IL_0de4: Unknown result type (might be due to invalid IL or missing references) //IL_0e0b: Unknown result type (might be due to invalid IL or missing references) //IL_0e15: Expected O, but got Unknown //IL_0d35: Unknown result type (might be due to invalid IL or missing references) //IL_0d3a: Unknown result type (might be due to invalid IL or missing references) //IL_0d40: Expected O, but got Unknown //IL_0a28: Unknown result type (might be due to invalid IL or missing references) //IL_0a21: Unknown result type (might be due to invalid IL or missing references) //IL_0ea0: Unknown result type (might be due to invalid IL or missing references) //IL_0a35: Unknown result type (might be due to invalid IL or missing references) //IL_0a47: Unknown result type (might be due to invalid IL or missing references) //IL_0a56: Expected O, but got Unknown GameObject val = new GameObject("Leaderboard"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddHLG(val, 6f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val2 = UIFactory.CreatePanel("LBSeries", val.transform, C_PANEL); UIFactory.AddVLG(val2, 2f, 8, 8, 6, 6); UIFactory.AddLE(val2, 340f, -1f, 400f, -1f, 1f, 1f); txtLiveHeader = UIFactory.CreateText("RSL", val2.transform, "* Live Ranked Games", 17f, C_WHITE, 513, (Vector2?)new Vector2(280f, 26f), richText: true, raycastTarget: false); txtLiveSeries = UIFactory.CreateText("LIVE", val2.transform, "No live games right now.", 13f, C_WHITE, 257, (Vector2?)new Vector2(280f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtLiveSeries, on: true); liveBetsContainer = new GameObject("LiveBets"); liveBetsContainer.transform.SetParent(val2.transform, false); liveBetsContainer.AddComponent(); UIFactory.AddVLG(liveBetsContainer); liveBetsPager = new GameObject("LivePg"); liveBetsPager.transform.SetParent(val2.transform, false); liveBetsPager.AddComponent(); UIFactory.AddHLG(liveBetsPager); UIFactory.AddLE(liveBetsPager, -1f, -1f, -1f, 18f, -1f, 0f); Transform transform = liveBetsPager.transform; Color c_LABEL = C_LABEL; Color c_BTN = C_BTN; object obj = <>c.<>9__396_0; if (obj == null) { UnityAction val3 = delegate { if (liveSeriesPage > 0) { liveSeriesPage--; dirty = true; } }; <>c.<>9__396_0 = val3; obj = (object)val3; } liveBetsPrev = UIFactory.CreateButton("lvP", transform, "< Prev", 10f, c_LABEL, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(50f, 18f)); txtLiveBetsPage = UIFactory.CreateText("lvPI", liveBetsPager.transform, "", 10f, C_LABEL, 514, (Vector2?)new Vector2(80f, 18f), richText: true, raycastTarget: false); Transform transform2 = liveBetsPager.transform; Color c_LABEL2 = C_LABEL; Color c_BTN2 = C_BTN; object obj2 = <>c.<>9__396_1; if (obj2 == null) { UnityAction val4 = delegate { liveSeriesPage++; dirty = true; }; <>c.<>9__396_1 = val4; obj2 = (object)val4; } liveBetsNext = UIFactory.CreateButton("lvN", transform2, "Next >", 10f, c_LABEL2, c_BTN2, (UnityAction)obj2, (Vector2?)new Vector2(50f, 18f)); txtMyBets = UIFactory.CreateText("MYBETS", val2.transform, "", 15f, C_WHITE, 257, (Vector2?)new Vector2(380f, 20f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtMyBets, on: true); UIFactory.SetTextAutoHeight(txtMyBets); UIFactory.SetBold(txtMyBets, b: true); liveBetsPager.SetActive(false); GameObject val5 = new GameObject("LRSp"); val5.transform.SetParent(val2.transform, false); val5.AddComponent(); UIFactory.AddLE(val5, -1f, 18f, -1f, 18f, -1f, 0f); UIFactory.CreateText("RSL", val2.transform, "Recent Ranked Series", 17f, C_WHITE, 513, (Vector2?)new Vector2(280f, 26f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("RSSV", val2.transform, 1f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); txtRecentSeries = UIFactory.CreateText("RST", scrollViewRefs.content.transform, "Loading...", 16f, C_DIM, 257, (Vector2?)new Vector2(380f, 20f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtRecentSeries, on: false); UIFactory.SetTextAutoHeight(txtRecentSeries); GameObject val6 = new GameObject("SPg"); val6.transform.SetParent(val2.transform, false); val6.AddComponent(); UIFactory.AddHLG(val6); UIFactory.AddLE(val6, -1f, -1f, -1f, 20f, -1f, 0f); GameObject val7 = new GameObject("S"); val7.transform.SetParent(val6.transform, false); val7.AddComponent(); UIFactory.AddLE(val7, -1f, -1f, -1f, -1f, 1f); Transform transform3 = val6.transform; Color c_LABEL3 = C_LABEL; Color c_BTN3 = C_BTN; object obj3 = <>c.<>9__396_2; if (obj3 == null) { UnityAction val8 = delegate { if (recentSeriesPage > 0) { recentSeriesPage--; dirty = true; } }; <>c.<>9__396_2 = val8; obj3 = (object)val8; } seriesPrev = UIFactory.CreateButton("sP", transform3, "< Prev", 10f, c_LABEL3, c_BTN3, (UnityAction)obj3, (Vector2?)new Vector2(50f, 18f)); txtSeriesPage = UIFactory.CreateText("sPI", val6.transform, "", 10f, C_LABEL, 514, (Vector2?)new Vector2(35f, 18f), richText: true, raycastTarget: false); Transform transform4 = val6.transform; Color c_LABEL4 = C_LABEL; Color c_BTN4 = C_BTN; object obj4 = <>c.<>9__396_3; if (obj4 == null) { UnityAction val9 = delegate { recentSeriesPage++; dirty = true; }; <>c.<>9__396_3 = val9; obj4 = (object)val9; } seriesNext = UIFactory.CreateButton("sN", transform4, "Next >", 10f, c_LABEL4, c_BTN4, (UnityAction)obj4, (Vector2?)new Vector2(50f, 18f)); GameObject val10 = new GameObject("S"); val10.transform.SetParent(val6.transform, false); val10.AddComponent(); UIFactory.AddLE(val10, -1f, -1f, -1f, -1f, 1f); GameObject val11 = new GameObject("LBMid"); val11.transform.SetParent(val.transform, false); val11.AddComponent(); UIFactory.AddVLG(val11); UIFactory.AddLE(val11, 620f, -1f, 772f, -1f, 0f, 1f); MakeSubTabAnchor(1, val11.transform, asFirst: true); GameObject val12 = new GameObject("LBSearch"); val12.transform.SetParent(val11.transform, false); val12.AddComponent(); UIFactory.AddHLG(val12, 6f); UIFactory.AddLE(val12, -1f, -1f, -1f, 24f, 0f, 0f); UIFactory.CreateText("LBSc", val12.transform, "Search", 13f, C_LABEL, 513, (Vector2?)new Vector2(52f, 22f), richText: true, raycastTarget: false); lbSearchField = UIFactory.CreateText("LBSLbl", val12.transform, "", 13f, C_WHITE, 513, (Vector2?)new Vector2(240f, 22f), richText: true, raycastTarget: false); Transform transform5 = val12.transform; Color c_LABEL5 = C_LABEL; Color bgColor = new Color(0.25f, 0.3f, 0.4f, 0.9f); object obj5 = <>c.<>9__396_4; if (obj5 == null) { UnityAction val13 = delegate { lbSearch = ""; dirty = true; }; <>c.<>9__396_4 = val13; obj5 = (object)val13; } UIFactory.CreateButton("LBSClr", transform5, "Clear", 11f, c_LABEL5, bgColor, (UnityAction)obj5, (Vector2?)new Vector2(48f, 20f)); string[] array = new string[8] { "#", "Lv", "Player", "Rating", "W", "L", "W/L", "Gold" }; string[] hK = new string[8] { "rank", "level", "display_name", "rating", "wins", "losses", "wl_ratio", "gold" }; GameObject val14 = new GameObject("LBH"); val14.transform.SetParent(val11.transform, false); val14.AddComponent(); UIFactory.AddHLG(val14, 2f); UIFactory.AddLE(val14, -1f, 28f, -1f, 28f, -1f, 0f); lbSortTexts = new object[array.Length]; lbSortBtns = (GameObject[])(object)new GameObject[array.Length]; for (int num = 0; num < array.Length; num++) { int idx = num; string text = ((!(lbSort == hK[num])) ? "" : (lbSortDesc ? " v" : " ^")); GameObject val15 = UIFactory.CreateButton($"LH{num}", val14.transform, array[num] + text, 14f, (lbSort == hK[num]) ? C_WHITE : C_LABEL, (lbSort == hK[num]) ? C_TABACT : C_TAB, (UnityAction)delegate { if (lbSort == hK[idx]) { lbSortDesc = !lbSortDesc; } else { lbSort = hK[idx]; lbSortDesc = idx >= 3; } dirty = true; }, (Vector2?)new Vector2(LB_COL_W[num], 22f)); if (UIFactory.tLE != null) { Component component = val15.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } UIFactory.AddLE(val15, -1f, -1f, LB_COL_W[num], 22f, -1f, 0f); lbSortBtns[num] = val15; lbSortTexts[num] = UIFactory.GetButtonText(val15); } UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("LBSV", val11.transform); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); for (int num2 = 0; num2 < 100; num2++) { lbRows.Add(CreateLBRow(scrollViewRefs2.content.transform, $"lb{num2}", num2)); } GameObject val16 = new GameObject("LBPg"); val16.transform.SetParent(val11.transform, false); val16.AddComponent(); UIFactory.AddHLG(val16, 6f); UIFactory.AddLE(val16, -1f, -1f, -1f, 24f, -1f, 0f); txtLBCount = UIFactory.CreateText("LBC", val16.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(160f, 22f), richText: true, raycastTarget: false); GameObject val17 = new GameObject("S"); val17.transform.SetParent(val16.transform, false); val17.AddComponent(); UIFactory.AddLE(val17, -1f, -1f, -1f, -1f, 1f); Transform transform6 = val16.transform; Color c_LABEL6 = C_LABEL; Color c_BTN5 = C_BTN; object obj6 = <>c.<>9__396_5; if (obj6 == null) { UnityAction val18 = delegate { if (lbPage > 0) { lbPage--; dirty = true; } }; <>c.<>9__396_5 = val18; obj6 = (object)val18; } lbPrev = UIFactory.CreateButton("lbP", transform6, "< Prev", 13f, c_LABEL6, c_BTN5, (UnityAction)obj6, (Vector2?)new Vector2(60f, 22f)); txtLBPage = UIFactory.CreateText("lbPI", val16.transform, "", 13f, C_LABEL, 514, (Vector2?)new Vector2(40f, 22f), richText: true, raycastTarget: false); Transform transform7 = val16.transform; Color c_LABEL7 = C_LABEL; Color c_BTN6 = C_BTN; object obj7 = <>c.<>9__396_6; if (obj7 == null) { UnityAction val19 = delegate { lbPage++; dirty = true; }; <>c.<>9__396_6 = val19; obj7 = (object)val19; } lbNext = UIFactory.CreateButton("lbN", transform7, "Next >", 13f, c_LABEL7, c_BTN6, (UnityAction)obj7, (Vector2?)new Vector2(60f, 22f)); GameObject val20 = UIFactory.CreatePanel("LBR", val.transform, C_PANEL); UIFactory.AddVLG(val20, 4f, 12, 12, 8, 8); UIFactory.AddLE(val20, -1f, -1f, 400f, -1f, 1f, 1f); txtLBPlayerName = UIFactory.CreateText("LBName", val20.transform, "Click a player", 20f, C_WHITE, 513, (Vector2?)new Vector2(340f, 26f), richText: true, raycastTarget: false); UIFactory.SetBold(txtLBPlayerName, b: true); lbGraphPanel = new GameObject("Graph"); lbGraphPanel.transform.SetParent(val20.transform, false); RectTransform val21 = lbGraphPanel.AddComponent(); UIFactory.AddLE(lbGraphPanel, -1f, 110f, -1f, 110f, -1f, 0f); Component obj8 = lbGraphPanel.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj8, (object)new Color(0f, 0f, 0f, 0.01f)); if (UIFactory.tMask != null) { Component obj9 = lbGraphPanel.AddComponent(UIFactory.tMask); try { UIFactory.tMask.GetProperty("showMaskGraphic", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj9, false); } catch { } } lbGraphPanel.SetActive(false); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("LBDSV", val20.transform, 0f); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); txtLBDetail = UIFactory.CreateText("LBD", scrollViewRefs3.content.transform, "", 16f, C_DIM, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); UIFactory.SetTextAutoHeight(txtLBDetail); h2hPager = new GameObject("H2HPg"); h2hPager.transform.SetParent(scrollViewRefs3.content.transform, false); h2hPager.AddComponent(); UIFactory.AddHLG(h2hPager, 6f); UIFactory.AddLE(h2hPager, -1f, -1f, -1f, 26f, -1f, 0f); GameObject val22 = new GameObject("S"); val22.transform.SetParent(h2hPager.transform, false); val22.AddComponent(); UIFactory.AddLE(val22, -1f, -1f, -1f, -1f, 1f); Transform transform8 = h2hPager.transform; Color c_LABEL8 = C_LABEL; Color c_BTN7 = C_BTN; object obj11 = <>c.<>9__396_7; if (obj11 == null) { UnityAction val23 = delegate { if (h2hSeriesPage > 0) { h2hSeriesPage--; dirty = true; } }; <>c.<>9__396_7 = val23; obj11 = (object)val23; } h2hPrev = UIFactory.CreateButton("h2hP", transform8, "< Newer", 13f, c_LABEL8, c_BTN7, (UnityAction)obj11, (Vector2?)new Vector2(78f, 24f)); UIFactory.SetBold(UIFactory.GetButtonText(h2hPrev), b: true); txtH2hPage = UIFactory.CreateText("h2hI", h2hPager.transform, "", 13f, C_LABEL, 514, (Vector2?)new Vector2(46f, 24f), richText: true, raycastTarget: false); UIFactory.SetBold(txtH2hPage, b: true); Transform transform9 = h2hPager.transform; Color c_LABEL9 = C_LABEL; Color c_BTN8 = C_BTN; object obj12 = <>c.<>9__396_8; if (obj12 == null) { UnityAction val24 = delegate { h2hSeriesPage++; dirty = true; }; <>c.<>9__396_8 = val24; obj12 = (object)val24; } h2hNext = UIFactory.CreateButton("h2hN", transform9, "Older >", 13f, c_LABEL9, c_BTN8, (UnityAction)obj12, (Vector2?)new Vector2(78f, 24f)); UIFactory.SetBold(UIFactory.GetButtonText(h2hNext), b: true); GameObject val25 = new GameObject("S"); val25.transform.SetParent(h2hPager.transform, false); val25.AddComponent(); UIFactory.AddLE(val25, -1f, -1f, -1f, -1f, 1f); h2hPager.SetActive(false); txtLBDetailB = UIFactory.CreateText("LBDB", scrollViewRefs3.content.transform, "", 16f, C_DIM, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); UIFactory.SetTextAutoHeight(txtLBDetailB); UIFactory.SetWordWrap(txtLBDetailB, on: true); txtLBAch = UIFactory.CreateText("LBDAch", scrollViewRefs3.content.transform, "", 16f, C_DIM, 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); UIFactory.SetTextAutoHeight(txtLBAch); UIFactory.SetWordWrap(txtLBAch, on: true); UIFactory.SetWordWrap(txtLBDetail, on: true); UIFactory.CreateText("LBDScrollHint", val20.transform, "scroll for full history — hover + mouse wheel", 11f, C_DIM, 514, (Vector2?)new Vector2(340f, 15f), richText: true, raycastTarget: false); lbBlockRow = new GameObject("BlockRow"); lbBlockRow.transform.SetParent(val20.transform, false); lbBlockRow.AddComponent(); UIFactory.AddHLG(lbBlockRow, 0f); UIFactory.AddLE(lbBlockRow, -1f, 28f, -1f, 28f, -1f, 0f); Transform transform10 = lbBlockRow.transform; Color c_WHITE = C_WHITE; Color bgColor2 = new Color(0.5f, 0.15f, 0.15f, 0.9f); object obj13 = <>c.<>9__396_9; if (obj13 == null) { UnityAction val26 = delegate { if (!string.IsNullOrEmpty(selectedSteamId) && !(selectedSteamId == MatchTracker.LocalSteamId)) { string localSteamId = MatchTracker.LocalSteamId; if (ApiClient.IsPlayerBlocked(selectedSteamId)) { ApiClient.UnblockPlayer(localSteamId, selectedSteamId); } else { ApiClient.BlockPlayer(localSteamId, selectedSteamId); } } }; <>c.<>9__396_9 = val26; obj13 = (object)val26; } lbBlockBtn = UIFactory.CreateButton("LBBlock", transform10, "Block from Ranked", 14f, c_WHITE, bgColor2, (UnityAction)obj13, (Vector2?)new Vector2(160f, 24f)); GameObject val27 = new GameObject("S"); val27.transform.SetParent(lbBlockRow.transform, false); val27.AddComponent(); UIFactory.AddLE(val27, -1f, -1f, -1f, -1f, 1f); lbBlockBtn.SetActive(true); lbBlockRow.SetActive(false); lbBlockTxt = UIFactory.GetButtonText(lbBlockBtn); txtLBSteamId = UIFactory.CreateText("LBSid", val20.transform, "", 13f, C_DIM, 513, (Vector2?)new Vector2(340f, 18f), richText: true, raycastTarget: true); Component sidComp = default(Component); ref Component reference = ref sidComp; object obj14 = txtLBSteamId; reference = (Component)((obj14 is Component) ? obj14 : null); if ((Object)(object)sidComp != (Object)null) { ClickHandler clickHandler = sidComp.gameObject.AddComponent(); clickHandler.onClick = delegate { //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (ClickGuard.Claim(sidComp.gameObject) && !string.IsNullOrEmpty(selectedSteamId)) { GUIUtility.systemCopyBuffer = selectedSteamId; CompetitiveUI.ShowNotification("Steam ID copied to clipboard", new Color(0.6f, 0.9f, 1f)); } }; } ((Component)txtLBSteamId).gameObject.SetActive(false); return val; } private static LBRow CreateLBRow(Transform parent, string name, int rowIndex) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) LBRow lBRow = new LBRow(); lBRow.root = new GameObject(name); lBRow.root.transform.SetParent(parent, false); lBRow.root.AddComponent(); UIFactory.AddHLG(lBRow.root, 0f); UIFactory.AddLE(lBRow.root, -1f, -1f, -1f, 28f); lBRow.hlWrap = new GameObject("W"); lBRow.hlWrap.transform.SetParent(lBRow.root.transform, false); lBRow.hlWrap.AddComponent(); UIFactory.AddHLG(lBRow.hlWrap, 2f); if (UIFactory.tImage != null) { Component obj = lBRow.hlWrap.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, (object)new Color(0.15f, 0.15f, 0.2f, 0.01f)); UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, true); } lBRow.txtRank = UIFactory.CreateText("r", lBRow.hlWrap.transform, "", 15f, C_GOLD, 514, (Vector2?)new Vector2(LB_COL_W[0], 25f), richText: true, raycastTarget: false); lBRow.txtLv = UIFactory.CreateText("l", lBRow.hlWrap.transform, "", 15f, C_BLUE, 514, (Vector2?)new Vector2(LB_COL_W[1], 25f), richText: true, raycastTarget: false); lBRow.txtName = UIFactory.CreateText("n", lBRow.hlWrap.transform, "", 16f, C_WHITE, 513, (Vector2?)new Vector2(LB_COL_W[2], 25f), richText: true, raycastTarget: false); lBRow.txtRating = UIFactory.CreateText("rt", lBRow.hlWrap.transform, "", 16f, C_WHITE, 514, (Vector2?)new Vector2(LB_COL_W[3], 25f), richText: true, raycastTarget: false); UIFactory.SetBold(lBRow.txtRating, b: true); lBRow.txtW = UIFactory.CreateText("w", lBRow.hlWrap.transform, "", 15f, C_GREEN, 514, (Vector2?)new Vector2(LB_COL_W[4], 25f), richText: true, raycastTarget: false); lBRow.txtL = UIFactory.CreateText("ls", lBRow.hlWrap.transform, "", 15f, C_RED, 514, (Vector2?)new Vector2(LB_COL_W[5], 25f), richText: true, raycastTarget: false); lBRow.txtWL = UIFactory.CreateText("wl", lBRow.hlWrap.transform, "", 15f, C_LABEL, 514, (Vector2?)new Vector2(LB_COL_W[6], 25f), richText: true, raycastTarget: false); lBRow.txtGold = UIFactory.CreateText("gd", lBRow.hlWrap.transform, "", 15f, C_GOLD, 514, (Vector2?)new Vector2(LB_COL_W[7], 25f), richText: true, raycastTarget: false); UIFactory.SetBold(lBRow.txtGold, b: true); int idx = rowIndex; ClickHandler clickHandler = lBRow.root.AddComponent(); clickHandler.onClick = delegate { if (ClickGuard.Claim() && idx >= 0 && idx < lbRows.Count && !string.IsNullOrEmpty(lbRows[idx].steamId)) { string sid = lbRows[idx].steamId; h2hSeriesPage = 0; if (selectedSteamId == sid) { selectedSteamId = ""; selectedStats = null; selectedViewHistory = null; } else { selectedSteamId = sid; selectedStats = null; selectedViewHistory = null; ApiClient.FetchPlayerStatsForView(sid, delegate(ApiClient.PlayerStatsData d) { selectedStats = d; dirty = true; }); ApiClient.FetchAchievementsForView(sid); ApiClient.FetchPlayerTournaments(sid); ApiClient.FetchPlayerModeHistories(sid); ApiClient.FetchMatchHistoryForView(sid, delegate(List h) { if (selectedSteamId == sid) { selectedViewHistory = h; dirty = true; } }); } dirty = true; } }; lBRow.root.SetActive(false); return lBRow; } private static GameObject BuildCardStatsTab(Transform parent) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_01b2: 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_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Expected O, but got Unknown //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Expected O, but got Unknown //IL_049c: Unknown result type (might be due to invalid IL or missing references) //IL_04a3: Expected O, but got Unknown //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Expected O, but got Unknown //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_05ec: Expected O, but got Unknown //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Expected O, but got Unknown //IL_07ca: Unknown result type (might be due to invalid IL or missing references) //IL_07d1: Expected O, but got Unknown //IL_06d2: Unknown result type (might be due to invalid IL or missing references) //IL_06cb: Unknown result type (might be due to invalid IL or missing references) //IL_06f9: Unknown result type (might be due to invalid IL or missing references) //IL_06f2: Unknown result type (might be due to invalid IL or missing references) //IL_0706: Unknown result type (might be due to invalid IL or missing references) //IL_0718: Unknown result type (might be due to invalid IL or missing references) //IL_0727: Expected O, but got Unknown GameObject val = new GameObject("CardStats"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 4f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(2, val.transform, asFirst: true); GameObject val2 = new GameObject("Filt"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddHLG(val2, 4f, 12); UIFactory.AddLE(val2, -1f, 34f, -1f, 34f, -1f, 0f); Transform transform = val2.transform; Color c_WHITE = C_WHITE; Color bgColor = new Color(0.2f, 0.55f, 0.3f, 0.95f); object obj = <>c.<>9__398_0; if (obj == null) { UnityAction val3 = delegate { ExportCardTierList(); }; <>c.<>9__398_0 = val3; obj = (object)val3; } GameObject val4 = UIFactory.CreateButton("ExpBtn", transform, "Export Tier List", 16f, c_WHITE, bgColor, (UnityAction)obj, (Vector2?)new Vector2(180f, 30f)); UIFactory.SetBold(UIFactory.GetButtonText(val4), b: true); if (UIFactory.tLE != null) { Component component = val4.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } UIFactory.AddLE(val4, 180f, 30f, 180f, 30f, 0f, 0f); Transform transform2 = val2.transform; Color c_WHITE2 = C_WHITE; Color bgColor2 = new Color(0.25f, 0.35f, 0.55f, 0.95f); object obj2 = <>c.<>9__398_1; if (obj2 == null) { UnityAction val5 = delegate { //IL_0066: Unknown result type (might be due to invalid IL or missing references) try { string text2; try { text2 = Path.GetFullPath(Path.Combine(Application.dataPath, "..", "CompetitiveRoundsTierLists")); Directory.CreateDirectory(text2); } catch { text2 = Application.persistentDataPath; } Application.OpenURL("file:///" + text2.Replace('\\', '/')); CompetitiveUI.ShowNotification("Tier lists live in " + text2, new Color(0.6f, 0.8f, 1f), 8f); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TIER-EXPORT] open folder: " + ex.Message)); } }; <>c.<>9__398_1 = val5; obj2 = (object)val5; } GameObject val6 = UIFactory.CreateButton("ExpDir", transform2, "Open Tier List Folder", 14f, c_WHITE2, bgColor2, (UnityAction)obj2, (Vector2?)new Vector2(180f, 30f)); if (UIFactory.tLE != null) { Component component2 = val6.GetComponent(UIFactory.tLE); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } } UIFactory.AddLE(val6, 180f, 30f, 180f, 30f, 0f, 0f); UIFactory.SetBold(UIFactory.GetButtonText(val6), b: true); GameObject val7 = new GameObject("S"); val7.transform.SetParent(val2.transform, false); val7.AddComponent(); UIFactory.AddLE(val7, -1f, -1f, -1f, -1f, 1f); string[] array = new string[3] { "All", "Ranked", "Casual" }; cardFilterBtns = (GameObject[])(object)new GameObject[3]; cardFilterTexts = new object[3]; float num = 0f; for (int num2 = 0; num2 < CS_COL_W.Length; num2++) { num += CS_COL_W[num2]; } float num3 = Mathf.Floor((num - 4f) / 3f); for (int num4 = 0; num4 < 3; num4++) { int idx = num4; GameObject val8 = UIFactory.CreateButton($"F{num4}", val2.transform, array[num4], 18f, C_LABEL, (num4 == 0) ? C_TABACT : C_TAB, (UnityAction)delegate { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) cardFilter = idx; string isRanked = ((idx == 1) ? "true" : ((idx == 2) ? "false" : null)); ApiClient.FetchCardStats(200, MatchTracker.LocalSteamId, "times_picked", isRanked); LoadCardTiersForCurrentFilter(); for (int i = 0; i < 3; i++) { UIFactory.SetImageColor(cardFilterBtns[i], (i == idx) ? C_TABACT : C_TAB); if (cardFilterTexts[i] != null) { UIFactory.SetColor(cardFilterTexts[i], (i == idx) ? C_WHITE : C_LABEL); UIFactory.SetBold(cardFilterTexts[i], i == idx); } } dirty = true; }, (Vector2?)new Vector2(num3, 30f)); if (UIFactory.tLE != null) { Component component3 = val8.GetComponent(UIFactory.tLE); if ((Object)(object)component3 != (Object)null) { Object.Destroy((Object)(object)component3); } } float prefW = num3; UIFactory.AddLE(val8, num3, 30f, prefW, 30f, 0f, 0f); UIFactory.SetBold(UIFactory.GetButtonText(val8), b: true); cardFilterBtns[num4] = val8; cardFilterTexts[num4] = UIFactory.GetButtonText(val8); } GameObject val9 = new GameObject("S"); val9.transform.SetParent(val2.transform, false); val9.AddComponent(); UIFactory.AddLE(val9, -1f, -1f, -1f, -1f, 1f); GameObject val10 = new GameObject("FBal"); val10.transform.SetParent(val2.transform, false); val10.AddComponent(); UIFactory.AddLE(val10, 364f, -1f, 364f, -1f, 0f); string[] array2 = new string[7] { "Tier", "Card", "Rarity", "Picks", "Wins", "WR%", "Pass%" }; string[] hK = new string[7] { "tier", "card_name", "card_rarity", "times_picked", "wins_with_card", "win_rate", "pass_rate" }; GameObject val11 = new GameObject("CHR"); val11.transform.SetParent(val.transform, false); val11.AddComponent(); UIFactory.AddHLG(val11, 2f); UIFactory.AddLE(val11, -1f, 32f, -1f, 32f, -1f, 0f); cardSortTexts = new object[7]; cardSortBtns = (GameObject[])(object)new GameObject[7]; GameObject val12 = new GameObject("S"); val12.transform.SetParent(val11.transform, false); val12.AddComponent(); UIFactory.AddLE(val12, -1f, -1f, -1f, -1f, 1f); for (int num5 = 0; num5 < 7; num5++) { int idx2 = num5; string text = ((!(cardSort == hK[num5])) ? "" : (cardSortDesc ? " v" : " ^")); GameObject val13 = UIFactory.CreateButton($"CS{num5}", val11.transform, array2[num5] + text, 18f, (cardSort == hK[num5]) ? C_WHITE : C_LABEL, (cardSort == hK[num5]) ? C_TABACT : C_TAB, (UnityAction)delegate { if (cardSort == hK[idx2]) { cardSortDesc = !cardSortDesc; } else { cardSort = hK[idx2]; cardSortDesc = true; } dirty = true; }, (Vector2?)new Vector2(CS_COL_W[num5], 26f)); if (UIFactory.tLE != null) { Component component4 = val13.GetComponent(UIFactory.tLE); if ((Object)(object)component4 != (Object)null) { Object.Destroy((Object)(object)component4); } } UIFactory.AddLE(val13, -1f, -1f, CS_COL_W[num5], 26f, -1f, 0f); UIFactory.SetBold(UIFactory.GetButtonText(val13), b: true); cardSortBtns[num5] = val13; cardSortTexts[num5] = UIFactory.GetButtonText(val13); } GameObject val14 = new GameObject("S"); val14.transform.SetParent(val11.transform, false); val14.AddComponent(); UIFactory.AddLE(val14, -1f, -1f, -1f, -1f, 1f); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("CSV", val.transform); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); for (int num6 = 0; num6 < 100; num6++) { cardRows.Add(CreateCardRow(scrollViewRefs.content.transform, $"cd{num6}")); } return val; } private static CardRow CreateCardRow(Transform parent, string name) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0538: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Expected O, but got Unknown //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_045c: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) CardRow row = new CardRow(); row.root = new GameObject(name); row.root.transform.SetParent(parent, false); row.root.AddComponent(); UIFactory.AddHLG(row.root, 0f); UIFactory.AddLE(row.root, -1f, -1f, -1f, 30f); GameObject val = new GameObject("S"); val.transform.SetParent(row.root.transform, false); val.AddComponent(); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, 1f); row.hl = new GameObject("hl"); row.hl.transform.SetParent(row.root.transform, false); row.hl.AddComponent(); Component obj = row.hl.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, (object)new Color(0f, 0f, 0f, 0f)); UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, false); UIFactory.AddHLG(row.hl, 2f); UIFactory.AddLE(row.hl, -1f, 30f, -1f, 30f, -1f, 0f); row.tierBtn = UIFactory.CreateButton("tb", row.hl.transform, "-", 18f, Color.black, new Color(0.18f, 0.2f, 0.24f, 0.85f), (UnityAction)delegate { if (!string.IsNullOrEmpty(row.cardName)) { CycleCardTierInPlace(row, row.cardName); } }, (Vector2?)new Vector2(CS_COL_W[0], 30f)); row.txtTier = UIFactory.GetButtonText(row.tierBtn); UIFactory.SetBold(row.txtTier, b: true); row.txtName = UIFactory.CreateText("t", row.hl.transform, "", 19f, C_WHITE, 513, (Vector2?)new Vector2(CS_COL_W[1], 30f), richText: true, raycastTarget: true); UIFactory.SetBold(row.txtName, b: true); row.txtRarity = UIFactory.CreateText("tr", row.hl.transform, "", 18f, C_LABEL, 514, (Vector2?)new Vector2(CS_COL_W[2], 30f), richText: true, raycastTarget: false); UIFactory.SetBold(row.txtRarity, b: true); row.txtPicks = UIFactory.CreateText("tp", row.hl.transform, "", 19f, C_WHITE, 514, (Vector2?)new Vector2(CS_COL_W[3], 30f), richText: true, raycastTarget: false); UIFactory.SetBold(row.txtPicks, b: true); row.txtWins = UIFactory.CreateText("tw", row.hl.transform, "", 19f, C_WHITE, 514, (Vector2?)new Vector2(CS_COL_W[4], 30f), richText: true, raycastTarget: false); UIFactory.SetBold(row.txtWins, b: true); row.txtWR = UIFactory.CreateText("wr", row.hl.transform, "", 19f, C_WHITE, 514, (Vector2?)new Vector2(CS_COL_W[5], 30f), richText: true, raycastTarget: false); UIFactory.SetBold(row.txtWR, b: true); row.txtPass = UIFactory.CreateText("pr", row.hl.transform, "", 19f, C_LABEL, 514, (Vector2?)new Vector2(CS_COL_W[6], 30f), richText: true, raycastTarget: false); UIFactory.SetBold(row.txtPass, b: true); try { object txtName = row.txtName; Component val2 = (Component)((txtName is Component) ? txtName : null); if ((Object)(object)val2 != (Object)null) { ClickHandler clickHandler = val2.gameObject.AddComponent(); clickHandler.onClick = delegate { if (ClickGuard.Claim() && !string.IsNullOrEmpty(row.cardName)) { ShowCardPreview(row.cardName); } }; } } catch { } GameObject val3 = new GameObject("S"); val3.transform.SetParent(row.root.transform, false); val3.AddComponent(); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, 1f); row.root.SetActive(false); return row; } private static CardStatTuple CST(bool p, string a, string s) { return new CardStatTuple { positive = p, amount = a, stat = s }; } private static string NormalizeStatLabel(string raw) { if (string.IsNullOrEmpty(raw)) { return raw; } string text = raw.Trim().ToUpperInvariant(); if (text.EndsWith(":")) { text = text.Substring(0, text.Length - 1).TrimEnd(); } switch (text) { case "DAMAGE": case "DMG": case "DAMAGE:": return "DMG"; case "ATTACK SPEED": case "ATKSPD": case "ATK SPEED": case "ATK SPD": return "ATK SPD"; case "BULLET SPEED": case "BULLET SPD": case "PROJ SPEED": case "PROJECTILE SPEED": return "BULLET SPD"; case "RELOAD": case "RELOAD TIME": case "RELOAD SPEED": case "RELOAD SPD": return "RELOAD"; case "BLOCK CD": case "BLOCK COOLDOWN": case "BLOCK COOLDOWN TIME": return "BLOCK CD"; case "HP": case "HEALTH": return "HP"; case "AMMO": case "MAGAZINE": case "MAG": return "AMMO"; case "BULLETS": case "BULLET COUNT": return "BULLETS"; case "BULLET": case "BULLET LOSS": return "BULLET"; case "LIFESTEAL": case "LIFE STEAL": return "LIFESTEAL"; case "BULLET BOUNCES": case "BOUNCES": return "BULLET BOUNCES"; case "BULLET BOUNCE": case "BOUNCE": return "BULLET BOUNCE"; case "BULLET SLOW": return "BULLET SLOW"; case "DRILL": case "WALL DRILL": case "DRILL THROUGH WALLS": return "DRILL"; case "SPLASH DMG": case "SPLASH DAMAGE": return "SPLASH DMG"; default: return text; } } private static string BuildStatBlockFromFallback(string cardName, int max) { if (string.IsNullOrEmpty(cardName)) { return ""; } string text = CardRarityLookup.GetCanonicalName(cardName) ?? cardName; string[] array = new string[2] { (text ?? "").ToLowerInvariant().Replace(" ", ""), (cardName ?? "").ToLowerInvariant().Replace(" ", "") }; CardStatTuple[] value = null; string[] array2 = array; foreach (string text2 in array2) { if (!string.IsNullOrEmpty(text2) && CARD_STATS_FALLBACK.TryGetValue(text2, out value)) { break; } } if (value == null || value.Length == 0) { return ""; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; for (int j = 0; j < value.Length; j++) { if (num >= max) { break; } CardStatTuple cardStatTuple = value[j]; string value2 = (cardStatTuple.positive ? "#88FF88" : "#FF8888"); if (stringBuilder.Length > 0) { stringBuilder.Append("\n"); } stringBuilder.Append("") .Append(cardStatTuple.amount) .Append(" ") .Append(cardStatTuple.stat); num++; } return stringBuilder.ToString(); } public static void ShowCardPreview(string cardName) { //IL_0582: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Expected O, but got Unknown //IL_05c2: Unknown result type (might be due to invalid IL or missing references) //IL_05cf: Unknown result type (might be due to invalid IL or missing references) //IL_05dc: Unknown result type (might be due to invalid IL or missing references) //IL_05e9: Unknown result type (might be due to invalid IL or missing references) //IL_0617: Unknown result type (might be due to invalid IL or missing references) //IL_0638: Unknown result type (might be due to invalid IL or missing references) //IL_0645: Unknown result type (might be due to invalid IL or missing references) //IL_0652: Unknown result type (might be due to invalid IL or missing references) //IL_065f: Unknown result type (might be due to invalid IL or missing references) //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_0730: Unknown result type (might be due to invalid IL or missing references) //IL_0747: Unknown result type (might be due to invalid IL or missing references) //IL_075e: Unknown result type (might be due to invalid IL or missing references) //IL_08eb: Unknown result type (might be due to invalid IL or missing references) //IL_092e: Unknown result type (might be due to invalid IL or missing references) //IL_0942: Unknown result type (might be due to invalid IL or missing references) //IL_0956: Unknown result type (might be due to invalid IL or missing references) //IL_095b: Unknown result type (might be due to invalid IL or missing references) //IL_0787: Unknown result type (might be due to invalid IL or missing references) //IL_07ae: Unknown result type (might be due to invalid IL or missing references) //IL_07b5: Expected O, but got Unknown //IL_0979: Unknown result type (might be due to invalid IL or missing references) //IL_098a: Unknown result type (might be due to invalid IL or missing references) //IL_09de: Unknown result type (might be due to invalid IL or missing references) //IL_09f2: Unknown result type (might be due to invalid IL or missing references) //IL_084b: Unknown result type (might be due to invalid IL or missing references) //IL_0a56: Unknown result type (might be due to invalid IL or missing references) //IL_0a6a: Unknown result type (might be due to invalid IL or missing references) //IL_0897: Unknown result type (might be due to invalid IL or missing references) //IL_08ab: Unknown result type (might be due to invalid IL or missing references) //IL_0cf5: Unknown result type (might be due to invalid IL or missing references) //IL_0d09: Unknown result type (might be due to invalid IL or missing references) //IL_0cb8: Unknown result type (might be due to invalid IL or missing references) //IL_0ccc: Unknown result type (might be due to invalid IL or missing references) //IL_0c77: Unknown result type (might be due to invalid IL or missing references) //IL_0c8b: Unknown result type (might be due to invalid IL or missing references) //IL_0c2d: Unknown result type (might be due to invalid IL or missing references) //IL_0c41: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(cardName)) { return; } HideCardPreview(); string lcTarget; string lcCanonical; try { Component val = null; string text = cardName; string text2 = "Unknown"; string text3 = ""; Array array = null; lcTarget = (cardName ?? "").ToLowerInvariant().Replace(" ", ""); string text4 = CardRarityLookup.GetCanonicalName(cardName) ?? cardName; lcCanonical = text4.ToLowerInvariant().Replace(" ", ""); try { Type type = (from a in AppDomain.CurrentDomain.GetAssemblies() select a.GetType("CardChoice")).FirstOrDefault((Type type5) => type5 != null); if (type != null) { object obj = type.GetField("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); Array arr = type.GetField("cards", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj) as Array; val = MatchInArray(arr); } if ((Object)(object)val == (Object)null) { CardInfo[] arr2 = Resources.FindObjectsOfTypeAll(); val = MatchInArray(arr2); } if ((Object)(object)val == (Object)null) { Plugin.Log.LogInfo((object)("[CARD-PREVIEW] CardInfo not found for '" + cardName + "' (canonical='" + text4 + "') — falling back to dict")); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CARD-PREVIEW] lookup: " + ex.Message)); } if ((Object)(object)val != (Object)null) { Type type2 = ((object)val).GetType(); FieldInfo field = type2.GetField("cardName", BindingFlags.Instance | BindingFlags.Public); FieldInfo field2 = type2.GetField("rarity", BindingFlags.Instance | BindingFlags.Public); FieldInfo fieldInfo = type2.GetField("cardDestription", BindingFlags.Instance | BindingFlags.Public) ?? type2.GetField("cardDescription", BindingFlags.Instance | BindingFlags.Public) ?? type2.GetField("description", BindingFlags.Instance | BindingFlags.Public); FieldInfo fieldInfo2 = type2.GetField("cardStats", BindingFlags.Instance | BindingFlags.Public) ?? type2.GetField("stats", BindingFlags.Instance | BindingFlags.Public); text = (field?.GetValue(val) as string) ?? cardName; object obj2 = field2?.GetValue(val); text2 = ((obj2 != null) ? obj2.ToString() : "Unknown"); text3 = (fieldInfo?.GetValue(val) as string) ?? ""; array = fieldInfo2?.GetValue(val) as Array; if (string.IsNullOrEmpty(text3)) { string text5 = (text4 ?? cardName ?? "").ToLowerInvariant().Replace(" ", ""); if (!string.IsNullOrEmpty(text5) && CARD_DESC_FALLBACK.TryGetValue(text5, out var value)) { text3 = value; } } if (string.IsNullOrEmpty(text3)) { try { string text6 = (text ?? "").ToLowerInvariant().Replace(" ", ""); string text7 = (text2 ?? "").ToLowerInvariant(); StringBuilder stringBuilder = new StringBuilder(); Type type3 = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type3 = assembly.GetType("TMPro.TMP_Text") ?? assembly.GetType("TMPro.TextMeshProUGUI"); if (type3 != null) { break; } } if (type3 != null) { PropertyInfo property = type3.GetProperty("text", BindingFlags.Instance | BindingFlags.Public); Component[] componentsInChildren = val.gameObject.GetComponentsInChildren(type3, true); Component[] array2 = componentsInChildren; foreach (Component val2 in array2) { if ((Object)(object)val2 == (Object)null || property == null) { continue; } string text8 = (property.GetValue(val2) as string) ?? ""; text8 = text8.Trim(); if (string.IsNullOrEmpty(text8)) { continue; } string text9 = text8.ToLowerInvariant().Replace(" ", ""); if (!(text9 == text6) && !(text9 == text7) && text8.Length >= 4 && text8.Length <= 200) { if (stringBuilder.Length > 0) { stringBuilder.Append("\n"); } stringBuilder.Append(text8); if (stringBuilder.Length > 240) { break; } } } } if (stringBuilder.Length > 0) { text3 = stringBuilder.ToString(); } } catch { } } } if (string.IsNullOrEmpty(text3)) { string text10 = (text4 ?? cardName ?? "").ToLowerInvariant().Replace(" ", ""); if (!string.IsNullOrEmpty(text10) && CARD_DESC_FALLBACK.TryGetValue(text10, out var value2)) { text3 = value2; } } EnsureOverlayCanvas(); cardPreviewGO = new GameObject("CR_CardPreview"); ((Object)cardPreviewGO).hideFlags = (HideFlags)61; cardPreviewGO.transform.SetParent(overlayCanvasGO.transform, false); RectTransform val3 = cardPreviewGO.AddComponent(); val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; GameObject val4 = UIFactory.CreatePanel("BD", cardPreviewGO.transform, new Color(0f, 0f, 0f, 0.45f)); RectTransform component = val4.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; Component component2 = val4.GetComponent(UIFactory.tImage); if ((Object)(object)component2 != (Object)null) { UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component2, true); } ClickHandler clickHandler = val4.AddComponent(); clickHandler.onClick = delegate { if (ClickGuard.Claim()) { HideCardPreview(); } }; Sprite sprite = CardImageLoader.GetSprite(cardName); GameObject val5 = UIFactory.CreatePanel("Card", cardPreviewGO.transform, new Color(0.1f, 0.12f, 0.16f, 0.97f)); RectTransform component3 = val5.GetComponent(); component3.anchorMin = new Vector2(0.5f, 0.5f); component3.anchorMax = new Vector2(0.5f, 0.5f); component3.pivot = new Vector2(0.5f, 0.5f); if ((Object)(object)sprite != (Object)null) { component3.sizeDelta = new Vector2(380f, 600f); UIFactory.AddVLG(val5, 6f, 10, 10, 10, 10); GameObject val6 = new GameObject("CardImg"); val6.transform.SetParent(val5.transform, false); val6.AddComponent(); Component obj4 = val6.AddComponent(UIFactory.tImage); PropertyInfo property2 = UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property3 = UIFactory.tImage.GetProperty("preserveAspect", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property4 = UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public); property2?.SetValue(obj4, sprite); property3?.SetValue(obj4, true); property4?.SetValue(obj4, Color.white); UIFactory.AddLE(val6, 360f, 545f, 360f, 545f, 0f, 0f); UIFactory.CreateText("CPHint", val5.transform, "click anywhere to close", 13f, C_DIM, 514, (Vector2?)new Vector2(360f, 20f), richText: true, raycastTarget: false); Plugin.Log.LogInfo((object)("[CARD-PREVIEW] showing image for '" + text + "'")); return; } component3.sizeDelta = new Vector2(440f, 360f); UIFactory.AddVLG(val5, 6f, 18, 18, 14, 14); UIFactory.CreateText("CPName", val5.transform, "" + text + "", 24f, C_WHITE, 514, (Vector2?)new Vector2(400f, 32f), richText: true, raycastTarget: false); Color rarityColor = GetRarityColor(text2); UIFactory.CreateText("CPRar", val5.transform, text2 ?? "Unknown", 16f, rarityColor, 514, (Vector2?)new Vector2(400f, 22f), richText: true, raycastTarget: false); if (!string.IsNullOrEmpty(text3)) { object t = UIFactory.CreateText("CPDesc", val5.transform, "" + text3 + "", 15f, new Color(0.85f, 0.88f, 0.95f), 514, (Vector2?)new Vector2(400f, 60f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t, on: true); } string text11 = null; if (array == null || array.Length == 0) { text11 = BuildStatBlockFromFallback(cardName, 8); } if (!string.IsNullOrEmpty(text11)) { object t2 = UIFactory.CreateText("CPStats", val5.transform, text11, 15f, C_LABEL, 257, (Vector2?)new Vector2(400f, 160f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t2, on: true); } else if (array != null && array.Length > 0) { StringBuilder stringBuilder2 = new StringBuilder(); for (int num3 = 0; num3 < array.Length; num3++) { object value3 = array.GetValue(num3); if (value3 != null) { Type type4 = value3.GetType(); string text12 = (type4.GetField("stat", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value3) as string) ?? ""; string value4 = (type4.GetField("amount", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value3) as string) ?? ""; bool flag = !(type4.GetField("positive", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value3) is bool flag2) || flag2; if (!string.IsNullOrEmpty(text12) || !string.IsNullOrEmpty(value4)) { string value5 = (flag ? "#88FF88" : "#FF6666"); stringBuilder2.Append(" ") .Append(value4) .Append(" ") .Append(NormalizeStatLabel(text12)) .Append("\n"); } } } string text13 = stringBuilder2.ToString().TrimEnd('\n'); if (!string.IsNullOrEmpty(text13)) { object t3 = UIFactory.CreateText("CPStats", val5.transform, text13, 15f, C_LABEL, 257, (Vector2?)new Vector2(400f, 160f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t3, on: true); } else { UIFactory.CreateText("CPStatsEmpty", val5.transform, "(Mechanic isn't expressed as numerical stats — check the card description above or pick it in-game.)", 13f, C_DIM, 514, (Vector2?)new Vector2(400f, 60f), richText: true, raycastTarget: false); } } else { UIFactory.CreateText("CPNoStats", val5.transform, "No stat data available for this card.", 13f, C_DIM, 514, (Vector2?)new Vector2(400f, 28f), richText: true, raycastTarget: false); } UIFactory.CreateText("CPHint", val5.transform, "click anywhere to close", 13f, C_DIM, 514, (Vector2?)new Vector2(400f, 18f), richText: true, raycastTarget: false); Plugin.Log.LogInfo((object)("[CARD-PREVIEW] showing text fallback for '" + text + "' (rarity=" + text2 + ")")); Component MatchInArray(IEnumerable enumerable) { if (enumerable == null) { return null; } foreach (object item in enumerable) { Component val7 = (Component)((item is Component) ? item : null); if (!((Object)(object)val7 == (Object)null)) { string s = ((Object)val7.gameObject).name?.Replace("(Clone)", "").Trim() ?? ""; string s2 = (((object)val7).GetType().GetField("cardName", BindingFlags.Instance | BindingFlags.Public)?.GetValue(val7) as string) ?? ""; if (Matches(s) || Matches(s2)) { return val7; } } } return null; } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[CARD-PREVIEW] failed: " + ex2.Message)); } bool Matches(string s) { if (string.IsNullOrEmpty(s)) { return false; } string text14 = s.ToLowerInvariant().Replace(" ", ""); return text14 == lcTarget || text14 == lcCanonical; } } public static void HideCardPreview() { try { if ((Object)(object)cardPreviewGO != (Object)null) { Object.Destroy((Object)(object)cardPreviewGO); cardPreviewGO = null; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CARD-PREVIEW] destroy: " + ex.Message)); } } public static void ShowInfoPopup(string title, string body) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_00aa: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) try { HideInfoPopup(); EnsureOverlayCanvas(); infoPopupGO = new GameObject("CR_InfoPopup"); ((Object)infoPopupGO).hideFlags = (HideFlags)61; infoPopupGO.transform.SetParent(overlayCanvasGO.transform, false); RectTransform val = infoPopupGO.AddComponent(); val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.offsetMin = Vector2.zero; val.offsetMax = Vector2.zero; GameObject bd = UIFactory.CreatePanel("BD", infoPopupGO.transform, new Color(0f, 0f, 0f, 0.55f)); RectTransform component = bd.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; Component component2 = bd.GetComponent(UIFactory.tImage); if ((Object)(object)component2 != (Object)null) { UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component2, true); } ClickHandler clickHandler = bd.AddComponent(); clickHandler.bypassModalBlock = true; clickHandler.onClick = delegate { if (ClickGuard.Claim(bd)) { HideInfoPopup(); } }; GameObject val2 = UIFactory.CreatePanel("Box", infoPopupGO.transform, new Color(0.1f, 0.12f, 0.16f, 0.97f)); RectTransform component3 = val2.GetComponent(); component3.anchorMin = new Vector2(0.5f, 0.5f); component3.anchorMax = new Vector2(0.5f, 0.5f); component3.pivot = new Vector2(0.5f, 0.5f); float num = 1010f; try { RectTransform component4 = overlayCanvasGO.GetComponent(); if ((Object)(object)component4 != (Object)null) { Rect rect = component4.rect; if (((Rect)(ref rect)).height > 200f) { rect = component4.rect; num = Mathf.Min(1010f, ((Rect)(ref rect)).height - 40f); } } } catch { } component3.sizeDelta = new Vector2(960f, num); UIFactory.AddVLG(val2, 10f, 30, 30, 22, 20); UIFactory.CreateText("IPTitle", val2.transform, title ?? "", 34f, C_GOLD, 514, (Vector2?)new Vector2(900f, 46f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("IPScroll", val2.transform, 0f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, 880f, -1f, 1f); object obj2 = UIFactory.CreateText("IPBody", scrollViewRefs.content.transform, body ?? "", 24f, C_LABEL, 257, (Vector2?)new Vector2(890f, 860f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(obj2, on: true); UIFactory.SetTextAutoHeight(obj2); UIFactory.CreateText("IPHint", val2.transform, "click anywhere to close", 22f, C_DIM, 514, (Vector2?)new Vector2(900f, 34f), richText: true, raycastTarget: false); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[INFO-POPUP] show: " + ex.Message)); } } public static void HideInfoPopup() { try { if ((Object)(object)infoPopupGO != (Object)null) { Object.Destroy((Object)(object)infoPopupGO); infoPopupGO = null; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[INFO-POPUP] destroy: " + ex.Message)); } } public static void LoadCardTiersForCurrentFilter() { string filter = ((cardFilter == 1) ? "ranked" : ((cardFilter == 2) ? "casual" : "all")); int filterIdx = cardFilter; ApiClient.FetchCardTiers(MatchTracker.LocalSteamId, filter, delegate(Dictionary loaded) { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair item in cardTierMap) { if (!item.Key.StartsWith($"{filterIdx}|")) { dictionary[item.Key] = item.Value; } } cardTierMap = dictionary; foreach (KeyValuePair item2 in loaded) { cardTierMap[CardTierKey(filterIdx, item2.Key)] = item2.Value; } _tierFiltersLoaded.Add(filterIdx); dirty = true; }); } private static GameObject BuildAchievementsTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_010b: Expected O, but got Unknown //IL_015f: 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_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Expected O, but got Unknown //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Expected O, but got Unknown //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Expected O, but got Unknown //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Expected O, but got Unknown //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Expected O, but got Unknown //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Expected O, but got Unknown //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Expected O, but got Unknown //IL_05a9: Unknown result type (might be due to invalid IL or missing references) //IL_05bd: Unknown result type (might be due to invalid IL or missing references) //IL_05d8: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Expected O, but got Unknown //IL_0651: Unknown result type (might be due to invalid IL or missing references) //IL_0665: Unknown result type (might be due to invalid IL or missing references) //IL_0692: Unknown result type (might be due to invalid IL or missing references) //IL_06a6: Unknown result type (might be due to invalid IL or missing references) //IL_06d9: Unknown result type (might be due to invalid IL or missing references) //IL_06ed: Unknown result type (might be due to invalid IL or missing references) //IL_071b: Unknown result type (might be due to invalid IL or missing references) //IL_0725: Expected O, but got Unknown //IL_076a: Unknown result type (might be due to invalid IL or missing references) //IL_0774: Expected O, but got Unknown //IL_07e2: Unknown result type (might be due to invalid IL or missing references) //IL_0855: Unknown result type (might be due to invalid IL or missing references) //IL_0869: Unknown result type (might be due to invalid IL or missing references) //IL_08e1: Unknown result type (might be due to invalid IL or missing references) //IL_08f5: Unknown result type (might be due to invalid IL or missing references) //IL_057b: Unknown result type (might be due to invalid IL or missing references) //IL_0977: Unknown result type (might be due to invalid IL or missing references) //IL_0981: Expected O, but got Unknown //IL_09eb: Unknown result type (might be due to invalid IL or missing references) //IL_09f2: Expected O, but got Unknown //IL_0a51: Unknown result type (might be due to invalid IL or missing references) //IL_0a56: Unknown result type (might be due to invalid IL or missing references) //IL_0a84: Unknown result type (might be due to invalid IL or missing references) //IL_0ab1: Unknown result type (might be due to invalid IL or missing references) //IL_0ac5: Unknown result type (might be due to invalid IL or missing references) //IL_0af4: Unknown result type (might be due to invalid IL or missing references) //IL_0af9: Unknown result type (might be due to invalid IL or missing references) //IL_0a6f: Unknown result type (might be due to invalid IL or missing references) //IL_0a74: Unknown result type (might be due to invalid IL or missing references) //IL_0a7a: Expected O, but got Unknown //IL_0b27: Unknown result type (might be due to invalid IL or missing references) //IL_0b40: Unknown result type (might be due to invalid IL or missing references) //IL_0b47: Expected O, but got Unknown //IL_0b12: Unknown result type (might be due to invalid IL or missing references) //IL_0b17: Unknown result type (might be due to invalid IL or missing references) //IL_0b1d: Expected O, but got Unknown GameObject val = new GameObject("AchOuter"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 0f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(3, val.transform, asFirst: true); GameObject val2 = new GameObject("Achievements"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddVLG(val2, 6f, 20, 20, 10); UIFactory.AddLE(val2, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.CreateText("AchH", val2.transform, "Achievements", 22f, C_GOLD, 258, (Vector2?)new Vector2(600f, 30f), richText: true, raycastTarget: false); GameObject val3 = new GameObject("AchCnt"); val3.transform.SetParent(val2.transform, false); val3.AddComponent(); UIFactory.AddLE(val3, -1f, -1f, -1f, 22f); txtAchCount = UIFactory.CreateText("AC", val3.transform, "", 15f, C_DIM, 514, (Vector2?)new Vector2(400f, 22f), richText: true, raycastTarget: false); GameObject val4 = new GameObject("AchSort"); val4.transform.SetParent(val2.transform, false); val4.AddComponent(); UIFactory.AddHLG(val4, 6f); UIFactory.AddLE(val4, -1f, -1f, -1f, 24f, -1f, 0f); UIFactory.CreateText("AchSortL", val4.transform, "Sort:", 14f, C_DIM, 513, (Vector2?)new Vector2(46f, 22f), richText: true, raycastTarget: false); Transform transform = val4.transform; Color c_WHITE = C_WHITE; Color c_BTN = C_BTN; object obj = <>c.<>9__435_0; if (obj == null) { UnityAction val5 = delegate { achSort = "default"; achSortDesc = false; dirty = true; }; <>c.<>9__435_0 = val5; obj = (object)val5; } achSortDefBtn = UIFactory.CreateButton("AchSD", transform, "Default", 12f, c_WHITE, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(72f, 22f)); Transform transform2 = val4.transform; Color c_WHITE2 = C_WHITE; Color c_BTN2 = C_BTN; object obj2 = <>c.<>9__435_1; if (obj2 == null) { UnityAction val6 = delegate { if (achSort == "rarity") { achSortDesc = !achSortDesc; } else { achSort = "rarity"; achSortDesc = false; } dirty = true; }; <>c.<>9__435_1 = val6; obj2 = (object)val6; } achSortRarBtn = UIFactory.CreateButton("AchSR", transform2, "Rarity", 12f, c_WHITE2, c_BTN2, (UnityAction)obj2, (Vector2?)new Vector2(72f, 22f)); Transform transform3 = val4.transform; Color c_WHITE3 = C_WHITE; Color c_BTN3 = C_BTN; object obj3 = <>c.<>9__435_2; if (obj3 == null) { UnityAction val7 = delegate { if (achSort == "gold") { achSortDesc = !achSortDesc; } else { achSort = "gold"; achSortDesc = false; } dirty = true; }; <>c.<>9__435_2 = val7; obj3 = (object)val7; } achSortGoldBtn = UIFactory.CreateButton("AchSG", transform3, "Gold", 12f, c_WHITE3, c_BTN3, (UnityAction)obj3, (Vector2?)new Vector2(72f, 22f)); Transform transform4 = val4.transform; Color c_WHITE4 = C_WHITE; Color c_BTN4 = C_BTN; object obj4 = <>c.<>9__435_3; if (obj4 == null) { UnityAction val8 = delegate { if (achSort == "date") { achSortDesc = !achSortDesc; } else { achSort = "date"; achSortDesc = false; } dirty = true; }; <>c.<>9__435_3 = val8; obj4 = (object)val8; } achSortDateBtn = UIFactory.CreateButton("AchSDt", transform4, "Date earned", 12f, c_WHITE4, c_BTN4, (UnityAction)obj4, (Vector2?)new Vector2(100f, 22f)); UIFactory.CreateText("AchClickHint", val4.transform, "click an achievement to see who earned it", 12f, C_DIM, 513, (Vector2?)new Vector2(320f, 22f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("AchSV", val2.transform, 4f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); achRows.Clear(); int num = 0; foreach (KeyValuePair achievementDef in ApiClient.AchievementDefs) { AchRow achRow = new AchRow(); string key = achievementDef.Key; string[] value = achievementDef.Value; achRow.key = key; achRow.root = new GameObject("ach_" + key); achRow.root.transform.SetParent(scrollViewRefs.content.transform, false); achRow.root.AddComponent(); UIFactory.AddVLG(achRow.root); achRow.main = new GameObject("main"); achRow.main.transform.SetParent(achRow.root.transform, false); achRow.main.AddComponent(); UIFactory.AddHLG(achRow.main, 10f, 8, 8, 6, 6); UIFactory.AddLE(achRow.main, -1f, -1f, -1f, 50f, -1f, 0f); if (UIFactory.tImage != null) { Component obj5 = achRow.main.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj5, C_PANEL); } achRow.txtIcon = UIFactory.CreateText("ic", achRow.main.transform, "", 24f, C_DIM, 514, (Vector2?)new Vector2(36f, 40f), richText: true, raycastTarget: false); GameObject val9 = new GameObject("Info"); val9.transform.SetParent(achRow.main.transform, false); val9.AddComponent(); UIFactory.AddVLG(val9, 1f); UIFactory.AddLE(val9, -1f, -1f, -1f, -1f, 1f); achRow.txtName = UIFactory.CreateText("nm", val9.transform, value[0], 17f, C_WHITE, 513, (Vector2?)new Vector2(500f, 22f), richText: true, raycastTarget: false); achRow.txtDesc = UIFactory.CreateText("ds", val9.transform, value[1], 14f, C_LABEL, 513, (Vector2?)new Vector2(500f, 20f), richText: true, raycastTarget: false); achRow.txtDate = UIFactory.CreateText("dt", achRow.main.transform, "", 13f, C_DIM, 516, (Vector2?)new Vector2(180f, 40f), richText: true, raycastTarget: false); int _ci = num; UIFactory.AddClick(achRow.main, (UnityAction)delegate { OnAchievementRowClicked(_ci); }); achRow.root.SetActive(true); achRows.Add(achRow); num++; } achEarnersStash = new GameObject("AchEarnStash"); achEarnersStash.transform.SetParent(val2.transform, false); achEarnersStash.AddComponent(); UIFactory.AddLE(achEarnersStash, -1f, 0f, -1f, 0f, -1f, 0f); achEarnersPanel = UIFactory.CreatePanel("AchEarn", achEarnersStash.transform, new Color(0.1f, 0.12f, 0.17f, 0.95f)); UIFactory.AddVLG(achEarnersPanel, 2f, 14, 10, 5, 5); UIFactory.AddLE(achEarnersPanel, -1f, 34f, -1f, 96f, -1f, 0f); achEarnersHdr = UIFactory.CreateText("AeH", achEarnersPanel.transform, "", 14f, C_GOLD, 257, (Vector2?)new Vector2(900f, 20f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("AeSV", achEarnersPanel.transform, 0f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); achEarnersBody = UIFactory.CreateText("AeB", scrollViewRefs2.content.transform, "", 13f, C_WHITE, 257, (Vector2?)new Vector2(900f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(achEarnersBody, on: true); object obj6 = achEarnersBody; object obj7 = ((obj6 is Component) ? obj6 : null); Component val10 = ((obj7 != null) ? ((Component)obj7).gameObject.GetComponent(UIFactory.tLE) : null); if ((Object)(object)val10 != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(val10, -1f); } achEarnPager = new GameObject("AePg"); achEarnPager.transform.SetParent(achEarnersPanel.transform, false); achEarnPager.AddComponent(); UIFactory.AddHLG(achEarnPager, 6f); UIFactory.AddLE(achEarnPager, -1f, -1f, -1f, 18f, -1f, 0f); GameObject val11 = new GameObject("S"); val11.transform.SetParent(achEarnPager.transform, false); val11.AddComponent(); UIFactory.AddLE(val11, -1f, -1f, -1f, -1f, 1f); Transform transform5 = achEarnPager.transform; Color c_LABEL = C_LABEL; Color c_BTN5 = C_BTN; object obj8 = <>c.<>9__435_4; if (obj8 == null) { UnityAction val12 = delegate { if (achEarnersPage > 0) { achEarnersPage--; dirty = true; } }; <>c.<>9__435_4 = val12; obj8 = (object)val12; } achEarnPrev = UIFactory.CreateButton("aeP", transform5, "< Prev", 10f, c_LABEL, c_BTN5, (UnityAction)obj8, (Vector2?)new Vector2(50f, 16f)); txtAchEarnPage = UIFactory.CreateText("aePI", achEarnPager.transform, "", 10f, C_LABEL, 514, (Vector2?)new Vector2(40f, 16f), richText: true, raycastTarget: false); Transform transform6 = achEarnPager.transform; Color c_LABEL2 = C_LABEL; Color c_BTN6 = C_BTN; object obj9 = <>c.<>9__435_5; if (obj9 == null) { UnityAction val13 = delegate { achEarnersPage++; dirty = true; }; <>c.<>9__435_5 = val13; obj9 = (object)val13; } achEarnNext = UIFactory.CreateButton("aeN", transform6, "Next >", 10f, c_LABEL2, c_BTN6, (UnityAction)obj9, (Vector2?)new Vector2(50f, 16f)); GameObject val14 = new GameObject("S2"); val14.transform.SetParent(achEarnPager.transform, false); val14.AddComponent(); UIFactory.AddLE(val14, -1f, -1f, -1f, -1f, 1f); achEarnPager.SetActive(false); achEarnersPanel.SetActive(false); return val; } private static void OnAchievementRowClicked(int rowIdx) { try { if (rowIdx < 0 || rowIdx >= achRows.Count) { return; } string key = achRows[rowIdx].key; if (!string.IsNullOrEmpty(key)) { if (achSelectedKey == key) { achSelectedKey = null; dirty = true; return; } achSelectedKey = key; achEarnersPage = 0; ApiClient.FetchAchievementEarners(key); dirty = true; } } catch { } } private static void RefreshAchievements() { //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) Dictionary ach = ApiClient.CachedAchievements; int count = ApiClient.AchievementDefs.Count; Func goldOf = delegate(string k) { int num11 = ((ach != null && ach.ContainsKey(k)) ? ach[k].gold : 0); if (num11 <= 0) { num11 = ((k == "regicide" || k == "stan_slayer") ? 1000 : 100); } return num11; }; Func pctOf = (string k) => (ach != null && ach.ContainsKey(k)) ? ach[k].global_pct : 0f; Func gotOf = (string k) => ach != null && ach.ContainsKey(k) && ach[k].unlocked; Func dateOf = delegate(string k) { if (gotOf(k)) { string unlocked_at2 = ach[k].unlocked_at; if (!string.IsNullOrEmpty(unlocked_at2) && unlocked_at2 != "null") { try { return DateTime.Parse(unlocked_at2); } catch { } } } return DateTime.MinValue; }; List list = new List(ApiClient.AchievementDefs.Keys); switch (achSort) { case "rarity": list.Sort((string a, string b) => pctOf(a).CompareTo(pctOf(b))); break; case "gold": list.Sort((string a, string b) => goldOf(b).CompareTo(goldOf(a))); break; case "date": list.Sort((string a, string b) => dateOf(b).CompareTo(dateOf(a))); break; } if (achSortDesc && achSort != "default") { list.Reverse(); } int num = 0; int num2 = 0; foreach (string item in list) { if (num2 >= achRows.Count) { break; } AchRow achRow = achRows[num2]; string[] array = ApiClient.AchievementDefs[item]; achRow.key = item; bool flag = gotOf(item); if (flag) { num++; } UIFactory.SetText(achRow.txtIcon, flag ? "[X]" : "[ ]"); UIFactory.SetColor(achRow.txtIcon, (Color)(flag ? C_GOLD : new Color(0.3f, 0.3f, 0.35f))); UIFactory.SetText(achRow.txtName, array[0]); UIFactory.SetColor(achRow.txtName, flag ? C_WHITE : C_DIM); float num3 = pctOf(item); string text = array[1]; if (num3 > 0f) { text += $" {num3:F1}% of players have this"; } UIFactory.SetText(achRow.txtDesc, text); UIFactory.SetColor(achRow.txtDesc, (Color)(flag ? C_LABEL : new Color(0.4f, 0.4f, 0.45f))); int num4 = goldOf(item); string s = (flag ? "" : $"+{num4}g"); if (flag) { string arg = ""; string unlocked_at = ach[item].unlocked_at; if (!string.IsNullOrEmpty(unlocked_at) && unlocked_at != "null") { try { arg = DateTime.Parse(unlocked_at).ToString("M/d/yyyy"); } catch { } } s = $"{arg} +{num4}g"; } UIFactory.SetText(achRow.txtDate, s); UIFactory.SetColor(achRow.txtDate, flag ? C_GREEN : C_DIM); try { if (UIFactory.tImage != null && (Object)(object)achRow.main != (Object)null) { Component component = achRow.main.GetComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (object)(Color)((item == achSelectedKey) ? new Color(0.22f, 0.25f, 0.34f, 0.95f) : C_PANEL)); } } catch { } num2++; } UIFactory.SetText(txtAchCount, $"{num} / {count} unlocked"); UIFactory.SetColor(txtAchCount, (num == count) ? C_GOLD : C_LABEL); try { UIFactory.SetImageColor(achSortDefBtn, (achSort == "default") ? C_TABACT : C_BTN); UIFactory.SetImageColor(achSortRarBtn, (achSort == "rarity") ? C_TABACT : C_BTN); UIFactory.SetImageColor(achSortGoldBtn, (achSort == "gold") ? C_TABACT : C_BTN); UIFactory.SetImageColor(achSortDateBtn, (achSort == "date") ? C_TABACT : C_BTN); } catch { } try { if (!((Object)(object)achEarnersPanel != (Object)null)) { return; } bool flag2 = !string.IsNullOrEmpty(achSelectedKey); AchRow achRow2 = null; if (flag2) { foreach (AchRow achRow3 in achRows) { if (achRow3.key == achSelectedKey) { achRow2 = achRow3; break; } } } Transform val = ((flag2 && achRow2 != null) ? achRow2.root.transform : achEarnersStash.transform); if ((Object)(object)achEarnersPanel.transform.parent != (Object)(object)val) { achEarnersPanel.transform.SetParent(val, false); achEarnersPanel.transform.SetAsLastSibling(); } achEarnersPanel.SetActive(flag2 && achRow2 != null); if (!flag2 || achRow2 == null) { return; } string text2 = (ApiClient.AchievementDefs.ContainsKey(achSelectedKey) ? ApiClient.AchievementDefs[achSelectedKey][0] : achSelectedKey); if (ApiClient.EarnersKey == achSelectedKey && ApiClient.CachedEarners != null) { List cachedEarners = ApiClient.CachedEarners; int num5 = Math.Max(ApiClient.CachedEarnersTotal, cachedEarners.Count); UIFactory.SetText(achEarnersHdr, string.Format("Earned by {0} player{1} (in the order they got it - click again to close)", num5, (num5 == 1) ? "" : "s")); int num6 = Math.Max(1, (cachedEarners.Count + 20 - 1) / 20); if (achEarnersPage > num6 - 1) { achEarnersPage = num6 - 1; } if (achEarnersPage < 0) { achEarnersPage = 0; } int num7 = 1; if (cachedEarners.Count == 0) { UIFactory.SetText(achEarnersBody, "Nobody has earned this yet. Be the first!"); } else { int num8 = achEarnersPage * 20; int num9 = Math.Min(num8 + 20, cachedEarners.Count); num7 = num9 - num8; StringBuilder stringBuilder = new StringBuilder(); for (int num10 = num8; num10 < num9; num10++) { ApiClient.AchEarnerData achEarnerData = cachedEarners[num10]; string text3 = ((achEarnerData.rating >= 0) ? achEarnerData.rating.ToString() : "--"); string text4 = ""; if (!string.IsNullOrEmpty(achEarnerData.unlocked_at) && achEarnerData.unlocked_at != "null") { try { text4 = DateTime.Parse(achEarnerData.unlocked_at).ToString("M/d/yyyy"); } catch { } } string text5 = ""; if (!string.IsNullOrEmpty(achEarnerData.title)) { string text6 = (string.IsNullOrEmpty(achEarnerData.title_color) ? "#CCCCCC" : achEarnerData.title_color); text5 = " [" + achEarnerData.title + "]"; } stringBuilder.Append($"{num10 + 1}. {Trunc(achEarnerData.display_name, 24)}{text5} {text3} {text4}\n"); } UIFactory.SetText(achEarnersBody, stringBuilder.ToString()); } bool flag3 = num6 > 1; if ((Object)(object)achEarnPager != (Object)null) { achEarnPager.SetActive(flag3); } if (flag3) { UIFactory.SetText(txtAchEarnPage, $"{achEarnersPage + 1}/{num6}"); if ((Object)(object)achEarnPrev != (Object)null) { achEarnPrev.SetActive(achEarnersPage > 0); } if ((Object)(object)achEarnNext != (Object)null) { achEarnNext.SetActive(achEarnersPage + 1 < num6); } } UIFactory.SetPrefH(achEarnersPanel, Mathf.Clamp(34f + (float)num7 * 19f + (flag3 ? 22f : 0f), 52f, 470f)); } else { UIFactory.SetText(achEarnersHdr, "loading earners..."); UIFactory.SetText(achEarnersBody, ""); if ((Object)(object)achEarnPager != (Object)null) { achEarnPager.SetActive(false); } UIFactory.SetPrefH(achEarnersPanel, 52f); } } catch { } } private static GameObject BuildArtistTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Expected O, but got Unknown //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03d1: Expected O, but got Unknown //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Expected O, but got Unknown //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) //IL_04a1: Unknown result type (might be due to invalid IL or missing references) //IL_04a7: Expected O, but got Unknown //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0536: Expected O, but got Unknown //IL_058e: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_050a: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Expected O, but got Unknown GameObject val = new GameObject("Artist"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 6f, 20, 20, 10, 10); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(10, val.transform, asFirst: true); UIFactory.CreateText("ArtH", val.transform, "Artist Studio", 22f, C_GOLD, 257, (Vector2?)new Vector2(600f, 30f), richText: true, raycastTarget: false); UIFactory.CreateText("ArtHint", val.transform, "Manage your cosmetics and earn 30% of every sale. Scale/placement changes return to admin review; badly scaled, obstructive, or misplaced art may be rejected or adjusted by an admin.", 13f, C_LABEL, 257, (Vector2?)new Vector2(900f, 32f), richText: true, raycastTarget: false); txtArtistStatus = UIFactory.CreateText("ArtSt", val.transform, "", 14f, C_LABEL, 257, (Vector2?)new Vector2(900f, 22f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("ArtSV", val.transform, 4f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); artistItemsContainer = scrollViewRefs.content; UIFactory.CreateText("ArtSalesH", val.transform, "Sales log (every purchase and gift of your items, newest first)", 16f, C_WHITE, 257, (Vector2?)new Vector2(900f, 24f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("ArtSalesSV", val.transform, 0f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, 100f, -1f, 150f, -1f, 0f); txtArtistSales = UIFactory.CreateText("ArtSales", scrollViewRefs2.content.transform, "No sales yet.", 13f, C_WHITE, 257, (Vector2?)new Vector2(900f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtArtistSales, on: true); object obj = txtArtistSales; object obj2 = ((obj is Component) ? obj : null); Component val2 = ((obj2 != null) ? ((Component)obj2).gameObject.GetComponent(UIFactory.tLE) : null); if ((Object)(object)val2 != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(val2, -1f); } object obj3 = UIFactory.CreateText("ArtBH", val.transform, "Blocked buyers (can't purchase your items; gifts still work)", 16f, C_WHITE, 257, (Vector2?)new Vector2(900f, 24f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("ArtBSV", val.transform, 3f); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, 90f, -1f, 130f, -1f, 0f); artistBlocksContainer = scrollViewRefs3.content; GameObject val3 = new GameObject("ArtBlockRow"); val3.transform.SetParent(val.transform, false); val3.AddComponent(); UIFactory.AddHLG(val3, 8f); UIFactory.AddLE(val3, -1f, 32f, -1f, 32f, -1f, 0f); Transform transform = val3.transform; Color c_WHITE = C_WHITE; Color bgColor = new Color(0.5f, 0.2f, 0.2f, 0.9f); object obj4 = <>c.<>9__450_0; if (obj4 == null) { UnityAction val4 = delegate { CompetitiveUI.OpenPlayerSearch("Block a buyer - find the player", delegate(string sid, string pname) { if (!string.IsNullOrEmpty(sid)) { string localSteamId = MatchTracker.LocalSteamId; ApiClient.ArtistBlock(localSteamId, sid, block: true, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Blocked " + pname + ".") : resp); }); } }); }; <>c.<>9__450_0 = val4; obj4 = (object)val4; } UIFactory.CreateButton("ArtBlockBtn", transform, "Block a player...", 14f, c_WHITE, bgColor, (UnityAction)obj4, (Vector2?)new Vector2(190f, 28f)); Transform transform2 = val3.transform; Color c_WHITE2 = C_WHITE; Color bgColor2 = new Color(0.2f, 0.4f, 0.55f, 0.9f); object obj5 = <>O.<1>__StartCosmeticUpload; if (obj5 == null) { UnityAction val5 = StartCosmeticUpload; <>O.<1>__StartCosmeticUpload = val5; obj5 = (object)val5; } UIFactory.CreateButton("ArtUpBtn", transform2, "Upload a cosmetic...", 14f, c_WHITE2, bgColor2, (UnityAction)obj5, (Vector2?)new Vector2(190f, 28f)); Transform transform3 = val3.transform; Color c_WHITE3 = C_WHITE; Color bgColor3 = new Color(0.25f, 0.35f, 0.55f, 0.95f); object obj6 = <>c.<>9__450_1; if (obj6 == null) { UnityAction val6 = delegate { try { string text = CosmeticUploadDir(); Application.OpenURL("file:///" + text.Replace('\\', '/')); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] open folder: " + ex.Message)); } }; <>c.<>9__450_1 = val6; obj6 = (object)val6; } UIFactory.CreateButton("ArtUpDir", transform3, "Open upload folder", 14f, c_WHITE3, bgColor3, (UnityAction)obj6, (Vector2?)new Vector2(180f, 28f)); Transform transform4 = val3.transform; Color c_WHITE4 = C_WHITE; Color bgColor4 = new Color(0.35f, 0.3f, 0.55f, 0.95f); object obj7 = <>O.<2>__StartCosmeticPlacementAdjustment; if (obj7 == null) { UnityAction val7 = StartCosmeticPlacementAdjustment; <>O.<2>__StartCosmeticPlacementAdjustment = val7; obj7 = (object)val7; } UIFactory.CreateButton("ArtPlace", transform4, "Adjust placement...", 14f, c_WHITE4, bgColor4, (UnityAction)obj7, (Vector2?)new Vector2(175f, 28f)); GameObject val8 = new GameObject("S"); val8.transform.SetParent(val3.transform, false); val8.AddComponent(); UIFactory.AddLE(val8, -1f, -1f, -1f, -1f, 1f); txtArtistSubs = UIFactory.CreateText("ArtSubs", val.transform, "", 13f, C_LABEL, 257, (Vector2?)new Vector2(900f, 20f), richText: true, raycastTarget: false); UIFactory.SetTextAutoHeight(txtArtistSubs); UIFactory.SetWordWrap(txtArtistSubs, on: true); return val; } private static string CosmeticUploadDir() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, "cosmetic-uploads"); Directory.CreateDirectory(text); return text; } private static void StartCosmeticUpload() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) try { string text = CosmeticUploadDir(); string[] files = Directory.GetFiles(text, "*.png"); if (files.Length == 0) { CompetitiveUI.ShowNotification("Drop a 512x512 transparent PNG into the upload folder first - opening it now.", new Color(1f, 0.8f, 0.4f), 6f); Application.OpenURL("file:///" + text.Replace('\\', '/')); return; } string[] array = new string[files.Length]; string[] array2 = new string[files.Length]; for (int i = 0; i < files.Length; i++) { array[i] = Path.GetFileName(files[i]); array2[i] = files[i]; } CompetitiveUI.OpenArtistPicker("Pick the PNG to submit", array, array2, ValidateAndNameCosmetic, "Next", showClear: false); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] upload start: " + ex.Message)); } } private static void ValidateAndNameCosmetic(string path) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown try { if (string.IsNullOrEmpty(path) || !File.Exists(path)) { return; } byte[] bytes = File.ReadAllBytes(path); if (bytes.Length > 1200000) { ShowArtistResult(ok: false, "{\"detail\":\"PNG too large - 1 MB max\"}"); return; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); bool flag = ImageConversion.LoadImage(val, bytes); int width = ((Texture)val).width; int height = ((Texture)val).height; int num = 0; int num2 = 1; if (flag) { Color32[] pixels = val.GetPixels32(); num2 = pixels.Length; for (int i = 0; i < pixels.Length; i++) { if (pixels[i].a < 250) { num++; } } } Object.Destroy((Object)(object)val); if (!flag) { ShowArtistResult(ok: false, "{\"detail\":\"that file is not a readable PNG\"}"); return; } if (width != 512 || height != 512) { ShowArtistResult(ok: false, $"{{\"detail\":\"must be exactly 512x512 - this one is {width}x{height}\"}}"); return; } if (num < num2 / 50) { ShowArtistResult(ok: false, "{\"detail\":\"no transparent background detected - export with an alpha layer\"}"); return; } CompetitiveUI.OpenArtistInput("Name your cosmetic", "Display name (letters/numbers, max 40)", "", delegate(string nm) { if (string.IsNullOrEmpty(nm) || nm.Trim().Length < 2) { ShowArtistResult(ok: false, "{\"detail\":\"name too short\"}"); } else { PickSlotAndSubmitCosmetic(bytes, nm.Trim()); } }); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COSMETIC] validate: " + ex.Message)); } } private static void PickSlotAndSubmitCosmetic(byte[] bytes, string name) { CompetitiveUI.OpenArtistPicker("What type of cosmetic is '" + name + "'?", new string[3] { "Eyes", "Mouth", "Detail (hat / accessory)" }, new string[3] { "eyes", "mouth", "detail" }, delegate(string slot) { if (!string.IsNullOrEmpty(slot)) { CompetitiveUI.OpenCosmeticTestPreview(bytes, name, slot, delegate(float renderScale, float renderOffsetX, float renderOffsetY) { string pngBase = Convert.ToBase64String(bytes); ApiClient.ArtistSubmitCosmetic(MatchTracker.LocalSteamId, name, slot, pngBase, renderScale, renderOffsetX, renderOffsetY, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? ("'" + name + "' submitted for scale/placement review. You'll see the status on this tab.") : resp); }); }); } }, "Preview", showClear: false); } private static void StartCosmeticPlacementAdjustment() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (cosmeticPlacementLoading) { CompetitiveUI.ShowNotification("The selected cosmetic is still loading.", new Color(0.55f, 0.75f, 1f), 3f); return; } List cachedMySubmissions = ApiClient.CachedMySubmissions; List list = ((cachedMySubmissions == null) ? new List() : cachedMySubmissions.Where((ApiClient.CosmeticSubmission s) => s != null && (s.status == "pending" || s.status == "approved")).ToList()); HashSet linkedSkus = new HashSet(from s in list where !string.IsNullOrEmpty(s.shop_sku) select s.shop_sku, StringComparer.OrdinalIgnoreCase); List legacyItems = (ApiClient.CachedArtistItems ?? new List()).Where((ApiClient.ArtistItemEntry it) => it != null && it.catalog_ready && string.Equals(it.kind, "face", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(it.sku) && !linkedSkus.Contains(it.sku)).ToList(); if (list.Count == 0 && legacyItems.Count == 0) { ShowArtistResult(ok: false, "{\"detail\":\"no pending or approved cosmetics to adjust\"}"); return; } string[] array = new string[list.Count + legacyItems.Count]; string[] array2 = new string[array.Length]; for (int num = 0; num < list.Count; num++) { ApiClient.CosmeticSubmission cosmeticSubmission = list[num]; string text = ((cosmeticSubmission.status == "approved") ? ((cosmeticSubmission.placement_status == "pending") ? "placement pending" : "approved") : "initial review pending"); array[num] = cosmeticSubmission.name + " (" + cosmeticSubmission.slot + ", " + text + ")"; array2[num] = $"submission:{cosmeticSubmission.id}"; } for (int num2 = 0; num2 < legacyItems.Count; num2++) { ApiClient.ArtistItemEntry artistItemEntry = legacyItems[num2]; int num3 = list.Count + num2; array[num3] = artistItemEntry.name + " (published; first placement revision)"; array2[num3] = "catalog:" + artistItemEntry.sku; } CompetitiveUI.OpenArtistPicker("Adjust which cosmetic? Changes return to admin review.", array, array2, delegate(string selected) { //IL_0153: Unknown result type (might be due to invalid IL or missing references) int result; if (selected.StartsWith("catalog:", StringComparison.Ordinal)) { string sku = selected.Substring("catalog:".Length); ApiClient.ArtistItemEntry item = legacyItems.FirstOrDefault((ApiClient.ArtistItemEntry it) => string.Equals(it.sku, sku, StringComparison.OrdinalIgnoreCase)); if (item == null || !CustomCosmetics.TryGetPublishedPlacement(sku, out var slot, out var publishedScale, out var publishedOffset, out var bytes)) { ShowArtistResult(ok: false, "{\"detail\":\"the published PNG is missing locally; reinstall or update the cosmetic art bundle\"}"); } else { CompetitiveUI.OpenCosmeticTestPreview(bytes, item.name, slot, delegate(float scale, float offsetX, float offsetY) { ApiClient.ArtistStartCatalogPlacementRevision(MatchTracker.LocalSteamId, sku, slot, Convert.ToBase64String(bytes), publishedScale, publishedOffset.x, publishedOffset.y, scale, offsetX, offsetY, delegate(bool saved, string saveResp) { ShowArtistResult(saved, saved ? ("'" + item.name + "' placement revision sent for admin review. Its current published placement stays active until the approved revision ships.") : saveResp); }); }, publishedScale, publishedOffset.x, publishedOffset.y, "Send to review", isRevision: true); } } else if (selected.StartsWith("submission:", StringComparison.Ordinal) && int.TryParse(selected.Substring("submission:".Length), out result)) { cosmeticPlacementLoading = true; int ticket = ++cosmeticPlacementLoadTicket; CompetitiveUI.ShowNotification("Loading the reviewed cosmetic...", new Color(0.55f, 0.75f, 1f), 3f); ApiClient.FetchCosmeticSubmissionPreview(MatchTracker.LocalSteamId, result, delegate(bool ok, ApiClient.CosmeticSubmission sub, string resp) { if (ticket == cosmeticPlacementLoadTicket) { cosmeticPlacementLoading = false; if (!ok || sub == null) { ShowArtistResult(ok: false, resp); } else { byte[] pngBytes; try { pngBytes = Convert.FromBase64String(sub.png_base64 ?? ""); } catch { ShowArtistResult(ok: false, "{\"detail\":\"could not decode the saved preview\"}"); return; } if (isOpen) { CompetitiveUI.OpenCosmeticTestPreview(pngBytes, sub.name, sub.slot, delegate(float scale, float offsetX, float offsetY) { ApiClient.ArtistUpdateCosmeticPlacement(MatchTracker.LocalSteamId, sub.id, sub.placement_revision, scale, offsetX, offsetY, delegate(bool saved, string saveResp) { ShowArtistResult(saved, saved ? ("'" + sub.name + "' placement revision sent for admin review. The last approved placement stays active until this one is approved and shipped.") : saveResp); }); }, sub.render_scale, sub.render_offset_x, sub.render_offset_y, "Send to review", isRevision: true); } } } }); } }, "Preview", showClear: false); } private static void ShowArtistResult(bool ok, string msg) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) CompetitiveUI.ShowNotification((!ok) ? ("Failed: " + ExtractServerDetail(msg)) : (string.IsNullOrEmpty(msg) ? "Done." : msg), ok ? new Color(0.4f, 0.9f, 0.5f) : new Color(1f, 0.45f, 0.4f)); dirty = true; } private static string ExtractServerDetail(string resp) { if (string.IsNullOrEmpty(resp)) { return "no response"; } int num = resp.IndexOf("\"detail\":\"", StringComparison.Ordinal); if (num < 0) { return (resp.Length > 90) ? resp.Substring(0, 90) : resp; } int num2 = num + 10; int num3 = resp.IndexOf('"', num2); return (num3 > num2) ? resp.Substring(num2, num3 - num2) : resp; } private static void RefreshArtistTab() { //IL_01a8: Unknown result type (might be due to invalid IL or missing references) if (!ApiClient.IsArtist) { UIFactory.SetText(txtArtistStatus, "Not an artist account."); return; } List cachedArtistItems = ApiClient.CachedArtistItems; List cachedArtistBlocks = ApiClient.CachedArtistBlocks; UIFactory.SetText(txtArtistStatus, (cachedArtistItems == null || cachedArtistItems.Count == 0) ? "No items assigned to you yet - art gets wired to your account when it ships in a mod update." : $"{cachedArtistItems.Count} item(s), {SumSold(cachedArtistItems)} cop(ies) out there."); int num = 0; if (cachedArtistItems != null) { foreach (ApiClient.ArtistItemEntry item in cachedArtistItems) { ArtistRow orCreateArtistRow = GetOrCreateArtistRow(num++); orCreateArtistRow.sku = item.sku; orCreateArtistRow.name = item.name; orCreateArtistRow.price = item.price; orCreateArtistRow.stock = item.stock_limit; orCreateArtistRow.catalogReady = item.catalog_ready; if ((Object)(object)orCreateArtistRow.stockBtn != (Object)null) { orCreateArtistRow.stockBtn.SetActive(item.catalog_ready); } if ((Object)(object)orCreateArtistRow.giftBtn != (Object)null) { orCreateArtistRow.giftBtn.SetActive(item.catalog_ready); } try { Sprite shopSprite = CustomCosmetics.GetShopSprite(item.sku); if ((Object)(object)shopSprite != (Object)null && orCreateArtistRow.artImg != null) { UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public)?.SetValue(orCreateArtistRow.artImg, shopSprite); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(orCreateArtistRow.artImg, Color.white); orCreateArtistRow.artImgGO.SetActive(true); } else if ((Object)(object)orCreateArtistRow.artImgGO != (Object)null) { orCreateArtistRow.artImgGO.SetActive(false); } } catch { } string arg = ((!item.catalog_ready) ? "APPROVED - awaiting mod update" : ((item.stock_limit < 0) ? "NOT OPENED - set stock to start selling!" : ((item.stock_limit > 0) ? $"{Math.Max(0, item.stock_limit - item.sold)} of {item.stock_limit} left" : "unlimited"))); UIFactory.SetText(orCreateArtistRow.txtInfo, "" + item.name + " (" + item.kind + ", " + item.rarity + ") " + $"{item.price}g {arg} " + $"sold {Math.Max(0, item.sold - item.gifted)}, gifted {item.gifted}" + ((item.earned > 0) ? $" earned {item.earned}g" : "")); orCreateArtistRow.root.SetActive(true); } } for (int i = num; i < artistRows.Count; i++) { artistRows[i].root.SetActive(false); } if (txtArtistSubs != null) { List cachedMySubmissions = ApiClient.CachedMySubmissions; if (cachedMySubmissions == null || cachedMySubmissions.Count == 0) { UIFactory.SetText(txtArtistSubs, ""); } else { StringBuilder stringBuilder = new StringBuilder("Your submissions:\n"); int num2 = 0; foreach (ApiClient.CosmeticSubmission item2 in cachedMySubmissions) { if (num2++ >= 6) { break; } string arg2 = ((item2.status == "approved" && item2.placement_status == "pending") ? "PLACEMENT PENDING REVIEW (last approved placement stays active)" : ((item2.status == "approved" && item2.placement_status == "denied") ? ("PLACEMENT CHANGE REJECTED" + (string.IsNullOrEmpty(item2.placement_review_note) ? "" : (" - " + HomeSan(item2.placement_review_note) + "")) + " (last approved placement stays active)") : ((!(item2.status == "approved")) ? ((!(item2.status == "denied")) ? "pending initial review" : ("DENIED" + (string.IsNullOrEmpty(item2.review_note) ? "" : (" - " + HomeSan(item2.review_note) + "")))) : ((item2.approved_placement_revision > item2.published_placement_revision) ? $"APPROVED (rev {item2.approved_placement_revision} awaits a mod update)" : ("APPROVED (" + item2.shop_sku + ")"))))); stringBuilder.Append($" {HomeSan(item2.name)} ({item2.slot}, {item2.render_scale:F2}x, " + $"rev {item2.placement_revision}) {arg2}\n"); } UIFactory.SetText(txtArtistSubs, stringBuilder.ToString().TrimEnd('\n')); } } if (txtArtistSales != null) { List cachedArtistSales = ApiClient.CachedArtistSales; if (cachedArtistSales == null || cachedArtistSales.Count == 0) { UIFactory.SetText(txtArtistSales, "No sales yet."); } else { StringBuilder stringBuilder2 = new StringBuilder(); foreach (ApiClient.ArtistSaleEntry item3 in cachedArtistSales) { string text = HomeSan(item3.item); string text2 = HomeSan(item3.buyer); if (item3.price <= 0) { stringBuilder2.Append("" + item3.when + " " + text2 + " received " + text + " (gift)\n"); } else { stringBuilder2.Append($"{item3.when} {text2} bought {text} for {item3.price}g +{item3.earned}g to you\n"); } } UIFactory.SetText(txtArtistSales, stringBuilder2.ToString().TrimEnd('\n')); } } int num3 = 0; if (cachedArtistBlocks != null) { foreach (ApiClient.ArtistBlockEntry item4 in cachedArtistBlocks) { ArtistBlockRow orCreateArtistBlockRow = GetOrCreateArtistBlockRow(num3++); orCreateArtistBlockRow.steamId = item4.steam_id; orCreateArtistBlockRow.name = item4.display_name; UIFactory.SetText(orCreateArtistBlockRow.txtInfo, item4.display_name + " (" + item4.steam_id + ")"); orCreateArtistBlockRow.root.SetActive(true); } } for (int j = num3; j < artistBlockRows.Count; j++) { artistBlockRows[j].root.SetActive(false); } } private static int SumSold(List items) { int num = 0; foreach (ApiClient.ArtistItemEntry item in items) { num += item.sold; } return num; } private static ArtistRow GetOrCreateArtistRow(int idx) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Expected O, but got Unknown //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Expected O, but got Unknown //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Expected O, but got Unknown //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) while (artistRows.Count <= idx) { ArtistRow artistRow = new ArtistRow(); artistRow.root = new GameObject($"artRow{artistRows.Count}"); artistRow.root.transform.SetParent(artistItemsContainer.transform, false); artistRow.root.AddComponent(); UIFactory.AddHLG(artistRow.root, 8f, 6, 6, 4, 4); UIFactory.AddLE(artistRow.root, -1f, -1f, -1f, 32f); if (UIFactory.tImage != null) { Component obj = artistRow.root.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, C_PANEL); } artistRow.artImgGO = new GameObject("art"); artistRow.artImgGO.transform.SetParent(artistRow.root.transform, false); artistRow.artImgGO.AddComponent(); UIFactory.AddLE(artistRow.artImgGO, 30f, -1f, 30f, 30f, 0f, 0f); if (UIFactory.tImage != null) { artistRow.artImg = artistRow.artImgGO.AddComponent(UIFactory.tImage); try { UIFactory.tImage.GetProperty("preserveAspect", BindingFlags.Instance | BindingFlags.Public)?.SetValue(artistRow.artImg, true); } catch { } try { UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(artistRow.artImg, false); } catch { } } artistRow.artImgGO.SetActive(false); artistRow.txtInfo = UIFactory.CreateText("i", artistRow.root.transform, "", 14f, C_WHITE, 513, (Vector2?)new Vector2(400f, 28f), richText: true, raycastTarget: false); ArtistRow r = artistRow; UIFactory.CreateButton("nm", artistRow.root.transform, "Name", 13f, C_WHITE, C_BTN, (UnityAction)delegate { CompetitiveUI.OpenArtistInput("Rename - " + r.name, "New display name (max 64 chars)", r.name ?? "", delegate(string v) { if (string.IsNullOrEmpty(v)) { ShowArtistResult(ok: false, "{\"detail\":\"name can't be empty\"}"); } else { ApiClient.ArtistSetName(MatchTracker.LocalSteamId, r.sku, v, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? "Renamed." : resp); }); } }); }, (Vector2?)new Vector2(56f, 24f)); UIFactory.CreateButton("ds", artistRow.root.transform, "Desc", 13f, C_WHITE, C_BTN, (UnityAction)delegate { CompetitiveUI.OpenArtistInput("Description - " + r.name, "Shop description (max 200 chars)", "", delegate(string v) { ApiClient.ArtistSetDesc(MatchTracker.LocalSteamId, r.sku, v, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? "Description updated." : resp); }); }); }, (Vector2?)new Vector2(52f, 24f)); artistRow.priceBtn = UIFactory.CreateButton("p", artistRow.root.transform, "Price", 13f, C_WHITE, C_BTN, (UnityAction)delegate { CompetitiveUI.OpenArtistInput("Set price - " + r.name, "New price in gold (0-100000)", r.price.ToString(), delegate(string v) { if (!int.TryParse(v, out var nv) || nv < 0 || nv > 100000) { ShowArtistResult(ok: false, "{\"detail\":\"price must be 0-100000\"}"); } else { ApiClient.ArtistSetPrice(MatchTracker.LocalSteamId, r.sku, nv, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? $"{r.name} is now {nv}g." : resp); }); } }); }, (Vector2?)new Vector2(60f, 24f)); artistRow.stockBtn = UIFactory.CreateButton("s", artistRow.root.transform, "Stock", 13f, C_WHITE, C_BTN, (UnityAction)delegate { if (!r.catalogReady) { ShowArtistResult(ok: false, "{\"detail\":\"art is still awaiting a mod update\"}"); } else { CompetitiveUI.OpenArtistInput("Set stock - " + r.name, "Max copies (0 = unlimited)", r.stock.ToString(), delegate(string v) { if (!int.TryParse(v, out var result) || result < 0 || result > 100000) { ShowArtistResult(ok: false, "{\"detail\":\"stock must be 0-100000\"}"); } else { ApiClient.ArtistSetStock(MatchTracker.LocalSteamId, r.sku, result, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? (r.name + " stock set.") : resp); }); } }); } }, (Vector2?)new Vector2(60f, 24f)); artistRow.giftBtn = UIFactory.CreateButton("g", artistRow.root.transform, "Gift", 13f, C_WHITE, new Color(0.2f, 0.45f, 0.25f, 0.9f), (UnityAction)delegate { if (!r.catalogReady) { ShowArtistResult(ok: false, "{\"detail\":\"art is still awaiting a mod update\"}"); } else { CompetitiveUI.OpenPlayerSearch("Gift " + r.name + " - find the recipient", delegate(string sid, string pname) { if (!string.IsNullOrEmpty(sid)) { ApiClient.ArtistGift(MatchTracker.LocalSteamId, r.sku, sid, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Gifted " + r.name + " to " + pname + ".") : resp); }); } }); } }, (Vector2?)new Vector2(60f, 24f)); artistRows.Add(artistRow); } return artistRows[idx]; } private static ArtistBlockRow GetOrCreateArtistBlockRow(int idx) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown while (artistBlockRows.Count <= idx) { ArtistBlockRow artistBlockRow = new ArtistBlockRow(); artistBlockRow.root = new GameObject($"artBlk{artistBlockRows.Count}"); artistBlockRow.root.transform.SetParent(artistBlocksContainer.transform, false); artistBlockRow.root.AddComponent(); UIFactory.AddHLG(artistBlockRow.root, 8f, 6, 6, 3, 3); UIFactory.AddLE(artistBlockRow.root, -1f, -1f, -1f, 26f); artistBlockRow.txtInfo = UIFactory.CreateText("i", artistBlockRow.root.transform, "", 13f, C_WHITE, 513, (Vector2?)new Vector2(420f, 22f), richText: true, raycastTarget: false); ArtistBlockRow r = artistBlockRow; artistBlockRow.unblockBtn = UIFactory.CreateButton("u", artistBlockRow.root.transform, "Unblock", 12f, C_WHITE, C_BTN, (UnityAction)delegate { CompetitiveUI.OpenConfirm("Unblock " + r.name + " from buying your items?", delegate { ApiClient.ArtistBlock(MatchTracker.LocalSteamId, r.steamId, block: false, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? (r.name + " unblocked.") : resp); }); }); }, (Vector2?)new Vector2(70f, 22f)); artistBlockRows.Add(artistBlockRow); } return artistBlockRows[idx]; } private static void RefreshData() { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.FetchPlayerStats(localSteamId); ApiClient.FetchMatchHistory(localSteamId); ApiClient.FetchAchievements(localSteamId); ApiClient.FetchTeamStats(localSteamId); } if (currentTab == 1) { ApiClient.FetchLeaderboard(); ApiClient.FetchRecentSeries(); ApiClient.FetchRecentMultimodeSeries(); } if (currentTab == 2) { ApiClient.FetchCardStats(200, MatchTracker.LocalSteamId); LoadCardTiersForCurrentFilter(); } } private static void RefreshCurrentTab() { RefreshQueueUI(); RefreshVersionStatus(); RefreshServerBanner(); RefreshTournamentGameIndicator(); UpdateTabBarVisual(); switch (currentTab) { case 0: RefreshMyStats(); break; case 1: RefreshLeaderboard(); RefreshRecentSeries(); RefreshLiveSeries(); break; case 2: RefreshCardStats(); break; case 3: RefreshAchievements(); break; case 4: RefreshShop(); break; case 5: RefreshSettings(); break; case 6: RefreshAdmin(); break; case 7: RefreshTournaments(); break; case 8: RefreshTeamTab(); break; case 9: RefreshCompare(); break; case 10: RefreshArtistTab(); break; case 11: RefreshOneVTwoTab(); break; case 12: RefreshFfaTab(); break; case 13: RefreshHomeTab(); break; } } private static void _EnsureRankedEnabledForTournamentMatch(ApiClient.ActiveTournamentMatch m) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if (m == null || string.IsNullOrEmpty(m.match_id) || _autoEnabledRankedForMatches.Contains(m.match_id)) { return; } _autoEnabledRankedForMatches.Add(m.match_id); if (Plugin.RankedEnabled == null || !Plugin.RankedEnabled.Value) { Plugin.RankedEnabled.Value = true; string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.ToggleRanked(localSteamId, enabled: true); } CompetitiveUI.ShowNotification("Ranked auto-enabled for your tournament match - results will auto-record", new Color(1f, 0.85f, 0.3f)); Plugin.Log.LogInfo((object)("[TOURNAMENT] Auto-enabled Ranked for match " + m.match_id)); } } private static void RefreshTournamentGameIndicator() { if ((Object)(object)tournamentIndRow == (Object)null || txtTournamentGame == null) { return; } ApiClient.FetchMyActiveTournamentMatches(MatchTracker.LocalSteamId); List cachedMyActiveTournamentMatches = ApiClient.CachedMyActiveTournamentMatches; if (cachedMyActiveTournamentMatches != null) { foreach (ApiClient.ActiveTournamentMatch item in cachedMyActiveTournamentMatches) { _EnsureRankedEnabledForTournamentMatch(item); } } List cachedMyActiveTournamentMatches2 = ApiClient.CachedMyActiveTournamentMatches; if (cachedMyActiveTournamentMatches2 == null || cachedMyActiveTournamentMatches2.Count == 0 || !GameStateWatcher.IsInRoom) { tournamentIndRow.SetActive(false); return; } string opponentSteamId = GameStateWatcher.OpponentSteamId; if (string.IsNullOrEmpty(opponentSteamId) || opponentSteamId.StartsWith("photon_")) { tournamentIndRow.SetActive(false); return; } foreach (ApiClient.ActiveTournamentMatch item2 in cachedMyActiveTournamentMatches2) { if (item2.opponent_steam_id == opponentSteamId) { string text = (item2.kind ?? "").ToUpper(); UIFactory.SetText(txtTournamentGame, "* " + text + " TOURNAMENT GAME - vs " + (item2.opponent_display_name ?? "opponent") + " (results auto-recorded)"); tournamentIndRow.SetActive(true); return; } } tournamentIndRow.SetActive(false); } private static void RefreshServerBanner() { if (!((Object)(object)srvStatusRow == (Object)null)) { bool apiLooksDown = ApiClient.ApiLooksDown; srvStatusRow.SetActive(apiLooksDown); if (apiLooksDown) { string s = (ApiClient.LastResponseWasMaintenance ? "* Server in maintenance - back in a moment" : "* Server reconnecting..."); UIFactory.SetText(txtServerStatus, s); } } } private static void RefreshLiveSeries() { if (txtLiveSeries == null) { return; } if (txtLiveHeader != null) { string text = (liveHeaderPulseFilled ? "#FF6688" : "#552233"); UIFactory.SetText(txtLiveHeader, "* Live Ranked Games"); } List cachedActiveSeries = ApiClient.CachedActiveSeries; List list = new List(); if (cachedActiveSeries != null) { foreach (ApiClient.ActiveSeriesEntry item in cachedActiveSeries) { if (!item.is_tournament || !(item.phase == "pre_match")) { list.Add(item); } } } List cachedActiveTeamSeries = ApiClient.CachedActiveTeamSeries; int count = list.Count; int num = cachedActiveTeamSeries?.Count ?? 0; foreach (GameObject item2 in liveBetRowPool) { item2.SetActive(false); } if (count == 0 && num == 0) { UIFactory.SetText(txtLiveSeries, "No live games right now."); if ((Object)(object)liveBetsPager != (Object)null) { liveBetsPager.SetActive(false); } RefreshMyBetsLedger(); return; } UIFactory.SetText(txtLiveSeries, ""); int num2 = Math.Max(1, (count + 5 - 1) / 5); liveSeriesPage = Math.Max(0, Math.Min(liveSeriesPage, num2 - 1)); int num3 = liveSeriesPage * 5; int num4 = Math.Min(num3 + 5, count); int num5 = 0; for (int i = num3; i < num4; i++) { ApiClient.ActiveSeriesEntry s = list[i]; GameObject orCreateLiveRow = GetOrCreateLiveRow(num5++); ApplyHeaderRow(orCreateLiveRow, s); GameObject orCreateLiveRow2 = GetOrCreateLiveRow(num5++); ApplyBetRow(orCreateLiveRow2, s, betOnP1: true); GameObject orCreateLiveRow3 = GetOrCreateLiveRow(num5++); ApplyBetRow(orCreateLiveRow3, s, betOnP1: false); } if (cachedActiveTeamSeries != null) { foreach (ApiClient.ActiveTeamSeriesEntry item3 in cachedActiveTeamSeries) { GameObject orCreateLiveRow4 = GetOrCreateLiveRow(num5++); ApplyTeamHeaderRow(orCreateLiveRow4, item3); GameObject orCreateLiveRow5 = GetOrCreateLiveRow(num5++); ApplyTeamBetRow(orCreateLiveRow5, item3, 1); GameObject orCreateLiveRow6 = GetOrCreateLiveRow(num5++); ApplyTeamBetRow(orCreateLiveRow6, item3, 2); } } if ((Object)(object)liveBetsPager != (Object)null) { bool flag = num2 > 1; liveBetsPager.SetActive(flag); if (flag) { UIFactory.SetText(txtLiveBetsPage, $"{count} live - {liveSeriesPage + 1}/{num2}"); liveBetsPrev.SetActive(liveSeriesPage > 0); liveBetsNext.SetActive(liveSeriesPage < num2 - 1); } } RefreshMyBetsLedger(); } private static void RefreshMyBetsLedger() { if (txtMyBets == null) { return; } List cachedMyBets = ApiClient.CachedMyBets; if (cachedMyBets == null || cachedMyBets.Count == 0) { UIFactory.SetText(txtMyBets, ""); return; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; foreach (ApiClient.MyBetEntry item in cachedMyBets) { if (!item.settled) { stringBuilder.Append($"{BetDate(item)} Bet {item.amount:N0} gold on {item.bet_on_name} vs {item.vs_name} - in play, score {item.series_score}\n"); } } foreach (ApiClient.MyBetEntry item2 in cachedMyBets) { if (item2.settled && num < 3 && BetWithinDays(item2, 3)) { num++; if (item2.payout == item2.amount) { stringBuilder.Append($"{BetDate(item2)} Bet {item2.amount:N0} gold on {item2.bet_on_name} vs {item2.vs_name} - refunded, series never finished\n"); } else if (item2.payout > 0) { stringBuilder.Append($"{BetDate(item2)} Bet {item2.amount:N0} gold on {item2.bet_on_name} vs {item2.vs_name} - WON {item2.payout - item2.amount:N0} gold\n"); } else { stringBuilder.Append($"{BetDate(item2)} Bet {item2.amount:N0} gold on {item2.bet_on_name} vs {item2.vs_name} - LOST\n"); } } } string text = stringBuilder.ToString().TrimEnd('\n'); UIFactory.SetText(txtMyBets, (text.Length > 0) ? ("\nYour Recent Bets\n" + text) : ""); } private static bool BetWithinDays(ApiClient.MyBetEntry b, int days) { try { if (string.IsNullOrEmpty(b.created_at)) { return true; } DateTime dateTime = DateTime.Parse(b.created_at, null, DateTimeStyles.RoundtripKind); return (DateTime.UtcNow - dateTime.ToUniversalTime()).TotalDays <= (double)days; } catch { return true; } } private static string BetDate(ApiClient.MyBetEntry b) { try { if (!string.IsNullOrEmpty(b.created_at)) { return DateTime.Parse(b.created_at, null, DateTimeStyles.RoundtripKind).ToLocalTime().ToString("M/d"); } } catch { } return ""; } private static GameObject GetOrCreateLiveRow(int idx) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown while (liveBetRowPool.Count <= idx) { GameObject val = new GameObject($"lb{liveBetRowPool.Count}"); val.transform.SetParent(liveBetsContainer.transform, false); val.AddComponent(); UIFactory.AddHLG(val); UIFactory.AddLE(val, -1f, -1f, -1f, 26f, -1f, 0f); liveBetRowPool.Add(val); } GameObject val2 = liveBetRowPool[idx]; for (int num = val2.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)val2.transform.GetChild(num)).gameObject); } val2.SetActive(true); return val2; } private static void ApplyHeaderRow(GameObject row, ApiClient.ActiveSeriesEntry s) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) string text = ""; if (s.is_tournament) { string text2 = (string.IsNullOrEmpty(s.tournament_kind) ? "" : (" " + char.ToUpper(s.tournament_kind[0]) + s.tournament_kind.Substring(1))); text = "[TOURNAMENT" + text2 + "] "; } else if (s.is_private) { text = "[PRIVATE] "; } string text3 = text + $"{Trunc(s.p1_name, 12)} ({s.p1_rating}) " + $"{s.p1_wins}-{s.p2_wins} " + $"{Trunc(s.p2_name, 12)} ({s.p2_rating})"; object t = UIFactory.CreateText("h", row.transform, text3, 15f, C_WHITE, 513, (Vector2?)new Vector2(384f, 24f), richText: true, raycastTarget: false); UIFactory.SetBold(t, b: true); UIFactory.SetWordWrap(t, on: false); } private static void ApplyBetRow(GameObject row, ApiClient.ActiveSeriesEntry s, bool betOnP1) { //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: 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) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) string s2 = (betOnP1 ? s.p1_name : s.p2_name); string text = (betOnP1 ? s.p1_steam_id : s.p2_steam_id); float num = (betOnP1 ? s.p1_odds : s.p2_odds); string localSteamId = MatchTracker.LocalSteamId; bool flag = !string.IsNullOrEmpty(localSteamId) && (localSteamId == s.p1_steam_id || localSteamId == s.p2_steam_id); ApiClient.MyBetEntry myBetForSeries = ApiClient.GetMyBetForSeries(s.series_id); if (myBetForSeries != null) { string arg = ((myBetForSeries.bet_on_steam_id == text) ? $" You bet {myBetForSeries.amount}g" : ""); object t = UIFactory.CreateText("bl", row.transform, $"{Trunc(s2, 10)} @{num:F1}x{arg}", 13f, C_LABEL, 513, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t, on: false); return; } if (s.bets_locked) { string arg2 = ((s.lock_reason == "no_meaningful_odds") ? "odds too uncertain" : "betting period over"); object t2 = UIFactory.CreateText("bl", row.transform, $"{Trunc(s2, 10)} @{num:F1}x {arg2}", 13f, C_LABEL, 513, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t2, on: false); return; } if (flag) { object t3 = UIFactory.CreateText("bl", row.transform, $"{Trunc(s2, 10)} @{num:F1}x your match", 13f, C_LABEL, 513, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t3, on: false); return; } object t4 = UIFactory.CreateText("bl", row.transform, $"Bet on {Trunc(s2, 10)} @{num:F1}x:", 13f, C_LABEL, 513, (Vector2?)new Vector2(240f, 22f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t4, on: false); AddBetButton(row.transform, s.series_id, text, 100); AddBetButton(row.transform, s.series_id, text, 500); AddBetButton(row.transform, s.series_id, text, 2000); AddCustomBetButton(row.transform, s.series_id, text, 0, isTeam: false, Trunc(s2, 14)); } private static void ApplyTeamHeaderRow(GameObject row, ApiClient.ActiveTeamSeriesEntry s) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) string text = "2v2 " + $"{Trunc(s.t1a_name, 7)}({s.t1a_rating})+{Trunc(s.t1b_name, 7)}({s.t1b_rating}) " + $"{s.t1_wins}-{s.t2_wins} " + $"{Trunc(s.t2a_name, 7)}({s.t2a_rating})+{Trunc(s.t2b_name, 7)}({s.t2b_rating})"; object t = UIFactory.CreateText("hdr", row.transform, text, 14f, C_WHITE, 513, (Vector2?)new Vector2(560f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t, on: false); UIFactory.SetBold(t, b: true); } private static void ApplyTeamBetRow(GameObject row, ApiClient.ActiveTeamSeriesEntry s, int team) { //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: 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_014c: Unknown result type (might be due to invalid IL or missing references) float num = ((team == 1) ? s.t1_odds : s.t2_odds); string text = ((team == 1) ? ("Team 1 (" + Trunc(s.t1a_name, 6) + "+" + Trunc(s.t1b_name, 6) + ")") : ("Team 2 (" + Trunc(s.t2a_name, 6) + "+" + Trunc(s.t2b_name, 6) + ")")); string localSteamId = MatchTracker.LocalSteamId; bool flag = !string.IsNullOrEmpty(localSteamId) && (localSteamId == s.t1a_steam || localSteamId == s.t1b_steam || localSteamId == s.t2a_steam || localSteamId == s.t2b_steam); if (s.bets_locked) { string arg = ((s.lock_reason == "no_meaningful_odds") ? "odds too uncertain" : "betting period over"); object t = UIFactory.CreateText("tbl", row.transform, $"{text} @{num:F1}x {arg}", 13f, C_LABEL, 513, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t, on: false); return; } if (flag) { object t2 = UIFactory.CreateText("tbl", row.transform, $"{text} @{num:F1}x your match", 13f, C_LABEL, 513, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t2, on: false); return; } object t3 = UIFactory.CreateText("tbl", row.transform, $"Bet on {text} @{num:F1}x:", 13f, C_LABEL, 513, (Vector2?)new Vector2(240f, 22f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t3, on: false); AddTeamBetButton(row.transform, s.series_id, team, 100); AddTeamBetButton(row.transform, s.series_id, team, 500); AddTeamBetButton(row.transform, s.series_id, team, 2000); AddCustomBetButton(row.transform, s.series_id, null, team, isTeam: true, text); } public static void OpenCustomBetPrompt(string seriesId, string betOnSteamId, int team, bool isTeam, string targetLabel) { customBetSeriesId = seriesId; customBetOnSteamId = betOnSteamId; customBetTeam = team; customBetIsTeam = isTeam; customBetIsFfa = false; CustomBetTargetLabel = targetLabel ?? ""; CustomBetAmountText = ""; CustomBetPromptOpen = true; } private static void OpenCustomFfaBetPrompt(string lobbyId, string betOnSteamId, string targetLabel, int gameNumber) { customBetSeriesId = lobbyId; customBetOnSteamId = betOnSteamId; customBetTeam = 0; customBetIsTeam = false; customBetIsFfa = true; customBetFfaGameNumber = gameNumber; CustomBetTargetLabel = targetLabel ?? ""; CustomBetAmountText = ""; CustomBetPromptOpen = true; } public static void CancelCustomBet() { CustomBetPromptOpen = false; } public static void SubmitCustomBet() { //IL_0080: Unknown result type (might be due to invalid IL or missing references) CustomBetPromptOpen = false; string s = (CustomBetAmountText ?? "").Replace(",", "").Replace(" ", "").Trim(); if (!int.TryParse(s, out var amount) || amount < 1 || amount > 2000) { CompetitiveUI.ShowNotification("Enter a whole amount between 1 and 2,000 gold.", new Color(1f, 0.5f, 0.5f), 3f); return; } string id = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(id) || id == "unknown") { return; } if (customBetIsFfa) { Plugin.Log.LogInfo((object)$"[FFA-BET] Placing CUSTOM {amount}g on {customBetOnSteamId} (lobby {customBetSeriesId})"); ApiClient.PlaceFfaBet(id, customBetSeriesId, customBetOnSteamId, amount, customBetFfaGameNumber, delegate(bool ok, string resp) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) Color color = (ok ? new Color(0.4f, 1f, 0.4f) : new Color(1f, 0.5f, 0.5f)); if (ok) { float num = ApiClient.ExtractJsonFloatPublic(resp, "odds_multiplier"); int num2 = ApiClient.ExtractJsonIntPublic(resp, "potential_payout"); string arg = ((num > 0f) ? (" at x" + num.ToString("0.00", CultureInfo.InvariantCulture)) : ""); string arg2 = ((num2 > 0) ? $" (pays {num2}g)" : ""); CompetitiveUI.ShowNotification($"Bet placed: {amount}g{arg}{arg2}", color, 3f); } else { CompetitiveUI.ShowNotification("Bet failed: " + resp, color, 3f); } }); return; } if (customBetIsTeam) { Plugin.Log.LogInfo((object)$"[TEAM-BET] Placing CUSTOM {amount}g on team {customBetTeam} (series {customBetSeriesId})"); ApiClient.PlaceTeamBet(id, customBetSeriesId, customBetTeam, amount, delegate(bool ok, string resp) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) Color color = (ok ? new Color(0.4f, 1f, 0.4f) : new Color(1f, 0.5f, 0.5f)); CompetitiveUI.ShowNotification(ok ? $"Bet placed: {amount}g on Team {customBetTeam}" : ("Bet failed: " + resp), color, 3f); if (ok) { ApiClient.FetchActiveTeamSeries(); ApiClient.FetchPlayerStats(id); } }); return; } Plugin.Log.LogInfo((object)$"[BET] Placing CUSTOM {amount}g on {customBetOnSteamId} (series {customBetSeriesId})"); ApiClient.PlaceBet(id, customBetSeriesId, customBetOnSteamId, amount, delegate(bool ok, string resp) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) Color color = (ok ? new Color(0.4f, 1f, 0.4f) : new Color(1f, 0.5f, 0.5f)); CompetitiveUI.ShowNotification(ok ? $"Bet placed: {amount}g" : ("Bet failed: " + resp), color, 3f); if (ok) { ApiClient.FetchActiveSeries(); ApiClient.FetchPlayerStats(id); ApiClient.FetchMyBets(id); } }); } private static void AddCustomBetButton(Transform parent, string seriesId, string betOnSteamId, int team, bool isTeam, string targetLabel) { //IL_005b: 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_0080: 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_009e: Expected O, but got Unknown GameObject go = UIFactory.CreateButton(isTeam ? $"tbc{team}" : "bc", parent, "...", 11f, C_WHITE, new Color(0.28f, 0.24f, 0.12f, 0.9f), (UnityAction)delegate { OpenCustomBetPrompt(seriesId, betOnSteamId, team, isTeam, targetLabel); }, (Vector2?)new Vector2(30f, 22f)); UIFactory.AddLE(go, -1f, -1f, 30f, 22f, 0f, 0f); } private static void AddTeamBetButton(Transform parent, string seriesId, int team, int amount) { //IL_0057: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown GameObject go = UIFactory.CreateButton($"tb{team}_{amount}", parent, $"{amount}g", 11f, C_WHITE, new Color(0.35f, 0.28f, 0.1f, 0.9f), (UnityAction)delegate { string id = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(id) && !(id == "unknown")) { Plugin.Log.LogInfo((object)$"[TEAM-BET] Placing {amount}g on team {team} (series {seriesId})"); ApiClient.PlaceTeamBet(id, seriesId, team, amount, delegate(bool ok, string resp) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) Color color = (ok ? new Color(0.4f, 1f, 0.4f) : new Color(1f, 0.5f, 0.5f)); CompetitiveUI.ShowNotification(ok ? $"Bet placed: {amount}g on Team {team}" : ("Bet failed: " + resp), color, 3f); if (ok) { ApiClient.FetchActiveTeamSeries(); ApiClient.FetchPlayerStats(id); } }); } }, (Vector2?)new Vector2(44f, 22f)); UIFactory.AddLE(go, -1f, -1f, 44f, 22f, 0f, 0f); } private static void AddBetButton(Transform parent, string seriesId, string betOnSteamId, int amount) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown GameObject go = UIFactory.CreateButton($"b{amount}", parent, $"{amount}g", 11f, C_WHITE, new Color(0.35f, 0.28f, 0.1f, 0.9f), (UnityAction)delegate { string id = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(id) && !(id == "unknown")) { Plugin.Log.LogInfo((object)$"[BET] Placing {amount}g on {betOnSteamId} (series {seriesId})"); ApiClient.PlaceBet(id, seriesId, betOnSteamId, amount, delegate(bool ok, string resp) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) Color color = (ok ? new Color(0.4f, 1f, 0.4f) : new Color(1f, 0.5f, 0.5f)); CompetitiveUI.ShowNotification(ok ? $"Bet placed: {amount}g" : ("Bet failed: " + resp), color, 3f); if (ok) { ApiClient.FetchActiveSeries(); ApiClient.FetchPlayerStats(id); ApiClient.FetchMyBets(id); } }); } }, (Vector2?)new Vector2(44f, 22f)); UIFactory.AddLE(go, -1f, -1f, 44f, 22f, 0f, 0f); } private static GameObject BuildShopTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Expected O, but got Unknown //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Expected O, but got Unknown //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Expected O, but got Unknown GameObject val = new GameObject("Shop"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 6f, 20, 20, 10, 10); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(4, val.transform, asFirst: true); GameObject val2 = new GameObject("SHHdr"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddHLG(val2, 14f); UIFactory.AddLE(val2, -1f, -1f, -1f, 32f, -1f, 0f); UIFactory.CreateText("SHTitle", val2.transform, "Shop", 22f, C_GOLD, 513, (Vector2?)new Vector2(300f, 30f), richText: true, raycastTarget: false); GameObject val3 = new GameObject("SHSp"); val3.transform.SetParent(val2.transform, false); val3.AddComponent(); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, 1f); txtShopBalance = UIFactory.CreateText("SHBal", val2.transform, "Balance: -", 18f, C_GOLD, 516, (Vector2?)new Vector2(320f, 30f), richText: true, raycastTarget: false); UIFactory.SetBold(txtShopBalance, b: true); txtShopStatus = UIFactory.CreateText("SHStatus", val.transform, "", 14f, C_LABEL, 257, (Vector2?)new Vector2(900f, 22f), richText: true, raycastTarget: false); GameObject val4 = new GameObject("SHTabs"); val4.transform.SetParent(val.transform, false); val4.AddComponent(); UIFactory.AddHLG(val4, 6f); UIFactory.AddLE(val4, -1f, 30f, -1f, 30f, -1f, 0f); shopTabBtns = (GameObject[])(object)new GameObject[SHOP_TAB_NAMES.Length]; shopTabTexts = new object[SHOP_TAB_NAMES.Length]; for (int i = 0; i < SHOP_TAB_NAMES.Length; i++) { int idx = i; GameObject val5 = UIFactory.CreateButton($"ShTab{i}", val4.transform, SHOP_TAB_NAMES[i], 14f, C_LABEL, C_TAB, (UnityAction)delegate { shopCategoryFilter = idx; dirty = true; }, (Vector2?)new Vector2(0f, 26f)); if (UIFactory.tLE != null) { Component component = val5.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } UIFactory.AddLE(val5, -1f, 26f, -1f, 26f, 1f, 0f); shopTabBtns[i] = val5; shopTabTexts[i] = UIFactory.GetButtonText(val5); } txtShopCategoryDesc = UIFactory.CreateText("SHDesc", val.transform, SHOP_TAB_DESCS[0], 13f, C_LABEL, 513, (Vector2?)new Vector2(900f, 22f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("SHSV", val.transform, 4f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); shopRowsContainer = scrollViewRefs.content; shopTitlesHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHT", "= TITLES ="); shopTrailsHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHTr", "= TRAILS ="); shopColorsHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHC", "= MAP COLORS ="); shopNametagsHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHN", "= NAME STYLES ="); shopPColorsHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHPC", "= BODY COLORS ="); shopCursorHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHCur", "= CURSOR COLORS ="); shopEffectsHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHEf", "= PLAYER EFFECTS ="); shopFacesHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHFc", "= CHARACTER COSMETICS ="); shopArtistFilterRow = new GameObject("SHArtF"); shopArtistFilterRow.transform.SetParent(shopRowsContainer.transform, false); shopArtistFilterRow.AddComponent(); UIFactory.AddHLG(shopArtistFilterRow, 6f, 8, 0, 0, 0, forceExpandW: false, forceExpandH: false); UIFactory.AddLE(shopArtistFilterRow, -1f, 36f, -1f, 36f, -1f, 0f); shopArtistFilterRow.SetActive(false); shopOtherHeader = CreateSectionHeader(shopRowsContainer.transform, "SHHOt", "= OTHER ="); for (int num = 0; num < 200; num++) { shopRows.Add(CreateShopRow(shopRowsContainer.transform, num)); } return val; } private static GameObject CreateSectionHeader(Transform parent, string name, string label) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_006b: 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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddHLG(val, 0f, 4, 4, 6, 2); UIFactory.AddLE(val, -1f, -1f, -1f, 30f, -1f, 0f); UIFactory.CreateText(name + "_txt", val.transform, label, 18f, C_WHITE, 513, (Vector2?)new Vector2(600f, 28f), richText: true, raycastTarget: false); return val; } private static ShopRow CreateShopRow(Transform parent, int idx) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Expected O, but got Unknown //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_0486: Unknown result type (might be due to invalid IL or missing references) //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Expected O, but got Unknown //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0548: Unknown result type (might be due to invalid IL or missing references) //IL_0554: Unknown result type (might be due to invalid IL or missing references) //IL_0563: Unknown result type (might be due to invalid IL or missing references) //IL_0572: Expected O, but got Unknown //IL_05d8: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Unknown result type (might be due to invalid IL or missing references) //IL_05fd: Unknown result type (might be due to invalid IL or missing references) //IL_060c: Unknown result type (might be due to invalid IL or missing references) //IL_061b: Expected O, but got Unknown //IL_067d: Unknown result type (might be due to invalid IL or missing references) //IL_0696: Unknown result type (might be due to invalid IL or missing references) //IL_06a2: Unknown result type (might be due to invalid IL or missing references) //IL_06b1: Unknown result type (might be due to invalid IL or missing references) //IL_06c0: Expected O, but got Unknown ShopRow shopRow = new ShopRow(); shopRow.root = UIFactory.CreatePanel($"sr{idx}", parent, C_PANEL); UIFactory.AddHLG(shopRow.root, 10f, 10, 10, 6, 6); UIFactory.AddLE(shopRow.root, -1f, -1f, -1f, 44f, -1f, 0f); int rowIdxCaptured = idx; UIFactory.AddClick(shopRow.root, (UnityAction)delegate { try { ShopRow shopRow2 = shopRows[rowIdxCaptured]; if (shopRow2 != null && !string.IsNullOrEmpty(shopRow2.sku)) { shopSelectedSku = ((shopSelectedSku == shopRow2.sku) ? null : shopRow2.sku); dirty = true; } } catch { } }); shopRow.artImgGO = new GameObject("art"); shopRow.artImgGO.transform.SetParent(shopRow.root.transform, false); shopRow.artImgGO.AddComponent(); UIFactory.AddLE(shopRow.artImgGO, 40f, -1f, 40f, 40f, 0f, 0f); if (UIFactory.tImage != null) { shopRow.artImg = shopRow.artImgGO.AddComponent(UIFactory.tImage); try { UIFactory.tImage.GetProperty("preserveAspect", BindingFlags.Instance | BindingFlags.Public)?.SetValue(shopRow.artImg, true); } catch { } try { UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(shopRow.artImg, false); } catch { } } shopRow.artImgGO.SetActive(false); shopRow.swatchGO = new GameObject("sw"); shopRow.swatchGO.transform.SetParent(shopRow.root.transform, false); shopRow.swatchGO.AddComponent(); UIFactory.AddHLG(shopRow.swatchGO, 3f); UIFactory.AddLE(shopRow.swatchGO, 66f, -1f, 66f, 22f, 0f, 0f); for (int num = 0; num < 3; num++) { GameObject val = new GameObject($"s{num}"); val.transform.SetParent(shopRow.swatchGO.transform, false); val.AddComponent(); UIFactory.AddLE(val, 20f, -1f, 20f, 20f, 0f, 0f); if (UIFactory.tImage != null) { shopRow.swatchImgs[num] = val.AddComponent(UIFactory.tImage); try { UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(shopRow.swatchImgs[num], false); } catch { } } } shopRow.swatchGO.SetActive(false); GameObject val2 = new GameObject("info"); val2.transform.SetParent(shopRow.root.transform, false); val2.AddComponent(); UIFactory.AddVLG(val2, 0f); UIFactory.AddLE(val2, -1f, -1f, -1f, -1f, 1f); shopRow.txtName = UIFactory.CreateText($"sn{idx}", val2.transform, "", 17f, C_WHITE, 513, (Vector2?)new Vector2(500f, 22f), richText: true, raycastTarget: false); UIFactory.SetBold(shopRow.txtName, b: true); shopRow.txtDesc = UIFactory.CreateText($"sd{idx}", val2.transform, "", 13f, C_DIM, 513, (Vector2?)new Vector2(500f, 18f), richText: true, raycastTarget: false); shopRow.txtPrice = UIFactory.CreateText($"sp{idx}", shopRow.root.transform, "", 17f, C_GOLD, 516, (Vector2?)new Vector2(120f, 30f), richText: true, raycastTarget: false); UIFactory.SetBold(shopRow.txtPrice, b: true); int captured = idx; shopRow.buyBtn = UIFactory.CreateButton($"sb{idx}", shopRow.root.transform, "Buy", 14f, C_WHITE, new Color(0.25f, 0.45f, 0.18f, 0.9f), (UnityAction)delegate { try { Plugin.Log.LogInfo((object)$"[SHOP] onClick ENTRY captured={captured}"); ShopRow shopRow2 = shopRows[captured]; if (shopRow2 == null) { Plugin.Log.LogWarning((object)"[SHOP] row is null"); } else { Plugin.Log.LogInfo((object)("[SHOP] row got sku=" + shopRow2.sku)); if (string.IsNullOrEmpty(shopRow2.sku)) { Plugin.Log.LogWarning((object)"[SHOP] empty sku - abort"); } else { string localSteamId = MatchTracker.LocalSteamId; Plugin.Log.LogInfo((object)("[SHOP] steam id=" + localSteamId)); if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { Plugin.Log.LogWarning((object)"[SHOP] no steam id yet - abort"); } else { Plugin.Log.LogInfo((object)"[SHOP] setting status"); UIFactory.SetText(txtShopStatus, "Buying " + shopRow2.sku + "..."); Plugin.Log.LogInfo((object)"[SHOP] calling PurchaseItem"); ApiClient.PurchaseItem(localSteamId, shopRow2.sku, delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)$"[SHOP] purchase complete ok={ok}"); UIFactory.SetText(txtShopStatus, ok ? "Purchased!" : ("Purchase failed: " + resp + "")); dirty = true; }); Plugin.Log.LogInfo((object)"[SHOP] onClick EXIT normally"); } } } } catch (Exception arg) { Plugin.Log.LogError((object)$"[SHOP] onClick threw: {arg}"); } }, (Vector2?)new Vector2(80f, 28f)); UIFactory.AddLE(shopRow.buyBtn, -1f, -1f, 80f, 28f, 0f, 0f); shopRow.buyBtnTxt = UIFactory.GetButtonText(shopRow.buyBtn); shopRow.previewBtn = UIFactory.CreateButton($"spv{idx}", shopRow.root.transform, "Preview", 13f, C_WHITE, new Color(0.25f, 0.4f, 0.55f, 0.9f), (UnityAction)delegate { try { ShopRow shopRow2 = shopRows[captured]; if (shopRow2 != null && !string.IsNullOrEmpty(shopRow2.sku)) { if (shopRow2.kind == "player_effect") { PlayerEffectCosmetic.TogglePreview(shopRow2.sku); } else { TrailPreview.Toggle(shopRow2.sku, shopRow2.previewColor, shopRow2.previewPrice); } dirty = true; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SHOP-PREVIEW] " + ex.Message)); } }, (Vector2?)new Vector2(80f, 28f)); UIFactory.AddLE(shopRow.previewBtn, -1f, -1f, 80f, 28f, 0f, 0f); shopRow.previewBtnTxt = UIFactory.GetButtonText(shopRow.previewBtn); shopRow.artistBtn = UIFactory.CreateButton($"sab{idx}", shopRow.root.transform, "Artist", 12f, C_WHITE, new Color(0.45f, 0.3f, 0.5f, 0.9f), (UnityAction)delegate { try { ShopRow shopRow2 = shopRows[captured]; if (shopRow2 != null && !string.IsNullOrEmpty(shopRow2.sku)) { string skuForPick = shopRow2.sku; ApiClient.FetchArtistsList(delegate { List cachedAllArtists = ApiClient.CachedAllArtists; if (cachedAllArtists == null || cachedAllArtists.Count == 0) { ShowArtistResult(ok: false, "{\"detail\":\"no artists defined yet - grant the role in the Admin tab first\"}"); } else { string[] array = new string[cachedAllArtists.Count]; string[] array2 = new string[cachedAllArtists.Count]; for (int i = 0; i < cachedAllArtists.Count; i++) { array[i] = cachedAllArtists[i].display_name; array2[i] = cachedAllArtists[i].steam_id; } CompetitiveUI.OpenArtistPicker("Assign artist - " + skuForPick, array, array2, delegate(string picked) { ApiClient.AdminSetItemArtist(MatchTracker.LocalSteamId, skuForPick, picked, delegate(bool flag, string resp) { ShowArtistResult(flag, flag ? (skuForPick + " assigned.") : resp); }); }); } }); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SHOP-ARTIST] " + ex.Message)); } }, (Vector2?)new Vector2(60f, 28f)); UIFactory.AddLE(shopRow.artistBtn, -1f, -1f, 60f, 28f, 0f, 0f); shopRow.artistBtn.SetActive(false); shopRow.setActiveBtn = UIFactory.CreateButton($"sa{idx}", shopRow.root.transform, "Set Active", 13f, C_WHITE, new Color(0.3f, 0.3f, 0.5f, 0.9f), (UnityAction)delegate { try { ShopRow shopRow2 = shopRows[captured]; string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && !(localSteamId == "unknown")) { List cachedShopItems = ApiClient.CachedShopItems; string kind = ""; string text = ""; string sku = shopRow2.sku; string text2 = ""; if (cachedShopItems != null) { foreach (ApiClient.ShopItemData item in cachedShopItems) { if (item.id == shopRow2.itemId) { kind = item.kind; text = item.name; text2 = item.preview_color; break; } } } Plugin.Log.LogInfo((object)("[SHOP] Set Active clicked sku=" + shopRow2.sku + " kind=" + kind)); ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; bool flag = kind == "title" && cachedPlayerStats != null && ((!string.IsNullOrEmpty(cachedPlayerStats.active_title_sku)) ? (cachedPlayerStats.active_title_sku == sku) : (cachedPlayerStats.active_title == text)); bool flag2 = kind == "trail" && cachedPlayerStats != null && cachedPlayerStats.active_trail_sku == sku; long itemId = ((flag || flag2) ? 0 : shopRow2.itemId); if (cachedPlayerStats != null) { if (kind == "title") { if (flag) { cachedPlayerStats.active_title = null; cachedPlayerStats.active_title_color = null; cachedPlayerStats.active_title_sku = null; } else { cachedPlayerStats.active_title = text; cachedPlayerStats.active_title_color = text2; cachedPlayerStats.active_title_sku = sku; } } else if (kind == "trail") { if (flag2) { cachedPlayerStats.active_trail_sku = null; cachedPlayerStats.active_trail_color = null; } else { cachedPlayerStats.active_trail_sku = sku; cachedPlayerStats.active_trail_color = text2; } } else if (kind == "color") { if (cachedPlayerStats.active_color_skus == null) { cachedPlayerStats.active_color_skus = new List(); } if (cachedPlayerStats.active_color_skus.Contains(sku)) { cachedPlayerStats.active_color_skus.Remove(sku); } else { cachedPlayerStats.active_color_skus.Add(sku); } cachedPlayerStats.active_color_sku = ((cachedPlayerStats.active_color_skus.Count > 0) ? cachedPlayerStats.active_color_skus[0] : null); } else if (kind == "nametag") { if (cachedPlayerStats.active_nametag_skus == null) { cachedPlayerStats.active_nametag_skus = new List(); } if (cachedPlayerStats.active_nametag_skus.Contains(sku)) { cachedPlayerStats.active_nametag_skus.Remove(sku); } else { string sub = NametagStyler.GetSubgroup(sku); if (sub != null) { cachedPlayerStats.active_nametag_skus.RemoveAll((string s) => NametagStyler.GetSubgroup(s) == sub); } cachedPlayerStats.active_nametag_skus.Add(sku); } } else if (kind == "player_color") { bool flag3 = cachedPlayerStats.active_player_color_sku == sku; cachedPlayerStats.active_player_color_sku = (flag3 ? null : sku); cachedPlayerStats.active_player_color_hex = (flag3 ? null : text2); cachedPlayerStats.active_player_color_name = (flag3 ? null : text); } else if (kind == "cursor_color") { bool flag4 = cachedPlayerStats.active_cursor_color_sku == sku; cachedPlayerStats.active_cursor_color_sku = (flag4 ? null : sku); cachedPlayerStats.active_cursor_color_hex = (flag4 ? null : text2); } else if (kind == "player_effect") { bool flag5 = cachedPlayerStats.active_player_effect_sku == sku; cachedPlayerStats.active_player_effect_sku = (flag5 ? null : sku); } else if (kind == "utility") { cachedPlayerStats.hide_gold = !cachedPlayerStats.hide_gold; } dirty = true; } Action callback = delegate(bool ok, string resp) { UIFactory.SetText(txtShopStatus, ok ? "Equipped." : ("Failed: " + resp + "")); dirty = true; if (ok && kind == "nametag") { NametagStyler.PublishToPhoton(); } if (ok && kind == "player_color") { try { PlayerColorCosmetic.PublishLocalProps(); } catch { } if (GameStateWatcher.IsInMatch) { try { PlayerColorCosmetic.OnMatchEnd(); PlayerColorCosmetic.OnMatchStart(); } catch { } } } if (ok && kind == "player_effect") { try { PlayerEffectCosmetic.PublishLocalProps(); } catch { } if (GameStateWatcher.IsInMatch) { try { PlayerEffectCosmetic.OnMatchEnd(); PlayerEffectCosmetic.OnMatchStart(); } catch { } } } if (ok && kind == "cursor_color") { try { CursorColorCosmetic.ApplyFromStats(); } catch { } } }; if (kind == "trail") { ApiClient.SetActiveTrail(localSteamId, itemId, callback); } else if (kind == "color") { ApiClient.ToggleMapColor(localSteamId, shopRow2.itemId, callback); } else if (kind == "nametag") { ApiClient.ToggleNametagStyle(localSteamId, shopRow2.itemId, callback); } else if (kind == "player_color") { ApiClient.SetActivePlayerColor(localSteamId, (cachedPlayerStats != null && cachedPlayerStats.active_player_color_sku == sku) ? shopRow2.itemId : 0, callback); } else if (kind == "cursor_color") { ApiClient.SetActiveCursorColor(localSteamId, (cachedPlayerStats != null && cachedPlayerStats.active_cursor_color_sku == sku) ? shopRow2.itemId : 0, callback); } else if (kind == "player_effect") { ApiClient.SetActivePlayerEffect(localSteamId, (cachedPlayerStats != null && cachedPlayerStats.active_player_effect_sku == sku) ? shopRow2.itemId : 0, callback); } else if (kind == "utility") { ApiClient.SetHideGold(localSteamId, cachedPlayerStats?.hide_gold ?? false, callback); } else { ApiClient.SetActiveTitle(localSteamId, itemId, callback); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"[SHOP] setActive threw: {arg}"); } }, (Vector2?)new Vector2(100f, 28f)); UIFactory.AddLE(shopRow.setActiveBtn, -1f, -1f, 100f, 28f, 0f, 0f); shopRow.root.SetActive(false); return shopRow; } private static void RefreshShop() { //IL_0096: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; int num = ((cachedPlayerStats != null) ? (cachedPlayerStats.gold_earned - cachedPlayerStats.gold_spent) : 0); if (txtShopBalance != null) { UIFactory.SetText(txtShopBalance, $"Balance: {num} gold"); } if (shopTabBtns != null) { for (int i = 0; i < shopTabBtns.Length; i++) { if (!((Object)(object)shopTabBtns[i] == (Object)null)) { bool flag = i == shopCategoryFilter; UIFactory.SetImageColor(shopTabBtns[i], flag ? C_TABACT : C_TAB); if (shopTabTexts != null && i < shopTabTexts.Length && shopTabTexts[i] != null) { UIFactory.SetColor(shopTabTexts[i], flag ? C_WHITE : C_LABEL); UIFactory.SetBold(shopTabTexts[i], flag); } } } } if (txtShopCategoryDesc != null) { int num2 = Math.Max(0, Math.Min(shopCategoryFilter, SHOP_TAB_DESCS.Length - 1)); UIFactory.SetText(txtShopCategoryDesc, SHOP_TAB_DESCS[num2]); } List cachedShopItems = ApiClient.CachedShopItems; List list = new List(); List list2 = new List(); List list3 = new List(); List list4 = new List(); List list5 = new List(); List list6 = new List(); List list7 = new List(); List list8 = new List(); List list9 = new List(); if (cachedShopItems != null) { foreach (ApiClient.ShopItemData item2 in cachedShopItems) { if (item2.kind == "trail") { list2.Add(item2); } else if (item2.kind == "color") { list3.Add(item2); } else if (item2.kind == "nametag") { list4.Add(item2); } else if (item2.kind == "player_color") { list5.Add(item2); } else if (item2.kind == "cursor_color") { list6.Add(item2); } else if (item2.kind == "player_effect") { list7.Add(item2); } else if (item2.kind == "face") { list8.Add(item2); } else if (item2.kind == "utility") { list9.Add(item2); } else { list.Add(item2); } } list.Sort((ApiClient.ShopItemData a, ApiClient.ShopItemData b) => a.price.CompareTo(b.price)); list2.Sort((ApiClient.ShopItemData a, ApiClient.ShopItemData b) => a.price.CompareTo(b.price)); list3.Sort(delegate(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { bool flag4 = CustomMapColors.IsVanillaStyled(a.sku); bool flag5 = CustomMapColors.IsVanillaStyled(b.sku); if (flag4 != flag5) { return (!flag4) ? 1 : (-1); } int num15 = a.price.CompareTo(b.price); return (num15 != 0) ? num15 : string.Compare(a.name, b.name, StringComparison.OrdinalIgnoreCase); }); list4.Sort(delegate(ApiClient.ShopItemData a, ApiClient.ShopItemData b) { int num15 = rank(a.sku).CompareTo(rank(b.sku)); if (num15 != 0) { return num15; } int num16 = a.price.CompareTo(b.price); return (num16 != 0) ? num16 : string.Compare(a.name, b.name, StringComparison.OrdinalIgnoreCase); }); list5.Sort((ApiClient.ShopItemData a, ApiClient.ShopItemData b) => a.price.CompareTo(b.price)); list6.Sort((ApiClient.ShopItemData a, ApiClient.ShopItemData b) => a.price.CompareTo(b.price)); list7.Sort((ApiClient.ShopItemData a, ApiClient.ShopItemData b) => a.price.CompareTo(b.price)); list8.Sort((ApiClient.ShopItemData a, ApiClient.ShopItemData b) => a.price.CompareTo(b.price)); list9.Sort((ApiClient.ShopItemData a, ApiClient.ShopItemData b) => a.price.CompareTo(b.price)); } List list10 = new List(); if (shopCategoryFilter != 0) { if (shopCategoryFilter != 1) { list8.Clear(); } if (shopCategoryFilter != 2) { list4.Clear(); } if (shopCategoryFilter != 3) { list3.Clear(); } if (shopCategoryFilter != 4) { list.Clear(); } if (shopCategoryFilter != 5) { list2.Clear(); } if (shopCategoryFilter != 6) { list5.Clear(); } if (shopCategoryFilter != 7) { list6.Clear(); } if (shopCategoryFilter != 8) { list7.Clear(); } if (shopCategoryFilter != 9) { list9.Clear(); } } list10.AddRange(list8); list10.AddRange(list4); list10.AddRange(list3); list10.AddRange(list); list10.AddRange(list2); list10.AddRange(list5); list10.AddRange(list6); list10.AddRange(list7); list10.AddRange(list9); int num3 = 0; int num4 = 0; if (list8.Count > 0 && (Object)(object)shopFacesHeader != (Object)null) { shopFacesHeader.SetActive(true); shopFacesHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopFacesHeader != (Object)null) { shopFacesHeader.SetActive(false); } List list11 = list8; bool flag2 = false; List list12 = new List(); foreach (ApiClient.ShopItemData item3 in list8) { string item = (string.IsNullOrEmpty(item3.artist_name) ? "House" : item3.artist_name); if (!string.IsNullOrEmpty(item3.artist_name)) { flag2 = true; } if (!list12.Contains(item)) { list12.Add(item); } } bool flag3 = list8.Count > 0 && flag2 && (Object)(object)shopArtistFilterRow != (Object)null; if ((Object)(object)shopArtistFilterRow != (Object)null) { shopArtistFilterRow.SetActive(flag3); } if (flag3) { list12.Sort(StringComparer.OrdinalIgnoreCase); if (list12.Remove("House")) { list12.Add("House"); } List list13 = new List { "" }; list13.AddRange(list12); SyncShopArtistFilterButtons(list13); shopArtistFilterRow.transform.SetSiblingIndex(num3++); if (!string.IsNullOrEmpty(shopArtistFilter)) { list11 = list8.FindAll((ApiClient.ShopItemData f) => (string.IsNullOrEmpty(f.artist_name) ? "House" : f.artist_name) == shopArtistFilter); if (list11.Count == 0) { shopArtistFilter = null; list11 = list8; } } } else { shopArtistFilter = null; } int num5 = 0; while (num5 < list11.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list11[num5], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num5++; num4++; } if (list4.Count > 0 && (Object)(object)shopNametagsHeader != (Object)null) { shopNametagsHeader.SetActive(true); shopNametagsHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopNametagsHeader != (Object)null) { shopNametagsHeader.SetActive(false); } int num6 = 0; while (num6 < list4.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list4[num6], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num6++; num4++; } if (list3.Count > 0 && (Object)(object)shopColorsHeader != (Object)null) { shopColorsHeader.SetActive(true); shopColorsHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopColorsHeader != (Object)null) { shopColorsHeader.SetActive(false); } int num7 = 0; while (num7 < list3.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list3[num7], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num7++; num4++; } if (list.Count > 0 && (Object)(object)shopTitlesHeader != (Object)null) { shopTitlesHeader.SetActive(true); shopTitlesHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopTitlesHeader != (Object)null) { shopTitlesHeader.SetActive(false); } int num8 = 0; while (num8 < list.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list[num8], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num8++; num4++; } if (list2.Count > 0 && (Object)(object)shopTrailsHeader != (Object)null) { shopTrailsHeader.SetActive(true); shopTrailsHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopTrailsHeader != (Object)null) { shopTrailsHeader.SetActive(false); } int num9 = 0; while (num9 < list2.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list2[num9], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num9++; num4++; } if (list5.Count > 0 && (Object)(object)shopPColorsHeader != (Object)null) { shopPColorsHeader.SetActive(true); shopPColorsHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopPColorsHeader != (Object)null) { shopPColorsHeader.SetActive(false); } int num10 = 0; while (num10 < list5.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list5[num10], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num10++; num4++; } if (list6.Count > 0 && (Object)(object)shopCursorHeader != (Object)null) { shopCursorHeader.SetActive(true); shopCursorHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopCursorHeader != (Object)null) { shopCursorHeader.SetActive(false); } int num11 = 0; while (num11 < list6.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list6[num11], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num11++; num4++; } if (list7.Count > 0 && (Object)(object)shopEffectsHeader != (Object)null) { shopEffectsHeader.SetActive(true); shopEffectsHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopEffectsHeader != (Object)null) { shopEffectsHeader.SetActive(false); } int num12 = 0; while (num12 < list7.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list7[num12], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num12++; num4++; } if (list9.Count > 0 && (Object)(object)shopOtherHeader != (Object)null) { shopOtherHeader.SetActive(true); shopOtherHeader.transform.SetSiblingIndex(num3++); } else if ((Object)(object)shopOtherHeader != (Object)null) { shopOtherHeader.SetActive(false); } int num13 = 0; while (num13 < list9.Count && num4 < shopRows.Count) { ApplyShopRow(shopRows[num4], list9[num13], num, cachedPlayerStats); shopRows[num4].root.transform.SetSiblingIndex(num3++); num13++; num4++; } for (int num14 = num4; num14 < shopRows.Count; num14++) { shopRows[num14].root.SetActive(false); } static int rank(string sku) { if (sku.StartsWith("nametag_neon_", StringComparison.OrdinalIgnoreCase)) { return 2; } return NametagStyler.GetSubgroup(sku) switch { null => 0, "color" => 1, "glow" => 3, "size" => 4, _ => 5, }; } } private static void SyncShopArtistFilterButtons(List names) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: 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) while (shopArtistBtns.Count < names.Count) { int ii = shopArtistBtns.Count; GameObject val = UIFactory.CreateButton($"shArt{ii}", shopArtistFilterRow.transform, "", 16f, C_LABEL, C_BTN, (UnityAction)delegate { string text = ((ii < shopArtistBtnNames.Count) ? shopArtistBtnNames[ii] : ""); shopArtistFilter = (string.IsNullOrEmpty(text) ? null : text); dirty = true; }, (Vector2?)new Vector2(150f, 30f)); shopArtistBtns.Add(val); shopArtistBtnTexts.Add(UIFactory.GetButtonText(val)); } while (shopArtistBtnNames.Count < shopArtistBtns.Count) { shopArtistBtnNames.Add(""); } for (int num = 0; num < shopArtistBtns.Count; num++) { bool flag = num < names.Count; shopArtistBtns[num].SetActive(flag); if (flag) { shopArtistBtnNames[num] = names[num]; bool flag2 = (string.IsNullOrEmpty(names[num]) ? (shopArtistFilter == null) : (shopArtistFilter == names[num])); UIFactory.SetText(shopArtistBtnTexts[num], string.IsNullOrEmpty(names[num]) ? "All" : names[num]); UIFactory.SetImageColor(shopArtistBtns[num], flag2 ? C_TABACT : C_BTN); UIFactory.SetColor(shopArtistBtnTexts[num], flag2 ? C_WHITE : C_LABEL); } } } private static string ReadableNameColor(string hex) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_007e: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(hex)) { return "#FFFFFF"; } Color val = default(Color); if (!ColorUtility.TryParseHtmlString(hex.StartsWith("#") ? hex : ("#" + hex), ref val)) { return "#FFFFFF"; } float num = 0.299f * val.r + 0.587f * val.g + 0.114f * val.b; if (num < 0.45f) { val = Color.Lerp(val, Color.white, (0.45f - num) / 0.45f * 0.8f); } return "#" + ColorUtility.ToHtmlStringRGB(val); } private static void ApplyShopRow(ShopRow r, ApiClient.ShopItemData it, int balance, ApiClient.PlayerStatsData s) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0436: 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_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_0811: Unknown result type (might be due to invalid IL or missing references) //IL_083f: Unknown result type (might be due to invalid IL or missing references) //IL_082c: Unknown result type (might be due to invalid IL or missing references) //IL_08a7: Unknown result type (might be due to invalid IL or missing references) //IL_08ae: Unknown result type (might be due to invalid IL or missing references) //IL_08db: Unknown result type (might be due to invalid IL or missing references) //IL_08f6: Unknown result type (might be due to invalid IL or missing references) //IL_0ba0: Unknown result type (might be due to invalid IL or missing references) //IL_0b85: Unknown result type (might be due to invalid IL or missing references) //IL_0d5c: Unknown result type (might be due to invalid IL or missing references) //IL_0d41: Unknown result type (might be due to invalid IL or missing references) r.itemId = it.id; r.sku = it.sku; r.kind = it.kind; UIFactory.SetImageColor(r.root, (!string.IsNullOrEmpty(shopSelectedSku) && shopSelectedSku == it.sku) ? C_ROWSEL : C_PANEL); string text = ReadableNameColor(it.preview_color); string text2 = ((!string.IsNullOrEmpty(it.artist_name)) ? (" by " + it.artist_name + "") : ""); UIFactory.SetText(r.txtName, "" + it.name + " (" + it.rarity + ")" + text2); bool flag = false; if (it.kind == "face" && r.artImg != null) { Sprite shopSprite = CustomCosmetics.GetShopSprite(it.sku); if ((Object)(object)shopSprite != (Object)null) { try { UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public)?.SetValue(r.artImg, shopSprite); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(r.artImg, Color.white); flag = true; float fps; Sprite[] shopFrames = CustomCosmetics.GetShopFrames(it.sku, out fps); TrackAnimatedThumb(r.artImg, shopFrames, fps); } catch { } } } else if (it.kind == "player_color" && r.artImg != null) { Sprite bodyGlyphSprite = GetBodyGlyphSprite(it.sku, it.preview_color); if ((Object)(object)bodyGlyphSprite != (Object)null) { try { UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public)?.SetValue(r.artImg, bodyGlyphSprite); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(r.artImg, Color.white); flag = true; } catch { } } TrackAnimatedThumb(r.artImg, null, 0f); } else if (r.artImg != null) { TrackAnimatedThumb(r.artImg, null, 0f); } if ((Object)(object)r.artImgGO != (Object)null && r.artImgGO.activeSelf != flag) { r.artImgGO.SetActive(flag); } bool flag2 = flag && it.kind == "face"; if ((Object)(object)r.artImgGO != (Object)null) { UIFactory.SetPrefWH(r.artImgGO, flag2 ? 80 : 40, flag2 ? 80 : 40); } UIFactory.SetPrefH(r.root, flag2 ? 88 : 44); bool flag3 = false; if (it.kind == "color" && (Object)(object)r.swatchGO != (Object)null && CustomMapColors.IsCustomSku(it.sku)) { Color? mapBlockColor = CustomMapColors.GetMapBlockColor(it.sku); Color secondaryColor = CustomMapColors.GetSecondaryColor(it.sku); Color? backgroundColor = CustomMapColors.GetBackgroundColor(it.sku); Color[] array = (Color[])(object)new Color[3] { (Color)(((??)mapBlockColor) ?? Color.grey), secondaryColor, (Color)(((??)backgroundColor) ?? new Color(0.25f, 0.28f, 0.35f)) }; for (int i = 0; i < 3 && i < r.swatchImgs.Length; i++) { if (r.swatchImgs[i] != null) { try { Color val = array[i]; val.a = 1f; UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(r.swatchImgs[i], val); } catch { } } } flag3 = true; } if ((Object)(object)r.swatchGO != (Object)null && r.swatchGO.activeSelf != flag3) { r.swatchGO.SetActive(flag3); } if ((Object)(object)r.artistBtn != (Object)null) { bool flag4 = ApiClient.IsAdmin && it.kind == "face"; if (r.artistBtn.activeSelf != flag4) { r.artistBtn.SetActive(flag4); } } UIFactory.SetBold(r.txtDesc, b: true); if (it.kind == "nametag") { string text3 = s?.display_name; if (string.IsNullOrEmpty(text3)) { text3 = MatchTracker.LocalDisplayName; } if (string.IsNullOrEmpty(text3)) { text3 = "Sid"; } string text4 = NametagStyler.WrapForSku(text3, it.sku); string text5 = ((it.sku == "nametag_bold") ? ("" + text4 + "") : ("" + text4 + "")); string subgroup = NametagStyler.GetSubgroup(it.sku); string text6 = subgroup switch { "typeface" => "one typeface at a time - modded players only", "size" => "one size at a time", "glow" => "one glow at a time - modded players only", "color" => "one color at a time", null => "stackable", _ => "one font at a time", }; UIFactory.SetText(r.txtDesc, "Preview: " + text5 + " (" + text6 + ")"); string sku = ((subgroup == "typeface") ? it.sku : ""); NametagFontRenderer.ApplyFontToLabel(r.txtDesc, sku, shopPreviewOriginalFonts); string sku2 = ((subgroup == "glow") ? it.sku : ""); NametagGlowRenderer.ApplyGlowToLabel(r.txtDesc, sku2, shopPreviewOriginalMats, shopPreviewGlowMatCache); } else { string text7 = it.description ?? ""; if (it.stock_limit < 0) { text7 += " (OUT OF STOCK - artist hasn't opened sales yet)"; } else if (it.stock_limit > 0) { int num = Math.Max(0, it.stock_limit - it.stock_sold); text7 += ((num > 0) ? $" ({num} of {it.stock_limit} left)" : " (SOLD OUT)"); } if (it.kind == "face") { text7 += " (equip in the character editor)"; } UIFactory.SetText(r.txtDesc, text7); NametagFontRenderer.ApplyFontToLabel(r.txtDesc, "", shopPreviewOriginalFonts); NametagGlowRenderer.ApplyGlowToLabel(r.txtDesc, "", shopPreviewOriginalMats, shopPreviewGlowMatCache); } UIFactory.SetText(r.txtPrice, $"{it.price}g"); bool owned = it.owned; bool flag5 = balance >= it.price; bool flag6 = !owned && it.stock_limit > 0 && it.stock_sold >= it.stock_limit; if (owned) { UIFactory.SetColor(r.txtPrice, C_GREEN); } else if (flag5) { UIFactory.SetColor(r.txtPrice, C_GOLD); } else { UIFactory.SetColor(r.txtPrice, C_DIM); } r.buyBtn.SetActive(!owned); if (r.buyBtnTxt != null) { UIFactory.SetText(r.buyBtnTxt, flag6 ? "Sold out" : "Buy"); UIFactory.SetColor(r.buyBtnTxt, (Color)((flag5 && !flag6) ? C_WHITE : new Color(0.55f, 0.55f, 0.6f))); UIFactory.SetImageColor(r.buyBtn, (flag5 && !flag6) ? new Color(0.25f, 0.45f, 0.18f, 0.9f) : new Color(0.25f, 0.25f, 0.28f, 0.8f)); } r.setActiveBtn.SetActive(owned && (it.kind == "title" || it.kind == "trail" || it.kind == "color" || it.kind == "nametag" || it.kind == "player_color" || it.kind == "cursor_color" || it.kind == "player_effect" || it.kind == "utility")); bool flag7 = s != null && it.kind == "title" && ((!string.IsNullOrEmpty(s.active_title_sku)) ? (s.active_title_sku == it.sku) : (s.active_title == it.name)); bool flag8 = s != null && it.kind == "trail" && s.active_trail_sku == it.sku; bool flag9 = s != null && it.kind == "color" && s.active_color_skus != null && s.active_color_skus.Contains(it.sku); bool flag10 = s != null && it.kind == "nametag" && s.active_nametag_skus != null && s.active_nametag_skus.Contains(it.sku); bool flag11 = s != null && it.kind == "player_color" && s.active_player_color_sku == it.sku; bool flag12 = s != null && it.kind == "cursor_color" && s.active_cursor_color_sku == it.sku; bool flag13 = s != null && it.kind == "player_effect" && s.active_player_effect_sku == it.sku; bool flag14 = s != null && it.kind == "utility" && it.sku == "util_hide_gold" && s.hide_gold; bool flag15 = flag7 || flag8 || flag9 || flag10 || flag11 || flag12 || flag13 || flag14; if ((Object)(object)r.setActiveBtn != (Object)null) { UIFactory.SetImageColor(r.setActiveBtn, flag15 ? new Color(0.2f, 0.55f, 0.2f, 0.95f) : new Color(0.3f, 0.3f, 0.5f, 0.9f)); object buttonText = UIFactory.GetButtonText(r.setActiveBtn); bool flag16 = it.kind == "nametag" || it.kind == "color"; if (buttonText != null) { if (it.kind == "utility") { UIFactory.SetText(buttonText, flag14 ? "Show Gold" : "Hide Gold"); } else { UIFactory.SetText(buttonText, (!flag15) ? (flag16 ? "Equip" : "Set Active") : (flag16 ? "Remove" : "Unequip")); } } } if ((Object)(object)r.previewBtn != (Object)null) { bool flag17 = it.kind == "trail"; bool flag18 = it.kind == "player_effect"; r.previewBtn.SetActive(flag17 || flag18); if (flag17 || flag18) { r.previewColor = it.preview_color ?? ""; r.previewPrice = it.price; bool flag19 = ((!flag17) ? (PlayerEffectCosmetic.PreviewSku == it.sku) : (TrailPreview.IsActive && TrailPreview.ActiveSku == it.sku)); if (r.previewBtnTxt != null) { UIFactory.SetText(r.previewBtnTxt, flag19 ? "Stop" : "Preview"); } UIFactory.SetImageColor(r.previewBtn, flag19 ? new Color(0.5f, 0.3f, 0.25f, 0.9f) : new Color(0.25f, 0.4f, 0.55f, 0.9f)); } } r.root.SetActive(true); } private static GameObject SettingsButton(Transform parent, string name, string label, Color textColor, Color bgColor, Vector2 size, UnityAction onClick) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown GameObject val = new GameObject(name + "_row"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddHLG(val, 6f); UIFactory.AddLE(val, -1f, -1f, -1f, size.y + 2f, -1f, 0f); GameObject val2 = UIFactory.CreateButton(name, val.transform, label, 14f, textColor, bgColor, onClick, size); UIFactory.AddLE(val2, -1f, -1f, size.x, size.y, 0f, 0f); GameObject val3 = new GameObject("S"); val3.transform.SetParent(val.transform, false); val3.AddComponent(); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, 1f); return val2; } private static GameObject SettingsToggle(Transform parent, string name, Vector2 size, UnityAction onClick, string desc = null, float descH = 18f) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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) GameObject val = new GameObject(name + "_grp"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 1f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 0f); GameObject result = SettingsButton(val.transform, name, "", C_WHITE, C_BTN, size, onClick); if (!string.IsNullOrEmpty(desc)) { UIFactory.CreateText(name + "_d", val.transform, desc, 13f, C_DIM, 257, (Vector2?)new Vector2(700f, descH), richText: true, raycastTarget: false); } return result; } private static GameObject BuildSettingsTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0144: 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_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Expected O, but got Unknown //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Expected O, but got Unknown //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Expected O, but got Unknown //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Expected O, but got Unknown //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Expected O, but got Unknown //IL_0560: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Expected O, but got Unknown //IL_05bd: Unknown result type (might be due to invalid IL or missing references) //IL_0579: Unknown result type (might be due to invalid IL or missing references) //IL_057e: Unknown result type (might be due to invalid IL or missing references) //IL_0584: Expected O, but got Unknown //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_05d6: Unknown result type (might be due to invalid IL or missing references) //IL_05db: Unknown result type (might be due to invalid IL or missing references) //IL_05e1: Expected O, but got Unknown //IL_066c: Unknown result type (might be due to invalid IL or missing references) //IL_06e2: Unknown result type (might be due to invalid IL or missing references) //IL_06f6: Unknown result type (might be due to invalid IL or missing references) //IL_071e: Unknown result type (might be due to invalid IL or missing references) //IL_0633: Unknown result type (might be due to invalid IL or missing references) //IL_0638: Unknown result type (might be due to invalid IL or missing references) //IL_063e: Expected O, but got Unknown //IL_077b: Unknown result type (might be due to invalid IL or missing references) //IL_0737: Unknown result type (might be due to invalid IL or missing references) //IL_073c: Unknown result type (might be due to invalid IL or missing references) //IL_0742: Expected O, but got Unknown //IL_07d8: Unknown result type (might be due to invalid IL or missing references) //IL_0794: Unknown result type (might be due to invalid IL or missing references) //IL_0799: Unknown result type (might be due to invalid IL or missing references) //IL_079f: Expected O, but got Unknown //IL_0835: Unknown result type (might be due to invalid IL or missing references) //IL_07f1: Unknown result type (might be due to invalid IL or missing references) //IL_07f6: Unknown result type (might be due to invalid IL or missing references) //IL_07fc: Expected O, but got Unknown //IL_0892: Unknown result type (might be due to invalid IL or missing references) //IL_084e: Unknown result type (might be due to invalid IL or missing references) //IL_0853: Unknown result type (might be due to invalid IL or missing references) //IL_0859: Expected O, but got Unknown //IL_08ef: Unknown result type (might be due to invalid IL or missing references) //IL_08ab: Unknown result type (might be due to invalid IL or missing references) //IL_08b0: Unknown result type (might be due to invalid IL or missing references) //IL_08b6: Expected O, but got Unknown //IL_094c: Unknown result type (might be due to invalid IL or missing references) //IL_0908: Unknown result type (might be due to invalid IL or missing references) //IL_090d: Unknown result type (might be due to invalid IL or missing references) //IL_0913: Expected O, but got Unknown //IL_09a9: Unknown result type (might be due to invalid IL or missing references) //IL_0965: Unknown result type (might be due to invalid IL or missing references) //IL_096a: Unknown result type (might be due to invalid IL or missing references) //IL_0970: Expected O, but got Unknown //IL_09fc: Unknown result type (might be due to invalid IL or missing references) //IL_0a6b: Unknown result type (might be due to invalid IL or missing references) //IL_0a70: Unknown result type (might be due to invalid IL or missing references) //IL_0a7f: Unknown result type (might be due to invalid IL or missing references) //IL_09c2: Unknown result type (might be due to invalid IL or missing references) //IL_09c7: Unknown result type (might be due to invalid IL or missing references) //IL_09cd: Expected O, but got Unknown //IL_0abb: Unknown result type (might be due to invalid IL or missing references) //IL_0ac5: Expected O, but got Unknown //IL_0a98: Unknown result type (might be due to invalid IL or missing references) //IL_0a9d: Unknown result type (might be due to invalid IL or missing references) //IL_0aa3: Expected O, but got Unknown //IL_0b56: Unknown result type (might be due to invalid IL or missing references) //IL_0b5b: Unknown result type (might be due to invalid IL or missing references) //IL_0b61: Expected O, but got Unknown //IL_0b8f: Unknown result type (might be due to invalid IL or missing references) //IL_0b94: Unknown result type (might be due to invalid IL or missing references) //IL_0b9a: Expected O, but got Unknown //IL_0bc8: Unknown result type (might be due to invalid IL or missing references) //IL_0bcd: Unknown result type (might be due to invalid IL or missing references) //IL_0bd3: Expected O, but got Unknown //IL_0c01: Unknown result type (might be due to invalid IL or missing references) //IL_0c06: Unknown result type (might be due to invalid IL or missing references) //IL_0c0c: Expected O, but got Unknown //IL_0c3a: Unknown result type (might be due to invalid IL or missing references) //IL_0c3f: Unknown result type (might be due to invalid IL or missing references) //IL_0c45: Expected O, but got Unknown //IL_0c73: Unknown result type (might be due to invalid IL or missing references) //IL_0c78: Unknown result type (might be due to invalid IL or missing references) //IL_0c7e: Expected O, but got Unknown //IL_0cac: Unknown result type (might be due to invalid IL or missing references) //IL_0cb1: Unknown result type (might be due to invalid IL or missing references) //IL_0cb7: Expected O, but got Unknown //IL_0d0b: Unknown result type (might be due to invalid IL or missing references) //IL_0d81: Unknown result type (might be due to invalid IL or missing references) //IL_0d95: Unknown result type (might be due to invalid IL or missing references) //IL_0dbd: Unknown result type (might be due to invalid IL or missing references) //IL_0dd1: Unknown result type (might be due to invalid IL or missing references) //IL_0df4: Unknown result type (might be due to invalid IL or missing references) //IL_0e0d: Unknown result type (might be due to invalid IL or missing references) //IL_0e1c: Unknown result type (might be due to invalid IL or missing references) //IL_0ce5: Unknown result type (might be due to invalid IL or missing references) //IL_0cea: Unknown result type (might be due to invalid IL or missing references) //IL_0cf0: Expected O, but got Unknown //IL_0e52: Unknown result type (might be due to invalid IL or missing references) //IL_0ec8: Unknown result type (might be due to invalid IL or missing references) //IL_0edc: Unknown result type (might be due to invalid IL or missing references) //IL_0f04: Unknown result type (might be due to invalid IL or missing references) //IL_0f18: Unknown result type (might be due to invalid IL or missing references) //IL_0f2f: Unknown result type (might be due to invalid IL or missing references) //IL_0f36: Expected O, but got Unknown //IL_0fa2: Unknown result type (might be due to invalid IL or missing references) //IL_0fbb: Unknown result type (might be due to invalid IL or missing references) //IL_0e35: Unknown result type (might be due to invalid IL or missing references) //IL_0e3a: Unknown result type (might be due to invalid IL or missing references) //IL_0e40: Expected O, but got Unknown //IL_0fe9: Unknown result type (might be due to invalid IL or missing references) //IL_1004: Unknown result type (might be due to invalid IL or missing references) //IL_107a: Unknown result type (might be due to invalid IL or missing references) //IL_108e: Unknown result type (might be due to invalid IL or missing references) //IL_10b6: Unknown result type (might be due to invalid IL or missing references) //IL_10ca: Unknown result type (might be due to invalid IL or missing references) //IL_10e1: Unknown result type (might be due to invalid IL or missing references) //IL_10e8: Expected O, but got Unknown //IL_1154: Unknown result type (might be due to invalid IL or missing references) //IL_116d: Unknown result type (might be due to invalid IL or missing references) //IL_0fd4: Unknown result type (might be due to invalid IL or missing references) //IL_0fd9: Unknown result type (might be due to invalid IL or missing references) //IL_0fdf: Expected O, but got Unknown //IL_119b: Unknown result type (might be due to invalid IL or missing references) //IL_11ee: Unknown result type (might be due to invalid IL or missing references) //IL_1207: Unknown result type (might be due to invalid IL or missing references) //IL_1186: Unknown result type (might be due to invalid IL or missing references) //IL_118b: Unknown result type (might be due to invalid IL or missing references) //IL_1191: Expected O, but got Unknown //IL_1235: Unknown result type (might be due to invalid IL or missing references) //IL_1294: Unknown result type (might be due to invalid IL or missing references) //IL_1299: Unknown result type (might be due to invalid IL or missing references) //IL_1220: Unknown result type (might be due to invalid IL or missing references) //IL_1225: Unknown result type (might be due to invalid IL or missing references) //IL_122b: Expected O, but got Unknown //IL_12c7: Unknown result type (might be due to invalid IL or missing references) //IL_1315: Unknown result type (might be due to invalid IL or missing references) //IL_131c: Expected O, but got Unknown //IL_1375: Unknown result type (might be due to invalid IL or missing references) //IL_1389: Unknown result type (might be due to invalid IL or missing references) //IL_12b2: Unknown result type (might be due to invalid IL or missing references) //IL_12b7: Unknown result type (might be due to invalid IL or missing references) //IL_12bd: Expected O, but got Unknown GameObject val = new GameObject("SettingsOuter"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 0f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("SettingsScroll", val.transform, 0f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val2 = new GameObject("Settings"); val2.transform.SetParent(scrollViewRefs.content.transform, false); val2.AddComponent(); UIFactory.AddVLG(val2, 10f, 20, 20, 10, 10); UIFactory.AddLE(val2, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("SH", val2.transform, "Settings", 22f, C_GOLD, 258, (Vector2?)new Vector2(600f, 30f), richText: true, raycastTarget: false); GameObject val3 = UIFactory.CreatePanel("SCB", val2.transform, C_PANEL); UIFactory.AddVLG(val3, 10f, 12, 12, 8, 8); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("SCL", val3.transform, "Data & Privacy", 17f, new Color(0.7f, 0.85f, 1f), 257, (Vector2?)new Vector2(700f, 24f), richText: true, raycastTarget: false); txtConsentStatus = UIFactory.CreateText("SCS", val3.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(700f, 22f), richText: true, raycastTarget: false); Transform transform = val3.transform; Vector2 size = new Vector2(220f, 28f); object obj = <>c.<>9__605_0; if (obj == null) { UnityAction val4 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Consent toggle clicked"); if (Plugin.DataConsentGranted) { Plugin.DataConsent.Value = "denied"; } else { Plugin.DataConsent.Value = "granted"; } ApiClient.OnConsentChanged(); dirty = true; }; <>c.<>9__605_0 = val4; obj = (object)val4; } consentToggleBtn = SettingsToggle(transform, "SCT", size, (UnityAction)obj, "Allow the mod to report your match results and stats to the community server."); consentToggleTxt = UIFactory.GetButtonText(consentToggleBtn); Transform transform2 = val3.transform; Vector2 size2 = new Vector2(340f, 28f); object obj2 = <>c.<>9__605_1; if (obj2 == null) { UnityAction val5 = delegate { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; string localSteamId = MatchTracker.LocalSteamId; if (cachedPlayerStats != null && !string.IsNullOrEmpty(localSteamId) && !(localSteamId == "unknown")) { Plugin.Log.LogInfo((object)"[SETTINGS] appear-offline toggled"); cachedPlayerStats.appear_offline = !cachedPlayerStats.appear_offline; dirty = true; ApiClient.SetAppearOffline(localSteamId, cachedPlayerStats.appear_offline, delegate(bool ok, string resp) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!ok) { CompetitiveUI.ShowNotification("Appear-offline update failed - try again", Color.yellow, 3f); } dirty = true; }); } }; <>c.<>9__605_1 = val5; obj2 = (object)val5; } appearOfflineBtn = SettingsToggle(transform2, "SAppOff", size2, (UnityAction)obj2, "Hides you from the Home tab's online and recently-online lists."); appearOfflineTxt = UIFactory.GetButtonText(appearOfflineBtn); Transform transform3 = val3.transform; Vector2 size3 = new Vector2(340f, 28f); object obj3 = <>c.<>9__605_2; if (obj3 == null) { UnityAction val6 = delegate { //IL_0054: Unknown result type (might be due to invalid IL or missing references) ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; string localSteamId = MatchTracker.LocalSteamId; if (cachedPlayerStats != null && !string.IsNullOrEmpty(localSteamId) && !(localSteamId == "unknown")) { if (string.IsNullOrEmpty(cachedPlayerStats.discord_username) && string.IsNullOrEmpty(cachedPlayerStats.discord_id)) { CompetitiveUI.ShowNotification("Link your Discord first (Home tab)", Color.yellow, 4f); } else { Plugin.Log.LogInfo((object)"[SETTINGS] show-discord toggled"); cachedPlayerStats.show_discord = !cachedPlayerStats.show_discord; dirty = true; ApiClient.SetShowDiscord(localSteamId, cachedPlayerStats.show_discord, delegate(bool ok, string resp) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!ok) { CompetitiveUI.ShowNotification("Show-Discord update failed - try again", Color.yellow, 3f); } dirty = true; }); } } }; <>c.<>9__605_2 = val6; obj3 = (object)val6; } showDiscordBtn = SettingsToggle(transform3, "SShowDc", size3, (UnityAction)obj3, "Shows your Discord name on the leaderboard (opt-in; link Discord on the Home tab first)."); showDiscordTxt = UIFactory.GetButtonText(showDiscordBtn); GameObject val7 = UIFactory.CreatePanel("SIntB", val2.transform, C_PANEL); UIFactory.AddVLG(val7, 10f, 12, 12, 8, 8); UIFactory.AddLE(val7, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("SIntL", val7.transform, "Interface", 17f, new Color(0.7f, 0.85f, 1f), 257, (Vector2?)new Vector2(700f, 24f), richText: true, raycastTarget: false); Transform transform4 = val7.transform; Vector2 size4 = new Vector2(260f, 28f); object obj4 = <>c.<>9__605_3; if (obj4 == null) { UnityAction val8 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] FPS toggled"); Plugin.ShowFps.Value = !Plugin.ShowFps.Value; dirty = true; }; <>c.<>9__605_3 = val8; obj4 = (object)val8; } fpsToggleBtn = SettingsToggle(transform4, "SFPS", size4, (UnityAction)obj4, "FPS counter in the corner of the screen."); fpsToggleTxt = UIFactory.GetButtonText(fpsToggleBtn); Transform transform5 = val7.transform; Vector2 size5 = new Vector2(260f, 28f); object obj5 = <>c.<>9__605_4; if (obj5 == null) { UnityAction val9 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Ping/region toggled"); Plugin.ShowRegionPing.Value = !Plugin.ShowRegionPing.Value; dirty = true; }; <>c.<>9__605_4 = val9; obj5 = (object)val9; } pingToggleBtn = SettingsToggle(transform5, "SPing", size5, (UnityAction)obj5, "Shows the current Photon region and your ping to it."); pingToggleTxt = UIFactory.GetButtonText(pingToggleBtn); Transform transform6 = val7.transform; Vector2 size6 = new Vector2(260f, 28f); object obj6 = <>c.<>9__605_5; if (obj6 == null) { UnityAction val10 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] In-game chat overlay toggled"); Plugin.ShowIngameChat.Value = !Plugin.ShowIngameChat.Value; dirty = true; }; <>c.<>9__605_5 = val10; obj6 = (object)val10; } ingameChatToggleBtn = SettingsToggle(transform6, "SIgChat", size6, (UnityAction)obj6, "Shows community chat messages on-screen while you play."); ingameChatToggleTxt = UIFactory.GetButtonText(ingameChatToggleBtn); Transform transform7 = val7.transform; Vector2 size7 = new Vector2(260f, 28f); object obj7 = <>c.<>9__605_6; if (obj7 == null) { UnityAction val11 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Notifications toggled"); Plugin.ShowNotifications.Value = !Plugin.ShowNotifications.Value; dirty = true; }; <>c.<>9__605_6 = val11; obj7 = (object)val11; } notifToggleBtn = SettingsToggle(transform7, "SNT", size7, (UnityAction)obj7, "On-screen pop-ups for incoming chat + XP / level notifications. Chat log on the Home tab still updates either way.", 34f); notifToggleTxt = UIFactory.GetButtonText(notifToggleBtn); Transform transform8 = val7.transform; Vector2 size8 = new Vector2(260f, 28f); object obj8 = <>c.<>9__605_7; if (obj8 == null) { UnityAction val12 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Input overlay toggled"); Plugin.ShowInputOverlay.Value = !Plugin.ShowInputOverlay.Value; dirty = true; }; <>c.<>9__605_7 = val12; obj8 = (object)val12; } inputOverlayToggleBtn = SettingsToggle(transform8, "SInpOv", size8, (UnityAction)obj8, "Input overlay (bottom-left): shows W/A/S/D/Space and L/R click. Keys glow red when pressed. Useful for streams or diagnosing missed inputs.", 34f); inputOverlayToggleTxt = UIFactory.GetButtonText(inputOverlayToggleBtn); Transform transform9 = val7.transform; Vector2 size9 = new Vector2(260f, 28f); object obj9 = <>c.<>9__605_8; if (obj9 == null) { UnityAction val13 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Block debug overlay toggled"); Plugin.ShowBlockDebug.Value = !Plugin.ShowBlockDebug.Value; dirty = true; }; <>c.<>9__605_8 = val13; obj9 = (object)val13; } blockDbgToggleBtn = SettingsToggle(transform9, "SBlkDbg", size9, (UnityAction)obj9, "Block debug overlay (corner): live act/succ counters + per-hit timing (too early / too slow / unblockable).", 34f); blockDbgToggleTxt = UIFactory.GetButtonText(blockDbgToggleBtn); Transform transform10 = val7.transform; Vector2 size10 = new Vector2(260f, 28f); object obj10 = <>c.<>9__605_9; if (obj10 == null) { UnityAction val14 = delegate { CursorColorCosmetic.CycleShape(); dirty = true; }; <>c.<>9__605_9 = val14; obj10 = (object)val14; } cursorShapeBtn = SettingsToggle(transform10, "SCursor", size10, (UnityAction)obj10, "Cycles the menu cursor shape; combines with an equipped cursor color."); cursorShapeTxt = UIFactory.GetButtonText(cursorShapeBtn); GameObject val15 = UIFactory.CreatePanel("SDispB", val2.transform, C_PANEL); UIFactory.AddVLG(val15, 10f, 12, 12, 8, 8); UIFactory.AddLE(val15, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("SDispL", val15.transform, "Visuals & Effects", 17f, new Color(0.7f, 0.85f, 1f), 257, (Vector2?)new Vector2(700f, 24f), richText: true, raycastTarget: false); Transform transform11 = val15.transform; Vector2 size11 = new Vector2(260f, 28f); object obj11 = <>c.<>9__605_10; if (obj11 == null) { UnityAction val16 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Trails toggled"); Plugin.ShowTrails.Value = !Plugin.ShowTrails.Value; if (Plugin.ShowTrails.Value) { if (GameStateWatcher.IsInMatch) { TrailCosmetic.OnMatchStart(); } } else { TrailCosmetic.OnMatchEnd(); } dirty = true; }; <>c.<>9__605_10 = val16; obj11 = (object)val16; } trailToggleBtn = SettingsToggle(transform11, "STrail", size11, (UnityAction)obj11, "Renders cosmetic trails on you and other modded players."); trailToggleTxt = UIFactory.GetButtonText(trailToggleBtn); Transform transform12 = val15.transform; Vector2 size12 = new Vector2(260f, 28f); object obj12 = <>c.<>9__605_11; if (obj12 == null) { UnityAction val17 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Custom player colors toggled"); Plugin.ShowPlayerColors.Value = !Plugin.ShowPlayerColors.Value; try { PlayerColorCosmetic.OnShowPlayerColorsToggled(); } catch { } try { PlayerEffectCosmetic.OnShowPlayerColorsToggled(); } catch { } dirty = true; }; <>c.<>9__605_11 = val17; obj12 = (object)val17; } playerColorToggleBtn = SettingsToggle(transform12, "SPColor", size12, (UnityAction)obj12, "Custom player body colors: render shop-purchased Body Colors on yourself + other modded players. Off = everyone falls back to default orange/blue.", 34f); playerColorToggleTxt = UIFactory.GetButtonText(playerColorToggleBtn); Transform transform13 = val15.transform; Vector2 size13 = new Vector2(260f, 28f); object obj13 = <>c.<>9__605_12; if (obj13 == null) { UnityAction val18 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Animated cosmetics toggled"); Plugin.AnimatedCosmetics.Value = !Plugin.AnimatedCosmetics.Value; try { PlayerEffectCosmetic.OnAnimatedCosmeticsToggled(); } catch { } dirty = true; }; <>c.<>9__605_12 = val18; obj13 = (object)val18; } animCosToggleBtn = SettingsToggle(transform13, "SAnimCos", size13, (UnityAction)obj13, "Animated cosmetics: prismatic/chrome body colors, prism trail, player effects, map-skin shimmer, animated faces. Off = all freeze to a static frame instantly.", 34f); animCosToggleTxt = UIFactory.GetButtonText(animCosToggleBtn); Transform transform14 = val15.transform; Vector2 size14 = new Vector2(260f, 28f); object obj14 = <>c.<>9__605_13; if (obj14 == null) { UnityAction val19 = delegate { MapPhysicalColorPatch.BloomStrengthSetting.Cycle(); Plugin.Log.LogInfo((object)("[SETTINGS] Bloom strength -> " + MapPhysicalColorPatch.BloomStrengthSetting.Level)); dirty = true; }; <>c.<>9__605_13 = val19; obj14 = (object)val19; } bloomToggleBtn = SettingsToggle(transform14, "SBloom", size14, (UnityAction)obj14, "Glow (bloom): the soft halo around bright cosmetics, map art and effects. Reduced = smaller, dimmer halo. Off = no halo. Local only — nothing is hidden, the cosmetic itself still renders the same. A few items have their glow painted into the artwork, and that part stays.", 46f); bloomToggleTxt = UIFactory.GetButtonText(bloomToggleBtn); Transform transform15 = val15.transform; Vector2 size15 = new Vector2(260f, 28f); object obj15 = <>c.<>9__605_14; if (obj15 == null) { UnityAction val20 = delegate { ScreenshakerDisablePatch.Cycle(); Plugin.Log.LogInfo((object)("[SETTINGS] Screen shake -> " + ScreenshakerDisablePatch.Level)); dirty = true; }; <>c.<>9__605_14 = val20; obj15 = (object)val20; } screenShakeToggleBtn = SettingsToggle(transform15, "SShake", size15, (UnityAction)obj15, "Camera screen shake on shots/hits/deaths. Full = vanilla. Reduced = softer, keeps the hit feedback. Off = a perfectly steady camera. Local only."); screenShakeToggleTxt = UIFactory.GetButtonText(screenShakeToggleBtn); Transform transform16 = val15.transform; Vector2 size16 = new Vector2(260f, 28f); object obj16 = <>c.<>9__605_15; if (obj16 == null) { UnityAction val21 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Chromatic aberration toggled"); Plugin.ChromaticAberrationEnabled.Value = !Plugin.ChromaticAberrationEnabled.Value; try { MapPhysicalColorPatch.ChromaticAberrationSetting.Apply(); } catch { } dirty = true; }; <>c.<>9__605_15 = val21; obj16 = (object)val21; } chromAbToggleBtn = SettingsToggle(transform16, "SChromAb", size16, (UnityAction)obj16, "Chromatic aberration: the RGB color-fringing that pulses on shots/hits/deaths. Off = crisp edges, tiny FPS gain. Visual only, local only.", 34f); chromAbToggleTxt = UIFactory.GetButtonText(chromAbToggleBtn); Transform transform17 = val15.transform; Vector2 size17 = new Vector2(260f, 28f); object obj17 = <>c.<>9__605_16; if (obj17 == null) { UnityAction val22 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Map lighting toggled"); Plugin.MapLightingEnabled.Value = !Plugin.MapLightingEnabled.Value; try { MapPhysicalColorPatch.RenderPerfSettings.Apply(); MapPhysicalColorPatch.RenderPerfSettings.ApplyBackdrop(); } catch { } dirty = true; }; <>c.<>9__605_16 = val22; obj17 = (object)val22; } mapLightingToggleBtn = SettingsToggle(transform17, "SLight", size17, (UnityAction)obj17, "Map lighting: the per-frame lightmap render. Off = flat full-bright scene, skips the whole pass for extra FPS."); mapLightingToggleTxt = UIFactory.GetButtonText(mapLightingToggleBtn); Transform transform18 = val15.transform; Vector2 size18 = new Vector2(260f, 28f); object obj18 = <>c.<>9__605_17; if (obj18 == null) { UnityAction val23 = delegate { Plugin.Log.LogInfo((object)"[SETTINGS] Map shadows toggled"); Plugin.MapShadowsEnabled.Value = !Plugin.MapShadowsEnabled.Value; try { MapPhysicalColorPatch.RenderPerfSettings.Apply(); MapPhysicalColorPatch.RenderPerfSettings.ApplyBackdrop(); } catch { } dirty = true; }; <>c.<>9__605_17 = val23; obj18 = (object)val23; } mapShadowsToggleBtn = SettingsToggle(transform18, "SShad", size18, (UnityAction)obj18, "Soft shadow beams cast by map lighting. Off = skips the shadow render pass (lighting stays) for extra FPS."); mapShadowsToggleTxt = UIFactory.GetButtonText(mapShadowsToggleBtn); GameObject val24 = UIFactory.CreatePanel("SPerfB", val15.transform, C_PANEL); UIFactory.AddVLG(val24, 2f, 8, 8, 6, 6); UIFactory.AddLE(val24, -1f, -1f, -1f, -1f, -1f, 0f); Transform transform19 = val24.transform; Color textColor = new Color(1f, 0.85f, 0.4f); Color c_BTN = C_BTN; Vector2 size19 = new Vector2(700f, 28f); object obj19 = <>c.<>9__605_18; if (obj19 == null) { UnityAction val25 = delegate { _perfSectionOpen = !_perfSectionOpen; if ((Object)(object)_perfSectionBody != (Object)null) { _perfSectionBody.SetActive(_perfSectionOpen); } dirty = true; }; <>c.<>9__605_18 = val25; obj19 = (object)val25; } GameObject btn = SettingsButton(transform19, "SPerfH", "", textColor, c_BTN, size19, (UnityAction)obj19); _perfSectionHeaderTxt = UIFactory.GetButtonText(btn); _perfSectionBody = new GameObject("SPerfBody"); _perfSectionBody.transform.SetParent(val24.transform, false); _perfSectionBody.AddComponent(); UIFactory.AddVLG(_perfSectionBody, 3f, 4, 4, 4, 4); UIFactory.AddLE(_perfSectionBody, -1f, -1f, -1f, -1f, -1f, 0f); _perfSectionBody.SetActive(_perfSectionOpen); object obj20 = <>c.<>9__605_20; if (obj20 == null) { UnityAction val26 = delegate { if (Plugin.PerfOptimizations != null) { Plugin.PerfOptimizations.Value = !Plugin.PerfOptimizations.Value; dirty = true; } }; <>c.<>9__605_20 = val26; obj20 = (object)val26; } AddPerfRow("Master", "Performance master switch — flips ALL the patches below at once.", (UnityAction)obj20, out perfMasterBtn, out perfMasterTxt); object obj21 = <>c.<>9__605_21; if (obj21 == null) { UnityAction val27 = delegate { if (Plugin.PerfStunPlayerNullGuard != null) { Plugin.PerfStunPlayerNullGuard.Value = !Plugin.PerfStunPlayerNullGuard.Value; dirty = true; } }; <>c.<>9__605_21 = val27; obj21 = (object)val27; } AddPerfRow("Stun", "StunPlayer null-guard — stops NRE spam when a player is destroyed mid-stun.", (UnityAction)obj21, out perfStunBtn, out perfStunTxt); object obj22 = <>c.<>9__605_22; if (obj22 == null) { UnityAction val28 = delegate { if (Plugin.PerfDespawnOffscreenBullets != null) { Plugin.PerfDespawnOffscreenBullets.Value = !Plugin.PerfDespawnOffscreenBullets.Value; dirty = true; } }; <>c.<>9__605_22 = val28; obj22 = (object)val28; } AddPerfRow("OOB", "Despawn off-screen bullets — host clears bullets that exit the camera viewport.", (UnityAction)obj22, out perfBulletsBtn, out perfBulletsTxt); object obj23 = <>c.<>9__605_23; if (obj23 == null) { UnityAction val29 = delegate { if (Plugin.PerfSwallowHitSoundNREs != null) { Plugin.PerfSwallowHitSoundNREs.Value = !Plugin.PerfSwallowHitSoundNREs.Value; dirty = true; } }; <>c.<>9__605_23 = val29; obj23 = (object)val29; } AddPerfRow("HitSnd", "Swallow RayHitBulletSound NREs from destroyed parents.", (UnityAction)obj23, out perfHitSndBtn, out perfHitSndTxt); object obj24 = <>c.<>9__605_24; if (obj24 == null) { UnityAction val30 = delegate { if (Plugin.PerfSwallowEdgeBounceNREs != null) { Plugin.PerfSwallowEdgeBounceNREs.Value = !Plugin.PerfSwallowEdgeBounceNREs.Value; dirty = true; } }; <>c.<>9__605_24 = val30; obj24 = (object)val30; } AddPerfRow("EdgeBn", "Swallow ScreenEdgeBounce NREs from destroyed bullets.", (UnityAction)obj24, out perfEdgeBnBtn, out perfEdgeBnTxt); object obj25 = <>c.<>9__605_25; if (obj25 == null) { UnityAction val31 = delegate { if (Plugin.PerfSkipMenuUpdateInMatch != null) { Plugin.PerfSkipMenuUpdateInMatch.Value = !Plugin.PerfSkipMenuUpdateInMatch.Value; dirty = true; } }; <>c.<>9__605_25 = val31; obj25 = (object)val31; } AddPerfRow("Menu", "Skip MenuControllerHandler.Update during an active match.", (UnityAction)obj25, out perfMenuBtn, out perfMenuTxt); object obj26 = <>c.<>9__605_26; if (obj26 == null) { UnityAction val32 = delegate { if (Plugin.PerfBulletHitParticleCap != null) { Plugin.PerfBulletHitParticleCap.Value = !Plugin.PerfBulletHitParticleCap.Value; dirty = true; } }; <>c.<>9__605_26 = val32; obj26 = (object)val32; } AddPerfRow("BulletCap", "Cap bullet-hit particles at 2/frame — biggest user-visible win on heavy firefights.", (UnityAction)obj26, out perfBulletCapBtn, out perfBulletCapTxt); object obj27 = <>c.<>9__605_27; if (obj27 == null) { UnityAction val33 = delegate { if (Plugin.PerfClampObjectPoolInit != null) { Plugin.PerfClampObjectPoolInit.Value = !Plugin.PerfClampObjectPoolInit.Value; dirty = true; } }; <>c.<>9__605_27 = val33; obj27 = (object)val33; } AddPerfRow("PoolInit", "Clamp ObjectPool init-spawn to 4 in-match — reduces frame stutter from new pool allocation.", (UnityAction)obj27, out perfPoolBtn, out perfPoolTxt); GameObject val34 = UIFactory.CreatePanel("SBugB", val2.transform, C_PANEL); UIFactory.AddVLG(val34, 4f, 12, 12, 8, 8); UIFactory.AddLE(val34, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("SBugL", val34.transform, "Report a bug", 17f, new Color(1f, 0.9f, 0.6f), 257, (Vector2?)new Vector2(700f, 24f), richText: true, raycastTarget: false); UIFactory.CreateText("SBugD", val34.transform, "Send a bug report straight to the mod team — description, severity, and optionally your game logs. Use the Preview button to see what gets attached.", 13f, C_DIM, 257, (Vector2?)new Vector2(700f, 38f), richText: true, raycastTarget: false); Transform transform20 = val34.transform; Color c_WHITE = C_WHITE; Color bgColor = new Color(0.2f, 0.3f, 0.45f, 0.9f); Vector2 size20 = new Vector2(260f, 28f); object obj28 = <>c.<>9__605_28; if (obj28 == null) { UnityAction val35 = delegate { CompetitiveUI.OpenBugReportModal(); }; <>c.<>9__605_28 = val35; obj28 = (object)val35; } GameObject val36 = SettingsButton(transform20, "SBugBtn", "Open Report Form", c_WHITE, bgColor, size20, (UnityAction)obj28); GameObject val37 = UIFactory.CreatePanel("SEB", val2.transform, C_PANEL); UIFactory.AddVLG(val37, 4f, 12, 12, 8, 8); UIFactory.AddLE(val37, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("SEL", val37.transform, "Leave All Queues", 17f, new Color(1f, 0.85f, 0.5f), 257, (Vector2?)new Vector2(700f, 24f), richText: true, raycastTarget: false); UIFactory.CreateText("SED", val37.transform, "Removes you from every queue and lobby in every mode - 1v1, 2v2, 1v2 and FFA.\nUse this if the game thinks you're still in a match you've already left, or if joining a queue keeps telling you you're busy. It won't affect a game you're actually playing, and it never touches your stats, gold or rating.", 13f, C_DIM, 257, (Vector2?)new Vector2(700f, 56f), richText: true, raycastTarget: false); GameObject val38 = new GameObject("SER"); val38.transform.SetParent(val37.transform, false); val38.AddComponent(); UIFactory.AddHLG(val38, 8f); UIFactory.AddLE(val38, -1f, -1f, -1f, 30f, -1f, 0f); Transform transform21 = val38.transform; Color c_WHITE2 = C_WHITE; Color bgColor2 = new Color(0.42f, 0.32f, 0.12f, 0.9f); object obj29 = <>c.<>9__605_29; if (obj29 == null) { UnityAction val39 = delegate { ApiClient.EscapeAllQueues(); dirty = true; }; <>c.<>9__605_29 = val39; obj29 = (object)val39; } UIFactory.CreateButton("SEBtn", transform21, "Leave all queues", 14f, c_WHITE2, bgColor2, (UnityAction)obj29, (Vector2?)new Vector2(200f, 28f)); GameObject val40 = UIFactory.CreatePanel("SDB", val2.transform, C_PANEL); UIFactory.AddVLG(val40, 4f, 12, 12, 8, 8); UIFactory.AddLE(val40, -1f, -1f, -1f, -1f, -1f, 0f); UIFactory.CreateText("SDL", val40.transform, "Delete My Data", 17f, new Color(1f, 0.6f, 0.6f), 257, (Vector2?)new Vector2(700f, 24f), richText: true, raycastTarget: false); UIFactory.CreateText("SDD", val40.transform, "Anonymizes your Steam ID, display name, and Discord link. Matches stay so other players' Elo and histories aren't affected. You will no longer appear on leaderboards.\nIRREVERSIBLE: this Steam ID can never re-register. Future matches from this account will show as [Deleted User] and won't count toward stats.", 13f, C_DIM, 257, (Vector2?)new Vector2(700f, 68f), richText: true, raycastTarget: false); GameObject val41 = new GameObject("SDR"); val41.transform.SetParent(val40.transform, false); val41.AddComponent(); UIFactory.AddHLG(val41, 8f); UIFactory.AddLE(val41, -1f, -1f, -1f, 30f, -1f, 0f); Transform transform22 = val41.transform; Color c_WHITE3 = C_WHITE; Color bgColor3 = new Color(0.45f, 0.18f, 0.18f, 0.9f); object obj30 = <>c.<>9__605_30; if (obj30 == null) { UnityAction val42 = delegate { if (ClickGuard.Claim()) { deleteArmed = true; dirty = true; } }; <>c.<>9__605_30 = val42; obj30 = (object)val42; } deleteBtn = UIFactory.CreateButton("SDBtn", transform22, "Delete my data...", 14f, c_WHITE3, bgColor3, (UnityAction)obj30, (Vector2?)new Vector2(200f, 28f)); UIFactory.AddLE(deleteBtn, -1f, -1f, 200f, 28f, 0f, 0f); Transform transform23 = val41.transform; Color c_WHITE4 = C_WHITE; Color bgColor4 = new Color(0.7f, 0.15f, 0.15f, 0.95f); object obj31 = <>c.<>9__605_31; if (obj31 == null) { UnityAction val43 = delegate { if (ClickGuard.Claim()) { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && !(localSteamId == "unknown")) { deleteArmed = false; ApiClient.DeletePlayerData(localSteamId, delegate(bool ok, string msg) { Plugin.Log.LogInfo((object)$"[PRIVACY] Delete result: ok={ok} msg={msg}"); if (ok) { Plugin.DataConsent.Value = "denied"; ApiClient.OnConsentChanged(); if (txtDeleteStatus != null) { UIFactory.SetText(txtDeleteStatus, "Your data has been anonymized. Consent is now Denied."); } } else if (txtDeleteStatus != null) { UIFactory.SetText(txtDeleteStatus, "Deletion failed: " + msg + ""); } dirty = true; }); } } }; <>c.<>9__605_31 = val43; obj31 = (object)val43; } confirmDeleteBtn = UIFactory.CreateButton("SDCBtn", transform23, "Confirm - really delete", 14f, c_WHITE4, bgColor4, (UnityAction)obj31, (Vector2?)new Vector2(220f, 28f)); UIFactory.AddLE(confirmDeleteBtn, -1f, -1f, 220f, 28f, 0f, 0f); confirmDeleteBtn.SetActive(false); Transform transform24 = val41.transform; Color c_LABEL = C_LABEL; Color c_BTN2 = C_BTN; object obj32 = <>c.<>9__605_32; if (obj32 == null) { UnityAction val44 = delegate { if (ClickGuard.Claim()) { deleteArmed = false; dirty = true; } }; <>c.<>9__605_32 = val44; obj32 = (object)val44; } cancelDelBtn = UIFactory.CreateButton("SDXBtn", transform24, "Cancel", 14f, c_LABEL, c_BTN2, (UnityAction)obj32, (Vector2?)new Vector2(90f, 28f)); UIFactory.AddLE(cancelDelBtn, -1f, -1f, 90f, 28f, 0f, 0f); cancelDelBtn.SetActive(false); GameObject val45 = new GameObject("SDSp"); val45.transform.SetParent(val41.transform, false); val45.AddComponent(); UIFactory.AddLE(val45, -1f, -1f, -1f, -1f, 1f); txtDeleteStatus = UIFactory.CreateText("SDS", val40.transform, "", 14f, C_LABEL, 257, (Vector2?)new Vector2(700f, 22f), richText: true, raycastTarget: false); return val; static void AddPerfRow(string id, string label, UnityAction onClick, out GameObject btnOut, out object txtOut) { //IL_002b: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) UIFactory.CreateText("SPerfL_" + id, _perfSectionBody.transform, "" + label + "", 12f, C_DIM, 257, (Vector2?)new Vector2(700f, 18f), richText: true, raycastTarget: false); btnOut = SettingsButton(_perfSectionBody.transform, "SPerf_" + id, "", C_WHITE, C_BTN, new Vector2(280f, 22f), onClick); txtOut = UIFactory.GetButtonText(btnOut); } } private static void RefreshSettings() { if (txtConsentStatus != null) { UIFactory.SetText(s: Plugin.DataConsentGranted ? "Status: Allowed - match data and linking are active." : ((!Plugin.DataConsentAsked) ? "Status: Unset - the consent prompt will appear on next launch." : "Status: Denied - mod runs offline. No data leaves your machine."), t: txtConsentStatus); } if (consentToggleTxt != null) { UIFactory.SetText(consentToggleTxt, Plugin.DataConsentGranted ? "Revoke consent" : "Allow data reporting"); } if ((Object)(object)deleteBtn != (Object)null) { deleteBtn.SetActive(!deleteArmed); } if ((Object)(object)confirmDeleteBtn != (Object)null) { confirmDeleteBtn.SetActive(deleteArmed); } if ((Object)(object)cancelDelBtn != (Object)null) { cancelDelBtn.SetActive(deleteArmed); } if (notifToggleTxt != null) { UIFactory.SetText(notifToggleTxt, Plugin.ShowNotifications.Value ? "Chat notifications: ON" : "Chat notifications: OFF"); } if (fpsToggleTxt != null && Plugin.ShowFps != null) { UIFactory.SetText(fpsToggleTxt, Plugin.ShowFps.Value ? "FPS counter: ON" : "FPS counter: OFF"); } if (appearOfflineTxt != null) { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; UIFactory.SetText(appearOfflineTxt, (cachedPlayerStats != null && cachedPlayerStats.appear_offline) ? "Appear offline (Home lists): ON" : "Appear offline (Home lists): OFF"); } if (showDiscordTxt != null) { ApiClient.PlayerStatsData cachedPlayerStats2 = ApiClient.CachedPlayerStats; bool flag = cachedPlayerStats2 != null && (!string.IsNullOrEmpty(cachedPlayerStats2.discord_username) || !string.IsNullOrEmpty(cachedPlayerStats2.discord_id)); UIFactory.SetText(showDiscordTxt, (!flag) ? "Show Discord on leaderboard: link Discord first" : (cachedPlayerStats2.show_discord ? "Show Discord on leaderboard: ON" : "Show Discord on leaderboard: OFF")); } if (pingToggleTxt != null && Plugin.ShowRegionPing != null) { UIFactory.SetText(pingToggleTxt, Plugin.ShowRegionPing.Value ? "Ping / region display: ON" : "Ping / region display: OFF"); } if (ingameChatToggleTxt != null && Plugin.ShowIngameChat != null) { UIFactory.SetText(ingameChatToggleTxt, Plugin.ShowIngameChat.Value ? "In-game chat overlay: ON" : "In-game chat overlay: OFF"); } if (cursorShapeTxt != null) { UIFactory.SetText(cursorShapeTxt, "Cursor: " + CursorColorCosmetic.CurrentShapeLabel() + ""); } if (trailToggleTxt != null && Plugin.ShowTrails != null) { UIFactory.SetText(trailToggleTxt, Plugin.ShowTrails.Value ? "Cosmetic trails: ON" : "Cosmetic trails: OFF"); } if (blockDbgToggleTxt != null && Plugin.ShowBlockDebug != null) { UIFactory.SetText(blockDbgToggleTxt, Plugin.ShowBlockDebug.Value ? "Block debug overlay: ON" : "Block debug overlay: OFF"); } if (playerColorToggleTxt != null && Plugin.ShowPlayerColors != null) { UIFactory.SetText(playerColorToggleTxt, Plugin.ShowPlayerColors.Value ? "Custom player body colors: ON" : "Custom player body colors: OFF"); } if (inputOverlayToggleTxt != null && Plugin.ShowInputOverlay != null) { UIFactory.SetText(inputOverlayToggleTxt, Plugin.ShowInputOverlay.Value ? "Input overlay: ON" : "Input overlay: OFF"); } if (screenShakeToggleTxt != null && Plugin.ScreenShakeStrength != null) { string level = ScreenshakerDisablePatch.Level; string text = ((level == "Full") ? "#88FF88" : ((level == "Reduced") ? "#FFDD88" : "#FF9966")); UIFactory.SetText(screenShakeToggleTxt, "Screen shake: " + level.ToUpperInvariant() + ""); } if (mapLightingToggleTxt != null && Plugin.MapLightingEnabled != null) { UIFactory.SetText(mapLightingToggleTxt, Plugin.MapLightingEnabled.Value ? "Map lighting: ON" : "Map lighting: OFF"); } if (mapShadowsToggleTxt != null && Plugin.MapShadowsEnabled != null) { UIFactory.SetText(mapShadowsToggleTxt, Plugin.MapShadowsEnabled.Value ? "Map shadows: ON" : "Map shadows: OFF"); } if (animCosToggleTxt != null && Plugin.AnimatedCosmetics != null) { UIFactory.SetText(animCosToggleTxt, Plugin.AnimatedCosmetics.Value ? "Animated cosmetics: ON" : "Animated cosmetics: OFF (static)"); } if (bloomToggleTxt != null && Plugin.BloomStrength != null) { string level2 = MapPhysicalColorPatch.BloomStrengthSetting.Level; string text2 = ((level2 == "Full") ? "#88FF88" : ((level2 == "Reduced") ? "#DDDD66" : "#FF9966")); UIFactory.SetText(bloomToggleTxt, "Glow (bloom): " + level2.ToUpperInvariant() + ""); } if (chromAbToggleTxt != null && Plugin.ChromaticAberrationEnabled != null) { UIFactory.SetText(chromAbToggleTxt, Plugin.ChromaticAberrationEnabled.Value ? "Chromatic aberration: ON" : "Chromatic aberration: OFF"); } if (_perfSectionHeaderTxt != null) { int num = 0; int num2 = 7; ConfigEntry perfStunPlayerNullGuard = Plugin.PerfStunPlayerNullGuard; if (perfStunPlayerNullGuard != null && perfStunPlayerNullGuard.Value) { num++; } ConfigEntry perfDespawnOffscreenBullets = Plugin.PerfDespawnOffscreenBullets; if (perfDespawnOffscreenBullets != null && perfDespawnOffscreenBullets.Value) { num++; } ConfigEntry perfSwallowHitSoundNREs = Plugin.PerfSwallowHitSoundNREs; if (perfSwallowHitSoundNREs != null && perfSwallowHitSoundNREs.Value) { num++; } ConfigEntry perfSwallowEdgeBounceNREs = Plugin.PerfSwallowEdgeBounceNREs; if (perfSwallowEdgeBounceNREs != null && perfSwallowEdgeBounceNREs.Value) { num++; } ConfigEntry perfSkipMenuUpdateInMatch = Plugin.PerfSkipMenuUpdateInMatch; if (perfSkipMenuUpdateInMatch != null && perfSkipMenuUpdateInMatch.Value) { num++; } ConfigEntry perfBulletHitParticleCap = Plugin.PerfBulletHitParticleCap; if (perfBulletHitParticleCap != null && perfBulletHitParticleCap.Value) { num++; } ConfigEntry perfClampObjectPoolInit = Plugin.PerfClampObjectPoolInit; if (perfClampObjectPoolInit != null && perfClampObjectPoolInit.Value) { num++; } ConfigEntry perfOptimizations = Plugin.PerfOptimizations; string text3 = ((perfOptimizations != null && perfOptimizations.Value) ? $"{num}/{num2} active" : "MASTER OFF"); string text4 = (_perfSectionOpen ? "v" : ">"); UIFactory.SetText(_perfSectionHeaderTxt, "" + text4 + " Performance patches " + text3); } SetPerfRow(perfMasterTxt, Plugin.PerfOptimizations, "Master"); SetPerfRow(perfStunTxt, Plugin.PerfStunPlayerNullGuard, "Stun null-guard"); SetPerfRow(perfBulletsTxt, Plugin.PerfDespawnOffscreenBullets, "OOB bullet despawn"); SetPerfRow(perfHitSndTxt, Plugin.PerfSwallowHitSoundNREs, "Hit-sound NRE swallow"); SetPerfRow(perfEdgeBnTxt, Plugin.PerfSwallowEdgeBounceNREs, "EdgeBounce NRE swallow"); SetPerfRow(perfMenuTxt, Plugin.PerfSkipMenuUpdateInMatch, "Menu update bail"); SetPerfRow(perfBulletCapTxt, Plugin.PerfBulletHitParticleCap, "Bullet-hit particle cap (2/frame)"); SetPerfRow(perfPoolTxt, Plugin.PerfClampObjectPoolInit, "ObjectPool init clamp (in-match)"); static void SetPerfRow(object txt, ConfigEntry e, string label) { if (txt != null) { if (e == null) { UIFactory.SetText(txt, label + ": (not bound)"); } else { UIFactory.SetText(txt, e.Value ? (label + ": ON") : (label + ": OFF")); } } } } private static string BuildMultimodeSeriesLine(ApiClient.MultimodeSeriesEntry m, string myName) { string text = ((m.mode == "2v2") ? "[2v2]" : ((m.mode == "1v2") ? "[1v2]" : "[FFA]")); string text2 = ((m.left_rating_change != 0f) ? $" +{m.left_rating_change:F0}" : ""); string text3 = ((m.right_rating_change != 0f) ? $" {m.right_rating_change:F0}" : ""); int budget = ((text2.Length == 0 && text3.Length == 0) ? 44 : 36); FitLabelPair(m.left_label ?? "?", m.right_label ?? "?", budget, out var outLeft, out var outRight); string text4 = "" + text + " " + outLeft + "" + text2 + " " + m.score + " " + outRight + "" + text3 + "\n"; if (m.bets != null) { foreach (ApiClient.MultimodeBet bet in m.bets) { string text5 = ((bet.bettor_name == myName) ? "You" : FfaSafeRich(Trunc(bet.bettor_name ?? "?", 14))); string text6 = FfaSafeRich(FitLabel(bet.bet_on_label ?? "?", 22)); text4 = ((!(bet.state == "won")) ? ((!(bet.state == "refunded")) ? ((!(bet.state == "open")) ? (text4 + $" -> {text5} bet {bet.amount}g on {text6} - lost\n") : (text4 + $" -> {text5} bet {bet.amount}g on {text6} - pending\n")) : (text4 + $" -> {text5} bet {bet.amount}g on {text6} - refunded\n")) : (text4 + $" -> {text5} bet {bet.amount}g on {text6} -> +{bet.payout}g\n")); } } return text4; } private static void RefreshRecentSeries() { if (txtRecentSeries == null) { return; } List list = ApiClient.CachedRecentSeries; if (list == null && ApiClient.CachedRecentMultimode == null) { if (Time.realtimeSinceStartup - _seriesAutoFetchAt > 8f) { _seriesAutoFetchAt = Time.realtimeSinceStartup; ApiClient.FetchRecentSeries(); } UIFactory.SetText(txtRecentSeries, "Loading recent series..."); if ((Object)(object)seriesPrev != (Object)null) { seriesPrev.SetActive(false); } if ((Object)(object)seriesNext != (Object)null) { seriesNext.SetActive(false); } if (txtSeriesPage != null) { UIFactory.SetText(txtSeriesPage, ""); } return; } if (list == null) { list = new List(); } List cachedRecentMultimode = ApiClient.CachedRecentMultimode; if (cachedRecentMultimode == null && Time.realtimeSinceStartup - _multiAutoFetchAt > 8f) { _multiAutoFetchAt = Time.realtimeSinceStartup; ApiClient.FetchRecentMultimodeSeries(); } List list2 = new List(); foreach (ApiClient.RecentSeriesEntry item in list) { list2.Add(new MergedSeriesRow { ts = (item.completed_at ?? ""), oneVone = item }); } if (cachedRecentMultimode != null) { foreach (ApiClient.MultimodeSeriesEntry item2 in cachedRecentMultimode) { list2.Add(new MergedSeriesRow { ts = (item2.ended_at ?? ""), multi = item2 }); } } list2.Sort((MergedSeriesRow a, MergedSeriesRow b) => string.CompareOrdinal(b.ts, a.ts)); if (list2.Count == 0) { UIFactory.SetText(txtRecentSeries, "No recent series"); if ((Object)(object)seriesPrev != (Object)null) { seriesPrev.SetActive(false); } if ((Object)(object)seriesNext != (Object)null) { seriesNext.SetActive(false); } if (txtSeriesPage != null) { UIFactory.SetText(txtSeriesPage, ""); } return; } int num = 50; int num2 = (list2.Count + num - 1) / num; recentSeriesPage = Math.Max(0, Math.Min(recentSeriesPage, num2 - 1)); int num3 = recentSeriesPage * num; int num4 = Math.Min(num3 + num, list2.Count); string text = ""; string text2 = ApiClient.CachedPlayerStats?.display_name ?? ""; for (int num5 = num3; num5 < num4; num5++) { if (list2[num5].multi != null) { text += BuildMultimodeSeriesLine(list2[num5].multi, text2); continue; } ApiClient.RecentSeriesEntry oneVone = list2[num5].oneVone; bool flag = oneVone.p1_wins > oneVone.p2_wins; string text3 = (flag ? oneVone.p1_name : oneVone.p2_name); string text4 = (flag ? oneVone.p2_name : oneVone.p1_name); int num6 = (flag ? oneVone.p1_wins : oneVone.p2_wins); int num7 = (flag ? oneVone.p2_wins : oneVone.p1_wins); int num8 = (flag ? oneVone.p1_rating : oneVone.p2_rating); int num9 = (flag ? oneVone.p2_rating : oneVone.p1_rating); float num10 = (flag ? oneVone.p1_rating_change : oneVone.p2_rating_change); float num11 = (flag ? oneVone.p2_rating_change : oneVone.p1_rating_change); bool flag2 = text3 == text2; bool flag3 = text4 == text2; string text5 = (flag2 ? "#00FF00" : "#FFFFFF"); string text6 = (flag3 ? "#FF6666" : "#AAAAAA"); string text7 = ((num10 != 0f) ? $" +{num10:F0}" : ""); string text8 = ((num11 != 0f) ? $" {num11:F0}" : ""); string text9 = ((num8 > 0) ? $" ({num8})" : ""); string text10 = ((num9 > 0) ? $" ({num9})" : ""); string text11 = Trunc(text3, 16); string text12 = Trunc(text4, 16); text += $"{text11}{text9}{text7} {num6}-{num7} {text12}{text10}{text8}\n"; if (oneVone.bets == null || oneVone.bets.Count <= 0) { continue; } foreach (ApiClient.SeriesBetEntry bet in oneVone.bets) { string text13 = ((bet.bettor_name == text2) ? "You" : Trunc(bet.bettor_name ?? "?", 14)); text = ((!bet.won) ? (text + string.Format(" -> {0} bet {1}g on {2} - lost\n", text13, bet.amount, Trunc(bet.bet_on_name ?? "?", 12))) : (text + string.Format(" -> {0} bet {1}g on {2} -> +{3}g\n", text13, bet.amount, Trunc(bet.bet_on_name ?? "?", 12), bet.payout))); } } UIFactory.SetText(txtRecentSeries, text); if ((Object)(object)seriesPrev != (Object)null) { seriesPrev.SetActive(recentSeriesPage > 0); } if ((Object)(object)seriesNext != (Object)null) { seriesNext.SetActive(recentSeriesPage < num2 - 1); } if (txtSeriesPage != null) { UIFactory.SetText(txtSeriesPage, (num2 > 1) ? $"{recentSeriesPage + 1}/{num2}" : ""); } } private static void RefreshVersionStatus() { if (txtVersionStatus == null) { return; } if (ApiClient.ForceUpdateRequired) { UIFactory.SetText(txtVersionStatus, "UPDATE REQUIRED - server is rejecting this mod version"); if ((Object)(object)updateBtn != (Object)null) { updateBtn.SetActive(true); } return; } if (ApiClient.UpdateReady) { UIFactory.SetText(txtVersionStatus, "Close ROUNDS to apply update"); if ((Object)(object)updateBtn != (Object)null) { updateBtn.SetActive(false); } return; } if (ApiClient.IsUpdating) { UIFactory.SetText(txtVersionStatus, "Downloading..."); if ((Object)(object)updateBtn != (Object)null) { updateBtn.SetActive(false); } return; } string latestModVersion = ApiClient.LatestModVersion; if (latestModVersion == null) { UIFactory.SetText(txtVersionStatus, ""); if ((Object)(object)updateBtn != (Object)null) { updateBtn.SetActive(false); } } else if (latestModVersion == "1.35.5") { UIFactory.SetText(txtVersionStatus, "up to date"); if ((Object)(object)updateBtn != (Object)null) { updateBtn.SetActive(false); } } else { UIFactory.SetText(txtVersionStatus, "v" + latestModVersion + " available!"); if ((Object)(object)updateBtn != (Object)null) { updateBtn.SetActive(true); } } } private static void RefreshMyStats() { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; if (cachedPlayerStats == null) { UIFactory.SetText(txtRating, "-"); return; } if (txtTopLeftName != null) { string s = ((!string.IsNullOrEmpty(cachedPlayerStats.display_name) && cachedPlayerStats.display_name != cachedPlayerStats.steam_id) ? cachedPlayerStats.display_name : (MatchTracker.LocalDisplayName ?? cachedPlayerStats.display_name ?? "")); UIFactory.SetText(txtTopLeftName, s); } UIFactory.SetText(txtRating, $"{cachedPlayerStats.rating:F0}"); UIFactory.SetText(txtRD, $"RD: {cachedPlayerStats.rating_deviation:F0} Peak: {cachedPlayerStats.peak_rating:F0}"); UIFactory.SetText(txtLevel, $"Level {cachedPlayerStats.level}"); if (cachedPlayerStats.level < 100 && cachedPlayerStats.xp_for_next_level > 0) { UIFactory.SetText(txtXPProg, $"{cachedPlayerStats.xp_into_level}/{cachedPlayerStats.xp_for_next_level} XP"); UIFactory.SetFill(xpFill, (float)cachedPlayerStats.xp_into_level / (float)cachedPlayerStats.xp_for_next_level); } else { UIFactory.SetText(txtXPProg, "MAX"); UIFactory.SetFill(xpFill, 1f); } UIFactory.SetText(txtTotalXP, $"{cachedPlayerStats.total_xp:N0} XP"); List cachedMatchHistory = ApiClient.CachedMatchHistory; List list = cachedMatchHistory?.FindAll((ApiClient.MatchHistoryEntry m) => m.is_ranked) ?? new List(); List list2 = cachedMatchHistory?.FindAll((ApiClient.MatchHistoryEntry m) => !m.is_ranked) ?? new List(); int casual_wins = cachedPlayerStats.casual_wins; int casual_losses = cachedPlayerStats.casual_losses; int sweeps_given = cachedPlayerStats.sweeps_given; int sweeps_taken = cachedPlayerStats.sweeps_taken; int ranked_series_wins = cachedPlayerStats.ranked_series_wins; int ranked_series_losses = cachedPlayerStats.ranked_series_losses; UIFactory.SetText(txtRankedRec, (ranked_series_wins + ranked_series_losses > 0) ? $"Ranked (series): {ranked_series_wins}W / {ranked_series_losses}L ({((ranked_series_losses > 0) ? $"{(float)ranked_series_wins / (float)ranked_series_losses:F1}" : $"{ranked_series_wins}:0")})" : "Ranked: -"); int num = ((cachedPlayerStats.current_ranked_game_streak != 0) ? cachedPlayerStats.current_ranked_game_streak : ((list.Count > 0) ? CalcStreak(list) : 0)); int best_ranked_game_streak = cachedPlayerStats.best_ranked_game_streak; int current_ranked_series_streak = cachedPlayerStats.current_ranked_series_streak; int num2 = ((cachedPlayerStats.best_ranked_series_streak > 0) ? cachedPlayerStats.best_ranked_series_streak : cachedPlayerStats.best_ranked_streak); if (num == 0 && best_ranked_game_streak == 0 && current_ranked_series_streak == 0 && num2 == 0) { UIFactory.SetText(txtRankedStrk, ""); } else { string text = ((num >= 0) ? "#00FF00" : "#FF6666"); string text2 = ((current_ranked_series_streak >= 0) ? "#00FF00" : "#FF6666"); string text3 = " Game streak: " + ((num >= 0) ? $"{num}W" : $"{-num}L") + "" + ((best_ranked_game_streak > 0) ? $" Best: {best_ranked_game_streak}W" : ""); string text4 = " Series streak: " + ((current_ranked_series_streak >= 0) ? $"{current_ranked_series_streak}W" : $"{-current_ranked_series_streak}L") + "" + ((num2 > 0) ? $" Best: {num2}W" : ""); UIFactory.SetText(txtRankedStrk, text3 + "\n" + text4); } ApiClient.TeamStatsData cachedTeamStats = ApiClient.CachedTeamStats; if (cachedTeamStats != null && cachedTeamStats.series_wins + cachedTeamStats.series_losses > 0) { string text5 = ((cachedTeamStats.series_losses > 0) ? $"{(float)cachedTeamStats.series_wins / (float)cachedTeamStats.series_losses:F1}" : ((cachedTeamStats.series_wins > 0) ? $"{cachedTeamStats.series_wins}:0" : "0:0")); UIFactory.SetText(txtTeam2v2Rec, $"2v2: {cachedTeamStats.series_wins}W / {cachedTeamStats.series_losses}L ({text5}) Rating: {cachedTeamStats.rating:F0} Peak: {cachedTeamStats.peak_rating:F0}"); int current_streak = cachedTeamStats.current_streak; if (current_streak != 0) { string text6 = ((current_streak > 0) ? "#00FF00" : "#FF6666"); UIFactory.SetText(txtTeam2v2Strk, " Streak: " + ((current_streak > 0) ? $"{current_streak}W" : $"{-current_streak}L") + ""); } else { UIFactory.SetText(txtTeam2v2Strk, ""); } } else { UIFactory.SetText(txtTeam2v2Rec, "2v2: -"); UIFactory.SetText(txtTeam2v2Strk, ""); } int ovt_solo_wins = cachedPlayerStats.ovt_solo_wins; int ovt_solo_losses = cachedPlayerStats.ovt_solo_losses; int ovt_duo_wins = cachedPlayerStats.ovt_duo_wins; int ovt_duo_losses = cachedPlayerStats.ovt_duo_losses; if (ovt_solo_wins + ovt_solo_losses + ovt_duo_wins + ovt_duo_losses > 0) { string text7 = ((ovt_solo_wins + ovt_solo_losses > 0) ? $"Solo {ovt_solo_wins}W/{ovt_solo_losses}L" : "Solo -"); string text8 = ((ovt_duo_wins + ovt_duo_losses > 0) ? $"Duo {ovt_duo_wins}W/{ovt_duo_losses}L" : "Duo -"); UIFactory.SetText(txtOvtRec, "1v2: " + text7 + " | " + text8); } else { UIFactory.SetText(txtOvtRec, "1v2: -"); } int ffa_games = cachedPlayerStats.ffa_games; int ffa_wins = cachedPlayerStats.ffa_wins; if (ffa_games > 0) { float num3 = 100f * (float)ffa_wins / (float)ffa_games; float num4 = 100f * (float)cachedPlayerStats.ffa_top3 / (float)ffa_games; UIFactory.SetText(txtFfaRec, $"FFA: {ffa_wins}W / {ffa_games - ffa_wins}L ({num3:F0}% win)"); string text9 = ((cachedPlayerStats.ffa_damage_games > 0) ? $" Dmg/game: {cachedPlayerStats.ffa_avg_damage:F0}" : ""); UIFactory.SetText(txtFfaExtra, $" Top 3: {num4:F0}% Kills/game: {cachedPlayerStats.ffa_avg_kills:F1} Avg place: {cachedPlayerStats.ffa_avg_placement:F1}{text9}"); } else { UIFactory.SetText(txtFfaRec, "FFA: -"); UIFactory.SetText(txtFfaExtra, ""); } UIFactory.SetText(txtCasualRec, (casual_wins + casual_losses > 0) ? string.Format("Casual: {0}W / {1}L ({2})", casual_wins, casual_losses, (casual_losses > 0) ? $"{(float)casual_wins / (float)casual_losses:F1}" : ((casual_wins > 0) ? $"{casual_wins}:0" : "")) : "Casual: -"); if (list2.Count > 0) { int num5 = CalcStreak(list2); string text10 = ((num5 > 0) ? "#00FF00" : "#FF6666"); UIFactory.SetText(txtCasualStrk, " Streak: " + ((num5 > 0) ? $"{num5}W" : $"{-num5}L") + "" + ((cachedPlayerStats.best_casual_streak > 0) ? $" Best: {cachedPlayerStats.best_casual_streak}W" : "")); } else { UIFactory.SetText(txtCasualStrk, ""); } UIFactory.SetText(txtSweeps, $"Sweeps: 5-0 x{sweeps_given} 0-5 x{sweeps_taken}"); UIFactory.SetText(txtTotalRec, $"Total: {cachedPlayerStats.total_matches} ({cachedPlayerStats.wins}W / {cachedPlayerStats.losses}L) Gold: {cachedPlayerStats.gold_earned - cachedPlayerStats.gold_spent}"); string text11 = ((cachedPlayerStats.bullets_fired > 0) ? $"Hit: {(float)cachedPlayerStats.bullets_hit * 100f / (float)cachedPlayerStats.bullets_fired:F1}% ({cachedPlayerStats.bullets_hit}/{cachedPlayerStats.bullets_fired})" : "Hit: -"); string text12 = ((cachedPlayerStats.blocks_activated > 0) ? $"Block: {(float)cachedPlayerStats.blocks_successful * 100f / (float)cachedPlayerStats.blocks_activated:F1}% ({cachedPlayerStats.blocks_successful}/{cachedPlayerStats.blocks_activated})" : "Block: -"); UIFactory.SetText(txtAccuracy, text11 + "\n" + text12); RefreshHistory(list, list2); RefreshSession(); } private static void RefreshHistory(List ranked, List casual) { //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) CompetitiveUI.ClearCardHoverRegions(); foreach (HistoryRow rankedRow in rankedRows) { rankedRow.root.SetActive(false); rankedRow.seriesGO.SetActive(false); } if (ranked.Count > 0) { List list = GroupBySeries(ranked); int num = 3; int num2 = (list.Count + num - 1) / num; int num3 = Math.Max(list.Count, ApiClient.HistoryTotalRankedGroups); int num4 = Math.Max(num2, (num3 + num - 1) / num); rankedPage = Math.Max(0, Math.Min(rankedPage, num2 - 1)); if (rankedPage >= num2 - 2 && !ApiClient.MatchHistoryLoadedAll) { ApiClient.FetchMoreMatchHistory(MatchTracker.LocalSteamId); } int num5 = rankedPage * num; int num6 = Math.Min(num5 + num, list.Count); int num7 = 0; for (int i = num5; i < num6; i++) { if (num7 >= rankedRows.Count) { break; } SGroup sGroup = list[i]; if (sGroup.matches.Count == 0) { continue; } ApiClient.MatchHistoryEntry matchHistoryEntry = sGroup.matches[0]; if (sGroup.series_id != null && num7 < rankedRows.Count) { HistoryRow historyRow = rankedRows[num7]; string text = matchHistoryEntry.series_score ?? "?-?"; string text2 = FormatOpponentForRow(matchHistoryEntry, 18); bool flag = false; bool flag2 = false; try { string[] array = text.Split('-'); int num8 = int.Parse(array[0]); int num9 = int.Parse(array[1]); flag = num8 >= 2 || num9 >= 2; flag2 = num8 > num9; } catch { } UIFactory.SetText(historyRow.txtSeriesHead, flag ? ("Series " + (flag2 ? "W" : "L") + " " + text + " vs " + text2) : ("Series " + text + " vs " + text2 + " (in progress)")); UIFactory.SetColor(historyRow.txtSeriesHead, (!flag) ? C_GOLD : (flag2 ? C_GREEN : C_RED)); int num10 = 0; foreach (ApiClient.MatchHistoryEntry match in sGroup.matches) { if (match.series_gold_gained > num10) { num10 = match.series_gold_gained; } } if (flag && (matchHistoryEntry.series_rating_change != 0f || num10 > 0)) { float series_rating_change = matchHistoryEntry.series_rating_change; string text3 = ((num10 > 0) ? $" +{num10}g" : ""); string text4 = ((series_rating_change != 0f) ? string.Format("{0}{1:F0} elo", (series_rating_change > 0f) ? "+" : "", series_rating_change) : ""); UIFactory.SetText(historyRow.txtSeriesElo, (text4 + text3).TrimStart()); UIFactory.SetColor(historyRow.txtSeriesElo, (series_rating_change > 0f) ? C_GREEN : ((series_rating_change < 0f) ? C_RED : C_GOLD)); } else { UIFactory.SetText(historyRow.txtSeriesElo, ""); } historyRow.seriesGO.SetActive(true); foreach (ApiClient.MatchHistoryEntry match2 in sGroup.matches) { if (num7 >= rankedRows.Count) { break; } FillRow(rankedRows[num7], match2, indent: true); num7++; } } else { FillRow(rankedRows[num7], matchHistoryEntry, indent: false); num7++; } } rPrev.SetActive(rankedPage > 0); rNext.SetActive(rankedPage < num2 - 1 || !ApiClient.MatchHistoryLoadedAll); UIFactory.SetText(txtRankedPage, (num4 > 1) ? $"{rankedPage + 1}/{num4}" : ""); } else { rPrev.SetActive(false); rNext.SetActive(false); UIFactory.SetText(txtRankedPage, ""); } foreach (HistoryRow casualRow in casualRows) { casualRow.root.SetActive(false); } if (casual.Count > 0) { int num11 = 6; int num12 = (casual.Count + num11 - 1) / num11; int num13 = Math.Max(casual.Count, ApiClient.HistoryTotalCasual); int num14 = Math.Max(num12, (num13 + num11 - 1) / num11); casualPage = Math.Max(0, Math.Min(casualPage, num12 - 1)); if (casualPage >= num12 - 2 && !ApiClient.MatchHistoryLoadedAll) { ApiClient.FetchMoreMatchHistory(MatchTracker.LocalSteamId); } int num15 = casualPage * num11; int num16 = Math.Min(num15 + num11, casual.Count); for (int j = num15; j < num16; j++) { int num17 = j - num15; if (num17 < casualRows.Count) { FillRow(casualRows[num17], casual[j], indent: false); } } cPrev.SetActive(casualPage > 0); cNext.SetActive(casualPage < num12 - 1 || !ApiClient.MatchHistoryLoadedAll); UIFactory.SetText(txtCasualPage, (num14 > 1) ? $"{casualPage + 1}/{num14}" : ""); } else { cPrev.SetActive(false); cNext.SetActive(false); UIFactory.SetText(txtCasualPage, ""); } } private static string FmtHalfScore(int rounds, int pts) { if (pts >= 2) { pts = 0; } return (pts > 0) ? ((float)rounds + (float)pts * 0.5f).ToString("0.#", CultureInfo.InvariantCulture) : rounds.ToString(); } private static void FillRow(HistoryRow row, ApiClient.MatchHistoryEntry m, bool indent) { //IL_0025: 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_002a: 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) string text = (m.won ? "W" : "L"); Color c = (m.won ? C_GREEN : C_RED); UIFactory.SetText(row.txtResult, (indent ? " " : " ") + text + " " + FmtHalfScore(m.player_rounds_won, m.player_points) + "-" + FmtHalfScore(m.opponent_rounds_won, m.opponent_points)); UIFactory.SetColor(row.txtResult, c); UIFactory.SetText(row.txtOpp, indent ? "" : ("vs " + FormatOpponentForRow(m, 20))); UIFactory.SetText(row.txtFps, BuildFpsTag(m)); UIFactory.SetText(row.txtPing, BuildPingTag(m)); RegisterTeleGraphRectFor(row.txtFps, m.player_fps_timeline, m.opp_fps_timeline, isPing: false, m.point_times, m.point_timeline); RegisterTeleGraphRectFor(row.txtPing, m.player_ping_timeline, m.opp_ping_timeline, isPing: true, m.point_times, m.point_timeline); string s = ((m.duration_seconds > 0) ? $" {m.duration_seconds / 60}:{m.duration_seconds % 60:00}" : ""); UIFactory.SetText(row.txtStats, s); string text2 = ""; string text3 = ""; string s2 = ""; string text4 = ""; string text5 = ""; string s3 = ""; if (m.player_bullets_fired > 0 || m.player_blocks_activated > 0) { float num = ((m.player_bullets_fired > 0) ? (100f * (float)m.player_bullets_hit / (float)m.player_bullets_fired) : 0f); float num2 = ((m.player_blocks_activated > 0) ? (100f * (float)m.player_blocks_successful / (float)m.player_blocks_activated) : 0f); float num3 = ((m.player_active_seconds > 0.5f) ? ((float)m.player_keys_pressed / m.player_active_seconds) : 0f); text2 = $"You: Hit {num:F0}%"; text3 = $"Block {num2:F0}%"; s2 = $"{num3:F1} keys/s"; if (m.opp_bullets_fired > 0 || m.opp_blocks_activated > 0) { float num4 = ((m.opp_bullets_fired > 0) ? (100f * (float)m.opp_bullets_hit / (float)m.opp_bullets_fired) : 0f); float num5 = ((m.opp_blocks_activated > 0) ? (100f * (float)m.opp_blocks_successful / (float)m.opp_blocks_activated) : 0f); float num6 = ((m.opp_active_seconds > 0.5f) ? ((float)m.opp_keys_pressed / m.opp_active_seconds) : 0f); text4 = $"Opp: Hit {num4:F0}%"; text5 = $"Block {num5:F0}%"; s3 = $"{num6:F1} keys/s"; } } UIFactory.SetText(row.txtHitYou, text2); UIFactory.SetText(row.txtBlockYou, text3); UIFactory.SetText(row.txtKpsYou, s2); UIFactory.SetText(row.txtHitOpp, text4); UIFactory.SetText(row.txtBlockOpp, text5); UIFactory.SetText(row.txtKpsOpp, s3); if (!string.IsNullOrEmpty(text2)) { RegisterPairGraphRectFor(row.txtHitYou, m.player_hit_timeline, isBlock: false, subjectIsOpp: false, m.point_times, m.point_timeline); } if (!string.IsNullOrEmpty(text3)) { RegisterPairGraphRectFor(row.txtBlockYou, m.player_block_timeline, isBlock: true, subjectIsOpp: false, m.point_times, m.point_timeline); } if (!string.IsNullOrEmpty(text4)) { RegisterPairGraphRectFor(row.txtHitOpp, m.opp_hit_timeline, isBlock: false, subjectIsOpp: true, m.point_times, m.point_timeline); } if (!string.IsNullOrEmpty(text5)) { RegisterPairGraphRectFor(row.txtBlockOpp, m.opp_block_timeline, isBlock: true, subjectIsOpp: true, m.point_times, m.point_timeline); } RegisterScoreGraphRectFor(row.txtResult, m.point_timeline, m.won); row.currentMatchId = m.match_id; if ((Object)(object)row.btnId != (Object)null) { row.btnId.SetActive(!string.IsNullOrEmpty(m.match_id)); } UIFactory.SetText(row.txtXP, (m.xp_gained <= 0) ? "" : ((m.gold_gained > 0) ? $"+{m.xp_gained}xp +{m.gold_gained}g" : $"+{m.xp_gained}xp")); string s4 = ""; try { if (!string.IsNullOrEmpty(m.ended_at) && m.ended_at.Length >= 10) { s4 = DateTime.Parse(m.ended_at).ToString("M/d"); } } catch { } UIFactory.SetText(row.txtDate, s4); UIFactory.SetText(row.txtCards, (!string.IsNullOrEmpty(m.cards_display)) ? (" Cards: " + (_historyCardsFull ? m.cards_display : FormatCardLine(m.cards_display))) : ""); UIFactory.SetText(row.txtOppCards, (!string.IsNullOrEmpty(m.opp_cards_display)) ? (" Opp: " + (_historyCardsFull ? m.opp_cards_display : FormatCardLine(m.opp_cards_display))) : ""); if (rCardModeTxt != null) { UIFactory.SetText(rCardModeTxt, HistoryCardModeLabel()); } if (cCardModeTxt != null) { UIFactory.SetText(cCardModeTxt, HistoryCardModeLabel()); } RegisterHoverRectFor(row.txtCards, m.cards_display, isOpponent: false); RegisterHoverRectFor(row.txtOppCards, m.opp_cards_display, isOpponent: true); row.root.SetActive(true); } private static bool ResolveHoverSource(object txt, out RectTransform rt, out Camera cam, out float frac, out Rect rect, out RectTransform clip) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) rt = null; cam = null; frac = -1f; rect = default(Rect); clip = null; try { Component val = (Component)((txt is Component) ? txt : null); if ((Object)(object)val == (Object)null) { return false; } rt = val.GetComponent(); if ((Object)(object)rt == (Object)null) { return false; } bool flag = true; Transform val2 = (Transform)(object)rt; while ((Object)(object)val2 != (Object)null) { if ((Object)(object)clip == (Object)null && ((Object)((Component)val2).gameObject).name == "Viewport") { clip = (RectTransform)(object)((val2 is RectTransform) ? val2 : null); } Component component = ((Component)val2).GetComponent(UIFactory.tCanvas); if ((Object)(object)component != (Object)null) { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; PropertyInfo property = UIFactory.tCanvas.GetProperty("renderMode", bindingAttr); if (property != null) { int num = (int)property.GetValue(component); flag = num == 0; if (!flag) { object? obj = UIFactory.tCanvas.GetProperty("worldCamera", bindingAttr)?.GetValue(component); cam = (Camera)(((obj is Camera) ? obj : null) ?? Camera.main); } } break; } val2 = val2.parent; } if (!flag && (Object)(object)cam == (Object)null) { return false; } Rect fallback; try { PropertyInfo property2 = ((object)val).GetType().GetProperty("preferredWidth", BindingFlags.Instance | BindingFlags.Public); fallback = rt.rect; float width = ((Rect)(ref fallback)).width; if (property2 != null && width > 0f) { float num2 = (float)property2.GetValue(val); if (num2 > 0f) { frac = Mathf.Clamp01(num2 / width); } } } catch { } RectTransform rt2 = rt; Camera cam2 = cam; float frac2 = frac; RectTransform clip2 = clip; fallback = default(Rect); rect = CompetitiveUI.LiveRegionRect(rt2, cam2, frac2, clip2, fallback); return true; } catch { return false; } } private static void RegisterHoverRectFor(object txt, string fullLine, bool isOpponent, string titleOverride = null, string bodyOverride = null) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (txt == null || string.IsNullOrEmpty(fullLine)) { return; } try { if (ResolveHoverSource(txt, out var rt, out var cam, out var frac, out var rect, out var clip)) { CompetitiveUI.RegisterCardHoverRegion(rect, fullLine, isOpponent, titleOverride, bodyOverride, rt, cam, frac, clip, txt); } } catch { } } private static void RegisterScoreGraphRectFor(object txt, string timeline, bool won) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (txt == null || string.IsNullOrEmpty(timeline) || timeline.IndexOf(':') < 0) { return; } try { if (ResolveHoverSource(txt, out var rt, out var cam, out var frac, out var rect, out var clip)) { CompetitiveUI.RegisterScoreGraphRegion(rect, timeline, won, rt, cam, frac, clip, txt); } } catch { } } private static void RegisterTeleGraphRectFor(object txt, string mySeries, string oppSeries, bool isPing, string pointTimes = null, string pointTimeline = null, float myStep = 0f) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (txt == null || (string.IsNullOrEmpty(mySeries) && string.IsNullOrEmpty(oppSeries))) { return; } try { if (ResolveHoverSource(txt, out var rt, out var cam, out var frac, out var rect, out var clip)) { CompetitiveUI.RegisterFpsGraphRegion(rect, mySeries, oppSeries, isPing, rt, cam, frac, clip, txt, pointTimes, pointTimeline, myStep); } } catch { } } private static void RegisterPairGraphRectFor(object txt, string pairSeries, bool isBlock, bool subjectIsOpp, string pointTimes, string pointTimeline) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (txt == null || string.IsNullOrEmpty(pairSeries)) { return; } try { if (ResolveHoverSource(txt, out var rt, out var cam, out var frac, out var rect, out var clip)) { CompetitiveUI.RegisterPairGraphRegion(rect, pairSeries, isBlock, subjectIsOpp, rt, cam, frac, clip, txt, pointTimes, pointTimeline); } } catch { } } private static void RegisterComboGraphRectFor(object txt, ApiClient.TeamPlayerTele tele, string playerName, bool isRightTeam) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (txt == null || tele == null) { return; } try { if (ResolveHoverSource(txt, out var rt, out var cam, out var frac, out var rect, out var clip)) { CompetitiveUI.RegisterPlayerComboRegion(rect, tele.fps_timeline, tele.ping_timeline, tele.hit_timeline, tele.block_timeline, playerName, isRightTeam, rt, cam, frac, clip, txt); } } catch { } } private static void FillTeleCell(object txt, ApiClient.TeamSeriesMatch m, ApiClient.TeamSeriesSlot sl, bool right) { string s = ""; ApiClient.TeamPlayerTele value = null; if (sl != null) { string text = (right ? "#FFB086" : "#8CCFFF"); string key = sl.steam_id ?? ""; if (m.telemetry_by_player != null) { m.telemetry_by_player.TryGetValue(key, out value); } int value2 = 0; if (m.fps_by_player != null) { m.fps_by_player.TryGetValue(key, out value2); } string text2 = sl.name ?? "?"; if (text2.Length > 10) { text2 = text2.Substring(0, 10); } if (value != null) { float num = ((value.bullets_fired > 0) ? (100f * (float)value.bullets_hit / (float)value.bullets_fired) : 0f); float num2 = ((value.blocks_activated > 0) ? (100f * (float)value.blocks_successful / (float)value.blocks_activated) : 0f); string text3 = ((value2 > 0) ? (value2 + "fps ") : ""); string text4 = ((value.ping_avg > 0) ? (value.ping_avg + "ms ") : ""); s = $"{text2} {text3}{text4}Hit {num:F0}% Blk {num2:F0}%"; } else if (value2 > 0) { s = $"{text2} {value2}fps"; } } UIFactory.SetText(txt, s); if (value != null) { RegisterComboGraphRectFor(txt, value, sl.name ?? "?", right); } } private static string FormatCardLine(string raw) { if (string.IsNullOrEmpty(raw)) { return ""; } StringBuilder stringBuilder = new StringBuilder(); string[] array = raw.Split(','); foreach (string text in array) { string text2 = text.Trim(); if (!string.IsNullOrEmpty(text2)) { int num = text2.IndexOf('>'); if (num >= 0 && num < text2.Length - 1) { text2 = text2.Substring(num + 1); } int num2 = text2.IndexOf('<'); if (num2 > 0) { text2 = text2.Substring(0, num2); } text2 = text2.Trim(); if (text2.Length != 0) { string value = ((text2.Length >= 2) ? text2.Substring(0, 2).ToUpperInvariant() : text2.ToUpperInvariant()); stringBuilder.Append('[').Append(value).Append("] "); } } } return stringBuilder.ToString().TrimEnd(); } private static string BuildFpsTag(ApiClient.MatchHistoryEntry m) { if (m == null) { return ""; } int player_fps_avg = m.player_fps_avg; int opponent_fps_avg = m.opponent_fps_avg; if (player_fps_avg <= 0 && opponent_fps_avg <= 0) { return ""; } string text = ((player_fps_avg > 0) ? player_fps_avg.ToString() : "-"); string text2 = ((opponent_fps_avg > 0) ? opponent_fps_avg.ToString() : "-"); return "FPS: " + text + " / " + text2 + ""; } private static string BuildPingTag(ApiClient.MatchHistoryEntry m) { if (m == null) { return ""; } int player_ping_avg = m.player_ping_avg; int opponent_ping_avg = m.opponent_ping_avg; if (player_ping_avg <= 0 && opponent_ping_avg <= 0) { return ""; } string text = ((player_ping_avg > 0) ? player_ping_avg.ToString() : "-"); string text2 = ((opponent_ping_avg > 0) ? opponent_ping_avg.ToString() : "-"); return "Ping: " + text + " / " + text2 + "ms"; } private static string FormatOpponentForRow(ApiClient.MatchHistoryEntry m, int nameMax) { string text = Trunc(m?.opponent_name ?? "", nameMax); if (m == null || string.IsNullOrEmpty(m.opponent_title)) { return text; } string text2 = (string.IsNullOrEmpty(m.opponent_title_color) ? "#CCCCCC" : m.opponent_title_color); if (IsPodiumTitle(m.opponent_title)) { return text + " " + PodiumSparkleSpan(m.opponent_title, text2, 0u); } return text + " [" + m.opponent_title + "]"; } private static void RefreshSession() { //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_090b: Unknown result type (might be due to invalid IL or missing references) //IL_091f: Unknown result type (might be due to invalid IL or missing references) //IL_09aa: Unknown result type (might be due to invalid IL or missing references) //IL_09a3: Unknown result type (might be due to invalid IL or missing references) //IL_099c: Unknown result type (might be due to invalid IL or missing references) if (sessionSplitLayoutTarget != txtSessionSplit) { sessionSplitLayoutTarget = txtSessionSplit; UIFactory.SetTextAutoHeight(txtSessionSplit); UIFactory.SetWordWrap(txtSessionSplit, on: true); } int sessionMatchCount = GameStateWatcher.SessionMatchCount; bool isInRoom = GameStateWatcher.IsInRoom; string opponentSteamId = GameStateWatcher.OpponentSteamId; string opponentDisplayName = GameStateWatcher.OpponentDisplayName; List cachedMatchHistory = ApiClient.CachedMatchHistory; if (isInRoom && !string.IsNullOrEmpty(opponentSteamId) && !opponentSteamId.StartsWith("photon_")) { ApiClient.FetchOpponentLifetime(opponentSteamId); int num = 0; int num2 = 0; string text = ""; if (cachedMatchHistory != null) { foreach (ApiClient.MatchHistoryEntry item in cachedMatchHistory) { if (item.opponent_steam_id != opponentSteamId) { continue; } if (item.won) { num++; } else { num2++; } if (string.IsNullOrEmpty(text)) { try { text = DateTime.Parse(item.ended_at).ToString("M/d/yyyy"); } catch { } } } } if (ApiClient.CachedOppLifetime.TryGetValue(opponentSteamId, out var value)) { num = value[0]; num2 = value[1]; } if (num + num2 > 0) { string text2 = ((num > num2) ? "#00FF00" : ((num < num2) ? "#FF6666" : "#AAAAAA")); string text3 = (string.IsNullOrEmpty(text) ? "" : (" (last: " + text + ")")); UIFactory.SetText(txtSessionOppLifetime, $" vs {opponentDisplayName}: {num}W-{num2}L lifetime{text3}"); } else { UIFactory.SetText(txtSessionOppLifetime, " vs " + opponentDisplayName + ": First time playing!"); } UIFactory.SetColor(txtSessionOppLifetime, new Color(0.6f, 0.75f, 1f)); } else if (isInRoom && !string.IsNullOrEmpty(opponentDisplayName) && opponentDisplayName != "Opponent") { UIFactory.SetText(txtSessionOppLifetime, " In room with " + opponentDisplayName); UIFactory.SetColor(txtSessionOppLifetime, C_DIM); } else { UIFactory.SetText(txtSessionOppLifetime, ""); } if (sessionMatchCount <= 0) { UIFactory.SetText(txtSessionSum, isInRoom ? "In game - no results yet" : "No games this session"); UIFactory.SetColor(txtSessionSum, C_DIM); UIFactory.SetText(txtSessionSplit, ""); UIFactory.SetText(txtSessionSweeps, ""); return; } int num3 = (int)(DateTime.UtcNow - GameStateWatcher.SessionStartTime).TotalMinutes; string text4 = ((num3 >= 60) ? $"{num3 / 60}h {num3 % 60}m" : $"{num3}m"); int sessionRankedWins = GameStateWatcher.SessionRankedWins; int sessionRankedLosses = GameStateWatcher.SessionRankedLosses; int sessionCasualWins = GameStateWatcher.SessionCasualWins; int sessionCasualLosses = GameStateWatcher.SessionCasualLosses; int sessionTeamSeriesWins = GameStateWatcher.SessionTeamSeriesWins; int sessionTeamSeriesLosses = GameStateWatcher.SessionTeamSeriesLosses; int sessionOvtWins = GameStateWatcher.SessionOvtWins; int sessionOvtLosses = GameStateWatcher.SessionOvtLosses; int sessionFfaWins = GameStateWatcher.SessionFfaWins; int sessionFfaLosses = GameStateWatcher.SessionFfaLosses; int num4 = 0; int num5 = 0; if (cachedMatchHistory != null) { DateTime sessionStartTime = GameStateWatcher.SessionStartTime; foreach (ApiClient.MatchHistoryEntry item2 in cachedMatchHistory) { DateTime dateTime = DateTime.UtcNow; try { if (!string.IsNullOrEmpty(item2.ended_at)) { dateTime = DateTime.Parse(item2.ended_at).ToUniversalTime(); } } catch { } if (!(dateTime < sessionStartTime)) { if (item2.won && item2.opponent_rounds_won == 0) { num4++; } if (!item2.won && item2.player_rounds_won == 0) { num5++; } } } } UIFactory.SetText(txtSessionSum, $"{sessionMatchCount} games {sessionRankedWins + sessionCasualWins + sessionOvtWins + sessionFfaWins}W - {sessionRankedLosses + sessionCasualLosses + sessionOvtLosses + sessionFfaLosses}L {text4}"); UIFactory.SetColor(txtSessionSum, C_WHITE); List list = new List(); if (sessionRankedWins + sessionRankedLosses > 0) { list.Add($"Ranked: {sessionRankedWins}W/{sessionRankedLosses}L"); } if (sessionTeamSeriesWins + sessionTeamSeriesLosses > 0) { list.Add($"2v2: {sessionTeamSeriesWins}W/{sessionTeamSeriesLosses}L"); } if (sessionOvtWins + sessionOvtLosses > 0) { list.Add($"1v2: {sessionOvtWins}W/{sessionOvtLosses}L"); } if (sessionFfaWins + sessionFfaLosses > 0) { string sessionFfaPlacementsCsv = GameStateWatcher.SessionFfaPlacementsCsv; list.Add($"FFA: {sessionFfaWins}W-{sessionFfaLosses}L" + (string.IsNullOrEmpty(sessionFfaPlacementsCsv) ? "" : (" (placements " + sessionFfaPlacementsCsv + ")"))); } if (sessionCasualWins + sessionCasualLosses > 0) { list.Add($"Casual: {sessionCasualWins}W/{sessionCasualLosses}L"); } UIFactory.SetText(txtSessionSplit, (list.Count > 0) ? (" " + string.Join(" ", list.ToArray())) : ""); if (num4 + num5 > 0) { UIFactory.SetText(txtSessionSweeps, $" Sweeps: 5-0 x{num4} 0-5 x{num5}"); } else { UIFactory.SetText(txtSessionSweeps, ""); } Dictionary sessionWLByOpponent = GameStateWatcher.SessionWLByOpponent; Dictionary sessionTimeByOpponent = GameStateWatcher.SessionTimeByOpponent; int num6 = 0; if (sessionWLByOpponent != null) { foreach (KeyValuePair item3 in sessionWLByOpponent) { int[] value2 = item3.Value; if (value2 != null && value2.Length >= 4) { int num7 = ((value2.Length > 4) ? value2[4] : 0); int num8 = ((value2.Length > 5) ? value2[5] : 0); int num9 = ((value2.Length > 6) ? value2[6] : 0); int num10 = ((value2.Length > 7) ? value2[7] : 0); int num11 = value2[0] + value2[2] + num7 + num9; int num12 = value2[1] + value2[3] + num8 + num10; string text5 = (item3.Key.StartsWith("w/ ") ? $" {item3.Key}: {num11}W-{num12}L" : $" vs {item3.Key}: {num11}W-{num12}L"); List list2 = new List(); if (value2[0] + value2[1] > 0) { list2.Add($"R:{value2[0]}-{value2[1]}"); } if (value2[2] + value2[3] > 0) { list2.Add($"C:{value2[2]}-{value2[3]}"); } if (num7 + num8 > 0) { list2.Add($"1v2:{num7}-{num8}"); } if (list2.Count > 1) { text5 = text5 + " (" + string.Join(" ", list2.ToArray()) + ")"; } if (num9 + num10 > 0) { text5 += $" FFA {num9}W-{num10}L"; } if (sessionTimeByOpponent != null && sessionTimeByOpponent.ContainsKey(item3.Key)) { int num13 = (int)sessionTimeByOpponent[item3.Key]; text5 += ((num13 >= 60) ? $" {num13 / 60}h {num13 % 60}m" : $" {num13}m"); } while (sessionOppTexts.Count <= num6) { object obj3 = UIFactory.CreateText($"so{sessionOppTexts.Count}", sessionOppContainer.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(340f, 22f), richText: true, raycastTarget: false); UIFactory.SetTextAutoHeight(obj3); UIFactory.SetWordWrap(obj3, on: true); sessionOppTexts.Add(obj3); } UIFactory.SetText(sessionOppTexts[num6], text5); UIFactory.SetColor(sessionOppTexts[num6], (num11 > num12) ? C_GREEN : ((num11 < num12) ? C_RED : C_DIM)); object obj4 = sessionOppTexts[num6]; object obj5 = ((obj4 is Component) ? obj4 : null); GameObject val = ((obj5 != null) ? ((Component)obj5).gameObject : null); if (Object.op_Implicit((Object)(object)val)) { val.SetActive(true); } num6++; } } } for (int i = num6; i < sessionOppTexts.Count; i++) { object obj6 = sessionOppTexts[i]; object obj7 = ((obj6 is Component) ? obj6 : null); GameObject val2 = ((obj7 != null) ? ((Component)obj7).gameObject : null); if (Object.op_Implicit((Object)(object)val2)) { val2.SetActive(false); } } } private static void RefreshLeaderboard() { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_141b: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_13fa: Unknown result type (might be due to invalid IL or missing references) //IL_13df: Unknown result type (might be due to invalid IL or missing references) //IL_06ec: Unknown result type (might be due to invalid IL or missing references) //IL_06d6: Unknown result type (might be due to invalid IL or missing references) //IL_06c0: Unknown result type (might be due to invalid IL or missing references) //IL_06aa: Unknown result type (might be due to invalid IL or missing references) //IL_0824: Unknown result type (might be due to invalid IL or missing references) //IL_081d: Unknown result type (might be due to invalid IL or missing references) //IL_1505: Unknown result type (might be due to invalid IL or missing references) //IL_09e2: Unknown result type (might be due to invalid IL or missing references) //IL_09c7: Unknown result type (might be due to invalid IL or missing references) //IL_09ac: Unknown result type (might be due to invalid IL or missing references) //IL_0991: Unknown result type (might be due to invalid IL or missing references) //IL_0976: Unknown result type (might be due to invalid IL or missing references) _podiumLbRows.Clear(); string[] array = new string[8] { "#", "Lv", "Player", "Rating", "W", "L", "W/L", "Gold" }; string[] array2 = new string[8] { "rank", "level", "display_name", "rating", "wins", "losses", "wl_ratio", "gold" }; if (lbSortTexts != null) { for (int i = 0; i < array2.Length && i < lbSortTexts.Length; i++) { if (lbSortTexts[i] != null) { string text = ((!(lbSort == array2[i])) ? "" : (lbSortDesc ? " v" : " ^")); UIFactory.SetText(lbSortTexts[i], array[i] + text); UIFactory.SetColor(lbSortTexts[i], (lbSort == array2[i]) ? C_WHITE : C_LABEL); if (lbSortBtns != null && i < lbSortBtns.Length) { UIFactory.SetImageColor(lbSortBtns[i], (lbSort == array2[i]) ? C_TABACT : C_TAB); } } } } ApiClient.LeaderboardData cachedLeaderboard = ApiClient.CachedLeaderboard; foreach (LBRow lbRow in lbRows) { lbRow.root.SetActive(false); } if (cachedLeaderboard == null || cachedLeaderboard.entries == null || cachedLeaderboard.entries.Length == 0) { UIFactory.SetText(txtLBDetail, "No leaderboard data"); UIFactory.SetText(txtLBDetailB, ""); UIFactory.SetText(txtLBCount, ""); return; } List list = new List(cachedLeaderboard.entries); switch (lbSort) { case "rank": list.Sort((ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) => lbSortDesc ? b.rank.CompareTo(a.rank) : a.rank.CompareTo(b.rank)); break; case "level": list.Sort((ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) => lbSortDesc ? b.level.CompareTo(a.level) : a.level.CompareTo(b.level)); break; case "display_name": list.Sort((ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) => lbSortDesc ? string.Compare(b.display_name, a.display_name, StringComparison.OrdinalIgnoreCase) : string.Compare(a.display_name, b.display_name, StringComparison.OrdinalIgnoreCase)); break; case "rating": list.Sort((ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) => lbSortDesc ? b.rating.CompareTo(a.rating) : a.rating.CompareTo(b.rating)); break; case "wins": list.Sort((ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) => lbSortDesc ? b.wins.CompareTo(a.wins) : a.wins.CompareTo(b.wins)); break; case "losses": list.Sort((ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) => lbSortDesc ? b.losses.CompareTo(a.losses) : a.losses.CompareTo(b.losses)); break; case "wl_ratio": list.Sort(delegate(ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) { float value2 = ((a.losses > 0) ? ((float)a.wins / (float)a.losses) : ((float)a.wins * 100f)); float value3 = ((b.losses > 0) ? ((float)b.wins / (float)b.losses) : ((float)b.wins * 100f)); return lbSortDesc ? value3.CompareTo(value2) : value2.CompareTo(value3); }); break; case "gold": list.Sort((ApiClient.LeaderboardEntry a, ApiClient.LeaderboardEntry b) => lbSortDesc ? b.gold.CompareTo(a.gold) : a.gold.CompareTo(b.gold)); break; } if (lbSearchField != null) { UIFactory.SetText(lbSearchField, ""); } string lbQ = (lbSearch ?? "").Trim(); if (lbQ != lbSearchLast) { lbSearchLast = lbQ; lbPage = 0; } if (lbQ.Length > 0) { list.RemoveAll((ApiClient.LeaderboardEntry e) => e.display_name == null || e.display_name.IndexOf(lbQ, StringComparison.OrdinalIgnoreCase) < 0); } int num = 100; int num2 = (list.Count + num - 1) / num; lbPage = Math.Max(0, Math.Min(lbPage, num2 - 1)); int num3 = lbPage * num; int num4 = Math.Min(num3 + num, list.Count); for (int num5 = num3; num5 < num4 && num5 - num3 < lbRows.Count; num5++) { ApiClient.LeaderboardEntry leaderboardEntry = list[num5]; LBRow lBRow = lbRows[num5 - num3]; lBRow.steamId = leaderboardEntry.steam_id; bool flag = leaderboardEntry.steam_id == MatchTracker.LocalSteamId; string s = ((leaderboardEntry.losses > 0) ? $"{(float)leaderboardEntry.wins / (float)leaderboardEntry.losses:F1}" : ((leaderboardEntry.wins > 0) ? $"{leaderboardEntry.wins}:0" : "0:0")); UIFactory.SetText(lBRow.txtRank, $"{leaderboardEntry.rank}"); UIFactory.SetColor(lBRow.txtRank, (Color)((leaderboardEntry.rank == 1) ? new Color(1f, 0.84f, 0f) : ((leaderboardEntry.rank == 2) ? new Color(0.75f, 0.75f, 0.75f) : ((leaderboardEntry.rank == 3) ? new Color(0.8f, 0.5f, 0.2f) : C_GOLD)))); UIFactory.SetText(lBRow.txtLv, $"{leaderboardEntry.level}"); string text2 = Trunc(leaderboardEntry.display_name, 20); if (!string.IsNullOrEmpty(leaderboardEntry.title)) { string text3 = (string.IsNullOrEmpty(leaderboardEntry.title_color) ? "#FFFFFF" : leaderboardEntry.title_color); if (IsPodiumTitle(leaderboardEntry.title)) { _podiumLbRows.Add(new object[4] { lBRow.txtName, text2, leaderboardEntry.title, text3 }); text2 = text2 + " " + PodiumSparkleSpan(leaderboardEntry.title, text3, _podiumTick); } else { text2 = text2 + " [" + leaderboardEntry.title + "]"; } } UIFactory.SetText(lBRow.txtName, text2); UIFactory.SetColor(lBRow.txtName, flag ? C_GREEN : C_WHITE); string arg = (string.IsNullOrEmpty(leaderboardEntry.rank_color) ? "#FFFFFF" : leaderboardEntry.rank_color); UIFactory.SetText(lBRow.txtRating, $"{leaderboardEntry.rating}"); UIFactory.SetText(lBRow.txtW, $"{leaderboardEntry.wins}"); UIFactory.SetText(lBRow.txtL, $"{leaderboardEntry.losses}"); UIFactory.SetText(lBRow.txtWL, s); if (leaderboardEntry.gold < 0) { UIFactory.SetText(lBRow.txtGold, "Hidden"); } else { UIFactory.SetText(lBRow.txtGold, (leaderboardEntry.gold > 0) ? $"{leaderboardEntry.gold}" : "0"); } bool flag2 = leaderboardEntry.steam_id == selectedSteamId; UIFactory.SetImageColor(lBRow.hlWrap, flag2 ? new Color(0.2f, 0.25f, 0.4f, 0.4f) : ((leaderboardEntry.rank == 1) ? new Color(1f, 0.84f, 0f, 0.11f) : ((leaderboardEntry.rank == 2) ? new Color(0.75f, 0.75f, 0.78f, 0.1f) : ((leaderboardEntry.rank == 3) ? new Color(0.8f, 0.5f, 0.2f, 0.1f) : new Color(0.15f, 0.15f, 0.2f, 0.01f))))); SetLbRowOutline(lBRow, leaderboardEntry.rank <= 3); lBRow.root.SetActive(true); } UIFactory.SetText(txtLBCount, (lbQ.Length > 0) ? $"{list.Count} of {cachedLeaderboard.total_players} players" : $"{cachedLeaderboard.total_players} players ranked"); lbPrev.SetActive(lbPage > 0); lbNext.SetActive(lbPage < num2 - 1); UIFactory.SetText(txtLBPage, (num2 > 1) ? $"{lbPage + 1}/{num2}" : ""); if (!string.IsNullOrEmpty(selectedSteamId) && selectedStats != null) { ApiClient.PlayerStatsData playerStatsData = selectedStats; UIFactory.SetText(txtLBPlayerName, $"{playerStatsData.display_name} Level {playerStatsData.level}"); string text4 = ((!string.IsNullOrEmpty(playerStatsData.rank_name)) ? ("Rank: " + playerStatsData.rank_name + " ") : ""); string text5 = $"\n{text4}Rating: {playerStatsData.rating:F0} RD: {playerStatsData.rating_deviation:F0} Peak: {playerStatsData.peak_rating:F0}\n{playerStatsData.total_matches} matches ({playerStatsData.wins}W / {playerStatsData.losses}L) WR: {((playerStatsData.total_matches > 0) ? ((float)playerStatsData.wins * 100f / (float)playerStatsData.total_matches) : 0f):F0}%\n"; if (playerStatsData.ranked_series_wins + playerStatsData.ranked_series_losses > 0) { text5 += $"Ranked (series): {playerStatsData.ranked_series_wins}W / {playerStatsData.ranked_series_losses}L\n"; } if (playerStatsData.ranked_dc_count > 0 || playerStatsData.ranked_series_wins + playerStatsData.ranked_series_losses > 0) { int num6 = playerStatsData.ranked_series_wins + playerStatsData.ranked_series_losses + playerStatsData.ranked_dc_count; int ranked_dc_count = playerStatsData.ranked_dc_count; if (num6 > 0) { float num7 = (float)ranked_dc_count / (float)num6 * 100f; string text6 = ((num7 < 5f) ? "#44AA44" : ((num7 < 15f) ? "#DDAA33" : "#FF4444")); text5 += $"Leave: {ranked_dc_count}/{num6} ({num7:F0}%)\n"; } } string text7 = ((playerStatsData.bullets_fired > 0) ? $"Hit: {(float)playerStatsData.bullets_hit * 100f / (float)playerStatsData.bullets_fired:F1}% ({playerStatsData.bullets_hit}/{playerStatsData.bullets_fired})" : "Hit: -"); string text8 = ((playerStatsData.blocks_activated > 0) ? $"Block: {(float)playerStatsData.blocks_successful * 100f / (float)playerStatsData.blocks_activated:F1}% ({playerStatsData.blocks_successful}/{playerStatsData.blocks_activated})" : "Block: -"); text5 = text5 + text7 + "\n" + text8 + "\n"; if (selectedSteamId != MatchTracker.LocalSteamId) { int h2h_ranked_wins = playerStatsData.h2h_ranked_wins; int h2h_ranked_losses = playerStatsData.h2h_ranked_losses; int h2h_casual_wins = playerStatsData.h2h_casual_wins; int h2h_casual_losses = playerStatsData.h2h_casual_losses; int h2h_series_wins = playerStatsData.h2h_series_wins; int h2h_series_losses = playerStatsData.h2h_series_losses; int num8 = h2h_ranked_wins + h2h_casual_wins; int num9 = h2h_ranked_losses + h2h_casual_losses; if (num8 + num9 > 0) { string text9 = ((num8 > num9) ? "#00FF00" : ((num8 < num9) ? "#FF6666" : "#AAAAAA")); text5 += $"\nvs You: {num8}W - {num9}L ({num8 + num9} games)\n"; if (h2h_series_wins + h2h_series_losses > 0) { text5 += $" Ranked Series: {h2h_series_wins}W / {h2h_series_losses}L\n"; } if (h2h_casual_wins + h2h_casual_losses > 0) { text5 += $" Casual: {h2h_casual_wins}W / {h2h_casual_losses}L\n"; } } } if (playerStatsData.show_discord && !string.IsNullOrEmpty(playerStatsData.discord_display_name)) { text5 = text5 + "\nDiscord: @" + Trunc(playerStatsData.discord_display_name, 24) + ""; } if (!string.IsNullOrEmpty(playerStatsData.mod_version)) { string text10 = ((playerStatsData.mod_version == "1.35.5") ? "#88FF88" : "#FFD94D"); text5 = text5 + "\nMod: v" + playerStatsData.mod_version + "\n"; } else { text5 += "\nMod: not detected\n"; } if (playerStatsData.top_card_names != null && playerStatsData.top_card_names.Count > 0) { text5 += "\nTop Cards:\n"; for (int num10 = 0; num10 < playerStatsData.top_card_names.Count && num10 < 8; num10++) { string text11 = ((playerStatsData.top_card_picks.Count > num10) ? $" ({playerStatsData.top_card_picks[num10]}x)" : ""); float num11 = ((playerStatsData.top_card_win_rates != null && playerStatsData.top_card_win_rates.Count > num10) ? (playerStatsData.top_card_win_rates[num10] * 100f) : 0f); string text12 = ((num11 >= 55f) ? "#00FF00" : ((num11 <= 45f) ? "#FF6666" : "#AAAAAA")); text5 += $" {playerStatsData.top_card_names[num10]}{text11} {num11:F0}%\n"; } } if (ApiClient.CachedPlayerTournaments.TryGetValue(selectedSteamId, out var value) && value != null && value.participant_count > 0) { text5 += "\nTournaments: "; text5 += $"1stx{value.winner_count} 2ndx{value.runner_up_count} 3rdx{value.third_place_count} (played {value.participant_count})\n"; if (value.recent != null && value.recent.Length != 0) { int num12 = 0; ApiClient.PlayerTournamentEntry[] recent = value.recent; foreach (ApiClient.PlayerTournamentEntry playerTournamentEntry in recent) { if (num12 >= 4) { break; } string text13 = playerTournamentEntry.ended_at; try { if (!string.IsNullOrEmpty(text13)) { text13 = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(playerTournamentEntry.ended_at, null, DateTimeStyles.RoundtripKind).ToUniversalTime(), _ResolveTz()).ToString("M/d/yy"); } } catch { } string arg2 = ((playerTournamentEntry.placed_rank == 1) ? "1st" : ((playerTournamentEntry.placed_rank == 2) ? "2nd" : ((playerTournamentEntry.placed_rank == 3) ? "3rd" : "-"))); text5 += $" {text13} {arg2} ({playerTournamentEntry.signup_count}p)\n"; num12++; } } } string historyPart; string text14 = BuildViewHistoryText(out historyPart); UIFactory.SetText(txtLBDetail, text5 + text14); UIFactory.SetText(txtLBDetailB, historyPart); UIFactory.SetText(txtLBAch, GetAchievementText()); BuildFormGraph(playerStatsData.rating_history, playerStatsData.recent_form); if ((Object)(object)lbBlockRow != (Object)null) { lbBlockRow.SetActive(true); bool flag3 = selectedSteamId != MatchTracker.LocalSteamId; lbBlockBtn.SetActive(flag3); if (flag3 && lbBlockTxt != null) { bool flag4 = ApiClient.IsPlayerBlocked(selectedSteamId); UIFactory.SetText(lbBlockTxt, flag4 ? "Unblock from Ranked" : "Block from Ranked"); UIFactory.SetImageColor(lbBlockBtn, flag4 ? new Color(0.15f, 0.3f, 0.15f, 0.9f) : new Color(0.5f, 0.15f, 0.15f, 0.9f)); } } if (txtLBSteamId != null) { GameObject gameObject = ((Component)txtLBSteamId).gameObject; bool flag5 = ApiClient.IsAdmin && !string.IsNullOrEmpty(selectedSteamId); if (gameObject.activeSelf != flag5) { gameObject.SetActive(flag5); } if (flag5) { UIFactory.SetText(txtLBSteamId, "Steam ID: " + selectedSteamId + " (click to copy)"); } } } else { UIFactory.SetText(txtLBPlayerName, "Click a player"); UIFactory.SetText(txtLBDetail, ""); UIFactory.SetText(txtLBDetailB, ""); UIFactory.SetText(txtLBAch, ""); BuildFormGraph(null, null); if ((Object)(object)lbBlockRow != (Object)null) { lbBlockRow.SetActive(false); } if (txtLBSteamId != null) { ((Component)txtLBSteamId).gameObject.SetActive(false); } if ((Object)(object)h2hPager != (Object)null) { h2hPager.SetActive(false); } } } private static void BuildFormGraph(List ratingHistory, List form) { //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_05f7: Unknown result type (might be due to invalid IL or missing references) //IL_05fc: Unknown result type (might be due to invalid IL or missing references) //IL_0612: Unknown result type (might be due to invalid IL or missing references) //IL_0617: Unknown result type (might be due to invalid IL or missing references) //IL_062d: Unknown result type (might be due to invalid IL or missing references) //IL_0632: Unknown result type (might be due to invalid IL or missing references) //IL_0648: Unknown result type (might be due to invalid IL or missing references) //IL_064d: Unknown result type (might be due to invalid IL or missing references) //IL_0663: Unknown result type (might be due to invalid IL or missing references) //IL_0668: Unknown result type (might be due to invalid IL or missing references) //IL_0a53: Unknown result type (might be due to invalid IL or missing references) //IL_0a38: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_04ae: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_0a58: Unknown result type (might be due to invalid IL or missing references) //IL_07ca: Unknown result type (might be due to invalid IL or missing references) //IL_07d1: Expected O, but got Unknown //IL_07f4: Unknown result type (might be due to invalid IL or missing references) //IL_0801: Unknown result type (might be due to invalid IL or missing references) //IL_0818: Unknown result type (might be due to invalid IL or missing references) //IL_0829: Unknown result type (might be due to invalid IL or missing references) //IL_083d: Unknown result type (might be due to invalid IL or missing references) //IL_085a: Unknown result type (might be due to invalid IL or missing references) //IL_085f: Unknown result type (might be due to invalid IL or missing references) //IL_0a8c: Unknown result type (might be due to invalid IL or missing references) //IL_0a71: Unknown result type (might be due to invalid IL or missing references) //IL_0886: Unknown result type (might be due to invalid IL or missing references) //IL_0a91: Unknown result type (might be due to invalid IL or missing references) //IL_092a: Unknown result type (might be due to invalid IL or missing references) //IL_093e: Unknown result type (might be due to invalid IL or missing references) //IL_0b3b: Unknown result type (might be due to invalid IL or missing references) //IL_0b42: Expected O, but got Unknown //IL_0b65: Unknown result type (might be due to invalid IL or missing references) //IL_0b72: Unknown result type (might be due to invalid IL or missing references) //IL_0b89: Unknown result type (might be due to invalid IL or missing references) //IL_0b9a: Unknown result type (might be due to invalid IL or missing references) //IL_0bab: Unknown result type (might be due to invalid IL or missing references) //IL_0bc4: Unknown result type (might be due to invalid IL or missing references) //IL_0bf6: Unknown result type (might be due to invalid IL or missing references) //IL_098e: Unknown result type (might be due to invalid IL or missing references) //IL_09a5: Unknown result type (might be due to invalid IL or missing references) //IL_09bc: Unknown result type (might be due to invalid IL or missing references) //IL_09d0: Unknown result type (might be due to invalid IL or missing references) //IL_072a: Unknown result type (might be due to invalid IL or missing references) //IL_072c: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0c78: Unknown result type (might be due to invalid IL or missing references) //IL_0c7f: Expected O, but got Unknown //IL_0ca2: Unknown result type (might be due to invalid IL or missing references) //IL_0caf: Unknown result type (might be due to invalid IL or missing references) //IL_0cc6: Unknown result type (might be due to invalid IL or missing references) //IL_0cd7: Unknown result type (might be due to invalid IL or missing references) //IL_0ce8: Unknown result type (might be due to invalid IL or missing references) //IL_0d1a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)lbGraphPanel == (Object)null) { return; } for (int num = lbGraphPanel.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)lbGraphPanel.transform.GetChild(num)).gameObject); } bool flag = ratingHistory != null && ratingHistory.Count >= 2; bool flag2 = !flag && form != null && form.Count >= 2; if (!flag && !flag2) { lbGraphPanel.SetActive(false); return; } lbGraphPanel.SetActive(true); float[] array2; string text; if (flag) { float[] array = ratingHistory.ToArray(); if (array.Length > 100) { int num2 = 100; array2 = new float[num2]; for (int i = 0; i < num2; i++) { int num3 = (int)((long)i * (long)array.Length / num2); int num4 = (int)((long)(i + 1) * (long)array.Length / num2); if (num4 <= num3) { num4 = num3 + 1; } if (num4 > array.Length) { num4 = array.Length; } float num5 = 0f; int num6 = 0; for (int j = num3; j < num4; j++) { num5 += array[j]; num6++; } array2[i] = ((num6 > 0) ? (num5 / (float)num6) : array[num3]); } text = $"Rating History ({array[^1]:F0} Elo, {array.Length} games)"; } else { array2 = array; text = $"Rating History ({array2[^1]:F0} Elo)"; } } else { List list = new List(form); list.Reverse(); array2 = new float[list.Count]; int num7 = 0; int num8 = 0; int num9 = 0; for (int k = 0; k < list.Count; k++) { num7 += ((list[k] == "W") ? 1 : (-1)); array2[k] = num7; if (list[k] == "W") { num8++; } else { num9++; } } string arg = ((num8 > num9) ? "#00FF00" : ((num8 < num9) ? "#FF6666" : "#AAAAAA")); text = $"Ranked Form {num8}W-{num9}L"; } int num10 = array2.Length; float num11 = 110f; float num12 = 6f; float num13 = 44f; float num14 = 18f; float num15 = 6f; float num16 = 0f; Rect rect; try { RectTransform component = lbGraphPanel.GetComponent(); if ((Object)(object)component != (Object)null) { rect = component.rect; num16 = ((Rect)(ref rect)).width; } } catch { } if (num16 < 100f) { try { Transform parent = lbGraphPanel.transform.parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val != (Object)null) { rect = val.rect; num16 = ((Rect)(ref rect)).width - 24f; } } catch { } } if (num16 < 100f) { num16 = 506f; } float num17 = num16 - num12 - num13; float num18 = num11 - num14 - num15; GameObject val2 = UIFactory.CreatePanel("GBG", lbGraphPanel.transform, new Color(0.08f, 0.09f, 0.12f, 0.8f)); RectTransform component2 = val2.GetComponent(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; object obj3 = UIFactory.CreateText("GL", lbGraphPanel.transform, text, 11f, C_DIM, 257, (Vector2?)new Vector2(300f, 14f), richText: true, raycastTarget: false); try { object obj4 = ((obj3 is Component) ? obj3 : null); GameObject val3 = ((obj4 != null) ? ((Component)obj4).gameObject : null); if ((Object)(object)val3 != (Object)null) { RectTransform component3 = val3.GetComponent(); component3.anchorMin = new Vector2(0f, 1f); component3.anchorMax = new Vector2(1f, 1f); component3.pivot = new Vector2(0f, 1f); component3.anchoredPosition = new Vector2(num12, -1f); component3.sizeDelta = new Vector2(300f, 14f); Component component4 = val3.GetComponent(UIFactory.tLE); if ((Object)(object)component4 != (Object)null) { Object.Destroy((Object)(object)component4); } } } catch { } float num19 = array2[0]; float num20 = array2[0]; for (int l = 1; l < num10; l++) { if (array2[l] < num19) { num19 = array2[l]; } if (array2[l] > num20) { num20 = array2[l]; } } float num21 = num20 - num19; if (num21 < 1f) { float num22 = (num19 + num20) * 0.5f; num19 = num22 - 0.5f; num20 = num22 + 0.5f; num21 = 1f; } float num23 = num21 * 0.1f; num19 -= num23; num20 += num23; num21 = num20 - num19; if (flag) { float[] array3 = new float[5] { 1139f, 1500f, 1675f, 1980f, 2330f }; Color[] array4 = (Color[])(object)new Color[5] { new Color(0.733f, 0.475f, 0.933f), new Color(0.992f, 0.78f, 0.467f), new Color(0.467f, 0.639f, 0.988f), new Color(0.333f, 0.847f, 0.275f), new Color(0.957f, 0.529f, 0.663f) }; string[] refTierNames = new string[5] { "Beginner", "Intermediate", "Advanced", "Master", "Grand Master" }; List cachedRankTiers = ApiClient.CachedRankTiers; if (cachedRankTiers != null && cachedRankTiers.Count > 0) { int ti; Color val4 = default(Color); for (ti = 0; ti < refTierNames.Length && ti < array4.Length; ti++) { ApiClient.RankTierEntry rankTierEntry = cachedRankTiers.Find((ApiClient.RankTierEntry x) => x != null && string.Equals(x.name, refTierNames[ti], StringComparison.OrdinalIgnoreCase)); if (rankTierEntry != null && ColorUtility.TryParseHtmlString(rankTierEntry.color ?? "", ref val4)) { array4[ti] = val4; } } } float num24 = -999f; for (int num25 = 0; num25 < array3.Length; num25++) { float num26 = array3[num25]; if (num26 < num19 || num26 > num20) { continue; } float num27 = num15 + (num26 - num19) / num21 * num18; GameObject val5 = new GameObject($"Ref{(int)num26}"); val5.transform.SetParent(lbGraphPanel.transform, false); RectTransform val6 = val5.AddComponent(); val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.zero; val6.pivot = new Vector2(0f, 0.5f); val6.anchoredPosition = new Vector2(num12, num27); val6.sizeDelta = new Vector2(num17, 1f); Component obj6 = val5.AddComponent(UIFactory.tImage); Color val7 = array4[num25]; val7.a = 0.38f; UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj6, val7); float num28 = Mathf.Clamp(num27, 6f, num11 - 8f); if (Mathf.Abs(num28 - num24) < 10f) { continue; } num24 = num28; object obj7 = UIFactory.CreateText($"RefL{(int)num26}", lbGraphPanel.transform, $"{num26:F0}", 9f, new Color(array4[num25].r, array4[num25].g, array4[num25].b, 0.85f), 516, (Vector2?)new Vector2(38f, 10f), richText: true, raycastTarget: false); try { object obj8 = ((obj7 is Component) ? obj7 : null); GameObject val8 = ((obj8 != null) ? ((Component)obj8).gameObject : null); if ((Object)(object)val8 != (Object)null) { RectTransform component5 = val8.GetComponent(); component5.anchorMin = new Vector2(1f, 0f); component5.anchorMax = new Vector2(1f, 0f); component5.pivot = new Vector2(1f, 0.5f); component5.anchoredPosition = new Vector2(-2f, num28); Component component6 = val8.GetComponent(UIFactory.tLE); if ((Object)(object)component6 != (Object)null) { Object.Destroy((Object)(object)component6); } } } catch { } } } Color val9 = (flag ? new Color(0.3f, 0.7f, 1f, 0.9f) : new Color(0.5f, 0.85f, 0.5f, 0.9f)); Color val10 = (flag ? new Color(0.4f, 0.8f, 1f, 1f) : new Color(0.6f, 1f, 0.6f, 1f)); float num29 = 2f; for (int num30 = 0; num30 < num10 - 1; num30++) { float num31 = num12 + ((num10 > 1) ? ((float)num30 / (float)(num10 - 1) * num17) : 0f); float num32 = num15 + (array2[num30] - num19) / num21 * num18; float num33 = num12 + (float)(num30 + 1) / (float)(num10 - 1) * num17; float num34 = num15 + (array2[num30 + 1] - num19) / num21 * num18; float num35 = num33 - num31; float num36 = num34 - num32; float num37 = Mathf.Sqrt(num35 * num35 + num36 * num36); float num38 = Mathf.Atan2(num36, num35) * 57.29578f; GameObject val11 = new GameObject($"L{num30}"); val11.transform.SetParent(lbGraphPanel.transform, false); RectTransform val12 = val11.AddComponent(); val12.anchorMin = Vector2.zero; val12.anchorMax = Vector2.zero; val12.pivot = new Vector2(0f, 0.5f); val12.anchoredPosition = new Vector2(num31, num32); val12.sizeDelta = new Vector2(num37, num29); ((Transform)val12).localRotation = Quaternion.Euler(0f, 0f, num38); Component obj10 = val11.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj10, val9); } float num39 = ((num10 > 15) ? 3f : 4f); for (int num40 = 0; num40 < num10; num40++) { float num41 = num12 + ((num10 > 1) ? ((float)num40 / (float)(num10 - 1) * num17) : 0f); float num42 = num15 + (array2[num40] - num19) / num21 * num18; GameObject val13 = new GameObject($"D{num40}"); val13.transform.SetParent(lbGraphPanel.transform, false); RectTransform val14 = val13.AddComponent(); val14.anchorMin = Vector2.zero; val14.anchorMax = Vector2.zero; val14.pivot = new Vector2(0.5f, 0.5f); val14.anchoredPosition = new Vector2(num41, num42); val14.sizeDelta = new Vector2(num39, num39); Component obj11 = val13.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj11, val10); } } public static Rect GetCompareSearchScreenRect() { //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) try { object obj = compareSearchField; object obj2 = ((obj is Component) ? obj : null); GameObject val = ((obj2 != null) ? ((Component)obj2).gameObject : null); if ((Object)(object)val == (Object)null) { return new Rect(0f, 0f, 0f, 0f); } RectTransform component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return new Rect(0f, 0f, 0f, 0f); } Vector3[] array = (Vector3[])(object)new Vector3[4]; component.GetWorldCorners(array); float x = array[0].x; float num = array[2].x - array[0].x; float num2 = array[1].y - array[0].y; float num3 = (float)Screen.height - array[1].y; if (num < 1f || num2 < 1f) { return new Rect(0f, 0f, 0f, 0f); } return new Rect(x, num3, num, num2); } catch { return new Rect(0f, 0f, 0f, 0f); } } public static Rect GetLbSearchScreenRect() { //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) try { object obj = lbSearchField; object obj2 = ((obj is Component) ? obj : null); GameObject val = ((obj2 != null) ? ((Component)obj2).gameObject : null); if ((Object)(object)val == (Object)null) { return new Rect(0f, 0f, 0f, 0f); } RectTransform component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return new Rect(0f, 0f, 0f, 0f); } Vector3[] array = (Vector3[])(object)new Vector3[4]; component.GetWorldCorners(array); float x = array[0].x; float num = array[2].x - array[0].x; float num2 = array[1].y - array[0].y; float num3 = (float)Screen.height - array[1].y; if (num < 1f || num2 < 1f) { return new Rect(0f, 0f, 0f, 0f); } return new Rect(x, num3, num, num2); } catch { return new Rect(0f, 0f, 0f, 0f); } } private static GameObject BuildCompareTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Expected O, but got Unknown //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Expected O, but got Unknown //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Expected O, but got Unknown //IL_07b0: Unknown result type (might be due to invalid IL or missing references) //IL_07c4: Unknown result type (might be due to invalid IL or missing references) //IL_080c: Unknown result type (might be due to invalid IL or missing references) //IL_0820: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Expected O, but got Unknown //IL_0572: Unknown result type (might be due to invalid IL or missing references) //IL_05d4: Unknown result type (might be due to invalid IL or missing references) //IL_05d9: Unknown result type (might be due to invalid IL or missing references) //IL_055d: Unknown result type (might be due to invalid IL or missing references) //IL_0562: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Expected O, but got Unknown //IL_0607: Unknown result type (might be due to invalid IL or missing references) //IL_0643: Unknown result type (might be due to invalid IL or missing references) //IL_064d: Expected O, but got Unknown //IL_05f2: Unknown result type (might be due to invalid IL or missing references) //IL_05f7: Unknown result type (might be due to invalid IL or missing references) //IL_05fd: Expected O, but got Unknown //IL_06d7: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("CompareOuter"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 4f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(9, val.transform, asFirst: true); GameObject val2 = new GameObject("Compare"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddHLG(val2, 8f); UIFactory.AddLE(val2, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val3 = UIFactory.CreatePanel("CmpL", val2.transform, C_PANEL); UIFactory.AddVLG(val3, 4f, 8, 8, 6, 6); UIFactory.AddLE(val3, 200f, -1f, 222f, -1f, 0f, 1f); UIFactory.CreateText("CmpLH", val3.transform, "Compare Players", 19f, C_GOLD, 513, (Vector2?)new Vector2(204f, 26f), richText: true, raycastTarget: false); txtCompareStatus = UIFactory.CreateText("CmpSt", val3.transform, "Select up to 12 players", 13f, C_LABEL, 257, (Vector2?)new Vector2(204f, 38f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtCompareStatus, on: true); UIFactory.CreateText("CmpSearchCap", val3.transform, "Search players", 12f, C_SUB, 513, (Vector2?)new Vector2(204f, 16f), richText: true, raycastTarget: false); compareSearchField = UIFactory.CreateText("CmpSearchLbl", val3.transform, "", 13f, C_SUB, 513, (Vector2?)new Vector2(204f, 22f), richText: true, raycastTarget: false); GameObject val4 = new GameObject("CmpBtns"); val4.transform.SetParent(val3.transform, false); val4.AddComponent(); UIFactory.AddHLG(val4); UIFactory.AddLE(val4, -1f, -1f, -1f, 24f, -1f, 0f); Transform transform = val4.transform; Color c_WHITE = C_WHITE; Color bgColor = new Color(0.4f, 0.2f, 0.2f, 0.9f); object obj = <>c.<>9__660_0; if (obj == null) { UnityAction val5 = delegate { compareSelected.Clear(); dirty = true; }; <>c.<>9__660_0 = val5; obj = (object)val5; } GameObject go = UIFactory.CreateButton("CmpClr", transform, "Clear", 13f, c_WHITE, bgColor, (UnityAction)obj, (Vector2?)new Vector2(120f, 24f)); UIFactory.AddLE(go, -1f, -1f, -1f, 24f, 1f, 0f); Transform transform2 = val4.transform; Color c_WHITE2 = C_WHITE; Color bgColor2 = new Color(0.25f, 0.3f, 0.4f, 0.9f); object obj2 = <>c.<>9__660_1; if (obj2 == null) { UnityAction val6 = delegate { compareSearch = ""; dirty = true; }; <>c.<>9__660_1 = val6; obj2 = (object)val6; } GameObject go2 = UIFactory.CreateButton("CmpClrS", transform2, "Clear search", 13f, c_WHITE2, bgColor2, (UnityAction)obj2, (Vector2?)new Vector2(120f, 24f)); UIFactory.AddLE(go2, -1f, -1f, -1f, 24f, 1f, 0f); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("CmpSV", val3.transform, 2f, childForceExpandWidth: false); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); comparePickerContent = scrollViewRefs.content; GameObject val7 = UIFactory.CreatePanel("CmpR", val2.transform, C_PANEL); UIFactory.AddVLG(val7, 6f, 10, 10, 8, 8); UIFactory.AddLE(val7, -1f, -1f, -1f, -1f, 1f, 1f); GameObject val8 = new GameObject("CmpMetRow"); val8.transform.SetParent(val7.transform, false); val8.AddComponent(); UIFactory.AddHLG(val8); UIFactory.AddLE(val8, -1f, -1f, -1f, 30f, -1f, 0f); Transform transform3 = val8.transform; Color c_WHITE3 = C_WHITE; Color c_TAB = C_TAB; object obj3 = <>c.<>9__660_2; if (obj3 == null) { UnityAction val9 = delegate { compareMetric = (compareMetric - 1 + COMPARE_METRICS.Length) % COMPARE_METRICS.Length; dirty = true; }; <>c.<>9__660_2 = val9; obj3 = (object)val9; } GameObject go3 = UIFactory.CreateButton("CmpMetP", transform3, "<", 15f, c_WHITE3, c_TAB, (UnityAction)obj3, (Vector2?)new Vector2(30f, 30f)); UIFactory.AddLE(go3, -1f, -1f, 30f, 30f, 0f, 0f); Transform transform4 = val8.transform; Color c_WHITE4 = C_WHITE; Color c_TAB2 = C_TAB; object obj4 = <>c.<>9__660_3; if (obj4 == null) { UnityAction val10 = delegate { compareMetric = (compareMetric + 1) % COMPARE_METRICS.Length; dirty = true; }; <>c.<>9__660_3 = val10; obj4 = (object)val10; } compareMetricBtn = UIFactory.CreateButton("CmpMet", transform4, "Metric: Elo over games", 15f, c_WHITE4, c_TAB2, (UnityAction)obj4, (Vector2?)new Vector2(320f, 30f)); UIFactory.AddLE(compareMetricBtn, -1f, -1f, -1f, 30f, 1f, 0f); compareMetricBtnTxt = UIFactory.GetButtonText(compareMetricBtn); Transform transform5 = val8.transform; Color c_WHITE5 = C_WHITE; Color c_TAB3 = C_TAB; object obj5 = <>c.<>9__660_4; if (obj5 == null) { UnityAction val11 = delegate { compareMetric = (compareMetric + 1) % COMPARE_METRICS.Length; dirty = true; }; <>c.<>9__660_4 = val11; obj5 = (object)val11; } GameObject go4 = UIFactory.CreateButton("CmpMetN", transform5, ">", 15f, c_WHITE5, c_TAB3, (UnityAction)obj5, (Vector2?)new Vector2(30f, 30f)); UIFactory.AddLE(go4, -1f, -1f, 30f, 30f, 0f, 0f); compareGraphPanel = new GameObject("CmpGraph"); compareGraphPanel.transform.SetParent(val7.transform, false); compareGraphPanel.AddComponent(); UIFactory.AddLE(compareGraphPanel, -1f, -1f, -1f, -1f, 1f, 1f); Component obj6 = compareGraphPanel.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj6, (object)new Color(0.08f, 0.09f, 0.12f, 0.7f)); if (UIFactory.tMask != null) { Component obj7 = compareGraphPanel.AddComponent(UIFactory.tMask); try { UIFactory.tMask.GetProperty("showMaskGraphic", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj7, true); } catch { } } UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("CmpCardsSV", val7.transform, 0f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); compareCardsScroll = scrollViewRefs2.scrollGO; compareCardsContent = scrollViewRefs2.content; txtCompareCards = UIFactory.CreateText("CmpCards", scrollViewRefs2.content.transform, "", 15f, C_DIM, 257, (Vector2?)new Vector2(820f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtCompareCards, on: true); UIFactory.SetTextAutoHeight(txtCompareCards); UIFactory.CreateText("CmpScrollHint", val7.transform, "scroll for more — hover the panel + mouse wheel", 12f, C_DIM, 514, (Vector2?)new Vector2(820f, 16f), richText: true, raycastTarget: false); return val; } private static void ToggleCompareSelect(int rowIdx) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (rowIdx < 0 || rowIdx >= comparePickerSteamIds.Count) { return; } string sid = comparePickerSteamIds[rowIdx]; if (string.IsNullOrEmpty(sid)) { return; } if (compareSelected.Contains(sid)) { compareSelected.Remove(sid); } else { if (compareSelected.Count >= 12) { CompetitiveUI.ShowNotification($"Max {12} players", new Color(1f, 0.6f, 0.3f)); return; } compareSelected.Add(sid); if (!compareStatsCache.ContainsKey(sid)) { ApiClient.FetchPlayerStatsForView(sid, delegate(ApiClient.PlayerStatsData d) { if (d != null) { compareStatsCache[sid] = d; } dirty = true; }); } } dirty = true; } private static void RefreshCompare() { //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0202: 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) //IL_0220: Expected O, but got Unknown //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) if (ApiClient.CachedLeaderboard == null) { ApiClient.FetchLeaderboard(); } string text = COMPARE_METRICS[Math.Max(0, Math.Min(compareMetric, COMPARE_METRICS.Length - 1))]; if (compareMetricBtnTxt != null) { UIFactory.SetText(compareMetricBtnTxt, "Metric: " + text + " (click / use < >)"); } if (txtCompareStatus != null) { UIFactory.SetText(txtCompareStatus, $"Selected {compareSelected.Count}/{12} - click a player to add/remove"); } if (compareSearchField != null) { UIFactory.SetText(compareSearchField, ""); } ApiClient.LeaderboardData cachedLeaderboard = ApiClient.CachedLeaderboard; ApiClient.LeaderboardEntry[] array = ((cachedLeaderboard != null && cachedLeaderboard.entries != null) ? cachedLeaderboard.entries : new ApiClient.LeaderboardEntry[0]); string value = (compareSearch ?? "").Trim(); List list = new List(); ApiClient.LeaderboardEntry[] array2 = array; foreach (ApiClient.LeaderboardEntry leaderboardEntry in array2) { if (string.IsNullOrEmpty(value) || (leaderboardEntry.display_name != null && leaderboardEntry.display_name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)) { list.Add(leaderboardEntry); } } int count = list.Count; while (comparePickerSteamIds.Count < count) { comparePickerSteamIds.Add(""); } for (int j = 0; j < count; j++) { ApiClient.LeaderboardEntry leaderboardEntry2 = list[j]; comparePickerSteamIds[j] = leaderboardEntry2.steam_id; while (comparePickerRows.Count <= j) { int idx = comparePickerRows.Count; GameObject val = UIFactory.CreateButton($"cmpP{idx}", comparePickerContent.transform, "", 13f, C_WHITE, C_TAB, (UnityAction)delegate { ToggleCompareSelect(idx); }, (Vector2?)new Vector2(168f, 24f)); UIFactory.AddLE(val, -1f, -1f, 168f, 24f, 0f, 0f); comparePickerRows.Add(val); comparePickerTexts.Add(UIFactory.GetButtonText(val)); } GameObject val2 = comparePickerRows[j]; val2.SetActive(true); bool flag = compareSelected.Contains(leaderboardEntry2.steam_id); int num = compareSelected.IndexOf(leaderboardEntry2.steam_id); Color c = ((flag && num >= 0) ? COMPARE_COLORS[num % COMPARE_COLORS.Length] : C_LABEL); string arg = (flag ? ("[X] ") : "[ ] "); UIFactory.SetText(comparePickerTexts[j], $"{arg}{Trunc(leaderboardEntry2.display_name, 16)} {leaderboardEntry2.rating}"); UIFactory.SetImageColor(val2, (Color)(flag ? new Color(0.2f, 0.3f, 0.25f, 0.9f) : C_TAB)); } for (int num2 = count; num2 < comparePickerRows.Count; num2++) { comparePickerRows[num2].SetActive(false); } bool flag2 = text == "Top Cards" || text == "Worst Cards"; bool active = !flag2; if ((Object)(object)compareGraphPanel != (Object)null) { compareGraphPanel.SetActive(active); } if ((Object)(object)compareCardsScroll != (Object)null) { compareCardsScroll.SetActive(flag2); } if (text == "Elo over games") { BuildCompareGraph(); } else if (text == "Elo over time") { BuildCompareGraph(timeAxis: true); } else if (flag2) { BuildCompareCardGrid(text); } else { BuildCompareBarChart(text); } } private static string ColorToHex(Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp((int)(c.r * 255f), 0, 255); int num2 = Mathf.Clamp((int)(c.g * 255f), 0, 255); int num3 = Mathf.Clamp((int)(c.b * 255f), 0, 255); return $"{num:X2}{num2:X2}{num3:X2}"; } private static void BuildCompareGraph(bool timeAxis = false) { //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_06a2: Unknown result type (might be due to invalid IL or missing references) //IL_06b2: Unknown result type (might be due to invalid IL or missing references) //IL_06c1: Unknown result type (might be due to invalid IL or missing references) //IL_06f7: Unknown result type (might be due to invalid IL or missing references) //IL_06fc: Unknown result type (might be due to invalid IL or missing references) //IL_0827: Unknown result type (might be due to invalid IL or missing references) //IL_0866: Unknown result type (might be due to invalid IL or missing references) //IL_0875: Unknown result type (might be due to invalid IL or missing references) //IL_0887: Unknown result type (might be due to invalid IL or missing references) //IL_05e3: Unknown result type (might be due to invalid IL or missing references) //IL_0639: Unknown result type (might be due to invalid IL or missing references) //IL_064e: Unknown result type (might be due to invalid IL or missing references) //IL_065d: Unknown result type (might be due to invalid IL or missing references) //IL_07a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)compareGraphPanel == (Object)null) { return; } for (int num = compareGraphPanel.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)compareGraphPanel.transform.GetChild(num)).gameObject); } List list = new List(); List list2 = new List(); List list3 = new List(); List list4 = new List(); for (int i = 0; i < compareSelected.Count; i++) { string key = compareSelected[i]; if (!compareStatsCache.TryGetValue(key, out var value) || value == null || value.rating_history == null || value.rating_history.Count < 2) { continue; } float[] item = null; if (timeAxis) { if (value.rating_history_times == null || value.rating_history_times.Count != value.rating_history.Count) { continue; } item = value.rating_history_times.ToArray(); } list.Add(Trunc(value.display_name ?? "?", 14)); list2.Add(COMPARE_COLORS[i % COMPARE_COLORS.Length]); list3.Add(value.rating_history.ToArray()); list4.Add(item); } CompareChartSize(out var W, out var H); float num2 = 56f; float num3 = 16f; float num4 = 30f; float num5 = 26f; float num6 = W - num2 - num3; float num7 = H - num4 - num5; if (list3.Count == 0) { object obj = UIFactory.CreateText("CmpNone", compareGraphPanel.transform, "Select 2+ players with ranked history to compare Elo.", 15f, C_DIM, 514, (Vector2?)new Vector2(W - 20f, 40f), richText: true, raycastTarget: false); object obj2 = ((obj is Component) ? obj : null); RectTransform val = ((obj2 != null) ? ((Component)obj2).gameObject.GetComponent() : null); if ((Object)(object)val != (Object)null) { val.anchorMin = new Vector2(0.5f, 0.5f); val.anchorMax = new Vector2(0.5f, 0.5f); val.anchoredPosition = Vector2.zero; } object obj3 = ((obj is Component) ? obj : null); Component val2 = ((obj3 != null) ? ((Component)obj3).gameObject.GetComponent(UIFactory.tLE) : null); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } return; } float num8 = float.MaxValue; float num9 = float.MinValue; int num10 = 0; foreach (float[] item2 in list3) { if (item2.Length > num10) { num10 = item2.Length; } float[] array = item2; foreach (float num11 in array) { if (num11 < num8) { num8 = num11; } if (num11 > num9) { num9 = num11; } } } if (num10 < 2) { num10 = 2; } float num12 = Mathf.Max(1f, num9 - num8); float num13 = NiceStep(num12 / 4f); float num14 = Mathf.Floor(num8 / num13) * num13; float num15 = Mathf.Ceil(num9 / num13) * num13; if (num15 - num14 < num13) { num15 = num14 + num13; } num8 = num14; num9 = num15; float num16 = num9 - num8; int num17 = Mathf.Clamp(Mathf.RoundToInt(num16 / num13), 2, 8); for (int k = 0; k <= num17; k++) { float num18 = num14 + (float)k * num13; if (num18 > num15 + 0.5f) { break; } float num19 = num5 + (num18 - num14) / num16 * num7; DrawBar($"CmpYGrid{k}", num2, num19, num6, 1f, new Color(1f, 1f, 1f, 0.1f)); MakeGraphLabel($"CmpYLbl{k}", "" + FullNum(num18) + "", new Vector2(0f, 0f), new Vector2(num2 - 4f, num19 - 6f), new Vector2(50f, 12f), 516); } float num20 = 0f; float num21 = 1f; if (timeAxis) { num20 = float.MaxValue; float num22 = float.MinValue; foreach (float[] item3 in list4) { float[] array2 = item3; foreach (float num23 in array2) { if (num23 < num20) { num20 = num23; } if (num23 > num22) { num22 = num23; } } } num21 = Mathf.Max(0.5f, num22 - num20); DateTime dateTime = new DateTime(2020, 1, 1); for (int m = 0; m <= 4; m++) { float num24 = num20 + num21 * (float)m / 4f; float num25 = num2 + (num24 - num20) / num21 * num6; DrawBar($"CmpXGrid{m}", num25, num5, 1f, num7, new Color(1f, 1f, 1f, 0.07f)); string text = dateTime.AddDays(num24).ToString("M/d", CultureInfo.InvariantCulture); MakeGraphLabel($"CmpXDate{m}", "" + text + "", new Vector2(0f, 0f), new Vector2(num25 - 24f, num5 - 16f), new Vector2(48f, 12f), 514); } } else { MakeGraphLabel("CmpXLbl", "games ->", new Vector2(1f, 0f), new Vector2(0f - num3, num5 - 14f), new Vector2(90f, 12f), 516); } for (int n = 0; n < list3.Count; n++) { float[] array3 = list3[n]; float[] array4 = list4[n]; Color col = list2[n]; for (int num26 = 0; num26 < array3.Length - 1; num26++) { float x = (timeAxis ? (num2 + (array4[num26] - num20) / num21 * num6) : (num2 + (float)num26 / (float)(num10 - 1) * num6)); float y = num5 + (array3[num26] - num8) / num16 * num7; float x2 = (timeAxis ? (num2 + (array4[num26 + 1] - num20) / num21 * num6) : (num2 + (float)(num26 + 1) / (float)(num10 - 1) * num6)); float y2 = num5 + (array3[num26 + 1] - num8) / num16 * num7; DrawGraphSegment($"CmpL{n}_{num26}", x, y, x2, y2, col, 2f); } int num27 = 3; float num28 = num6 / (float)num27; float num29 = num2 + (float)(n % num27) * num28; float num30 = -2f - (float)(n / num27) * 16f; float num31 = H + num30 - 7f; DrawGraphSegment($"CmpLegSw{n}", num29 + 2f, num31, num29 + 24f, num31, col, 4f); MakeGraphLabel($"CmpLeg{n}", "" + list[n] + "", new Vector2(0f, 1f), new Vector2(num29 + 30f, num30), new Vector2(num28 - 30f, 16f), 513, 13f); } } private static void DrawGraphSegment(string name, float x1, float y1, float x2, float y2, Color col, float thick) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) float num = x2 - x1; float num2 = y2 - y1; float num3 = Mathf.Sqrt(num * num + num2 * num2); float num4 = Mathf.Atan2(num2, num) * 57.29578f; GameObject val = new GameObject(name); val.transform.SetParent(compareGraphPanel.transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.zero; val2.pivot = new Vector2(0f, 0.5f); val2.anchoredPosition = new Vector2(x1, y1); val2.sizeDelta = new Vector2(num3, thick); ((Transform)val2).localRotation = Quaternion.Euler(0f, 0f, num4); Component obj = val.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, col); } private static void MakeGraphLabel(string name, string text, Vector2 anchor, Vector2 pos, Vector2 size, int align, float fontSize = 11f) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) object obj = UIFactory.CreateText(name, compareGraphPanel.transform, text, fontSize, C_DIM, align, size); object obj2 = ((obj is Component) ? obj : null); GameObject val = ((obj2 != null) ? ((Component)obj2).gameObject : null); if (!((Object)(object)val == (Object)null)) { RectTransform component = val.GetComponent(); component.anchorMin = anchor; component.anchorMax = anchor; component.pivot = anchor; component.anchoredPosition = pos; component.sizeDelta = size; Component component2 = val.GetComponent(UIFactory.tLE); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } } } private static void DrawBar(string name, float x, float y, float w, float h, Color col) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_003b: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) if (h < 0f) { h = 0f; } GameObject val = new GameObject(name); val.transform.SetParent(compareGraphPanel.transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.zero; val2.pivot = new Vector2(0f, 0f); val2.anchoredPosition = new Vector2(x, y); val2.sizeDelta = new Vector2(w, h); Component obj = val.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, col); } private static Color RegionColor(string region) { //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) switch ((region ?? "").ToLowerInvariant()) { case "us": return new Color(0.25f, 0.55f, 1f); case "usw": return new Color(0.15f, 0.85f, 0.85f); case "ussc": return new Color(0.35f, 0.8f, 0.35f); case "eu": return new Color(1f, 0.62f, 0.18f); case "asia": return new Color(0.95f, 0.32f, 0.32f); case "jp": return new Color(1f, 0.42f, 0.8f); case "au": return new Color(0.68f, 0.42f, 1f); case "sa": return new Color(0.8f, 0.85f, 0.2f); case "kr": return new Color(1f, 0.82f, 0.28f); case "in": return new Color(0.45f, 0.4f, 0.92f); case "cae": return new Color(0.5f, 0.78f, 0.62f); case "za": return new Color(0.9f, 0.55f, 0.35f); case "ru": case "rue": return new Color(0.8f, 0.5f, 0.55f); default: return new Color(0.7f, 0.7f, 0.74f); } } private static void CompareChartSize(out float W, out float H) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) W = 900f; H = 460f; try { RectTransform val = (((Object)(object)compareGraphPanel != (Object)null) ? compareGraphPanel.GetComponent() : null); if ((Object)(object)val != (Object)null) { Rect rect = val.rect; if (((Rect)(ref rect)).width > 50f) { rect = val.rect; W = ((Rect)(ref rect)).width; } rect = val.rect; if (((Rect)(ref rect)).height > 50f) { rect = val.rect; H = ((Rect)(ref rect)).height; } } } catch { } } private static float NiceStep(float roughStep) { if (roughStep <= 0f) { return 1f; } float num = Mathf.Pow(10f, Mathf.Floor(Mathf.Log10(roughStep))); float num2 = roughStep / num; float num3 = ((num2 <= 1f) ? 1f : ((num2 <= 2f) ? 2f : ((num2 <= 2.5f) ? 2.5f : ((num2 <= 5f) ? 5f : 10f)))); return num3 * num; } private static string FullNum(float v) { return Mathf.RoundToInt(v).ToString("N0"); } private static long TotalXpForLevel(int level) { long num = 0L; for (int i = 1; i <= level && i <= 100; i++) { num += (long)(100.0 * Math.Pow(i, 1.5)); } return num; } private static int LevelForXp(float xp) { long num = (long)Math.Max(0f, xp); int result = 0; for (int i = 1; i <= 100; i++) { long num2 = (long)(100.0 * Math.Pow(i, 1.5)); if (num < num2) { return result; } num -= num2; result = i; } return 100; } private static Color GradeColor(float t) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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) t = Mathf.Clamp01(t); Color val = default(Color); ((Color)(ref val))..ctor(0.35f, 0.85f, 0.4f); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.95f, 0.82f, 0.3f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.95f, 0.4f, 0.4f); return (t < 0.5f) ? Color.Lerp(val, val2, t * 2f) : Color.Lerp(val2, val3, (t - 0.5f) * 2f); } private static Sprite GetCircleSprite() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_00dc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_pieCircleSprite != (Object)null) { return _pieCircleSprite; } try { int num = 128; float num2 = (float)num * 0.5f; float num3 = num2; float num4 = num2; Texture2D val = new Texture2D(num, num, (TextureFormat)4, false); ((Object)val).hideFlags = (HideFlags)61; Color32[] array = (Color32[])(object)new Color32[num * num]; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { float num5 = (float)j + 0.5f - num3; float num6 = (float)i + 0.5f - num4; bool flag = num5 * num5 + num6 * num6 <= (num2 - 1f) * (num2 - 1f); array[i * num + j] = (flag ? new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) : new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)0)); } } val.SetPixels32(array); val.Apply(); _pieCircleSprite = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f), 100f); ((Object)_pieCircleSprite).hideFlags = (HideFlags)61; } catch { _pieCircleSprite = null; } return _pieCircleSprite; } internal static Sprite GetBodyGlyphSprite(string sku, string hex) { //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) string text = ((sku == "pcolor_prismatic") ? "prismatic" : (hex ?? "").Trim().ToLowerInvariant()); if (string.IsNullOrEmpty(text)) { text = "#666a80"; } if (_bodyGlyphCache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null) { return value; } try { bool[] mask = new bool[4096]; Action action = delegate(float cx, float cy, float r) { for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num5 = (float)j + 0.5f - cx; float num6 = (float)i + 0.5f - cy; if (num5 * num5 + num6 * num6 <= r * r) { mask[i * 64 + j] = true; } } } }; action(32f, 36f, 20f); action(8f, 34f, 6f); action(56f, 34f, 6f); action(22f, 9f, 5f); action(42f, 9f, 5f); Color val = default(Color); ((Color)(ref val))..ctor(0.4f, 0.42f, 0.5f); bool flag = text == "prismatic"; if (!flag) { string text2 = (text.StartsWith("#") ? text : ("#" + text)); if (!ColorUtility.TryParseHtmlString(text2, ref val)) { ((Color)(ref val))..ctor(0.4f, 0.42f, 0.5f); } } float num = 0.299f * val.r + 0.587f * val.g + 0.114f * val.b; Color val2 = ((flag || num > 0.5f) ? new Color(0.06f, 0.06f, 0.08f, 1f) : new Color(0.85f, 0.87f, 0.92f, 1f)); Texture2D val3 = new Texture2D(64, 64, (TextureFormat)4, false); ((Object)val3).hideFlags = (HideFlags)61; Color32[] array = (Color32[])(object)new Color32[4096]; for (int num2 = 0; num2 < 64; num2++) { for (int num3 = 0; num3 < 64; num3++) { int num4 = num2 * 64 + num3; if (!mask[num4]) { array[num4] = new Color32((byte)0, (byte)0, (byte)0, (byte)0); continue; } Color val4 = ((num3 == 0 || num2 == 0 || num3 == 63 || num2 == 63 || !mask[num4 - 1] || !mask[num4 + 1] || !mask[num4 - 64] || !mask[num4 + 64]) ? val2 : ((!flag) ? val : Color.HSVToRGB((float)num3 / 63f, 0.85f, 1f))); array[num4] = Color32.op_Implicit(val4); } } val3.SetPixels32(array); val3.Apply(); Sprite val5 = Sprite.Create(val3, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f); ((Object)val5).hideFlags = (HideFlags)61; _bodyGlyphCache[text] = val5; return val5; } catch { return null; } } private static void DrawPieSlice(string name, float cx, float cy, float radius, float startFrac, float sweepFrac, Color col) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) Sprite circleSprite = GetCircleSprite(); if ((Object)(object)circleSprite == (Object)null) { return; } GameObject val = new GameObject(name); val.transform.SetParent(compareGraphPanel.transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.zero; val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = new Vector2(cx, cy); val2.sizeDelta = new Vector2(radius * 2f, radius * 2f); ((Transform)val2).localRotation = Quaternion.Euler(0f, 0f, (0f - startFrac) * 360f); Component obj = val.AddComponent(UIFactory.tImage); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; UIFactory.tImage.GetProperty("sprite", bindingAttr)?.SetValue(obj, circleSprite); UIFactory.tImage.GetProperty("color", bindingAttr)?.SetValue(obj, col); try { UIFactory.tImage.GetProperty("type", bindingAttr)?.SetValue(obj, Enum.ToObject(UIFactory.tImage.GetProperty("type", bindingAttr).PropertyType, 3)); } catch { } try { UIFactory.tImage.GetProperty("fillMethod", bindingAttr)?.SetValue(obj, Enum.ToObject(UIFactory.tImage.GetProperty("fillMethod", bindingAttr).PropertyType, 4)); } catch { } try { UIFactory.tImage.GetProperty("fillOrigin", bindingAttr)?.SetValue(obj, 2); } catch { } try { UIFactory.tImage.GetProperty("fillClockwise", bindingAttr)?.SetValue(obj, true); } catch { } try { UIFactory.tImage.GetProperty("fillAmount", bindingAttr)?.SetValue(obj, Mathf.Clamp01(sweepFrac)); } catch { } } private static void BuildCompareBarChart(string metricName) { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04eb: Unknown result type (might be due to invalid IL or missing references) //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_0afe: Unknown result type (might be due to invalid IL or missing references) //IL_0b12: Unknown result type (might be due to invalid IL or missing references) //IL_0b21: Unknown result type (might be due to invalid IL or missing references) //IL_0c9f: Unknown result type (might be due to invalid IL or missing references) //IL_0b97: Unknown result type (might be due to invalid IL or missing references) //IL_0bce: Unknown result type (might be due to invalid IL or missing references) //IL_0be2: Unknown result type (might be due to invalid IL or missing references) //IL_0bf1: Unknown result type (might be due to invalid IL or missing references) //IL_0d85: Unknown result type (might be due to invalid IL or missing references) //IL_0d92: Unknown result type (might be due to invalid IL or missing references) //IL_0da1: Unknown result type (might be due to invalid IL or missing references) //IL_0cef: Unknown result type (might be due to invalid IL or missing references) //IL_0d03: Unknown result type (might be due to invalid IL or missing references) //IL_0d12: Unknown result type (might be due to invalid IL or missing references) //IL_0e03: Unknown result type (might be due to invalid IL or missing references) //IL_0e08: Unknown result type (might be due to invalid IL or missing references) //IL_104d: Unknown result type (might be due to invalid IL or missing references) //IL_104f: Unknown result type (might be due to invalid IL or missing references) //IL_0e9a: Unknown result type (might be due to invalid IL or missing references) //IL_0ea1: Unknown result type (might be due to invalid IL or missing references) //IL_0ea8: Unknown result type (might be due to invalid IL or missing references) //IL_0eb4: Unknown result type (might be due to invalid IL or missing references) //IL_0ee4: Unknown result type (might be due to invalid IL or missing references) //IL_0ef1: Unknown result type (might be due to invalid IL or missing references) //IL_0efe: Unknown result type (might be due to invalid IL or missing references) //IL_0f10: Unknown result type (might be due to invalid IL or missing references) //IL_0f4e: Unknown result type (might be due to invalid IL or missing references) //IL_0f6c: Unknown result type (might be due to invalid IL or missing references) //IL_0f7e: Unknown result type (might be due to invalid IL or missing references) //IL_0fc6: Unknown result type (might be due to invalid IL or missing references) //IL_0fea: Unknown result type (might be due to invalid IL or missing references) //IL_0ffc: Unknown result type (might be due to invalid IL or missing references) //IL_11b1: Unknown result type (might be due to invalid IL or missing references) //IL_11e9: Unknown result type (might be due to invalid IL or missing references) //IL_11fe: Unknown result type (might be due to invalid IL or missing references) //IL_1210: Unknown result type (might be due to invalid IL or missing references) //IL_109b: Unknown result type (might be due to invalid IL or missing references) //IL_1075: Unknown result type (might be due to invalid IL or missing references) //IL_107a: Unknown result type (might be due to invalid IL or missing references) //IL_114a: Unknown result type (might be due to invalid IL or missing references) //IL_1168: Unknown result type (might be due to invalid IL or missing references) //IL_117a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)compareGraphPanel == (Object)null) { return; } for (int num = compareGraphPanel.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)compareGraphPanel.transform.GetChild(num)).gameObject); } List list = new List(); for (int i = 0; i < compareSelected.Count; i++) { if (compareStatsCache.TryGetValue(compareSelected[i], out var value) && value != null) { list.Add(i); } } CompareChartSize(out var W, out var H); if (list.Count == 0) { MakeGraphLabel("CmpBarNone", "Select players (left) to chart " + metricName + ".", new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(W - 40f, 40f), 514); return; } if (metricName == "Region Time") { BuildComparePieChart(list, W, H); return; } if (metricName == "Achievement Grid") { BuildCompareAchievementGrid(list, W, H); return; } float num2 = 60f; float num3 = 16f; float num4 = 34f; float num5 = 48f; float num6 = W - num2 - num3; float num7 = H - num4 - num5; int count = list.Count; float num8 = num6 / (float)count; bool flag = false; bool flag2 = false; string text = ""; string text2; switch (metricName) { case "Hit / Block %": text2 = "Hit % vs Block %"; flag = true; text = "%"; break; case "Avg Cards / Game": text2 = "Avg Cards per Game (lower = stronger)"; flag2 = true; break; case "Avg FPS": text2 = "Average FPS"; break; case "Peak Elo": text2 = "Peak Elo"; break; case "Total XP": text2 = "Total XP"; break; case "Achievements": text2 = "Achievements unlocked"; break; case "Top Streaks": text2 = "Best Win Streak"; flag = true; break; case "5-0s Given / Taken": text2 = "5-0 Sweeps"; flag = true; break; case "Bets Won / Lost": text2 = "Betting Record"; flag = true; break; case "Keys / Sec": text2 = "Avg Keystrokes per Second (in combat)"; break; case "Keys / Game": text2 = "Avg Key Presses per Game"; break; case "Avg Game Length": text2 = "Avg Game Length (minutes)"; break; case "2v2 Rating": text2 = "2v2 Rating"; break; default: text2 = metricName; break; } string text3 = "Hit"; string text4 = "Block"; switch (metricName) { case "Top Streaks": text3 = "Ranked (series)"; text4 = "Casual (games)"; break; case "5-0s Given / Taken": text3 = "Given"; text4 = "Taken"; break; case "Bets Won / Lost": text3 = "Won"; text4 = "Lost"; break; } bool flag3 = metricName == "Hit / Block %"; MakeGraphLabel("CmpBarTitle", "" + text2 + "", new Vector2(0f, 1f), new Vector2(num2, -4f), new Vector2(W - num2, 18f), 513); Func func = null; Func func2 = null; switch (metricName) { case "Hit / Block %": func = (ApiClient.PlayerStatsData ps) => (ps.bullets_fired > 0) ? ((float)ps.bullets_hit * 100f / (float)ps.bullets_fired) : 0f; func2 = (ApiClient.PlayerStatsData ps) => (ps.blocks_activated > 0) ? ((float)ps.blocks_successful * 100f / (float)ps.blocks_activated) : 0f; break; case "Avg Cards / Game": func = (ApiClient.PlayerStatsData ps) => ps.avg_cards_per_game; break; case "Avg FPS": func = (ApiClient.PlayerStatsData ps) => ps.avg_fps; break; case "Peak Elo": func = (ApiClient.PlayerStatsData ps) => ps.peak_rating; break; case "Total XP": func = (ApiClient.PlayerStatsData ps) => ps.total_xp; break; case "Achievements": func = (ApiClient.PlayerStatsData ps) => ps.achievements_unlocked; break; case "Top Streaks": func = (ApiClient.PlayerStatsData ps) => ps.best_ranked_streak; func2 = (ApiClient.PlayerStatsData ps) => ps.best_casual_streak; break; case "5-0s Given / Taken": func = (ApiClient.PlayerStatsData ps) => ps.sweeps_given; func2 = (ApiClient.PlayerStatsData ps) => ps.sweeps_taken; break; case "Bets Won / Lost": func = (ApiClient.PlayerStatsData ps) => ps.bets_won; func2 = (ApiClient.PlayerStatsData ps) => ps.bets_lost; break; case "Keys / Sec": func = (ApiClient.PlayerStatsData ps) => ps.avg_keys_per_sec; break; case "Keys / Game": func = (ApiClient.PlayerStatsData ps) => ps.avg_keys_per_game; break; case "Avg Game Length": func = (ApiClient.PlayerStatsData ps) => (float)ps.avg_game_seconds / 60f; break; case "2v2 Rating": func = (ApiClient.PlayerStatsData ps) => ps.team_rating; break; default: func = (ApiClient.PlayerStatsData ps) => 0f; break; } float num9; float num10; if (flag3) { num9 = 100f; num10 = 25f; } else if (flag2) { num9 = 5f; num10 = 1f; } else { float num11 = 0.0001f; foreach (int item in list) { ApiClient.PlayerStatsData arg = compareStatsCache[compareSelected[item]]; float num12 = func(arg); if (num12 > num11) { num11 = num12; } if (flag && func2 != null) { float num13 = func2(arg); if (num13 > num11) { num11 = num13; } } } num10 = NiceStep(num11 / 4f); num9 = Mathf.Ceil(num11 * 1.08f / num10) * num10; if (num9 < num10) { num9 = num10; } } if (metricName == "Total XP") { int num14 = LevelForXp(num9); int num15 = Mathf.Max(1, Mathf.CeilToInt((float)num14 / 6f)); MakeGraphLabel("CmpBarY0", "Lv 0", new Vector2(0f, 0f), new Vector2(num2 - 4f, num5 - 6f), new Vector2(52f, 12f), 516); for (int num16 = num15; num16 <= num14; num16 += num15) { float num17 = TotalXpForLevel(num16); if (num17 > num9) { break; } float num18 = num5 + num17 / num9 * num7; DrawBar($"CmpBarGridL{num16}", num2, num18, num6, 1f, new Color(1f, 1f, 1f, 0.1f)); MakeGraphLabel($"CmpBarYL{num16}", $"Lv {num16}", new Vector2(0f, 0f), new Vector2(num2 - 4f, num18 - 6f), new Vector2(52f, 12f), 516); } } else { int num19 = Mathf.Clamp(Mathf.RoundToInt(num9 / num10), 2, 10); for (int num20 = 0; num20 <= num19; num20++) { float num21 = (float)num20 * num10; if (num21 > num9 + 0.001f) { break; } float num22 = num5 + num21 / num9 * num7; DrawBar($"CmpBarGrid{num20}", num2, num22, num6, 1f, new Color(1f, 1f, 1f, 0.1f)); MakeGraphLabel($"CmpBarYLbl{num20}", "" + (flag2 ? num21.ToString("0") : FullNum(num21)) + text + "", new Vector2(0f, 0f), new Vector2(num2 - 4f, num22 - 6f), new Vector2(52f, 12f), 516); } } if (flag) { MakeGraphLabel("CmpHBLeg", "solid = " + text3 + " dim = " + text4 + "", new Vector2(1f, 1f), new Vector2(0f - num3, -4f), new Vector2(260f, 14f), 516); } int max = Mathf.Clamp((int)(num8 / 8f), 5, 18); for (int num23 = 0; num23 < count; num23++) { int num24 = list[num23]; ApiClient.PlayerStatsData playerStatsData = compareStatsCache[compareSelected[num24]]; Color val = COMPARE_COLORS[num24 % COMPARE_COLORS.Length]; float num25 = num2 + (float)num23 * num8; if (flag) { float num26 = num8 * 0.32f; float num27 = num8 * 0.06f; float num28 = num25 + (num8 - (num26 * 2f + num27)) * 0.5f; float num29 = Mathf.Clamp(func(playerStatsData), 0f, num9); float num30 = Mathf.Clamp(func2(playerStatsData), 0f, num9); DrawBar($"CmpGrpA{num23}", num28, num5, num26, num29 / num9 * num7, new Color(val.r, val.g, val.b, 1f)); DrawBar($"CmpGrpB{num23}", num28 + num26 + num27, num5, num26, num30 / num9 * num7, new Color(val.r * 0.5f, val.g * 0.5f, val.b * 0.5f, 1f)); MakeGraphLabel($"CmpGrpVA{num23}", $"{func(playerStatsData):F1}", new Vector2(0f, 0f), new Vector2(num28 - 8f, num5 + num29 / num9 * num7 + 1f), new Vector2(num26 + 16f, 11f), 514); MakeGraphLabel($"CmpGrpVB{num23}", $"{func2(playerStatsData):F1}", new Vector2(0f, 0f), new Vector2(num28 + num26 + num27 - 8f, num5 + num30 / num9 * num7 + 1f), new Vector2(num26 + 16f, 11f), 514); } else { float num31 = num8 * 0.58f; float num32 = num25 + (num8 - num31) * 0.5f; float num33 = func(playerStatsData); float num34 = Mathf.Clamp(num33, 0f, num9); Color col = val; if (flag2 && num33 > 0f) { col = GradeColor((num33 - 1f) / 4f); } DrawBar($"CmpBar{num23}", num32, num5, num31, num34 / num9 * num7, col); string text5 = (flag2 ? num33.ToString("F2") : (metricName switch { "Keys / Sec" => num33.ToString("F1"), "Avg Game Length" => $"{num33:F1}m", "Total XP" => $"Lv {playerStatsData.level}", _ => FullNum(num33), })); MakeGraphLabel($"CmpBarV{num23}", "" + text5 + "", new Vector2(0f, 0f), new Vector2(num32 - 6f, num5 + num34 / num9 * num7 + 1f), new Vector2(num31 + 12f, 12f), 514); } MakeGraphLabel($"CmpBarName{num23}", "" + Trunc(playerStatsData.display_name, max) + "", new Vector2(0f, 0f), new Vector2(num25 - 4f, num5 - 18f), new Vector2(num8 + 8f, 16f), 514, 13f); } } private static void BuildCompareAchievementGrid(List idxs, float W, float H) { //IL_0016: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Unknown result type (might be due to invalid IL or missing references) //IL_049e: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) try { MakeGraphLabel("CmpAchTitle", "Achievement comparison", new Vector2(0f, 1f), new Vector2(16f, -4f), new Vector2(W - 20f, 18f), 513); bool flag = false; foreach (int idx in idxs) { string text = compareSelected[idx]; if (!ApiClient.CompareAchievements.ContainsKey(text)) { ApiClient.FetchAchievementsForCompare(text); flag = true; } } if (flag) { MakeGraphLabel("CmpAchLoad", "Loading achievements...", new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(W - 40f, 30f), 514); return; } List list = new List(); foreach (int idx2 in idxs) { foreach (string key in ApiClient.CompareAchievements[compareSelected[idx2]].Keys) { if (!list.Contains(key)) { list.Add(key); } } } list.Sort((string a, string b) => string.CompareOrdinal(AchName(a), AchName(b))); if (list.Count == 0) { MakeGraphLabel("CmpAchNone", "No achievement data.", new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(W - 40f, 30f), 514); return; } int num = (list.Count + 1) / 2; float num2 = (W - 36f) / 2f; float num3 = Mathf.Min(200f, num2 * 0.46f); float num4 = (num2 - num3 - 8f) / (float)Mathf.Max(1, idxs.Count); float num5 = -26f; float num6 = Mathf.Clamp((H - 66f) / (float)Mathf.Max(1, num), 20f, 28f); for (int num7 = 0; num7 < 2; num7++) { float num8 = 12f + (float)num7 * (num2 + 12f); int num9 = num7 * num; int num10 = Mathf.Min(list.Count, (num7 + 1) * num); if (num9 >= num10) { break; } for (int num11 = 0; num11 < idxs.Count; num11++) { int num12 = idxs[num11]; ApiClient.PlayerStatsData playerStatsData = compareStatsCache[compareSelected[num12]]; Color c = COMPARE_COLORS[num12 % COMPARE_COLORS.Length]; MakeGraphLabel($"CmpAchHdr{num7}_{num11}", "" + Trunc(playerStatsData.display_name, Mathf.Clamp((int)(num4 / 9f), 4, 16)) + "", new Vector2(0f, 1f), new Vector2(num8 + num3 + (float)num11 * num4, num5), new Vector2(num4, 16f), 514, 13f); } for (int num13 = num9; num13 < num10; num13++) { float num14 = num5 - 20f - (float)(num13 - num9) * num6; MakeGraphLabel($"CmpAchN{num13}", "" + Trunc(AchName(list[num13]), 24) + "", new Vector2(0f, 1f), new Vector2(num8, num14), new Vector2(num3, num6), 513, 13f); for (int num15 = 0; num15 < idxs.Count; num15++) { int num16 = idxs[num15]; Dictionary dictionary = ApiClient.CompareAchievements[compareSelected[num16]]; ApiClient.AchievementData value; bool flag2 = dictionary.TryGetValue(list[num13], out value) && value.unlocked; Color c2 = COMPARE_COLORS[num16 % COMPARE_COLORS.Length]; string text2 = (flag2 ? ("YES") : "-"); MakeGraphLabel($"CmpAchC{num13}_{num15}", text2, new Vector2(0f, 1f), new Vector2(num8 + num3 + (float)num15 * num4, num14), new Vector2(num4, num6), 514, 13f); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COMPARE] achievement grid failed: " + ex.Message)); } } private static string AchName(string key) { if (ApiClient.AchievementDisplayNames.TryGetValue(key, out var value) && !string.IsNullOrEmpty(value)) { return value; } string[] array = (key ?? "").Split('_'); for (int i = 0; i < array.Length; i++) { if (array[i].Length > 0) { array[i] = char.ToUpperInvariant(array[i][0]) + array[i].Substring(1); } } return string.Join(" ", array); } private static void BuildComparePieChart(List idxs, float W, float H) { //IL_0016: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Unknown result type (might be due to invalid IL or missing references) //IL_0662: Unknown result type (might be due to invalid IL or missing references) //IL_0671: Unknown result type (might be due to invalid IL or missing references) //IL_0680: Unknown result type (might be due to invalid IL or missing references) try { MakeGraphLabel("CmpPieTitle", "Region distribution", new Vector2(0f, 1f), new Vector2(16f, -4f), new Vector2(W - 20f, 18f), 513); List list = new List(); foreach (int idx in idxs) { ApiClient.PlayerStatsData playerStatsData = compareStatsCache[compareSelected[idx]]; if (playerStatsData.region_names == null) { continue; } foreach (string region_name in playerStatsData.region_names) { if (!list.Contains(region_name)) { list.Add(region_name); } } } for (int i = 0; i < list.Count; i++) { float num = -14f - (float)(i % 4) * 104f; float num2 = -4f - (float)(i / 4) * 17f; string text = ColorToHex(RegionColor(list[i])); MakeGraphLabel($"CmpPieLeg{i}", " " + list[i].ToUpperInvariant() + "", new Vector2(1f, 1f), new Vector2(num, num2), new Vector2(96f, 14f), 513, 13f); } int count = idxs.Count; int num3 = ((count <= 1) ? 1 : ((count <= 2) ? 2 : ((count <= 6) ? 3 : 4))); int num4 = (count + num3 - 1) / num3; float num5 = 30f + Mathf.Ceil((float)list.Count / 4f) * 17f; float num6 = 8f; float num7 = (W - 20f) / (float)num3; float num8 = (H - num5 - num6) / (float)Mathf.Max(1, num4); float num9 = Mathf.Max(26f, Mathf.Min(num7, num8) * 0.36f); bool flag = num3 <= 3; for (int j = 0; j < count; j++) { int num10 = idxs[j]; ApiClient.PlayerStatsData playerStatsData2 = compareStatsCache[compareSelected[num10]]; int num11 = j % num3; int num12 = j / num3; float num13 = 10f + (float)num11 * num7 + num7 * 0.5f; float num14 = H - num5 - (float)num12 * num8 - num8 * 0.5f; MakeGraphLabel($"CmpPieName{j}", "" + Trunc(playerStatsData2.display_name, 14) + "", new Vector2(0f, 0f), new Vector2(num13 - num7 * 0.5f, num14 + num9 + 4f), new Vector2(num7, 16f), 514, 14f); int num15 = 0; if (playerStatsData2.region_matches != null) { foreach (int region_match in playerStatsData2.region_matches) { num15 += region_match; } } if (playerStatsData2.region_names == null || num15 <= 0) { MakeGraphLabel($"CmpPieNo{j}", "no data", new Vector2(0f, 0f), new Vector2(num13 - 40f, num14 - 6f), new Vector2(80f, 12f), 514); continue; } DrawPieSlice($"CmpPieBdr{j}", num13, num14, num9 + 2.5f, 0f, 1f, new Color(0.1f, 0.11f, 0.14f, 1f)); float num16 = 0f; for (int k = 0; k < playerStatsData2.region_names.Count; k++) { int num17 = ((playerStatsData2.region_matches.Count > k) ? playerStatsData2.region_matches[k] : 0); if (num17 > 0) { float num18 = (float)num17 / (float)num15; DrawPieSlice($"CmpPie{j}_{k}", num13, num14, num9, num16, num18, RegionColor(playerStatsData2.region_names[k])); if (flag && num18 >= 0.07f) { float num19 = num16 + num18 * 0.5f; float num20 = MathF.PI / 2f - num19 * 2f * MathF.PI; float x = num13 + Mathf.Cos(num20) * num9; float y = num14 + Mathf.Sin(num20) * num9; float num21 = num13 + Mathf.Cos(num20) * (num9 + 20f); float num22 = num14 + Mathf.Sin(num20) * (num9 + 20f); DrawGraphSegment($"CmpPieLn{j}_{k}", x, y, num21, num22, new Color(0.8f, 0.8f, 0.8f, 0.7f), 1.5f); bool flag2 = Mathf.Cos(num20) >= 0f; int align = (flag2 ? 513 : 516); float num23 = (flag2 ? (num21 + 2f) : (num21 - 66f)); MakeGraphLabel($"CmpPieLbl{j}_{k}", $"{playerStatsData2.region_names[k].ToUpperInvariant()} {num18 * 100f:F0}%", new Vector2(0f, 0f), new Vector2(num23, num22 - 6f), new Vector2(64f, 12f), align); } num16 += num18; } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COMPARE] pie chart failed: " + ex.Message)); } } private static void BuildCompareCardGrid(string metricName) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)compareCardsContent == (Object)null || txtCompareCards == null) { return; } Transform val = compareCardsContent.transform.Find("CmpCardCols"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } if (compareSelected.Count == 0) { UIFactory.SetText(txtCompareCards, "Select players (left) to compare " + metricName + "."); ((Component)txtCompareCards).gameObject.SetActive(true); return; } ((Component)txtCompareCards).gameObject.SetActive(false); int num = ((compareSelected.Count <= 3) ? compareSelected.Count : ((compareSelected.Count <= 8) ? 2 : 3)); if (num < 1) { num = 1; } int num2 = (compareSelected.Count + num - 1) / num; GameObject val2 = new GameObject("CmpCardCols"); val2.transform.SetParent(compareCardsContent.transform, false); val2.AddComponent(); UIFactory.AddHLG(val2, 10f, 0, 0, 0, 0, forceExpandW: false, forceExpandH: false); GameObject[] array = (GameObject[])(object)new GameObject[num]; for (int i = 0; i < num; i++) { GameObject val3 = new GameObject($"CmpCol{i}"); val3.transform.SetParent(val2.transform, false); val3.AddComponent(); UIFactory.AddVLG(val3, 8f); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, 1f); array[i] = val3; } for (int j = 0; j < compareSelected.Count; j++) { int num3 = Math.Min(j / num2, num - 1); string key = compareSelected[j]; Color c = COMPARE_COLORS[j % COMPARE_COLORS.Length]; StringBuilder stringBuilder = new StringBuilder(); if (!compareStatsCache.TryGetValue(key, out var value) || value == null) { stringBuilder.Append("(loading...)"); } else { stringBuilder.Append("" + value.display_name + "\n"); if (metricName == "Worst Cards") { AppendCardList(stringBuilder, value.worst_card_names, value.worst_card_picks, value.worst_card_win_rates, "not enough data (4+ picks)"); } else { AppendCardList(stringBuilder, value.top_card_names, value.top_card_picks, value.top_card_win_rates, "no card data"); } } object obj = UIFactory.CreateText($"CmpCell{j}", array[num3].transform, stringBuilder.ToString(), 14f, C_DIM, 257, (Vector2?)new Vector2(250f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(obj, on: true); UIFactory.SetTextAutoHeight(obj); } } private static void BuildCompareMetricTable() { //IL_0090: 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_00e9: 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) if (txtCompareCards == null) { return; } string text = COMPARE_METRICS[Math.Max(0, Math.Min(compareMetric, COMPARE_METRICS.Length - 1))]; if (compareSelected.Count == 0) { UIFactory.SetText(txtCompareCards, "Select players (left) to compare " + text + "."); return; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < compareSelected.Count; i++) { string key = compareSelected[i]; Color c = COMPARE_COLORS[i % COMPARE_COLORS.Length]; if (!compareStatsCache.TryGetValue(key, out var value) || value == null) { stringBuilder.Append("(loading...)\n\n"); continue; } stringBuilder.Append("" + value.display_name + " "); switch (text) { case "Top Cards": stringBuilder.Append("\n"); AppendCardList(stringBuilder, value.top_card_names, value.top_card_picks, value.top_card_win_rates, "no card data"); break; case "Worst Cards": stringBuilder.Append("\n"); AppendCardList(stringBuilder, value.worst_card_names, value.worst_card_picks, value.worst_card_win_rates, "not enough card data (need 4+ picks)"); break; case "Hit / Block %": { string text2 = ((value.bullets_fired > 0) ? $"Hit {(float)value.bullets_hit * 100f / (float)value.bullets_fired:F1}% ({value.bullets_hit}/{value.bullets_fired})" : "Hit —"); string text3 = ((value.blocks_activated > 0) ? $"Block {(float)value.blocks_successful * 100f / (float)value.blocks_activated:F1}% ({value.blocks_successful}/{value.blocks_activated})" : "Block —"); stringBuilder.Append(text2 + " " + text3 + "\n"); break; } case "Avg Cards / Game": { float avg_cards_per_game = value.avg_cards_per_game; string arg = ((avg_cards_per_game > 0f && avg_cards_per_game <= 2f) ? "#00FF00" : ((avg_cards_per_game <= 3f) ? "#AAAAAA" : "#FF6666")); stringBuilder.Append((avg_cards_per_game > 0f) ? $"{avg_cards_per_game:F2} cards/game (lower = stronger)\n" : "no data\n"); break; } case "Avg FPS": stringBuilder.Append((value.avg_fps > 0) ? $"{value.avg_fps} avg fps\n" : "no fps data\n"); break; case "Peak Elo": stringBuilder.Append($"{value.peak_rating:F0} peak (now {value.rating:F0})\n"); break; case "Total XP": stringBuilder.Append($"{value.total_xp:N0} XP (Lv {value.level})\n"); break; case "Achievements": { int num4 = ((ApiClient.AchievementDefs != null) ? ApiClient.AchievementDefs.Count : 0); stringBuilder.Append((num4 > 0) ? $"{value.achievements_unlocked}/{num4} unlocked ({value.achievements_unlocked * 100 / Math.Max(1, num4)}%)\n" : $"{value.achievements_unlocked} unlocked\n"); break; } case "Region Time": stringBuilder.Append("\n"); if (value.region_names != null && value.region_names.Count > 0) { int num = 0; foreach (int region_match in value.region_matches) { num += region_match; } for (int j = 0; j < value.region_names.Count && j < 8; j++) { int num2 = ((value.region_matches.Count > j) ? value.region_matches[j] : 0); int num3 = ((num > 0) ? (num2 * 100 / num) : 0); stringBuilder.Append($" {value.region_names[j].ToUpperInvariant()} {num3}% ({num2})\n"); } } else { stringBuilder.Append(" no region data\n"); } break; default: stringBuilder.Append("\n"); break; } stringBuilder.Append("\n"); } UIFactory.SetText(txtCompareCards, stringBuilder.ToString()); } private static void AppendCardList(StringBuilder sb, List names, List picks, List wrs, string emptyMsg) { if (names != null && names.Count > 0) { for (int i = 0; i < names.Count && i < 8; i++) { string text = ((picks != null && picks.Count > i) ? $" ({picks[i]}x)" : ""); float num = ((wrs != null && wrs.Count > i) ? (wrs[i] * 100f) : 0f); string text2 = ((num >= 55f) ? "#00FF00" : ((num <= 45f) ? "#FF6666" : "#AAAAAA")); sb.Append($" {names[i]}{text} {num:F0}%\n"); } } else { sb.Append(" " + emptyMsg + "\n"); } } private static string GetAchievementText() { Dictionary selectedPlayerAchievements = ApiClient.SelectedPlayerAchievements; if (selectedPlayerAchievements == null) { return ""; } int num = 0; string text = "\nAchievements:\n"; foreach (KeyValuePair achievementDef in ApiClient.AchievementDefs) { bool flag = selectedPlayerAchievements.ContainsKey(achievementDef.Key) && selectedPlayerAchievements[achievementDef.Key].unlocked; if (flag) { num++; } string text2 = (flag ? "[X]" : "[ ]"); string text3 = (flag ? "#FFFFFF" : "#666666"); text = text + " " + text2 + " " + achievementDef.Value[0] + "\n"; } return text + $"\n {num} / {ApiClient.AchievementDefs.Count} unlocked"; } private static string ModeHistoryDate(string iso) { if (string.IsNullOrEmpty(iso)) { return ""; } if (DateTimeOffset.TryParse(iso, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var result)) { return result.ToLocalTime().ToString("M/d", CultureInfo.InvariantCulture); } return ""; } private static string ModeHistoryDelta(float value) { string text = ((value > 0f) ? "#00FF00" : ((value < 0f) ? "#FF6666" : "#AAAAAA")); return "" + value.ToString("+0.0;-0.0;0.0", CultureInfo.InvariantCulture) + ""; } private static string BuildPlayerModeHistoryText(string steamId) { StringBuilder stringBuilder = new StringBuilder(); if (ApiClient.CachedPlayerTeamHistory.TryGetValue(steamId, out var value) && value != null && value.Count > 0) { stringBuilder.Append("\n2v2 History\n"); foreach (ApiClient.PlayerTeamHistoryEntry item in value) { string value2 = (item.won ? "W" : "L"); string value3 = ((item.opponents != null && item.opponents.Count > 0) ? FfaSafeRich(Trunc(item.opponents[0] ?? "?", 12)) : "?"); string value4 = ((item.opponents != null && item.opponents.Count > 1) ? FfaSafeRich(Trunc(item.opponents[1] ?? "?", 12)) : "?"); string value5 = (item.has_rating_change ? (" " + ModeHistoryDelta(item.rating_change)) : ""); stringBuilder.Append(" ").Append(value2).Append(' ') .Append(item.score ?? "?") .Append(" w/ ") .Append(FfaSafeRich(Trunc(item.mate ?? "?", 12))) .Append(" vs ") .Append(value3) .Append(" + ") .Append(value4) .Append(value5) .Append(" ") .Append(ModeHistoryDate(item.completed_at)) .Append("\n"); } } if (ApiClient.CachedPlayerOvtHistory.TryGetValue(steamId, out var value6) && value6 != null && value6.Count > 0) { stringBuilder.Append("\n1v2 History\n"); string b = selectedStats?.display_name ?? ""; foreach (ApiClient.PlayerOvtHistoryEntry item2 in value6) { string value7 = (item2.won ? "W" : "L"); string value8; if (string.Equals(item2.role, "solo", StringComparison.OrdinalIgnoreCase)) { string text = ((item2.duo != null && item2.duo.Count > 0) ? FfaSafeRich(Trunc(item2.duo[0] ?? "?", 12)) : "?"); string text2 = ((item2.duo != null && item2.duo.Count > 1) ? FfaSafeRich(Trunc(item2.duo[1] ?? "?", 12)) : "?"); value8 = "as SOLO vs " + text + " + " + text2; } else { string s = "?"; if (item2.duo != null) { foreach (string item3 in item2.duo) { if (!string.Equals(item3, b, StringComparison.OrdinalIgnoreCase)) { s = item3 ?? "?"; break; } } } value8 = "as DUO (w/ " + FfaSafeRich(Trunc(s, 12)) + ") vs " + FfaSafeRich(Trunc(item2.solo ?? "?", 12)); } int num = item2.gold_gained + item2.series_gold_gained; string value9 = ((num > 0) ? $" +{num}g" : ""); stringBuilder.Append(" ").Append(value7).Append(' ') .Append(item2.score ?? "?") .Append(' ') .Append(value8) .Append(value9) .Append(" ") .Append(ModeHistoryDate(item2.ended_at)) .Append("\n"); } } if (ApiClient.CachedPlayerFfaHistory.TryGetValue(steamId, out var value10) && value10 != null && value10.Count > 0) { stringBuilder.Append("\nFFA History\n"); foreach (ApiClient.PlayerFfaHistoryEntry item4 in value10) { string value11 = ((item4.placement == 1) ? "" : ""); stringBuilder.Append(" ").Append(value11).Append('#') .Append(item4.placement) .Append(" of ") .Append(item4.player_count); if (item4.has_rating_change) { stringBuilder.Append(" ").Append(ModeHistoryDelta(item4.rating_change)); } else { stringBuilder.Append(" --"); } stringBuilder.Append(" ").Append(item4.kills).Append("k ") .Append(ModeHistoryDate(item4.ended_at)) .Append(""); List participants = item4.participants; if (participants != null && participants.Count > 0) { stringBuilder.Append("\nvs "); for (int i = 0; i < participants.Count; i++) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(FfaSafeRich(Trunc(participants[i] ?? "?", 16))); } stringBuilder.Append(""); } stringBuilder.Append('\n'); } } return stringBuilder.ToString(); } private static string BuildViewHistoryText(out string historyPart) { historyPart = ""; if (string.IsNullOrEmpty(selectedSteamId)) { return ""; } List list = selectedViewHistory; if (list == null) { return "\nLoading match history...\n"; } StringBuilder stringBuilder = new StringBuilder(); string myId = MatchTracker.LocalSteamId; bool flag = selectedSteamId == myId; string text = Trunc(selectedStats?.display_name ?? "Them", 12); int num = 0; if (!flag && !string.IsNullOrEmpty(myId) && myId != "unknown") { List list2 = list.FindAll((ApiClient.MatchHistoryEntry m) => m.opponent_steam_id == myId && !string.IsNullOrEmpty(m.series_id) && m.series_id != "null" && m.is_ranked); if (list2.Count > 0) { List list3 = GroupBySeries(list2); list3.RemoveAll((SGroup g) => g.matches == null || g.matches.Count == 0); num = list3.Count; if (num > 0) { int num2 = (h2hSeriesTotalPages = (num + 2 - 1) / 2); if (h2hSeriesPage < 0) { h2hSeriesPage = 0; } if (h2hSeriesPage > num2 - 1) { h2hSeriesPage = num2 - 1; } int num3 = h2hSeriesPage * 2; int num4 = Math.Min(num3 + 2, num); string text2 = ((num2 > 1) ? $" (page {h2hSeriesPage + 1}/{num2}, {num} total)" : ""); stringBuilder.Append("\nRanked Series vs You" + text2 + "\n"); for (int num5 = num3; num5 < num4; num5++) { SGroup sGroup = list3[num5]; ApiClient.MatchHistoryEntry matchHistoryEntry = sGroup.matches[0]; string text3 = matchHistoryEntry.series_score ?? "?-?"; string text4 = ""; try { if (!string.IsNullOrEmpty(matchHistoryEntry.ended_at) && matchHistoryEntry.ended_at.Length >= 10) { text4 = DateTime.Parse(matchHistoryEntry.ended_at).ToString("M/d/yy"); } } catch { } bool flag2 = false; bool flag3 = false; try { string[] array = text3.Split('-'); int num6 = int.Parse(array[0]); int num7 = int.Parse(array[1]); flag2 = num6 >= 2 || num7 >= 2; flag3 = num7 > num6; } catch { } string text5 = ((!flag2) ? "in progress" : (flag3 ? "WON" : "LOST")); stringBuilder.Append(" " + text5 + " " + text3 + " their side " + text4 + "\n"); foreach (ApiClient.MatchHistoryEntry match in sGroup.matches) { string text6 = ((!match.won) ? "W" : "L"); string text7 = ""; try { if (!string.IsNullOrEmpty(match.ended_at) && match.ended_at.Length >= 10) { text7 = DateTime.Parse(match.ended_at).ToString("M/d"); } } catch { } stringBuilder.Append($" {text6} {match.opponent_rounds_won}-{match.player_rounds_won} {text7}\n"); if (!string.IsNullOrEmpty(match.opp_cards_display)) { stringBuilder.Append(" You: " + FormatCardLine(match.opp_cards_display) + "\n"); } if (!string.IsNullOrEmpty(match.cards_display)) { stringBuilder.Append(" " + text + ": " + FormatCardLine(match.cards_display) + "\n"); } } } } } } if ((Object)(object)h2hPager != (Object)null) { bool flag4 = num > 2; h2hPager.SetActive(flag4); if (flag4) { if (txtH2hPage != null) { UIFactory.SetText(txtH2hPage, $"{h2hSeriesPage + 1}/{h2hSeriesTotalPages}"); } if ((Object)(object)h2hPrev != (Object)null) { h2hPrev.SetActive(h2hSeriesPage > 0); } if ((Object)(object)h2hNext != (Object)null) { h2hNext.SetActive(h2hSeriesPage < h2hSeriesTotalPages - 1); } } } StringBuilder stringBuilder2 = new StringBuilder(); List list4 = list.FindAll((ApiClient.MatchHistoryEntry m) => m.is_ranked && !string.IsNullOrEmpty(m.series_id) && m.series_id != "null"); if (list4.Count > 0) { List list5 = GroupBySeries(list4); stringBuilder2.Append("\nRanked History (recent series)\n"); int num8 = 0; foreach (SGroup item in list5) { if (num8 >= 12) { break; } if (item.matches == null || item.matches.Count == 0) { continue; } ApiClient.MatchHistoryEntry matchHistoryEntry2 = item.matches[0]; string text8 = matchHistoryEntry2.series_score ?? "?-?"; bool flag5 = false; bool flag6 = false; try { string[] array2 = text8.Split('-'); int num9 = int.Parse(array2[0]); int num10 = int.Parse(array2[1]); flag5 = num9 >= 2 || num10 >= 2; flag6 = num9 > num10; } catch { } string text9 = Trunc(matchHistoryEntry2.opponent_name ?? "?", 14); string text10 = ""; try { if (!string.IsNullOrEmpty(matchHistoryEntry2.ended_at) && matchHistoryEntry2.ended_at.Length >= 10) { text10 = DateTime.Parse(matchHistoryEntry2.ended_at).ToString("M/d"); } } catch { } string text11 = ((!flag5) ? "-" : (flag6 ? "W" : "L")); string text12 = ((flag5 && matchHistoryEntry2.series_rating_change != 0f) ? string.Format(" {1}{2:F0}", (matchHistoryEntry2.series_rating_change > 0f) ? "#00FF00" : "#FF6666", (matchHistoryEntry2.series_rating_change > 0f) ? "+" : "", matchHistoryEntry2.series_rating_change) : ""); stringBuilder2.Append(" " + text11 + " " + text8 + " vs " + text9 + text12 + " " + text10 + "\n"); num8++; } } else { stringBuilder2.Append("\nRanked History: no ranked series yet\n"); } stringBuilder2.Append(BuildPlayerModeHistoryText(selectedSteamId)); historyPart = stringBuilder2.ToString(); return stringBuilder.ToString(); } private static void RefreshCardStats() { //IL_0113: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0703: Unknown result type (might be due to invalid IL or missing references) //IL_0708: Unknown result type (might be due to invalid IL or missing references) //IL_06fc: Unknown result type (might be due to invalid IL or missing references) //IL_06f5: Unknown result type (might be due to invalid IL or missing references) //IL_075f: Unknown result type (might be due to invalid IL or missing references) //IL_07d5: Unknown result type (might be due to invalid IL or missing references) //IL_086a: Unknown result type (might be due to invalid IL or missing references) //IL_0842: Unknown result type (might be due to invalid IL or missing references) //IL_083b: Unknown result type (might be due to invalid IL or missing references) //IL_0834: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[7] { "Tier", "Card", "Rarity", "Picks", "Wins", "WR%", "Pass%" }; string[] array2 = new string[7] { "tier", "card_name", "card_rarity", "times_picked", "wins_with_card", "win_rate", "pass_rate" }; if (cardSortTexts != null) { for (int i = 0; i < 7 && i < cardSortTexts.Length; i++) { if (cardSortTexts[i] != null) { string text = ((!(cardSort == array2[i])) ? "" : (cardSortDesc ? " v" : " ^")); UIFactory.SetText(cardSortTexts[i], array[i] + text); UIFactory.SetColor(cardSortTexts[i], (cardSort == array2[i]) ? C_WHITE : C_LABEL); if (cardSortBtns != null && i < cardSortBtns.Length) { UIFactory.SetImageColor(cardSortBtns[i], (cardSort == array2[i]) ? C_TABACT : C_TAB); } } } } List cachedCardStats = ApiClient.CachedCardStats; foreach (CardRow cardRow2 in cardRows) { cardRow2.root.SetActive(false); } if (cachedCardStats == null && Time.realtimeSinceStartup - _cardStatsAutoFetchAt > 8f) { _cardStatsAutoFetchAt = Time.realtimeSinceStartup; ApiClient.FetchCardStats(200, MatchTracker.LocalSteamId); } if (!_tierFiltersLoaded.Contains(cardFilter) && Time.realtimeSinceStartup - _tierAutoFetchAt > 8f) { _tierAutoFetchAt = Time.realtimeSinceStartup; LoadCardTiersForCurrentFilter(); } if (cachedCardStats == null || cachedCardStats.Count == 0) { return; } List list = new List(); Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (ApiClient.CardStatData item in cachedCardStats) { string key = (item.card_name ?? "?").ToLower().Replace(" ", ""); if (dictionary.ContainsKey(key)) { ApiClient.CardStatData cardStatData = list[dictionary[key]]; cardStatData.times_picked += item.times_picked; cardStatData.wins_with_card += item.wins_with_card; cardStatData.win_rate = ((cardStatData.times_picked > 0) ? ((float)cardStatData.wins_with_card / (float)cardStatData.times_picked) : 0f); cardStatData.times_offered = Math.Max(cardStatData.times_offered, item.times_offered); if (item.times_offered > 0) { cardStatData.pass_rate = item.pass_rate; } if ((cardStatData.card_rarity == null || cardStatData.card_rarity == "Unknown") && item.card_rarity != null && item.card_rarity != "Unknown") { cardStatData.card_rarity = item.card_rarity; } } else { dictionary[key] = list.Count; list.Add(new ApiClient.CardStatData { card_name = item.card_name, card_rarity = item.card_rarity, times_picked = item.times_picked, wins_with_card = item.wins_with_card, win_rate = item.win_rate, times_offered = item.times_offered, pass_rate = item.pass_rate }); } } switch (cardSort) { case "tier": list.Sort(delegate(ApiClient.CardStatData a, ApiClient.CardStatData b) { string value3; int value2 = TierRank(cardTierMap.TryGetValue(CardTierKey(cardFilter, a.card_name), out value3) ? value3 : ""); string value5; int value4 = TierRank(cardTierMap.TryGetValue(CardTierKey(cardFilter, b.card_name), out value5) ? value5 : ""); return cardSortDesc ? value2.CompareTo(value4) : value4.CompareTo(value2); }); break; case "card_name": list.Sort((ApiClient.CardStatData a, ApiClient.CardStatData b) => cardSortDesc ? string.Compare(b.card_name, a.card_name, StringComparison.OrdinalIgnoreCase) : string.Compare(a.card_name, b.card_name, StringComparison.OrdinalIgnoreCase)); break; case "card_rarity": list.Sort((ApiClient.CardStatData a, ApiClient.CardStatData b) => cardSortDesc ? string.Compare(b.card_rarity, a.card_rarity, StringComparison.OrdinalIgnoreCase) : string.Compare(a.card_rarity, b.card_rarity, StringComparison.OrdinalIgnoreCase)); break; case "times_picked": list.Sort((ApiClient.CardStatData a, ApiClient.CardStatData b) => cardSortDesc ? b.times_picked.CompareTo(a.times_picked) : a.times_picked.CompareTo(b.times_picked)); break; case "wins_with_card": list.Sort((ApiClient.CardStatData a, ApiClient.CardStatData b) => cardSortDesc ? b.wins_with_card.CompareTo(a.wins_with_card) : a.wins_with_card.CompareTo(b.wins_with_card)); break; case "win_rate": list.Sort((ApiClient.CardStatData a, ApiClient.CardStatData b) => cardSortDesc ? b.win_rate.CompareTo(a.win_rate) : a.win_rate.CompareTo(b.win_rate)); break; case "pass_rate": list.Sort((ApiClient.CardStatData a, ApiClient.CardStatData b) => cardSortDesc ? b.pass_rate.CompareTo(a.pass_rate) : a.pass_rate.CompareTo(b.pass_rate)); break; default: list.Sort((ApiClient.CardStatData a, ApiClient.CardStatData b) => cardSortDesc ? b.times_picked.CompareTo(a.times_picked) : a.times_picked.CompareTo(b.times_picked)); break; } for (int num = 0; num < list.Count && num < cardRows.Count; num++) { ApiClient.CardStatData cardStatData2 = list[num]; CardRow cardRow = cardRows[num]; float num2 = cardStatData2.win_rate * 100f; Color c = ((num2 >= 55f) ? C_GREEN : ((num2 <= 45f) ? C_RED : C_WHITE)); cardRow.cardName = cardStatData2.card_name; UIFactory.SetText(cardRow.txtName, cardStatData2.card_name ?? "?"); string text2 = cardStatData2.card_rarity ?? "Unknown"; UIFactory.SetText(cardRow.txtRarity, text2); UIFactory.SetColor(cardRow.txtRarity, GetRarityColor(text2)); UIFactory.SetText(cardRow.txtPicks, $"{cardStatData2.times_picked}"); UIFactory.SetText(cardRow.txtWins, $"{cardStatData2.wins_with_card}"); UIFactory.SetText(cardRow.txtWR, $"{num2:F0}%"); UIFactory.SetColor(cardRow.txtWR, c); if (cardStatData2.times_offered > 0) { float num3 = cardStatData2.pass_rate * 100f; UIFactory.SetText(cardRow.txtPass, $"{num3:F0}%"); UIFactory.SetColor(cardRow.txtPass, (num3 >= 70f) ? C_RED : ((num3 <= 30f) ? C_GREEN : C_LABEL)); } else { UIFactory.SetText(cardRow.txtPass, "-"); UIFactory.SetColor(cardRow.txtPass, C_DIM); } string key2 = CardTierKey(cardFilter, cardStatData2.card_name); string value; string tierLetter = (cardTierMap.TryGetValue(key2, out value) ? value : ""); ApplyRowTierVisuals(cardRow, tierLetter); cardRow.root.SetActive(true); } static int TierRank(string tier) { if (string.IsNullOrEmpty(tier)) { return 99; } return tier switch { "S" => 0, "A" => 1, "B" => 2, "C" => 3, "D" => 4, "E" => 5, "F" => 6, _ => 99, }; } } private static void ApplyRowTierVisuals(CardRow row, string tierLetter) { //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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_005c: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(tierLetter)) { UIFactory.SetText(row.txtTier, "-"); UIFactory.SetImageColor(row.tierBtn, new Color(0.18f, 0.2f, 0.24f, 0.85f)); UIFactory.SetImageColor(row.hl, new Color(0f, 0f, 0f, 0f)); } else { UIFactory.SetText(row.txtTier, "" + tierLetter + ""); Color tierColor = GetTierColor(tierLetter); UIFactory.SetImageColor(row.tierBtn, tierColor); UIFactory.SetImageColor(row.hl, new Color(tierColor.r, tierColor.g, tierColor.b, 0.25f)); } } private static void CycleCardTierInPlace(CardRow row, string cardName) { if (!string.IsNullOrEmpty(cardName)) { string filter = ((cardFilter == 1) ? "ranked" : ((cardFilter == 2) ? "casual" : "all")); string key = CardTierKey(cardFilter, cardName); string value2; string value = (cardTierMap.TryGetValue(key, out value2) ? value2 : ""); int num = Array.IndexOf(TIER_CYCLE, value); if (num < 0) { num = 0; } string text = TIER_CYCLE[(num + 1) % TIER_CYCLE.Length]; cardTierMap[key] = text; ApiClient.SetCardTier(MatchTracker.LocalSteamId, cardName, filter, text); ApplyRowTierVisuals(row, text); } } private static Color GetTierColor(string t) { //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: 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) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) return (Color)(t switch { "S" => new Color(0.95f, 0.3f, 0.3f, 0.9f), "A" => new Color(1f, 0.55f, 0.22f, 0.9f), "B" => new Color(0.95f, 0.85f, 0.3f, 0.9f), "C" => new Color(0.45f, 0.85f, 0.45f, 0.9f), "D" => new Color(0.45f, 0.7f, 0.95f, 0.9f), "E" => new Color(0.65f, 0.55f, 0.95f, 0.9f), "F" => new Color(0.55f, 0.55f, 0.55f, 0.9f), _ => new Color(0.18f, 0.2f, 0.24f, 0.85f), }); } private static string BuildCellStatLine(string cardName) { try { if (string.IsNullOrEmpty(cardName)) { return ""; } string text = CardRarityLookup.GetCanonicalName(cardName) ?? cardName; string lcA = (cardName ?? "").ToLowerInvariant().Replace(" ", ""); string lcB = text.ToLowerInvariant().Replace(" ", ""); Component val = null; Type type = (from a in AppDomain.CurrentDomain.GetAssemblies() select a.GetType("CardChoice")).FirstOrDefault((Type t) => t != null); if (type != null) { object obj = type.GetField("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); Array arr = type.GetField("cards", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj) as Array; val = MatchOne(arr); } if ((Object)(object)val == (Object)null) { val = MatchOne(Resources.FindObjectsOfTypeAll()); } if ((Object)(object)val == (Object)null) { return BuildStatBlockFromFallback(cardName, 8); } if (!((((object)val).GetType().GetField("cardStats", BindingFlags.Instance | BindingFlags.Public) ?? ((object)val).GetType().GetField("stats", BindingFlags.Instance | BindingFlags.Public))?.GetValue(val) is Array { Length: not 0 } array)) { return BuildStatBlockFromFallback(cardName, 8); } StringBuilder stringBuilder = new StringBuilder(); int num = 0; for (int num2 = 0; num2 < array.Length; num2++) { if (num >= 8) { break; } object value = array.GetValue(num2); if (value == null) { continue; } Type type2 = value.GetType(); string text2 = ((type2.GetField("stat", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value) as string) ?? "").Trim(); string value2 = ((type2.GetField("amount", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value) as string) ?? "").Trim(); bool flag = !(type2.GetField("positive", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value) is bool flag2) || flag2; if (!string.IsNullOrEmpty(text2) || !string.IsNullOrEmpty(value2)) { string value3 = (flag ? "#88FF88" : "#FF8888"); if (stringBuilder.Length > 0) { stringBuilder.Append("\n"); } string text3 = NormalizeStatLabel(text2); string value4 = ((text3.Length > 16) ? (text3.Substring(0, 14) + "…") : text3); stringBuilder.Append("") .Append(value2) .Append(" ") .Append(value4); num++; } } return stringBuilder.ToString(); Component MatchOne(IEnumerable enumerable) { if (enumerable == null) { return null; } foreach (object item in enumerable) { Component val2 = (Component)((item is Component) ? item : null); if (!((Object)(object)val2 == (Object)null)) { string text4 = ((Object)val2.gameObject).name?.Replace("(Clone)", "").Trim() ?? ""; string text5 = (((object)val2).GetType().GetField("cardName", BindingFlags.Instance | BindingFlags.Public)?.GetValue(val2) as string) ?? ""; if (text4.ToLowerInvariant().Replace(" ", "") == lcA || text4.ToLowerInvariant().Replace(" ", "") == lcB || text5.ToLowerInvariant().Replace(" ", "") == lcA || text5.ToLowerInvariant().Replace(" ", "") == lcB) { return val2; } } } return null; } } catch { return ""; } } public static void ExportCardTierList() { if ((Object)(object)Plugin.Instance == (Object)null) { return; } try { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ExportTierListCoroutine()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TIER-EXPORT] failed: " + ex.Message)); } } private static IEnumerator ExportTierListCoroutine() { if ((Object)(object)tierExportPanel != (Object)null) { Object.Destroy((Object)(object)tierExportPanel); } tierExportPanel = new GameObject("CR_TierExport"); ((Object)tierExportPanel).hideFlags = (HideFlags)61; tierExportPanel.transform.position = new Vector3(50000f, 50000f, 0f); Component canvasComp = tierExportPanel.AddComponent(UIFactory.tCanvas); try { PropertyInfo rmProp = UIFactory.tCanvas.GetProperty("renderMode", BindingFlags.Instance | BindingFlags.Public); if (rmProp != null) { rmProp.SetValue(canvasComp, Enum.ToObject(rmProp.PropertyType, 2)); } PropertyInfo sortProp = UIFactory.tCanvas.GetProperty("sortingOrder", BindingFlags.Instance | BindingFlags.Public); if (sortProp != null) { sortProp.SetValue(canvasComp, 30000); } } catch { } RectTransform rootRT = tierExportPanel.GetComponent(); if ((Object)(object)rootRT == (Object)null) { rootRT = tierExportPanel.AddComponent(); } rootRT.sizeDelta = new Vector2(3000f, 6000f); ((Transform)rootRT).localScale = Vector3.one; GameObject bg = UIFactory.CreatePanel("BG", tierExportPanel.transform, new Color(0.07f, 0.08f, 0.1f, 1f)); RectTransform bgRT = bg.GetComponent(); bgRT.anchorMin = Vector2.zero; bgRT.anchorMax = Vector2.one; bgRT.offsetMin = Vector2.zero; bgRT.offsetMax = Vector2.zero; UIFactory.AddVLG(bg, 14f, 24, 24, 18, 18); try { Type csfType = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly asm in assemblies) { csfType = asm.GetType("UnityEngine.UI.ContentSizeFitter"); if (csfType != null) { break; } } if (csfType != null) { Component csf = bg.AddComponent(csfType); PropertyInfo ft = csfType.GetProperty("verticalFit", BindingFlags.Instance | BindingFlags.Public); if (ft != null) { ft.SetValue(csf, Enum.ToObject(ft.PropertyType, 2)); } } } catch { } string filterStr = ((cardFilter == 1) ? "Ranked" : ((cardFilter == 2) ? "Casual" : "All")); UIFactory.CreateText("TXTitle", bg.transform, "Sid's Competitive Rounds · Card Tier List (" + filterStr + ")", 36f, C_WHITE, 513, (Vector2?)new Vector2(2900f, 52f), richText: true, raycastTarget: false); List cards = ApiClient.CachedCardStats ?? new List(); List merged = new List(); Dictionary seen = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (ApiClient.CardStatData c in cards) { string key = (c.card_name ?? "?").ToLower().Replace(" ", ""); if (seen.ContainsKey(key)) { ApiClient.CardStatData e = merged[seen[key]]; e.times_picked += c.times_picked; e.wins_with_card += c.wins_with_card; e.win_rate = ((e.times_picked > 0) ? ((float)e.wins_with_card / (float)e.times_picked) : 0f); if ((e.card_rarity == null || e.card_rarity == "Unknown") && !string.IsNullOrEmpty(c.card_rarity) && c.card_rarity != "Unknown") { e.card_rarity = c.card_rarity; } } else { seen[key] = merged.Count; merged.Add(new ApiClient.CardStatData { card_name = c.card_name, card_rarity = c.card_rarity, times_picked = c.times_picked, wins_with_card = c.wins_with_card, win_rate = c.win_rate, times_offered = c.times_offered, pass_rate = c.pass_rate }); } } string[] tierOrder = new string[8] { "S", "A", "B", "C", "D", "E", "F", "" }; Dictionary> byTier = new Dictionary>(); string[] array = tierOrder; foreach (string t in array) { byTier[t] = new List(); } foreach (ApiClient.CardStatData c2 in merged) { string tv; string t2 = (cardTierMap.TryGetValue(CardTierKey(cardFilter, c2.card_name), out tv) ? tv : ""); if (!byTier.ContainsKey(t2)) { t2 = ""; } byTier[t2].Add(c2); tv = null; } int cardsAreaW = 2808; int cellsPerRow = Math.Max(3, cardsAreaW / 234); PropertyInfo pImgSprite = UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public); PropertyInfo pImgPreserve = UIFactory.tImage.GetProperty("preserveAspect", BindingFlags.Instance | BindingFlags.Public); PropertyInfo pImgColor = UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public); string[] array2 = tierOrder; foreach (string tier in array2) { List list = byTier[tier]; if (list.Count == 0) { continue; } Color tc = (Color)(string.IsNullOrEmpty(tier) ? new Color(0.3f, 0.32f, 0.36f, 0.95f) : GetTierColor(tier)); int rowsNeeded = (list.Count + cellsPerRow - 1) / cellsPerRow; int tierBlockH = rowsNeeded * 416 + 12; GameObject tierGO = new GameObject("T_" + tier); tierGO.transform.SetParent(bg.transform, false); tierGO.AddComponent(); UIFactory.AddHLG(tierGO, 8f, 8, 8, 6, 6); float prefH = tierBlockH; UIFactory.AddLE(tierGO, -1f, tierBlockH, -1f, prefH, -1f, 0f); GameObject badge = UIFactory.CreatePanel("B_" + tier, tierGO.transform, tc); prefH = tierBlockH - 12; UIFactory.AddLE(badge, 130f, tierBlockH - 12, 130f, prefH, 0f); UIFactory.CreateText("BL", badge.transform, "" + (string.IsNullOrEmpty(tier) ? "Unranked" : tier) + "", string.IsNullOrEmpty(tier) ? 36f : 84f, Color.black, 514, (Vector2?)new Vector2(130f, (float)(tierBlockH - 12)), richText: true, raycastTarget: false); GameObject cardsCol = new GameObject("R_" + tier); cardsCol.transform.SetParent(tierGO.transform, false); cardsCol.AddComponent(); UIFactory.AddVLG(cardsCol, 6f, 4, 4); prefH = tierBlockH - 12; UIFactory.AddLE(cardsCol, -1f, tierBlockH - 12, -1f, prefH, 1f, 0f); GameObject curRow = null; int curIdx = 0; foreach (ApiClient.CardStatData c3 in list) { if ((Object)(object)curRow == (Object)null || curIdx >= cellsPerRow) { curRow = new GameObject($"row{list.IndexOf(c3)}"); curRow.transform.SetParent(cardsCol.transform, false); curRow.AddComponent(); UIFactory.AddHLG(curRow, 8f); UIFactory.AddLE(curRow, -1f, 410f, -1f, 410f, -1f, 0f); curIdx = 0; } GameObject cell = UIFactory.CreatePanel("C_" + c3.card_name, curRow.transform, new Color(tc.r, tc.g, tc.b, 0.22f)); UIFactory.AddVLG(cell, 4f, 4, 4, 6, 6); UIFactory.AddLE(cell, 226f, 410f, 226f, 410f, 0f); Sprite sp = CardImageLoader.GetSprite(c3.card_name); GameObject imgGO = new GameObject("Img"); imgGO.transform.SetParent(cell.transform, false); imgGO.AddComponent(); Component imgComp = imgGO.AddComponent(UIFactory.tImage); if ((Object)(object)sp != (Object)null) { pImgSprite?.SetValue(imgComp, sp); pImgPreserve?.SetValue(imgComp, true); pImgColor?.SetValue(imgComp, Color.white); } else { pImgColor?.SetValue(imgComp, (object)new Color(0.2f, 0.22f, 0.26f, 1f)); UIFactory.CreateText("Miss", imgGO.transform, "" + Trunc(c3.card_name ?? "?", 14) + "", 22f, C_WHITE, 514, (Vector2?)new Vector2(212f, 60f), richText: true, raycastTarget: false); } UIFactory.AddLE(imgGO, 220f, 330f, 220f, 330f, 0f, 0f); object playedTxt = UIFactory.CreateText("P", cell.transform, $"{c3.times_picked} played", 26f, C_WHITE, 514, (Vector2?)new Vector2(218f, 30f), richText: true, raycastTarget: false); UIFactory.SetBold(playedTxt, b: true); float wr = c3.win_rate * 100f; string wrCol = ((wr >= 55f) ? "#88FF88" : ((wr <= 45f) ? "#FF8888" : "#FFFFFF")); object wrTxt = UIFactory.CreateText("W", cell.transform, $"{wr:F0}% won", 26f, C_WHITE, 514, (Vector2?)new Vector2(218f, 30f), richText: true, raycastTarget: false); UIFactory.SetBold(wrTxt, b: true); curIdx++; } while ((Object)(object)curRow != (Object)null && curIdx < cellsPerRow) { GameObject pad = new GameObject("pad"); pad.transform.SetParent(curRow.transform, false); pad.AddComponent(); UIFactory.AddLE(pad, 226f, -1f, 226f, -1f, 0f); curIdx++; } } string steamName = MatchTracker.LocalDisplayName; if (string.IsNullOrEmpty(steamName) || steamName == "unknown") { steamName = "Anonymous"; } GameObject wm = new GameObject("WM"); wm.transform.SetParent(bg.transform, false); wm.AddComponent(); UIFactory.AddHLG(wm, 0f); UIFactory.AddLE(wm, -1f, -1f, -1f, 50f, -1f, 0f); UIFactory.CreateText("WMSteam", wm.transform, "" + steamName + "'s tier list", 26f, C_DIM, 513, (Vector2?)new Vector2(1400f, 50f), richText: true, raycastTarget: false); GameObject wmSp = new GameObject("S"); wmSp.transform.SetParent(wm.transform, false); wmSp.AddComponent(); UIFactory.AddLE(wmSp, -1f, -1f, -1f, -1f, 1f); UIFactory.CreateText("WMTxt", wm.transform, string.Format("Sid's Competitive Rounds mod · v{0} · {1:yyyy-MM-dd}", "1.35.5", DateTime.Now), 22f, C_DIM, 516, (Vector2?)new Vector2(1500f, 50f), richText: true, raycastTarget: false); yield return null; yield return null; try { Type canvasT = null; Assembly[] assemblies2 = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly asm2 in assemblies2) { canvasT = asm2.GetType("UnityEngine.Canvas"); if (canvasT != null) { break; } } canvasT?.GetMethod("ForceUpdateCanvases", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); } catch { } yield return null; Rect rect = bgRT.rect; int finalH = Mathf.CeilToInt(((Rect)(ref rect)).height); if (finalH < 600) { finalH = 600; } rootRT.sizeDelta = new Vector2(3000f, (float)finalH); yield return null; string outDir; try { outDir = Path.GetFullPath(Path.Combine(Application.dataPath, "..", "CompetitiveRoundsTierLists")); Directory.CreateDirectory(outDir); } catch { outDir = Application.persistentDataPath; } string fn = $"tierlist-{filterStr}-{DateTime.Now:yyyyMMdd-HHmmss}.png"; string fullPath = Path.Combine(outDir, fn); GameObject camGO = null; RenderTexture renderT = null; Texture2D tex = null; try { camGO = new GameObject("CR_TierCam"); ((Object)camGO).hideFlags = (HideFlags)61; camGO.transform.position = new Vector3(50000f, 50000f, -10f); Camera cam = camGO.AddComponent(); cam.orthographic = true; cam.orthographicSize = (float)finalH / 2f; cam.aspect = 3000f / (float)Math.Max(1, finalH); cam.clearFlags = (CameraClearFlags)2; cam.backgroundColor = new Color(0.07f, 0.08f, 0.1f, 1f); cam.cullingMask = -1; cam.nearClipPlane = 0.1f; cam.farClipPlane = 100f; renderT = (cam.targetTexture = new RenderTexture(3000, finalH, 24)); cam.Render(); RenderTexture prevActive = RenderTexture.active; RenderTexture.active = renderT; tex = new Texture2D(3000, finalH, (TextureFormat)3, false); tex.ReadPixels(new Rect(0f, 0f, 3000f, (float)finalH), 0, 0); tex.Apply(); RenderTexture.active = prevActive; byte[] png = ImageConversion.EncodeToPNG(tex); File.WriteAllBytes(fullPath, png); Plugin.Log.LogInfo((object)$"[TIER-EXPORT] saved {3000}×{finalH} → {fullPath}"); } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogWarning((object)("[TIER-EXPORT] capture failed: " + ex2.Message)); } finally { try { if ((Object)(object)camGO != (Object)null) { Object.Destroy((Object)(object)camGO); } } catch { } try { if ((Object)(object)renderT != (Object)null) { Object.Destroy((Object)(object)renderT); } } catch { } try { if ((Object)(object)tex != (Object)null) { Object.Destroy((Object)(object)tex); } } catch { } } try { if ((Object)(object)tierExportPanel != (Object)null) { Object.Destroy((Object)(object)tierExportPanel); } } catch { } tierExportPanel = null; CompetitiveUI.ShowNotification("Tier list saved to " + fullPath, new Color(0.4f, 0.9f, 0.4f), 12f); Plugin.Log.LogInfo((object)("[TIER-EXPORT] done — " + fullPath)); } private static Color GetRarityColor(string r) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(r)) { return C_LABEL; } return (Color)(r.ToLower() switch { "common" => C_COMMON, "uncommon" => C_UNCOMMON, "rare" => C_RARE, _ => C_LABEL, }); } public static void OnChatMessage(string json) { try { string text = ExtractChatField(json, "source"); string text2 = ExtractChatField(json, "display_name"); string text3 = ExtractChatField(json, "message"); int num = ExtractChatIntField(json, "rating"); string text4 = ExtractChatField(json, "title"); string text5 = ExtractChatField(json, "title_color"); if (string.IsNullOrEmpty(text3)) { return; } int num2 = ExtractChatIntField(json, "id"); if (num2 > 0) { if (num2 <= _lastChatIdSeen) { return; } _lastChatIdSeen = num2; } if (IsMuted(text2)) { Plugin.Log.LogInfo((object)("[CHAT] muted msg from " + text2 + " dropped locally")); return; } if (text3.Length > 500) { text3 = text3.Substring(0, 497) + "..."; } string text6 = ((text == "discord") ? "[D]" : "[game]"); string text7 = ((num > 0) ? $" ({num})" : ""); string text8 = ""; if (!string.IsNullOrEmpty(text4)) { string text9 = (string.IsNullOrEmpty(text5) ? "#CCCCCC" : text5); text8 = " [" + Escape(text4) + "]"; } string line = text6 + " " + Escape(text2) + "" + text8 + text7 + ": " + Escape(text3); lock (chatLinesLock) { chatLines.Add(new ChatEntry { Line = line, AddedUtc = DateTime.UtcNow }); while (chatLines.Count > 60) { chatLines.RemoveAt(0); } } MarkDirty(); } catch { } } private static HashSet GetMutedSet() { string text = Plugin.MutedChatNames?.Value ?? ""; HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); string[] array = text.Split('|'); foreach (string text2 in array) { string text3 = (text2 ?? "").Trim(); if (!string.IsNullOrEmpty(text3)) { hashSet.Add(text3); } } _mutedCache = hashSet; return hashSet; } private static bool IsMuted(string name) { if (string.IsNullOrEmpty(name)) { return false; } HashSet hashSet = _mutedCache ?? GetMutedSet(); return hashSet.Contains(name); } private static void SaveMutedSet(HashSet set) { if (Plugin.MutedChatNames != null) { Plugin.MutedChatNames.Value = string.Join("|", set); _mutedCache = set; } } public static void HandleMuteCommand(string text) { try { if (text.Equals("/muted", StringComparison.OrdinalIgnoreCase)) { HashSet mutedSet = GetMutedSet(); string text2 = ((mutedSet.Count == 0) ? "(none)" : string.Join(", ", mutedSet)); AppendSystemChatLine("Muted: " + text2); return; } int num = text.IndexOf(' '); if (num < 0) { return; } string text3 = text.Substring(0, num).ToLowerInvariant(); string text4 = text.Substring(num + 1).Trim(); if (string.IsNullOrEmpty(text4)) { return; } HashSet mutedSet2 = GetMutedSet(); if (text3 == "/mute") { if (mutedSet2.Add(text4)) { SaveMutedSet(mutedSet2); AppendSystemChatLine("Muted " + Escape(text4) + ""); } else { AppendSystemChatLine("" + Escape(text4) + " is already muted"); } } else if (text3 == "/unmute") { if (mutedSet2.Remove(text4)) { SaveMutedSet(mutedSet2); AppendSystemChatLine("Unmuted " + Escape(text4) + ""); } else { AppendSystemChatLine("" + Escape(text4) + " isn't muted"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MUTE] " + ex.Message)); } } private static void AppendSystemChatLine(string body) { string line = "[system] " + body; lock (chatLinesLock) { chatLines.Add(new ChatEntry { Line = line, AddedUtc = DateTime.UtcNow }); while (chatLines.Count > 60) { chatLines.RemoveAt(0); } } MarkDirty(); } private static void RefreshChatLog() { if (txtChatLog == null) { return; } string s; lock (chatLinesLock) { if (chatLines.Count == 0) { return; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < chatLines.Count; i++) { if (i > 0) { stringBuilder.Append('\n'); } stringBuilder.Append(chatLines[i].Line); } s = stringBuilder.ToString(); } UIFactory.SetText(txtChatLog, s); CompetitiveRoundsBehaviour instance = Plugin.Instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(ScrollChatToBottomNextFrame()); } } private static IEnumerator ScrollChatToBottomNextFrame() { yield return null; if ((Object)(object)chatScrollRect == (Object)null) { yield break; } try { UIFactory.tScrollRect.GetProperty("verticalNormalizedPosition", BindingFlags.Instance | BindingFlags.Public)?.SetValue(chatScrollRect, 0f); } catch { } } private static string Escape(string s) { if (string.IsNullOrEmpty(s)) { return ""; } return s.Replace("<", "(").Replace(">", ")"); } private static int ExtractChatIntField(string json, string key) { if (string.IsNullOrEmpty(json)) { return 0; } string text = "\"" + key + "\""; int num = json.IndexOf(text); if (num < 0) { return 0; } int i; for (i = num + text.Length; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } if (i >= json.Length || json[i] != ':') { return 0; } for (i++; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } int j; for (j = i; j < json.Length && (char.IsDigit(json[j]) || json[j] == '-' || json[j] == '.'); j++) { } if (j == i) { return 0; } try { float num2 = float.Parse(json.Substring(i, j - i), CultureInfo.InvariantCulture); return (int)Math.Round(num2); } catch { return 0; } } private static string ExtractChatField(string json, string key) { if (string.IsNullOrEmpty(json)) { return ""; } string text = "\"" + key + "\""; int num = json.IndexOf(text); if (num < 0) { return ""; } int i; for (i = num + text.Length; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } if (i >= json.Length || json[i] != ':') { return ""; } for (i++; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++) { } if (i >= json.Length || json[i] != '"') { return ""; } i++; StringBuilder stringBuilder = new StringBuilder(); while (i < json.Length) { char c = json[i]; if (c == '\\' && i + 1 < json.Length) { char c2 = json[i + 1]; switch (c2) { case 'n': stringBuilder.Append('\n'); break; case 't': stringBuilder.Append('\t'); break; default: stringBuilder.Append(c2); break; } i += 2; } else { if (c == '"') { break; } stringBuilder.Append(c); i++; } } return stringBuilder.ToString(); } private static void RefreshQueueUI() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) if (txtRankedStatus == null) { return; } bool value = Plugin.RankedEnabled.Value; ApiClient.QueueState currentQueueState = ApiClient.CurrentQueueState; UIFactory.SetText(txtRankedStatus, value ? "RANKED: ON" : "RANKED: OFF"); UIFactory.SetColor(txtRankedStatus, value ? C_GREEN : Color.gray); rankOnBtn.SetActive(!value); rankOffBtn.SetActive(value && !inGameMode); bool flag = GameStateWatcher.IsInMatch && GameStateWatcher.MatchIsRanked; try { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; if (cachedPlayerStats != null && cachedPlayerStats != _lfpStatsRef) { _lfpStatsRef = cachedPlayerStats; LfpArmCooldown(cachedPlayerStats.lfp_seconds_left); } if ((Object)(object)lfpBtn != (Object)null) { lfpBtn.SetActive(value && !flag); float num = lfpCooldownUntil - Time.realtimeSinceStartup; object buttonText = UIFactory.GetButtonText(lfpBtn); if (buttonText != null) { UIFactory.SetText(buttonText, (num > 0f) ? $"RLFP ({(int)(num / 60f) + 1}m)" : "RLFP Ping"); } } } catch { } qSearchBtn.SetActive(value && currentQueueState == ApiClient.QueueState.Idle && !flag); qCancelBtn.SetActive(value && currentQueueState == ApiClient.QueueState.Searching); if (currentQueueState == ApiClient.QueueState.Searching) { ApiClient.QueuePollData lastPollData = ApiClient.LastPollData; string text = "Searching..."; if (lastPollData != null && lastPollData.status == "searching") { int num2 = lastPollData.wait_time / 60; int num3 = lastPollData.wait_time % 60; text = string.Format("Searching... {0}{1}s +/-{2}", (num2 > 0) ? $"{num2}m " : "", num3, lastPollData.elo_range) + ((lastPollData.queue_size > 1) ? $" ({lastPollData.queue_size} in queue)" : ""); } text += OnlineSuffix(); UIFactory.SetText(txtQueueInfo, text); UIFactory.SetColor(txtQueueInfo, C_BLUE); object obj2 = txtQueueInfo; object obj3 = ((obj2 is Component) ? obj2 : null); GameObject obj4 = ((obj3 != null) ? ((Component)obj3).gameObject : null); if (obj4 != null) { obj4.SetActive(true); } } else if (currentQueueState == ApiClient.QueueState.Idle && value) { int cachedQueueSearching = ApiClient.CachedQueueSearching; if (cachedQueueSearching > 0) { UIFactory.SetText(txtQueueInfo, $"{cachedQueueSearching} searching" + OnlineSuffix()); UIFactory.SetColor(txtQueueInfo, C_GREEN); } else { UIFactory.SetText(txtQueueInfo, "0 in queue" + OnlineSuffix()); UIFactory.SetColor(txtQueueInfo, C_DIM); } object obj5 = txtQueueInfo; object obj6 = ((obj5 is Component) ? obj5 : null); GameObject obj7 = ((obj6 != null) ? ((Component)obj6).gameObject : null); if (obj7 != null) { obj7.SetActive(true); } } else if (currentQueueState == ApiClient.QueueState.Leaving && value) { UIFactory.SetText(txtQueueInfo, "Leaving queue..."); UIFactory.SetColor(txtQueueInfo, C_DIM); object obj8 = txtQueueInfo; object obj9 = ((obj8 is Component) ? obj8 : null); GameObject obj10 = ((obj9 != null) ? ((Component)obj9).gameObject : null); if (obj10 != null) { obj10.SetActive(true); } } else { UIFactory.SetText(txtQueueInfo, ""); object obj11 = txtQueueInfo; object obj12 = ((obj11 is Component) ? obj11 : null); GameObject obj13 = ((obj12 != null) ? ((Component)obj12).gameObject : null); if (obj13 != null) { obj13.SetActive(false); } } if (currentQueueState == ApiClient.QueueState.Matched || currentQueueState == ApiClient.QueueState.ReadySent) { qMatchPanel.SetActive(true); ApiClient.QueuePollData lastPollData2 = ApiClient.LastPollData; if (lastPollData2 != null) { string text2 = $"MATCH FOUND! vs {lastPollData2.opponent_name} ({lastPollData2.opponent_rating:F0})"; if (currentQueueState == ApiClient.QueueState.ReadySent && lastPollData2.opponent_ready) { text2 += " [Opponent Ready]"; } UIFactory.SetText(txtMatchFound, text2); } bool flag2 = currentQueueState == ApiClient.QueueState.ReadySent; readyBtn.SetActive(!flag2); connectLabel.SetActive(flag2); if (flag2 && txtConnectLabel != null && lastPollData2 != null) { string s = ((!string.IsNullOrEmpty(lastPollData2.opponent_name)) ? $"Waiting for {lastPollData2.opponent_name} ({lastPollData2.opponent_rating:F0})..." : "Waiting for opponent..."); if (lastPollData2.opponent_ready) { s = lastPollData2.opponent_name + " ready! Joining..."; } UIFactory.SetText(txtConnectLabel, s); } declineBtn.SetActive(true); } else { qMatchPanel.SetActive(false); } } private static string OnlineSuffix() { int cachedOnlineCount = ApiClient.CachedOnlineCount; return (cachedOnlineCount > 0) ? $" | {cachedOnlineCount} online" : ""; } private static int CalcStreak(List m) { if (m == null || m.Count == 0) { return 0; } bool won = m[0].won; int num = 0; for (int i = 0; i < m.Count && m[i].won == won; i++) { num++; } return won ? num : (-num); } private static string Trunc(string s, int max) { if (string.IsNullOrEmpty(s)) { return ""; } if (max <= 2) { return (s.Length <= max) ? s : ".."; } return (s.Length <= max) ? s : (s.Substring(0, max - 2) + ".."); } private static void FitLabelPair(string left, string right, int budget, out string outLeft, out string outRight) { _lblParts.Clear(); int num = SplitLabel(left, _lblParts); int num2 = SplitLabel(right, _lblParts); int count = _lblParts.Count; outLeft = ""; outRight = ""; if (count == 0 || count > _lblGrant.Length) { int max = Math.Max(2, budget / 2); outLeft = Trunc(left ?? "", max); outRight = Trunc(right ?? "", max); return; } int num3 = (Math.Max(0, num - 1) + Math.Max(0, num2 - 1)) * " + ".Length; int num4 = Math.Max(count * 2, budget - num3); _lblOrder.Clear(); for (int i = 0; i < count; i++) { _lblOrder.Add(i); } _lblOrder.Sort((int a, int b) => _lblParts[a].Length.CompareTo(_lblParts[b].Length)); int num5 = num4; int num6 = count; for (int num7 = 0; num7 < _lblOrder.Count; num7++) { int num8 = _lblOrder[num7]; int val = num5 / Math.Max(1, num6); int length = _lblParts[num8].Length; int num9 = Math.Min(length, val); if (num9 < 6) { num9 = Math.Min(length, 6); } _lblGrant[num8] = num9; num5 = Math.Max(0, num5 - num9); num6--; } outLeft = JoinFitted(0, num); outRight = JoinFitted(num, num2); int num10 = outLeft.Length + outRight.Length - budget; if (num10 > 0) { if (outLeft.Length >= outRight.Length) { outLeft = Trunc(outLeft, Math.Max(2, outLeft.Length - num10)); } else { outRight = Trunc(outRight, Math.Max(2, outRight.Length - num10)); } } } private static int SplitLabel(string label, List into) { if (string.IsNullOrEmpty(label)) { return 0; } int num = 0; int num2 = 0; while (true) { int num3 = label.IndexOf(" + ", num2, StringComparison.Ordinal); if (num3 < 0) { break; } into.Add(label.Substring(num2, num3 - num2)); num++; num2 = num3 + " + ".Length; } into.Add(label.Substring(num2)); return num + 1; } private static string JoinFitted(int start, int count) { if (count <= 0) { return ""; } StringBuilder stringBuilder = new StringBuilder(48); for (int i = 0; i < count; i++) { if (i > 0) { stringBuilder.Append(" + "); } stringBuilder.Append(Trunc(_lblParts[start + i], _lblGrant[start + i])); } return stringBuilder.ToString(); } private static string FitLabel(string label, int budget) { FitLabelPair(label, "", budget, out var outLeft, out var _); return outLeft; } private static List GroupBySeries(List ranked) { List list = new List(); SGroup item = new SGroup { series_id = null, matches = null }; foreach (ApiClient.MatchHistoryEntry item2 in ranked) { string series_id = item2.series_id; bool flag = !string.IsNullOrEmpty(series_id) && series_id != "null"; if (flag && item.matches != null && item.series_id == series_id) { item.matches.Add(item2); continue; } if (item.matches != null && item.matches.Count > 0) { list.Add(item); } item = new SGroup { series_id = (flag ? series_id : null), matches = new List { item2 } }; } if (item.matches != null && item.matches.Count > 0) { list.Add(item); } return list; } private static GameObject BuildAdminTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Expected O, but got Unknown //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Expected O, but got Unknown //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Expected O, but got Unknown //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Expected O, but got Unknown //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Expected O, but got Unknown //IL_0486: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Expected O, but got Unknown //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_0517: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Expected O, but got Unknown //IL_055e: Unknown result type (might be due to invalid IL or missing references) //IL_0573: Unknown result type (might be due to invalid IL or missing references) //IL_057a: Expected O, but got Unknown //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_0608: Unknown result type (might be due to invalid IL or missing references) //IL_067e: Unknown result type (might be due to invalid IL or missing references) //IL_0685: Expected O, but got Unknown //IL_06ff: Unknown result type (might be due to invalid IL or missing references) //IL_0713: Unknown result type (might be due to invalid IL or missing references) //IL_0789: Unknown result type (might be due to invalid IL or missing references) //IL_0790: Expected O, but got Unknown //IL_07ea: Unknown result type (might be due to invalid IL or missing references) //IL_07f1: Expected O, but got Unknown //IL_086c: Unknown result type (might be due to invalid IL or missing references) //IL_0880: Unknown result type (might be due to invalid IL or missing references) //IL_08f7: Unknown result type (might be due to invalid IL or missing references) //IL_08fe: Expected O, but got Unknown //IL_0979: Unknown result type (might be due to invalid IL or missing references) //IL_098d: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Unknown result type (might be due to invalid IL or missing references) //IL_0554: Expected O, but got Unknown GameObject val = new GameObject("AdminPanel"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 6f, 8, 8, 6, 6); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val2 = new GameObject("AHdr"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddHLG(val2, 8f); UIFactory.AddLE(val2, -1f, -1f, -1f, 32f, -1f, 0f); UIFactory.CreateText("AT", val2.transform, "Admin Panel (visible only to whitelisted Steam IDs)", 18f, new Color(1f, 0.7f, 0.3f), 513, (Vector2?)new Vector2(600f, 28f), richText: true, raycastTarget: false); Transform transform = val2.transform; Color c_WHITE = C_WHITE; Color c_BTN = C_BTN; object obj = <>c.<>9__747_0; if (obj == null) { UnityAction val3 = delegate { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.FetchFlaggedMatches(localSteamId); ApiClient.FetchBannedUsers(localSteamId); ApiClient.FetchAdminRecentSeries(localSteamId); ApiClient.FetchAdminQuarantine(localSteamId); } }; <>c.<>9__747_0 = val3; obj = (object)val3; } UIFactory.CreateButton("ARefresh", transform, "Refresh", 13f, c_WHITE, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(90f, 26f)); GameObject val4 = new GameObject("AAct"); val4.transform.SetParent(val.transform, false); val4.AddComponent(); UIFactory.AddHLG(val4, 8f); UIFactory.AddLE(val4, -1f, -1f, -1f, 30f, -1f, 0f); Transform transform2 = val4.transform; Color c_WHITE2 = C_WHITE; Color bgColor = new Color(0.55f, 0.15f, 0.15f, 0.9f); object obj2 = <>c.<>9__747_1; if (obj2 == null) { UnityAction val5 = delegate { CompetitiveUI.OpenAdminPrompt("ban"); }; <>c.<>9__747_1 = val5; obj2 = (object)val5; } UIFactory.CreateButton("ABan", transform2, "Ban Steam ID...", 13f, c_WHITE2, bgColor, (UnityAction)obj2, (Vector2?)new Vector2(140f, 26f)); Transform transform3 = val4.transform; Color c_WHITE3 = C_WHITE; Color bgColor2 = new Color(0.2f, 0.45f, 0.2f, 0.9f); object obj3 = <>c.<>9__747_2; if (obj3 == null) { UnityAction val6 = delegate { CompetitiveUI.OpenAdminPrompt("grant"); }; <>c.<>9__747_2 = val6; obj3 = (object)val6; } UIFactory.CreateButton("AGrant", transform3, "Grant Achievement...", 13f, c_WHITE3, bgColor2, (UnityAction)obj3, (Vector2?)new Vector2(170f, 26f)); Transform transform4 = val4.transform; Color c_WHITE4 = C_WHITE; Color bgColor3 = new Color(0.45f, 0.3f, 0.55f, 0.9f); object obj4 = <>c.<>9__747_3; if (obj4 == null) { UnityAction val7 = delegate { CompetitiveUI.OpenAdminPrompt("reverse"); }; <>c.<>9__747_3 = val7; obj4 = (object)val7; } UIFactory.CreateButton("ARev", transform4, "Reverse Series...", 13f, c_WHITE4, bgColor3, (UnityAction)obj4, (Vector2?)new Vector2(150f, 26f)); Transform transform5 = val4.transform; Color c_WHITE5 = C_WHITE; Color bgColor4 = new Color(0.2f, 0.3f, 0.5f, 0.9f); object obj5 = <>c.<>9__747_4; if (obj5 == null) { UnityAction val8 = delegate { CompetitiveUI.OpenBugReportAdminViewer(); }; <>c.<>9__747_4 = val8; obj5 = (object)val8; } UIFactory.CreateButton("ABugRpt", transform5, "Bug Reports...", 13f, c_WHITE5, bgColor4, (UnityAction)obj5, (Vector2?)new Vector2(150f, 26f)); GameObject val9 = new GameObject("AArtistAct"); val9.transform.SetParent(val.transform, false); val9.AddComponent(); UIFactory.AddHLG(val9, 8f); UIFactory.AddLE(val9, -1f, -1f, -1f, 30f, -1f, 0f); Transform transform6 = val9.transform; Color c_WHITE6 = C_WHITE; Color bgColor5 = new Color(0.3f, 0.45f, 0.35f, 0.9f); object obj6 = <>c.<>9__747_5; if (obj6 == null) { UnityAction val10 = delegate { CompetitiveUI.OpenPlayerSearch("Grant the artist role - find the player", delegate(string sid, string pname) { if (!string.IsNullOrEmpty(sid)) { ApiClient.AdminSetArtist(MatchTracker.LocalSteamId, sid, grant: true, delegate(bool ok, string resp) { ShowArtistResult(ok, ok ? ("Artist role granted to " + pname + ".") : resp); }); } }); }; <>c.<>9__747_5 = val10; obj6 = (object)val10; } UIFactory.CreateButton("AArtG", transform6, "Grant Artist...", 13f, c_WHITE6, bgColor5, (UnityAction)obj6, (Vector2?)new Vector2(130f, 26f)); Transform transform7 = val9.transform; Color c_WHITE7 = C_WHITE; Color bgColor6 = new Color(0.45f, 0.3f, 0.3f, 0.9f); object obj7 = <>c.<>9__747_6; if (obj7 == null) { UnityAction val11 = delegate { ApiClient.FetchArtistsList(delegate { List cachedAllArtists = ApiClient.CachedAllArtists; if (cachedAllArtists == null || cachedAllArtists.Count == 0) { ShowArtistResult(ok: false, "{\"detail\":\"no artists defined\"}"); } else { string[] array = new string[cachedAllArtists.Count]; string[] array2 = new string[cachedAllArtists.Count]; for (int i = 0; i < cachedAllArtists.Count; i++) { array[i] = cachedAllArtists[i].display_name; array2[i] = cachedAllArtists[i].steam_id; } CompetitiveUI.OpenArtistPicker("Revoke which artist?", array, array2, delegate(string picked) { if (!string.IsNullOrEmpty(picked)) { ApiClient.AdminSetArtist(MatchTracker.LocalSteamId, picked, grant: false, delegate(bool flag, string resp) { ShowArtistResult(flag, flag ? "Artist revoked." : resp); }); } }, "Revoke", showClear: false); } }); }; <>c.<>9__747_6 = val11; obj7 = (object)val11; } UIFactory.CreateButton("AArtR", transform7, "Revoke Artist...", 13f, c_WHITE7, bgColor6, (UnityAction)obj7, (Vector2?)new Vector2(135f, 26f)); Transform transform8 = val9.transform; Color c_WHITE8 = C_WHITE; Color bgColor7 = new Color(0.3f, 0.4f, 0.55f, 0.9f); object obj8 = <>c.<>9__747_7; if (obj8 == null) { UnityAction val12 = delegate { CompetitiveUI.OpenCosmeticReview(); }; <>c.<>9__747_7 = val12; obj8 = (object)val12; } UIFactory.CreateButton("ACosR", transform8, "Cosmetic Reviews...", 13f, c_WHITE8, bgColor7, (UnityAction)obj8, (Vector2?)new Vector2(150f, 26f)); Transform transform9 = val9.transform; Color c_WHITE9 = C_WHITE; Color bgColor8 = new Color(0.35f, 0.3f, 0.6f, 0.95f); object obj9 = <>c.<>9__747_8; if (obj9 == null) { UnityAction val13 = delegate { CompetitiveUI.OpenCosmeticReleaseQueue(); }; <>c.<>9__747_8 = val13; obj9 = (object)val13; } UIFactory.CreateButton("ACosQ", transform9, "Approved Update Queue...", 13f, c_WHITE9, bgColor8, (UnityAction)obj9, (Vector2?)new Vector2(190f, 26f)); GameObject val14 = new GameObject("ASHRow"); val14.transform.SetParent(val.transform, false); val14.AddComponent(); UIFactory.AddHLG(val14, 8f); UIFactory.AddLE(val14, -1f, -1f, -1f, 24f, -1f, 0f); txtAdminSeriesHdr = UIFactory.CreateText("ASH", val14.transform, "Recent Ranked Series", 16f, new Color(0.6f, 0.85f, 1f), 513, (Vector2?)new Vector2(700f, 22f), richText: true, raycastTarget: false); UIFactory.SetBold(txtAdminSeriesHdr, b: true); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("ASSV", val.transform, 3f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, 80f, -1f, -1f, -1f, 1f); adminSeriesContainer = scrollViewRefs.content; GameObject val15 = new GameObject("AQHRow"); val15.transform.SetParent(val.transform, false); val15.AddComponent(); UIFactory.AddHLG(val15, 8f); UIFactory.AddLE(val15, -1f, -1f, -1f, 24f, -1f, 0f); txtAdminQuarantineHdr = UIFactory.CreateText("AQH", val15.transform, "Rejected Reports", 16f, new Color(1f, 0.65f, 0.35f), 513, (Vector2?)new Vector2(700f, 22f), richText: true, raycastTarget: false); UIFactory.SetBold(txtAdminQuarantineHdr, b: true); UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("AQSV", val.transform, 3f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, 72f, -1f, -1f, -1f, 1f); adminQuarantineContainer = scrollViewRefs2.content; GameObject val16 = new GameObject("ASplit"); val16.transform.SetParent(val.transform, false); val16.AddComponent(); UIFactory.AddHLG(val16, 8f); UIFactory.AddLE(val16, -1f, 140f, -1f, -1f, -1f, 2f); GameObject val17 = new GameObject("AFLeft"); val17.transform.SetParent(val16.transform, false); val17.AddComponent(); UIFactory.AddVLG(val17, 4f); UIFactory.AddLE(val17, -1f, -1f, -1f, -1f, 1f, 1f); txtAdminFlagsHdr = UIFactory.CreateText("AFH", val17.transform, "Flagged Matches", 16f, new Color(1f, 0.55f, 0.3f), 257, (Vector2?)new Vector2(500f, 24f), richText: true, raycastTarget: false); UIFactory.SetBold(txtAdminFlagsHdr, b: true); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("AFSV", val17.transform); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); adminFlagsContainer = scrollViewRefs3.content; GameObject val18 = new GameObject("AFRight"); val18.transform.SetParent(val16.transform, false); val18.AddComponent(); UIFactory.AddVLG(val18, 4f); UIFactory.AddLE(val18, -1f, -1f, 360f, -1f, -1f, 1f); txtAdminBansHdr = UIFactory.CreateText("ABH", val18.transform, "Banned Users", 16f, new Color(1f, 0.45f, 0.45f), 257, (Vector2?)new Vector2(340f, 24f), richText: true, raycastTarget: false); UIFactory.SetBold(txtAdminBansHdr, b: true); UIFactory.ScrollViewRefs scrollViewRefs4 = UIFactory.CreateScrollView("ABSV", val18.transform); UIFactory.AddLE(scrollViewRefs4.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); adminBansContainer = scrollViewRefs4.content; return val; } private static void RefreshAdmin() { List list = ApiClient.CachedFlaggedMatches ?? new List(); UIFactory.SetText(txtAdminFlagsHdr, $"Flagged Matches ({list.Count} actionable)"); for (int i = list.Count; i < adminFlagRowPool.Count; i++) { adminFlagRowPool[i].SetActive(false); } for (int j = 0; j < list.Count; j++) { if (j >= adminFlagRowPool.Count) { adminFlagRowPool.Add(BuildAdminFlagRow(adminFlagsContainer.transform, j)); } FillAdminFlagRow(adminFlagRowPool[j], list[j]); } List list2 = ApiClient.CachedBannedUsers ?? new List(); UIFactory.SetText(txtAdminBansHdr, $"Banned Users ({list2.Count})"); for (int k = list2.Count; k < adminBanRowPool.Count; k++) { adminBanRowPool[k].SetActive(false); } for (int l = 0; l < list2.Count; l++) { if (l >= adminBanRowPool.Count) { adminBanRowPool.Add(BuildAdminBanRow(adminBansContainer.transform, l)); } FillAdminBanRow(adminBanRowPool[l], list2[l]); } List list3 = ApiClient.CachedAdminSeries ?? new List(); int num = 0; foreach (ApiClient.AdminSeriesEntry item in list3) { if (item.incomplete && item.ladder == "2v2") { num++; } } UIFactory.SetText(txtAdminSeriesHdr, (num > 0) ? $"Recent Ranked Series ({num} 2v2 need resolving)" : "Recent Ranked Series"); for (int m = list3.Count; m < adminSeriesRowPool.Count; m++) { adminSeriesRowPool[m].SetActive(false); } for (int n = 0; n < list3.Count; n++) { if (n >= adminSeriesRowPool.Count) { adminSeriesRowPool.Add(BuildAdminSeriesRow(adminSeriesContainer.transform, n)); } FillAdminSeriesRow(adminSeriesRowPool[n], list3[n]); } List list4 = ApiClient.CachedQuarantineReports ?? new List(); int num2 = Math.Min(20, list4.Count); UIFactory.SetText(s: (ApiClient.IsAdminQuarantineLoading && !ApiClient.AdminQuarantineLoaded) ? "Rejected Reports (loading...)" : ((!string.IsNullOrEmpty(ApiClient.AdminQuarantineError)) ? $"Rejected Reports ({list4.Count}) refresh failed" : ((list4.Count <= num2) ? $"Rejected Reports ({list4.Count})" : $"Rejected Reports ({list4.Count}, showing {num2})")), t: txtAdminQuarantineHdr); for (int num3 = num2; num3 < adminQuarantineRowPool.Count; num3++) { adminQuarantineRowPool[num3].SetActive(false); } for (int num4 = 0; num4 < num2; num4++) { if (num4 >= adminQuarantineRowPool.Count) { adminQuarantineRowPool.Add(BuildAdminQuarantineRow(adminQuarantineContainer.transform, num4)); } FillAdminQuarantineRow(adminQuarantineRowPool[num4], list4[num4]); } } private static GameObject BuildAdminQuarantineRow(Transform parent, int idx) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: 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) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Expected O, but got Unknown //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Expected O, but got Unknown while (adminQuarantineRowBindings.Count <= idx) { adminQuarantineRowBindings.Add(null); } GameObject val = UIFactory.CreatePanel($"AQ{idx}", parent, new Color(0.19f, 0.14f, 0.11f, 0.9f)); UIFactory.AddHLG(val, 6f, 6, 6, 4, 4); UIFactory.AddLE(val, -1f, -1f, -1f, 128f, -1f, 0f); GameObject val2 = new GameObject("AQInfo"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddVLG(val2, 1f); UIFactory.AddLE(val2, 420f, -1f, -1f, 120f, 1f, 0f); object t = UIFactory.CreateText($"AQT{idx}", val2.transform, "", 13f, C_WHITE, 513, (Vector2?)new Vector2(680f, 20f), richText: true, raycastTarget: false); object t2 = UIFactory.CreateText($"AQP{idx}", val2.transform, "", 12f, C_WHITE, 257, (Vector2?)new Vector2(680f, 54f), richText: true, raycastTarget: false); object t3 = UIFactory.CreateText($"AQR{idx}", val2.transform, "", 12f, new Color(1f, 0.75f, 0.55f), 513, (Vector2?)new Vector2(680f, 20f), richText: true, raycastTarget: false); object t4 = UIFactory.CreateText($"AQX{idx}", val2.transform, "", 12f, C_LABEL, 513, (Vector2?)new Vector2(680f, 20f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t, on: false); UIFactory.SetOverflowMode(t, 1); UIFactory.SetWordWrap(t2, on: true); UIFactory.SetOverflowMode(t2, 1); UIFactory.SetWordWrap(t3, on: false); UIFactory.SetOverflowMode(t3, 1); UIFactory.SetWordWrap(t4, on: false); UIFactory.SetOverflowMode(t4, 1); GameObject val3 = new GameObject("AQActions"); val3.transform.SetParent(val.transform, false); val3.AddComponent(); UIFactory.AddVLG(val3, 4f); UIFactory.AddLE(val3, -1f, -1f, 88f, 60f, 0f, 0f); UIFactory.CreateButton($"AQA{idx}", val3.transform, "Accept", 11f, C_WHITE, new Color(0.2f, 0.45f, 0.2f, 0.9f), (UnityAction)delegate { OnAdminQuarantineAction(idx, accept: true); }, (Vector2?)new Vector2(84f, 27f)); UIFactory.CreateButton($"AQD{idx}", val3.transform, "Discard", 11f, C_WHITE, new Color(0.5f, 0.25f, 0.16f, 0.9f), (UnityAction)delegate { OnAdminQuarantineAction(idx, accept: false); }, (Vector2?)new Vector2(84f, 27f)); val.SetActive(false); return val; } private static void FillAdminQuarantineRow(GameObject row, ApiClient.QuarantineReportEntry e) { //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) row.SetActive(true); string text = ((Object)row).name.Substring(2); if (int.TryParse(text, out var result) && result >= 0 && result < adminQuarantineRowBindings.Count) { adminQuarantineRowBindings[result] = e; } string text2; if (e.player_names == null || e.player_names.Count == 0) { text2 = "(players unavailable)"; } else { List list = new List(); foreach (string player_name in e.player_names) { list.Add(AdminDisplay(string.IsNullOrWhiteSpace(player_name) ? "(deleted player)" : player_name, 24)); } text2 = string.Join(" vs ", list.ToArray()); } string text3 = FormatAdminQuarantineTime(e.created_at); string text4 = AdminDisplay(string.IsNullOrEmpty(e.mode) ? "unknown" : e.mode, 12); string text5 = AdminDisplay(string.IsNullOrEmpty(e.score) ? "score unavailable" : e.score, 64); string text6 = AdminDisplay(string.IsNullOrEmpty(e.room) ? "room unavailable" : e.room, 24); string value = "[" + text4 + "] " + text3 + " " + text5 + " " + text6 + ""; string value2 = "Players: " + text2; string value3 = "Rejected: " + AdminDisplay(string.IsNullOrEmpty(e.reason) ? "reason unavailable" : e.reason, 140) + ((e.http_status > 0) ? $" HTTP {e.http_status}" : ""); string value4 = (e.can_accept ? ("Status: " + AdminDisplay(string.IsNullOrEmpty(e.status) ? "pending" : e.status, 24) + "; safe to accept") : ("Accept blocked: " + AdminDisplay(string.IsNullOrEmpty(e.accept_blocked_reason) ? "server did not provide a reason" : e.accept_blocked_reason, 140) + "")); SetAdminRowText(row.transform.Find("AQInfo/AQT" + text), value); SetAdminRowText(row.transform.Find("AQInfo/AQP" + text), value2); SetAdminRowText(row.transform.Find("AQInfo/AQR" + text), value3); SetAdminRowText(row.transform.Find("AQInfo/AQX" + text), value4); Transform obj = row.transform.Find("AQActions/AQA" + text); GameObject val = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)val != (Object)null) { SetButtonInteractable(val, e.can_accept); UIFactory.SetImageColor(val, e.can_accept ? new Color(0.2f, 0.45f, 0.2f, 0.9f) : new Color(0.18f, 0.18f, 0.18f, 0.75f)); UIFactory.SetColor(UIFactory.GetButtonText(val), e.can_accept ? C_WHITE : C_DIM); } } private static void OnAdminQuarantineAction(int index, bool accept) { if (index < 0 || index >= adminQuarantineRowBindings.Count) { return; } ApiClient.QuarantineReportEntry e = adminQuarantineRowBindings[index]; if (e == null || (accept && !e.can_accept)) { return; } string sid = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(sid) || string.IsNullOrEmpty(e.id)) { return; } string verb = (accept ? "Accept" : "Discard"); string text = ((e.player_names == null || e.player_names.Count == 0) ? "this rejected report" : string.Join(" vs ", e.player_names.Select((string n) => AdminDisplay(n, 24)).ToArray())); string message = (accept ? ("Accept the rejected report for " + text + "?\n\nServer eligibility will be rechecked.") : ("Discard the rejected report for " + text + "?\n\nThis cannot be accepted later.")); CompetitiveUI.OpenConfirm(message, delegate { Action callback = delegate(bool ok, string resp) { //IL_00a5: 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) string text2 = ApiClient.ExtractJsonStringPublic(resp ?? "", "detail"); if (string.IsNullOrEmpty(text2)) { text2 = resp; } if (ok) { CompetitiveUI.ShowNotification(accept ? "Rejected report accepted." : "Rejected report discarded.", new Color(0.45f, 0.9f, 0.5f), 4f); ApiClient.FetchAdminQuarantine(sid); } else { CompetitiveUI.ShowNotification(verb + " failed: " + AdminDisplay(string.IsNullOrEmpty(text2) ? "request failed" : text2, 180), new Color(1f, 0.45f, 0.35f), 7f); } }; if (accept) { ApiClient.AdminQuarantineAccept(sid, e.id, callback); } else { ApiClient.AdminQuarantineDiscard(sid, e.id, "Discarded from in-game admin panel.", callback); } }); } private static void SetAdminRowText(Transform textTransform, string value) { if ((Object)(object)textTransform == (Object)null) { return; } Component[] components = ((Component)textTransform).GetComponents(); foreach (Component val in components) { if (((object)val).GetType().Name == "TextMeshProUGUI") { UIFactory.SetText(val, value); break; } } } private static string FormatAdminQuarantineTime(string value) { if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result)) { return result.ToString("MM-dd HH:mm 'UTC'", CultureInfo.InvariantCulture); } return "time unavailable"; } private static string AdminDisplay(string value, int max) { if (string.IsNullOrEmpty(value)) { return ""; } StringBuilder stringBuilder = new StringBuilder(value.Length); bool flag = false; foreach (char c in value) { char c2 = c switch { '>' => ']', '<' => '[', _ => c, }; if (c2 == '\r' || c2 == '\n' || c2 == '\t') { c2 = ' '; } if (c2 < ' ') { c2 = ' '; } if (c2 == ' ') { if (flag) { continue; } flag = true; } else { flag = false; } stringBuilder.Append(c2); } return Trunc(stringBuilder.ToString().Trim(), max); } private static void SetButtonInteractable(GameObject button, bool interactable) { try { Component obj = ((button != null) ? button.GetComponent(UIFactory.tButton) : null); (UIFactory.tButton?.GetProperty("interactable", BindingFlags.Instance | BindingFlags.Public))?.SetValue(obj, interactable); } catch { } } private static GameObject BuildAdminFlagRow(Transform parent, int idx) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown GameObject val = UIFactory.CreatePanel($"AF{idx}", parent, new Color(0.18f, 0.13f, 0.13f, 0.85f)); UIFactory.AddHLG(val, 6f, 6, 6, 4, 4); UIFactory.AddLE(val, -1f, -1f, -1f, 38f, -1f, 0f); object obj = UIFactory.CreateText("AFT", val.transform, "", 13f, C_WHITE, 513, (Vector2?)new Vector2(420f, 30f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(obj, on: false); Component val2 = (Component)((obj is Component) ? obj : null); if ((Object)(object)val2 != (Object)null && UIFactory.tLE != null) { Component obj2 = val2.gameObject.GetComponent(UIFactory.tLE) ?? val2.gameObject.AddComponent(UIFactory.tLE); UIFactory.tLE.GetProperty("flexibleWidth", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj2, 1f); UIFactory.tLE.GetProperty("minWidth", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj2, 240f); } UIFactory.SetOverflowMode(obj, 1); string name = $"AFDT{idx}"; Transform transform = val.transform; Color c_WHITE = C_WHITE; Color bgColor = new Color(0.25f, 0.38f, 0.55f, 0.95f); object obj3 = <>c.<>9__756_0; if (obj3 == null) { UnityAction val3 = delegate { }; <>c.<>9__756_0 = val3; obj3 = (object)val3; } UIFactory.CreateButton(name, transform, "Details", 11f, c_WHITE, bgColor, (UnityAction)obj3, (Vector2?)new Vector2(76f, 26f)); val.SetActive(false); return val; } private static void FillAdminFlagRow(GameObject row, ApiClient.FlaggedMatchEntry e) { row.SetActive(true); Transform val = row.transform.Find("AFT"); if ((Object)(object)val != (Object)null) { string text = ""; try { if (!string.IsNullOrEmpty(e.created_at)) { text = DateTime.Parse(e.created_at).ToString("HH:mm"); } } catch { } string text2 = (e.restoration_required ? "FALSE+ / MANUAL REPAIR" : (e.auto_invalidated ? "auto-inv" : "advisory")); string text3 = (e.is_ranked ? "R" : "C"); string text4 = ((!string.IsNullOrEmpty(e.duration_text)) ? e.duration_text : ((e.duration_seconds > 0) ? (e.duration_seconds + "s") : "not recorded")); string s = "[" + text + "] " + e.flag_reason + " " + text2 + " " + Trunc(HomeSan(e.p1_name), 12) + " vs " + Trunc(HomeSan(e.p2_name), 12) + " " + text3 + "/" + text4 + " " + e.game_code + ""; Component[] components = ((Component)val).GetComponents(); foreach (Component val2 in components) { if (((object)val2).GetType().Name == "TextMeshProUGUI") { UIFactory.SetText(val2, s); break; } } } Transform val3 = row.transform.Find("AFDT" + ((Object)row).name.Substring(2)); if ((Object)(object)val3 != (Object)null) { WireButton(((Component)val3).gameObject, delegate { CompetitiveUI.OpenFlagEvidence(e); }); } } private static GameObject BuildAdminBanRow(Transform parent, int idx) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_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_0109: Expected O, but got Unknown GameObject val = UIFactory.CreatePanel($"AB{idx}", parent, new Color(0.2f, 0.13f, 0.13f, 0.85f)); UIFactory.AddHLG(val, 6f, 6, 6, 4, 4); UIFactory.AddLE(val, -1f, -1f, -1f, 32f, -1f, 0f); UIFactory.CreateText("ABT", val.transform, "", 13f, C_WHITE, 513, (Vector2?)new Vector2(220f, 26f), richText: true, raycastTarget: false); string name = $"ABU{idx}"; Transform transform = val.transform; Color c_WHITE = C_WHITE; Color bgColor = new Color(0.2f, 0.45f, 0.2f, 0.9f); object obj = <>c.<>9__758_0; if (obj == null) { UnityAction val2 = delegate { }; <>c.<>9__758_0 = val2; obj = (object)val2; } UIFactory.CreateButton(name, transform, "Unban", 11f, c_WHITE, bgColor, (UnityAction)obj, (Vector2?)new Vector2(70f, 24f)); val.SetActive(false); return val; } private static void FillAdminBanRow(GameObject row, ApiClient.BannedUserEntry e) { row.SetActive(true); Transform val = row.transform.Find("ABT"); if ((Object)(object)val != (Object)null) { string s = "" + Trunc(e.display_name ?? e.steam_id, 16) + " " + Trunc(e.reason, 28) + ""; Component[] components = ((Component)val).GetComponents(); foreach (Component val2 in components) { if (((object)val2).GetType().Name == "TextMeshProUGUI") { UIFactory.SetText(val2, s); break; } } } Transform val3 = row.transform.Find("ABU" + ((Object)row).name.Substring(2)); if (!((Object)(object)val3 != (Object)null)) { return; } WireButton(((Component)val3).gameObject, delegate { string sid = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(sid)) { ApiClient.AdminUnban(sid, e.steam_id, delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)("[ADMIN] unban " + e.steam_id + ": " + (ok ? "OK" : "FAIL") + " " + resp)); if (ok) { ApiClient.FetchBannedUsers(sid); ApiClient.FetchFlaggedMatches(sid); } }); } }); } private static GameObject BuildAdminSeriesRow(Transform parent, int idx) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Expected O, but got Unknown //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Expected O, but got Unknown GameObject val = UIFactory.CreatePanel($"AS{idx}", parent, new Color(0.13f, 0.15f, 0.19f, 0.9f)); UIFactory.AddVLG(val, 2f, 6, 6, 4, 4); UIFactory.AddLE(val, -1f, -1f, -1f, 52f, -1f, 0f); GameObject val2 = new GameObject("AStop"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddHLG(val2, 6f); UIFactory.AddLE(val2, -1f, -1f, -1f, 26f, -1f, 0f); object t = UIFactory.CreateText($"ASI{idx}", val2.transform, "", 13f, C_WHITE, 513, (Vector2?)new Vector2(500f, 24f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t, on: false); Transform obj = val2.transform.Find($"ASI{idx}"); GameObject val3 = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)val3 != (Object)null) { UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, 1f, 0f); } string name = $"ASB1{idx}"; Transform transform = val2.transform; Color c_WHITE = C_WHITE; Color bgColor = new Color(0.2f, 0.45f, 0.2f, 0.9f); object obj2 = <>c.<>9__760_0; if (obj2 == null) { UnityAction val4 = delegate { }; <>c.<>9__760_0 = val4; obj2 = (object)val4; } UIFactory.CreateButton(name, transform, "", 11f, c_WHITE, bgColor, (UnityAction)obj2, (Vector2?)new Vector2(78f, 24f)); string name2 = $"ASB2{idx}"; Transform transform2 = val2.transform; Color c_WHITE2 = C_WHITE; Color bgColor2 = new Color(0.2f, 0.45f, 0.2f, 0.9f); object obj3 = <>c.<>9__760_1; if (obj3 == null) { UnityAction val5 = delegate { }; <>c.<>9__760_1 = val5; obj3 = (object)val5; } UIFactory.CreateButton(name2, transform2, "", 11f, c_WHITE2, bgColor2, (UnityAction)obj3, (Vector2?)new Vector2(78f, 24f)); string name3 = $"ASB3{idx}"; Transform transform3 = val2.transform; Color c_WHITE3 = C_WHITE; Color bgColor3 = new Color(0.5f, 0.35f, 0.15f, 0.9f); object obj4 = <>c.<>9__760_2; if (obj4 == null) { UnityAction val6 = delegate { }; <>c.<>9__760_2 = val6; obj4 = (object)val6; } UIFactory.CreateButton(name3, transform3, "", 11f, c_WHITE3, bgColor3, (UnityAction)obj4, (Vector2?)new Vector2(78f, 24f)); object t2 = UIFactory.CreateText($"ASC{idx}", val.transform, "", 11f, new Color(0.6f, 0.6f, 0.62f), 513, (Vector2?)new Vector2(760f, 18f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(t2, on: false); val.SetActive(false); return val; } private static string SeriesPairName(ApiClient.AdminSeriesEntry e, int team) { if (e.num_players == 4) { return (team == 1) ? (e.p1_name + "+" + e.p2_name) : (e.p3_name + "+" + e.p4_name); } return (team == 1) ? e.p1_name : e.p2_name; } private static string BuildSeriesCards(ApiClient.AdminSeriesEntry e, out int lineCount) { List<(string, string[])> list = new List<(string, string[])> { (e.p1_name, SplitGames(e.p1_cards)), (e.p2_name, SplitGames(e.p2_cards)) }; if (e.num_players == 4) { list.Add((e.p3_name, SplitGames(e.p3_cards))); list.Add((e.p4_name, SplitGames(e.p4_cards))); } int num = 0; foreach (var item3 in list) { num = Math.Max(num, item3.Item2.Length); } List list2 = new List(); for (int i = 0; i < num; i++) { List list3 = new List(); foreach (var item4 in list) { string item = item4.Item1; string[] item2 = item4.Item2; string text = ((i < item2.Length) ? item2[i] : ""); if (!string.IsNullOrEmpty(text)) { list3.Add(Trunc(item, 8) + ": " + text.Replace("|", ", ")); } } if (list3.Count != 0) { string text2 = string.Format("G{0} {1}", i + 1, string.Join(" ", list3)); if (text2.Length > 170) { text2 = text2.Substring(0, 168) + ".."; } list2.Add(text2); } } lineCount = Math.Max(1, list2.Count); string text3 = ((list2.Count > 0) ? string.Join("\n", list2) : "(no cards recorded)"); return "" + text3 + ""; static string[] SplitGames(string cards) { return string.IsNullOrEmpty(cards) ? Array.Empty() : cards.Split(new string[1] { "||" }, StringSplitOptions.None); } } private static void FillAdminSeriesRow(GameObject row, ApiClient.AdminSeriesEntry e) { //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_04d0: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) row.SetActive(true); string text = ((Object)row).name.Substring(2); string text2 = ((e.ladder == "2v2") ? "#88CCFF" : "#CFA0FF"); string text3 = ((e.num_players == 4) ? (Trunc(e.p1_name, 10) + "+" + Trunc(e.p2_name, 10)) : Trunc(e.p1_name, 14)); string text4 = ((e.num_players == 4) ? (Trunc(e.p3_name, 10) + "+" + Trunc(e.p4_name, 10)) : Trunc(e.p2_name, 14)); if (e.winner_team == 1) { text3 = "" + text3 + ""; } else if (e.winner_team == 2) { text4 = "" + text4 + ""; } string text5 = (string.IsNullOrEmpty(e.dc_name) ? "" : (" DC:" + Trunc(e.dc_name, 10) + "")); string text6 = (e.incomplete ? "#FFCC44" : ((e.status == "completed") ? "#88DD88" : "#AAAAAA")); string s = $"#{e.series_number} {e.ladder} {text3} {e.score} {text4}{text5} {e.status}"; Transform val = row.transform.Find("AStop/ASI" + text); if ((Object)(object)val != (Object)null) { Component[] components = ((Component)val).GetComponents(); foreach (Component val2 in components) { if (((object)val2).GetType().Name == "TextMeshProUGUI") { UIFactory.SetText(val2, s); break; } } } Transform val3 = row.transform.Find("ASC" + text); if ((Object)(object)val3 != (Object)null) { int lineCount; string s2 = BuildSeriesCards(e, out lineCount); Component[] components2 = ((Component)val3).GetComponents(); foreach (Component val4 in components2) { if (((object)val4).GetType().Name == "TextMeshProUGUI") { UIFactory.SetText(val4, s2); break; } } UIFactory.SetPrefH(row, Math.Max(52, 34 + 16 * lineCount)); RectTransform component = ((Component)val3).GetComponent(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(component.sizeDelta.x, (float)(16 * lineCount + 2)); } } Transform obj = row.transform.Find("AStop/ASB1" + text); GameObject b = ((obj != null) ? ((Component)obj).gameObject : null); Transform obj2 = row.transform.Find("AStop/ASB2" + text); GameObject b2 = ((obj2 != null) ? ((Component)obj2).gameObject : null); Transform obj3 = row.transform.Find("AStop/ASB3" + text); GameObject b3 = ((obj3 != null) ? ((Component)obj3).gameObject : null); if (e.ladder == "2v2" && e.incomplete) { setBtn(b, show: true, "Win T1", new Color(0.2f, 0.45f, 0.2f, 0.9f), delegate { ConfirmResolveTeam(e, "complete", 1); }); setBtn(b2, show: true, "Win T2", new Color(0.2f, 0.45f, 0.2f, 0.9f), delegate { ConfirmResolveTeam(e, "complete", 2); }); setBtn(b3, show: true, "Void", new Color(0.5f, 0.35f, 0.15f, 0.9f), delegate { ConfirmResolveTeam(e, "void", 0); }); } else if (e.status == "completed") { setBtn(b, show: true, "Reverse", new Color(0.55f, 0.2f, 0.5f, 0.9f), delegate { ConfirmReverseSeries(e); }); setBtn(b2, show: false, "", C_BTN, null); setBtn(b3, show: false, "", C_BTN, null); } else { setBtn(b, show: false, "", C_BTN, null); setBtn(b2, show: false, "", C_BTN, null); setBtn(b3, show: false, "", C_BTN, null); } static void setBtn(GameObject val5, bool show, string label, Color col, Action onClick) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)val5 == (Object)null)) { val5.SetActive(show); if (show) { UIFactory.SetText(UIFactory.GetButtonText(val5), label); UIFactory.SetImageColor(val5, col); WireButton(val5, onClick); } } } } private static void ConfirmResolveTeam(ApiClient.AdminSeriesEntry e, string action, int winner) { string sid = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(sid)) { return; } string arg = ((action == "void") ? "VOID this series (no result, no rating/gold)" : $"award the win to Team {winner} ({SeriesPairName(e, winner)}) — applies Glicko + gold now"); CompetitiveUI.OpenConfirm($"2v2 series #{e.series_number}\n\n{arg}?", delegate { ApiClient.AdminResolveTeamSeries(sid, e.series_id, action, winner, delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)string.Format("[ADMIN] resolve {0} T{1} on {2}: {3} {4}", action, winner, e.series_id, ok ? "OK" : "FAIL", resp)); if (ok) { ApiClient.FetchAdminRecentSeries(sid); } }); }); } private static void ConfirmReverseSeries(ApiClient.AdminSeriesEntry e) { string sid = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(sid)) { return; } CompetitiveUI.OpenConfirm($"Reverse {e.ladder} series #{e.series_number}?\n\nUndoes the ratings + gold and cancels the series.", delegate { Action callback = delegate(bool ok, string resp) { Plugin.Log.LogInfo((object)("[ADMIN] reverse " + e.series_id + ": " + (ok ? "OK" : "FAIL") + " " + resp)); if (ok) { ApiClient.FetchAdminRecentSeries(sid); } }; if (e.ladder == "2v2") { ApiClient.AdminReverseTeamSeries(sid, e.series_id, "admin_reverse", callback); } else { ApiClient.AdminReverseSeries(sid, e.series_id, "admin_reverse", callback); } }); } private static void WireButton(GameObject btn, Action onClick) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown try { Component component = btn.GetComponent(UIFactory.tButton); if ((Object)(object)component == (Object)null) { return; } object obj = UIFactory.tButton.GetProperty("onClick", BindingFlags.Instance | BindingFlags.Public)?.GetValue(component); if (obj != null) { obj.GetType().GetMethod("RemoveAllListeners")?.Invoke(obj, null); MethodInfo method = obj.GetType().GetMethod("AddListener"); if (method != null) { UnityAction val = (UnityAction)delegate { if (ClickGuard.Claim(btn)) { onClick(); } }; method.Invoke(obj, new object[1] { val }); } } ClickHandler component2 = btn.GetComponent(); if (!((Object)(object)component2 != (Object)null)) { return; } component2.onClick = delegate { if (ClickGuard.Claim(btn)) { onClick(); } }; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ADMIN] WireButton failed: " + ex.Message)); } } public static void MaybeRefreshTournament() { if (currentTab == 7 && Time.unscaledTime >= tTournamentRefreshAt) { tTournamentRefreshAt = Time.unscaledTime + 10f; ApiClient.FetchTournamentCurrent(MatchTracker.LocalSteamId); } } private static GameObject BuildTournamentsTab(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Expected O, but got Unknown //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Expected O, but got Unknown //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_04b8: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Expected O, but got Unknown //IL_04eb: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Unknown result type (might be due to invalid IL or missing references) //IL_052e: Expected O, but got Unknown //IL_0599: Unknown result type (might be due to invalid IL or missing references) //IL_05ad: Unknown result type (might be due to invalid IL or missing references) //IL_05d5: Unknown result type (might be due to invalid IL or missing references) //IL_05da: Unknown result type (might be due to invalid IL or missing references) //IL_04d6: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Expected O, but got Unknown //IL_0608: Unknown result type (might be due to invalid IL or missing references) //IL_0632: Unknown result type (might be due to invalid IL or missing references) //IL_0646: Unknown result type (might be due to invalid IL or missing references) //IL_066e: Unknown result type (might be due to invalid IL or missing references) //IL_0673: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Unknown result type (might be due to invalid IL or missing references) //IL_05f8: Unknown result type (might be due to invalid IL or missing references) //IL_05fe: Expected O, but got Unknown //IL_06a1: Unknown result type (might be due to invalid IL or missing references) //IL_06da: Unknown result type (might be due to invalid IL or missing references) //IL_06ee: Unknown result type (might be due to invalid IL or missing references) //IL_0709: Unknown result type (might be due to invalid IL or missing references) //IL_0710: Expected O, but got Unknown //IL_077b: Unknown result type (might be due to invalid IL or missing references) //IL_0794: Unknown result type (might be due to invalid IL or missing references) //IL_068c: Unknown result type (might be due to invalid IL or missing references) //IL_0691: Unknown result type (might be due to invalid IL or missing references) //IL_0697: Expected O, but got Unknown //IL_07c2: Unknown result type (might be due to invalid IL or missing references) //IL_07ec: Unknown result type (might be due to invalid IL or missing references) //IL_0805: Unknown result type (might be due to invalid IL or missing references) //IL_07ad: Unknown result type (might be due to invalid IL or missing references) //IL_07b2: Unknown result type (might be due to invalid IL or missing references) //IL_07b8: Expected O, but got Unknown //IL_0833: Unknown result type (might be due to invalid IL or missing references) //IL_0878: Unknown result type (might be due to invalid IL or missing references) //IL_088c: Unknown result type (might be due to invalid IL or missing references) //IL_08b7: Unknown result type (might be due to invalid IL or missing references) //IL_08cb: Unknown result type (might be due to invalid IL or missing references) //IL_08ec: Unknown result type (might be due to invalid IL or missing references) //IL_095d: Unknown result type (might be due to invalid IL or missing references) //IL_0971: Unknown result type (might be due to invalid IL or missing references) //IL_098c: Unknown result type (might be due to invalid IL or missing references) //IL_0996: Expected O, but got Unknown //IL_081e: Unknown result type (might be due to invalid IL or missing references) //IL_0823: Unknown result type (might be due to invalid IL or missing references) //IL_0829: Expected O, but got Unknown //IL_09e9: Unknown result type (might be due to invalid IL or missing references) //IL_09f0: Expected O, but got Unknown //IL_0bd6: Unknown result type (might be due to invalid IL or missing references) //IL_0bdd: Expected O, but got Unknown //IL_0c49: Unknown result type (might be due to invalid IL or missing references) //IL_0c62: Unknown result type (might be due to invalid IL or missing references) //IL_0c90: Unknown result type (might be due to invalid IL or missing references) //IL_0cba: Unknown result type (might be due to invalid IL or missing references) //IL_0cce: Unknown result type (might be due to invalid IL or missing references) //IL_0cfa: Unknown result type (might be due to invalid IL or missing references) //IL_0d13: Unknown result type (might be due to invalid IL or missing references) //IL_0c7b: Unknown result type (might be due to invalid IL or missing references) //IL_0c80: Unknown result type (might be due to invalid IL or missing references) //IL_0c86: Expected O, but got Unknown //IL_0a7d: Unknown result type (might be due to invalid IL or missing references) //IL_0a84: Expected O, but got Unknown //IL_0b01: Unknown result type (might be due to invalid IL or missing references) //IL_0b06: Unknown result type (might be due to invalid IL or missing references) //IL_0b13: Unknown result type (might be due to invalid IL or missing references) //IL_0b22: Unknown result type (might be due to invalid IL or missing references) //IL_0b31: Expected O, but got Unknown //IL_0b67: Unknown result type (might be due to invalid IL or missing references) //IL_0b7b: Unknown result type (might be due to invalid IL or missing references) //IL_0d41: Unknown result type (might be due to invalid IL or missing references) //IL_0d60: Unknown result type (might be due to invalid IL or missing references) //IL_0dd3: Unknown result type (might be due to invalid IL or missing references) //IL_0de7: Unknown result type (might be due to invalid IL or missing references) //IL_0e3d: Unknown result type (might be due to invalid IL or missing references) //IL_0e51: Unknown result type (might be due to invalid IL or missing references) //IL_0e6c: Unknown result type (might be due to invalid IL or missing references) //IL_0e73: Expected O, but got Unknown //IL_0ee2: Unknown result type (might be due to invalid IL or missing references) //IL_0efb: Unknown result type (might be due to invalid IL or missing references) //IL_0d2c: Unknown result type (might be due to invalid IL or missing references) //IL_0d31: Unknown result type (might be due to invalid IL or missing references) //IL_0d37: Expected O, but got Unknown //IL_0f29: Unknown result type (might be due to invalid IL or missing references) //IL_0f53: Unknown result type (might be due to invalid IL or missing references) //IL_0f6c: Unknown result type (might be due to invalid IL or missing references) //IL_0f14: Unknown result type (might be due to invalid IL or missing references) //IL_0f19: Unknown result type (might be due to invalid IL or missing references) //IL_0f1f: Expected O, but got Unknown //IL_0f9a: Unknown result type (might be due to invalid IL or missing references) //IL_0fd0: Unknown result type (might be due to invalid IL or missing references) //IL_0fe9: Unknown result type (might be due to invalid IL or missing references) //IL_0f85: Unknown result type (might be due to invalid IL or missing references) //IL_0f8a: Unknown result type (might be due to invalid IL or missing references) //IL_0f90: Expected O, but got Unknown //IL_1017: Unknown result type (might be due to invalid IL or missing references) //IL_103c: Unknown result type (might be due to invalid IL or missing references) //IL_1043: Expected O, but got Unknown //IL_10a4: Unknown result type (might be due to invalid IL or missing references) //IL_1109: Unknown result type (might be due to invalid IL or missing references) //IL_111d: Unknown result type (might be due to invalid IL or missing references) //IL_1002: Unknown result type (might be due to invalid IL or missing references) //IL_1007: Unknown result type (might be due to invalid IL or missing references) //IL_100d: Expected O, but got Unknown //IL_1199: Unknown result type (might be due to invalid IL or missing references) //IL_11a0: Expected O, but got Unknown //IL_120f: Unknown result type (might be due to invalid IL or missing references) //IL_1223: Unknown result type (might be due to invalid IL or missing references) //IL_124c: Unknown result type (might be due to invalid IL or missing references) //IL_1260: Unknown result type (might be due to invalid IL or missing references) //IL_1289: Unknown result type (might be due to invalid IL or missing references) //IL_129d: Unknown result type (might be due to invalid IL or missing references) //IL_1308: Unknown result type (might be due to invalid IL or missing references) //IL_1379: Unknown result type (might be due to invalid IL or missing references) //IL_138d: Unknown result type (might be due to invalid IL or missing references) //IL_13a8: Unknown result type (might be due to invalid IL or missing references) //IL_13b2: Expected O, but got Unknown //IL_1406: Unknown result type (might be due to invalid IL or missing references) //IL_146b: Unknown result type (might be due to invalid IL or missing references) //IL_147f: Unknown result type (might be due to invalid IL or missing references) //IL_150b: Unknown result type (might be due to invalid IL or missing references) //IL_1512: Expected O, but got Unknown //IL_1581: Unknown result type (might be due to invalid IL or missing references) //IL_1595: Unknown result type (might be due to invalid IL or missing references) //IL_1686: Unknown result type (might be due to invalid IL or missing references) //IL_1690: Expected O, but got Unknown //IL_16c3: Unknown result type (might be due to invalid IL or missing references) //IL_16da: Unknown result type (might be due to invalid IL or missing references) //IL_16f1: Unknown result type (might be due to invalid IL or missing references) //IL_1708: Unknown result type (might be due to invalid IL or missing references) //IL_176d: Unknown result type (might be due to invalid IL or missing references) //IL_1781: Unknown result type (might be due to invalid IL or missing references) //IL_17a3: Unknown result type (might be due to invalid IL or missing references) //IL_1808: Unknown result type (might be due to invalid IL or missing references) //IL_181c: Unknown result type (might be due to invalid IL or missing references) //IL_1612: Unknown result type (might be due to invalid IL or missing references) //IL_1898: Unknown result type (might be due to invalid IL or missing references) //IL_189f: Expected O, but got Unknown //IL_190e: Unknown result type (might be due to invalid IL or missing references) //IL_1922: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Tournaments"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddHLG(val, 8f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val2 = new GameObject("TLeftOuter"); val2.transform.SetParent(val.transform, false); val2.AddComponent(); UIFactory.AddVLG(val2, 0f); UIFactory.AddLE(val2, 360f, -1f, 430f, -1f, 0f, 1f); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("TLeftSV", val2.transform, 0f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); GameObject val3 = new GameObject("TLeft"); val3.transform.SetParent(scrollViewRefs.content.transform, false); val3.AddComponent(); UIFactory.AddVLG(val3, 6f); UIFactory.AddLE(val3, -1f, -1f, -1f, -1f, -1f, 0f); GameObject val4 = new GameObject("TSubTabs"); val4.transform.SetParent(val3.transform, false); val4.AddComponent(); UIFactory.AddHLG(val4); UIFactory.AddLE(val4, -1f, -1f, -1f, 30f, -1f, 0f); Transform transform = val4.transform; Color c_WHITE = C_WHITE; Color c_TABACT = C_TABACT; object obj = <>c.<>9__819_0; if (obj == null) { UnityAction val5 = delegate { if (!(ApiClient.TournamentKind == "sync")) { ApiClient.TournamentKind = "sync"; ApiClient.FetchTournamentCurrent(MatchTracker.LocalSteamId, force: true); dirty = true; } }; <>c.<>9__819_0 = val5; obj = (object)val5; } tSubTabSyncBtn = UIFactory.CreateButton("TSTSy", transform, "SYNC (weekly)", 14f, c_WHITE, c_TABACT, (UnityAction)obj, (Vector2?)new Vector2(180f, 26f)); Transform transform2 = val4.transform; Color c_LABEL = C_LABEL; Color c_TAB = C_TAB; object obj2 = <>c.<>9__819_1; if (obj2 == null) { UnityAction val6 = delegate { if (!(ApiClient.TournamentKind == "async")) { ApiClient.TournamentKind = "async"; ApiClient.FetchTournamentCurrent(MatchTracker.LocalSteamId, force: true); dirty = true; } }; <>c.<>9__819_1 = val6; obj2 = (object)val6; } tSubTabAsyncBtn = UIFactory.CreateButton("TSTAs", transform2, "ASYNC (6-week)", 14f, c_LABEL, c_TAB, (UnityAction)obj2, (Vector2?)new Vector2(180f, 26f)); GameObject val7 = UIFactory.CreatePanel("THdr", val3.transform, C_PANEL); UIFactory.AddVLG(val7, 2f, 10, 10, 6, 6); UIFactory.AddLE(val7, -1f, -1f, -1f, -1f, -1f, 0f); txtTState = UIFactory.CreateText("TS", val7.transform, "Loading...", 24f, C_GOLD, 513, (Vector2?)new Vector2(410f, 32f), richText: true, raycastTarget: false); UIFactory.SetBold(txtTState, b: true); txtTWhen = UIFactory.CreateText("TW", val7.transform, "", 17f, C_SUB, 513, (Vector2?)new Vector2(410f, 26f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtTWhen, on: true); object obj3 = txtTWhen; object obj4 = ((obj3 is Component) ? obj3 : null); Component val8 = ((obj4 != null) ? ((Component)obj4).gameObject.GetComponent(UIFactory.tLE) : null); if ((Object)(object)val8 != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(val8, -1f); } GameObject val9 = new GameObject("TInfoRow"); val9.transform.SetParent(val7.transform, false); val9.AddComponent(); UIFactory.AddHLG(val9, 6f); UIFactory.AddLE(val9, -1f, -1f, -1f, 30f, -1f, 0f); Transform transform3 = val9.transform; Color c_WHITE2 = C_WHITE; Color c_BTN = C_BTN; object obj5 = <>c.<>9__819_2; if (obj5 == null) { UnityAction val10 = delegate { ShowInfoPopup(_tInfoTitle, _tInfoInstructions); }; <>c.<>9__819_2 = val10; obj5 = (object)val10; } GameObject go = UIFactory.CreateButton("TInfoHow", transform3, "How It Works", 14f, c_WHITE2, c_BTN, (UnityAction)obj5, (Vector2?)new Vector2(150f, 26f)); UIFactory.AddLE(go, -1f, -1f, 150f, 26f, 0f, 0f); Transform transform4 = val9.transform; Color c_WHITE3 = C_WHITE; Color c_BTN2 = C_BTN; object obj6 = <>c.<>9__819_3; if (obj6 == null) { UnityAction val11 = delegate { ShowInfoPopup("Prizes", string.IsNullOrEmpty(_tInfoPrizes) ? "Prizes are announced when signups open." : _tInfoPrizes); }; <>c.<>9__819_3 = val11; obj6 = (object)val11; } GameObject go2 = UIFactory.CreateButton("TInfoPrz", transform4, "Prizes & Rules", 14f, c_WHITE3, c_BTN2, (UnityAction)obj6, (Vector2?)new Vector2(150f, 26f)); UIFactory.AddLE(go2, -1f, -1f, 150f, 26f, 0f, 0f); GameObject val12 = new GameObject("TZRow"); val12.transform.SetParent(val3.transform, false); val12.AddComponent(); UIFactory.AddHLG(val12, 6f); UIFactory.AddLE(val12, -1f, -1f, -1f, 26f, -1f, 0f); UIFactory.CreateText("TZL", val12.transform, "Times in:", 14f, C_LABEL, 513, (Vector2?)new Vector2(80f, 24f), richText: true, raycastTarget: false); Transform transform5 = val12.transform; string label = _TzLabel(); Color c_WHITE4 = C_WHITE; Color c_BTN3 = C_BTN; object obj7 = <>c.<>9__819_4; if (obj7 == null) { UnityAction val13 = delegate { _CycleTz(); }; <>c.<>9__819_4 = val13; obj7 = (object)val13; } txtTTzButton = UIFactory.CreateButton("TZBtn", transform5, label, 14f, c_WHITE4, c_BTN3, (UnityAction)obj7, (Vector2?)new Vector2(80f, 24f)); UIFactory.CreateText("TDL", val12.transform, "fmt:", 14f, C_LABEL, 513, (Vector2?)new Vector2(40f, 24f), richText: true, raycastTarget: false); Transform transform6 = val12.transform; string label2 = _DateFormat(); Color c_WHITE5 = C_WHITE; Color c_BTN4 = C_BTN; object obj8 = <>c.<>9__819_5; if (obj8 == null) { UnityAction val14 = delegate { _CycleDateFormat(); }; <>c.<>9__819_5 = val14; obj8 = (object)val14; } txtTDateFmtButton = UIFactory.CreateButton("TDFBtn", transform6, label2, 14f, c_WHITE5, c_BTN4, (UnityAction)obj8, (Vector2?)new Vector2(60f, 24f)); txtTTzNow = UIFactory.CreateText("TZN", val12.transform, "", 13f, new Color(0.8f, 0.9f, 1f), 513, (Vector2?)new Vector2(180f, 24f), richText: true, raycastTarget: false); GameObject val15 = new GameObject("TSAct"); val15.transform.SetParent(val3.transform, false); val15.AddComponent(); UIFactory.AddHLG(val15, 6f); UIFactory.AddLE(val15, -1f, -1f, -1f, 30f, -1f, 0f); Transform transform7 = val15.transform; Color c_WHITE6 = C_WHITE; Color bgColor = new Color(0.22f, 0.5f, 0.3f, 0.95f); object obj9 = <>c.<>9__819_6; if (obj9 == null) { UnityAction val16 = delegate { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) string localSteamId = MatchTracker.LocalSteamId; ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id) && !string.IsNullOrEmpty(localSteamId) && !(localSteamId == "unknown")) { if (ApiClient.TournamentKind != "async") { List list = new List(); for (int i = 0; i < tSlotChecked.Count; i++) { int num6 = i; string[] time_slot_options = cachedTournament.time_slot_options; if (num6 >= ((time_slot_options != null) ? time_slot_options.Length : 0)) { break; } if (tSlotChecked[i]) { list.Add(cachedTournament.time_slot_options[i]); } } if (list.Count == 0) { CompetitiveUI.ShowNotification("Pick at least one start time below first", new Color(1f, 0.75f, 0.35f)); } else { ApiClient.TournamentSignup(cachedTournament.tournament_id, localSteamId, MatchTracker.LocalDisplayName, list.ToArray()); } } else { ApiClient.TournamentSignup(cachedTournament.tournament_id, localSteamId, MatchTracker.LocalDisplayName); } } }; <>c.<>9__819_6 = val16; obj9 = (object)val16; } txtTSignupBtn = UIFactory.CreateButton("TSign", transform7, "Sign Up for Tournament", 15f, c_WHITE6, bgColor, (UnityAction)obj9, (Vector2?)new Vector2(220f, 28f)); Transform transform8 = val15.transform; Color c_WHITE7 = C_WHITE; Color bgColor2 = new Color(0.5f, 0.2f, 0.2f, 0.95f); object obj10 = <>c.<>9__819_7; if (obj10 == null) { UnityAction val17 = delegate { string localSteamId = MatchTracker.LocalSteamId; ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id) && !string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.TournamentUnsignup(cachedTournament.tournament_id, localSteamId); } }; <>c.<>9__819_7 = val17; obj10 = (object)val17; } txtTUnsignupBtn = UIFactory.CreateButton("TUns", transform8, "Leave Signup", 15f, c_WHITE7, bgColor2, (UnityAction)obj10, (Vector2?)new Vector2(150f, 28f)); txtTUnsignupBtn.SetActive(false); txtTDiscordGate = UIFactory.CreateText("TDG", val15.transform, "", 13f, new Color(1f, 0.6f, 0.4f), 513, (Vector2?)new Vector2(260f, 28f), richText: true, raycastTarget: false); txtTPenalty = UIFactory.CreateText("TPen", val3.transform, "", 14f, C_LABEL, 513, (Vector2?)new Vector2(400f, 22f), richText: true, raycastTarget: false); tVoteBoxPanel = UIFactory.CreatePanel("TVoteBox", val3.transform, C_PANEL); GameObject val18 = tVoteBoxPanel; UIFactory.AddVLG(val18, 2f, 10, 10, 6, 6); UIFactory.AddLE(val18, -1f, -1f, -1f, -1f, -1f, 0f); txtTVoteHdr = UIFactory.CreateText("TVH", val18.transform, "Pick Your Start Times (multi-select)", 16f, C_SUB, 513, (Vector2?)new Vector2(410f, 22f), richText: true, raycastTarget: false); tTimeVoteRow = new GameObject("TVR"); tTimeVoteRow.transform.SetParent(val18.transform, false); tTimeVoteRow.AddComponent(); UIFactory.AddVLG(tTimeVoteRow); for (int num = 0; num < 4; num++) { GameObject val19 = new GameObject($"SlotRow{num}"); val19.transform.SetParent(tTimeVoteRow.transform, false); val19.AddComponent(); UIFactory.AddHLG(val19, 10f); UIFactory.AddLE(val19, -1f, -1f, -1f, 24f, -1f, 0f); for (int num2 = 0; num2 < 2; num2++) { int idx = num * 2 + num2; GameObject val20 = new GameObject($"Slot{idx}"); val20.transform.SetParent(val19.transform, false); val20.AddComponent(); UIFactory.AddHLG(val20, 5f); UIFactory.AddLE(val20, 180f, -1f, 200f, -1f, 0f, 0f); GameObject item = UIFactory.CreateButton($"Tog{idx}", val20.transform, "[ ]", 14f, C_WHITE, C_BTN, (UnityAction)delegate { if (tSlotChecked.Count > idx) { tSlotChecked[idx] = !tSlotChecked[idx]; _tVoteLocalEdited = true; dirty = true; } }, (Vector2?)new Vector2(36f, 22f)); tSlotToggles.Add(item); object item2 = UIFactory.CreateText($"Lbl{idx}", val20.transform, "", 13f, C_LABEL, 513, (Vector2?)new Vector2(158f, 22f), richText: true, raycastTarget: false); tSlotLabels.Add(item2); tSlotChecked.Add(item: false); } } GameObject val21 = new GameObject("TVSub"); val21.transform.SetParent(val18.transform, false); val21.AddComponent(); UIFactory.AddHLG(val21, 6f); UIFactory.AddLE(val21, -1f, -1f, -1f, 28f, -1f, 0f); Transform transform9 = val21.transform; Color c_WHITE8 = C_WHITE; Color bgColor3 = new Color(0.22f, 0.38f, 0.65f, 0.95f); object obj11 = <>c.<>9__819_8; if (obj11 == null) { UnityAction val22 = delegate { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id)) { List list = new List(); for (int i = 0; i < tSlotChecked.Count; i++) { int num6 = i; string[] time_slot_options = cachedTournament.time_slot_options; if (num6 >= ((time_slot_options != null) ? time_slot_options.Length : 0)) { break; } if (tSlotChecked[i]) { list.Add(cachedTournament.time_slot_options[i]); } } ApiClient.TournamentTimeVote(cachedTournament.tournament_id, MatchTracker.LocalSteamId, list.ToArray()); _tVoteLocalEdited = false; } }; <>c.<>9__819_8 = val22; obj11 = (object)val22; } tVoteSaveBtn = UIFactory.CreateButton("TVSubmit", transform9, "Save Votes", 15f, c_WHITE8, bgColor3, (UnityAction)obj11, (Vector2?)new Vector2(120f, 26f)); txtTForceCount = UIFactory.CreateText("TFC", val21.transform, "", 13f, C_DIM, 513, (Vector2?)new Vector2(180f, 26f), richText: true, raycastTarget: false); Transform transform10 = val21.transform; Color c_WHITE9 = C_WHITE; Color bgColor4 = new Color(0.55f, 0.35f, 0.15f, 0.95f); object obj12 = <>c.<>9__819_9; if (obj12 == null) { UnityAction val23 = delegate { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id)) { ApiClient.TournamentForceStartVote(cachedTournament.tournament_id, MatchTracker.LocalSteamId); } }; <>c.<>9__819_9 = val23; obj12 = (object)val23; } txtTForceBtn = UIFactory.CreateButton("TFS", transform10, "Force Start", 15f, c_WHITE9, bgColor4, (UnityAction)obj12, (Vector2?)new Vector2(110f, 26f)); tMyMatchPanel = UIFactory.CreatePanel("TMM", val3.transform, C_PANEL); UIFactory.AddVLG(tMyMatchPanel, 3f, 10, 10, 6, 6); UIFactory.AddLE(tMyMatchPanel, -1f, -1f, -1f, -1f, -1f, 0f); txtTMyMatch = UIFactory.CreateText("TMMTxt", tMyMatchPanel.transform, "", 17f, C_WHITE, 513, (Vector2?)new Vector2(400f, 26f), richText: true, raycastTarget: false); UIFactory.SetBold(txtTMyMatch, b: true); UIFactory.SetWordWrap(txtTMyMatch, on: true); txtTRoomCode = UIFactory.CreateText("TRC", tMyMatchPanel.transform, "", 14f, new Color(0.7f, 0.9f, 1f), 513, (Vector2?)new Vector2(400f, 22f), richText: true, raycastTarget: false); GameObject val24 = new GameObject("TMBR"); val24.transform.SetParent(tMyMatchPanel.transform, false); val24.AddComponent(); UIFactory.AddHLG(val24, 6f); UIFactory.AddLE(val24, -1f, -1f, -1f, 28f, -1f, 0f); Transform transform11 = val24.transform; Color c_WHITE10 = C_WHITE; Color bgColor5 = new Color(0.22f, 0.5f, 0.3f, 0.95f); object obj13 = <>c.<>9__819_10; if (obj13 == null) { UnityAction val25 = delegate { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id)) { ApiClient.TournamentReady(cachedTournament.tournament_id, MatchTracker.LocalSteamId); } }; <>c.<>9__819_10 = val25; obj13 = (object)val25; } txtTReadyBtn = UIFactory.CreateButton("TRdy", transform11, "Ready Up (heartbeat)", 15f, c_WHITE10, bgColor5, (UnityAction)obj13, (Vector2?)new Vector2(200f, 26f)); Transform transform12 = val24.transform; Color c_WHITE11 = C_WHITE; Color bgColor6 = new Color(0.55f, 0.4f, 0.15f, 0.95f); object obj14 = <>c.<>9__819_11; if (obj14 == null) { UnityAction val26 = delegate { ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && !string.IsNullOrEmpty(cachedTournament.tournament_id) && cachedTournament.matches != null) { ApiClient.TournamentMatchRow[] matches = cachedTournament.matches; foreach (ApiClient.TournamentMatchRow tournamentMatchRow in matches) { if (tournamentMatchRow.status == "scheduled" && (tournamentMatchRow.p1_signup_id == cachedTournament.my_signup_id || tournamentMatchRow.p2_signup_id == cachedTournament.my_signup_id) && !string.IsNullOrEmpty(tournamentMatchRow.match_id)) { ApiClient.TournamentPlayNow(cachedTournament.tournament_id, tournamentMatchRow.match_id, MatchTracker.LocalSteamId); break; } } } }; <>c.<>9__819_11 = val26; obj14 = (object)val26; } tPlayNowBtn = UIFactory.CreateButton("TPlayNow", transform12, "Play Now (skip break)", 15f, c_WHITE11, bgColor6, (UnityAction)obj14, (Vector2?)new Vector2(190f, 26f)); tPlayNowBtn.SetActive(false); Transform transform13 = val24.transform; Color c_WHITE12 = C_WHITE; Color bgColor7 = new Color(0.22f, 0.38f, 0.65f, 0.95f); object obj15 = <>c.<>9__819_12; if (obj15 == null) { UnityAction val27 = delegate { //IL_0148: Unknown result type (might be due to invalid IL or missing references) ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament != null && cachedTournament.matches != null) { ApiClient.TournamentMatchRow[] matches = cachedTournament.matches; foreach (ApiClient.TournamentMatchRow tournamentMatchRow in matches) { if ((tournamentMatchRow.status == "ready" || tournamentMatchRow.status == "active") && (tournamentMatchRow.p1_signup_id == cachedTournament.my_signup_id || tournamentMatchRow.p2_signup_id == cachedTournament.my_signup_id) && !string.IsNullOrEmpty(tournamentMatchRow.match_id)) { string text = ((!string.IsNullOrEmpty(tournamentMatchRow.photon_room_name)) ? tournamentMatchRow.photon_room_name : ("sct-" + tournamentMatchRow.match_id.Replace("-", "").Substring(0, 12))); _tournamentDispatchedMatches.Remove(tournamentMatchRow.match_id); Plugin.SetPendingRoom(text, cachedTournament.photon_region); CompetitiveUI.ShowNotification("Reconnecting to " + text + " (region " + (cachedTournament.photon_region ?? "default") + ")", new Color(0.5f, 0.8f, 1f)); break; } } } }; <>c.<>9__819_12 = val27; obj15 = (object)val27; } txtTReconnectBtn = UIFactory.CreateButton("TRC_btn", transform13, "Reconnect to Match", 14f, c_WHITE12, bgColor7, (UnityAction)obj15, (Vector2?)new Vector2(170f, 26f)); tMyMatchPanel.SetActive(false); GameObject val28 = new GameObject("TRight"); val28.transform.SetParent(val.transform, false); val28.AddComponent(); UIFactory.AddVLG(val28, 4f); UIFactory.AddLE(val28, -1f, -1f, -1f, -1f, 1f, 1f); GameObject val29 = UIFactory.CreatePanel("TSignBox", val28.transform, C_PANEL); UIFactory.AddVLG(val29, 2f, 8, 8, 6, 6); UIFactory.AddLE(val29, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.CreateText("TSH", val29.transform, "Signups", 18f, C_GOLD, 513, (Vector2?)new Vector2(280f, 24f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("TSSV", val29.transform, 1f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); tSignupList = scrollViewRefs2.content; for (int num3 = 0; num3 < 24; num3++) { GameObject val30 = new GameObject($"TSig{num3}"); val30.transform.SetParent(tSignupList.transform, false); val30.AddComponent(); UIFactory.AddHLG(val30, 6f); UIFactory.AddLE(val30, -1f, -1f, -1f, 22f, -1f, 0f); object obj16 = UIFactory.CreateText("sd", val30.transform, "", 14f, C_GOLD, 514, (Vector2?)new Vector2(40f, 22f), richText: true, raycastTarget: false); object obj17 = UIFactory.CreateText("nm", val30.transform, "", 15f, C_WHITE, 513, (Vector2?)new Vector2(280f, 22f), richText: true, raycastTarget: false); object obj18 = UIFactory.CreateText("st", val30.transform, "", 13f, C_DIM, 516, (Vector2?)new Vector2(140f, 22f), richText: true, raycastTarget: false); tSignupRowPool.Add(val30); tSignupRowTexts.Add(new object[3] { obj16, obj17, obj18 }); val30.SetActive(false); } tTournBetsBox = UIFactory.CreatePanel("TBetsBox", val28.transform, C_PANEL); UIFactory.AddVLG(tTournBetsBox, 2f, 8, 8, 6, 6); UIFactory.AddLE(tTournBetsBox, -1f, -1f, -1f, -1f, -1f, 0f); tTournBetsHeader = UIFactory.CreateText("TBH_Bets", tTournBetsBox.transform, "Upcoming Match Bets", 17f, C_WHITE, 513, (Vector2?)new Vector2(360f, 24f), richText: true, raycastTarget: false); tTournBetsContainer = new GameObject("TBetsRows"); tTournBetsContainer.transform.SetParent(tTournBetsBox.transform, false); tTournBetsContainer.AddComponent(); UIFactory.AddVLG(tTournBetsContainer); tTournBetsBox.SetActive(false); GameObject val31 = UIFactory.CreatePanel("TBrkBox", val28.transform, C_PANEL); UIFactory.AddVLG(val31, 2f, 8, 8, 6, 6); UIFactory.AddLE(val31, -1f, -1f, -1f, -1f, -1f, 1f); UIFactory.CreateText("TBH", val31.transform, "Bracket", 18f, C_GOLD, 513, (Vector2?)new Vector2(280f, 24f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("TBSV", val31.transform, 1f); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); tBracketList = scrollViewRefs3.content; for (int num4 = 0; num4 < 50; num4++) { int idx2 = num4; GameObject val32 = new GameObject($"TBR{num4}"); val32.transform.SetParent(tBracketList.transform, false); val32.AddComponent(); UIFactory.AddHLG(val32, 6f); UIFactory.AddLE(val32, -1f, -1f, -1f, 22f, -1f, 0f); object item3 = UIFactory.CreateText("txt", val32.transform, "", 14f, C_WHITE, 513, (Vector2?)new Vector2(500f, 22f), richText: true, raycastTarget: true); ClickHandler clickHandler = val32.AddComponent(); clickHandler.onClick = delegate { if (ClickGuard.Claim() && idx2 < _tBracketRowPurposes.Count) { BracketRowPurpose bracketRowPurpose = _tBracketRowPurposes[idx2]; if (bracketRowPurpose.isHeader && !string.IsNullOrEmpty(bracketRowPurpose.groupKey)) { _tBracketExpanded.TryGetValue(bracketRowPurpose.groupKey, out var value); _tBracketExpanded[bracketRowPurpose.groupKey] = !value; dirty = true; } } }; if (UIFactory.tImage != null) { Component obj19 = val32.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj19, (object)new Color(1f, 1f, 1f, 0.01f)); UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj19, true); } tBracketRowPool.Add(val32); tBracketRowTexts.Add(item3); val32.SetActive(false); } tBracketVisual = new GameObject("TBV"); tBracketVisual.transform.SetParent(tBracketList.transform, false); RectTransform val33 = tBracketVisual.AddComponent(); val33.anchorMin = new Vector2(0f, 1f); val33.anchorMax = new Vector2(0f, 1f); val33.pivot = new Vector2(0f, 1f); val33.sizeDelta = new Vector2(900f, 600f); UIFactory.AddLE(tBracketVisual, 900f, 600f, 900f, 600f, 0f, 0f); tBracketVisual.SetActive(false); txtTMyHistory = UIFactory.CreateText("TMH", val28.transform, "", 14f, new Color(1f, 0.87f, 0.52f), 513, (Vector2?)new Vector2(600f, 22f), richText: true, raycastTarget: false); GameObject val34 = UIFactory.CreatePanel("TRH", val28.transform, C_PANEL); UIFactory.AddVLG(val34, 2f, 8, 8, 6, 6); UIFactory.AddLE(val34, -1f, -1f, -1f, 150f, -1f, 0f); UIFactory.CreateText("TRH_h", val34.transform, "Recent Tournaments", 16f, C_SUB, 513, (Vector2?)new Vector2(260f, 22f), richText: true, raycastTarget: false); UIFactory.ScrollViewRefs scrollViewRefs4 = UIFactory.CreateScrollView("TRHSV", val34.transform, 1f); UIFactory.AddLE(scrollViewRefs4.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); tHistoryList = scrollViewRefs4.content; for (int num5 = 0; num5 < 12; num5++) { GameObject val35 = new GameObject($"TH{num5}"); val35.transform.SetParent(tHistoryList.transform, false); val35.AddComponent(); UIFactory.AddHLG(val35); UIFactory.AddLE(val35, -1f, -1f, -1f, 20f, -1f, 0f); object item4 = UIFactory.CreateText("txt", val35.transform, "", 13f, C_LABEL, 513, (Vector2?)new Vector2(520f, 20f), richText: true, raycastTarget: false); tHistoryRowPool.Add(val35); tHistoryRowTexts.Add(item4); val35.SetActive(false); } return val; } private static TimeZoneInfo _ResolveTz() { string text = Plugin.TournamentTimezone?.Value ?? "Local"; if (text == "Local") { return TimeZoneInfo.Local; } (string, string)[] tzPresets = _tzPresets; for (int i = 0; i < tzPresets.Length; i++) { (string, string) tuple = tzPresets[i]; if (!string.Equals(tuple.Item1, text, StringComparison.OrdinalIgnoreCase)) { continue; } if (string.IsNullOrEmpty(tuple.Item2)) { return TimeZoneInfo.Local; } try { return TimeZoneInfo.FindSystemTimeZoneById(tuple.Item2); } catch { return TimeZoneInfo.Local; } } try { return TimeZoneInfo.FindSystemTimeZoneById(text); } catch { return TimeZoneInfo.Local; } } private static string _TzLabel() { string text = Plugin.TournamentTimezone?.Value ?? "Local"; (string, string)[] tzPresets = _tzPresets; for (int i = 0; i < tzPresets.Length; i++) { (string, string) tuple = tzPresets[i]; if (string.Equals(tuple.Item1, text, StringComparison.OrdinalIgnoreCase)) { return tuple.Item1; } } return text; } private static void _CycleTz() { string b = Plugin.TournamentTimezone?.Value ?? "Local"; int num = 0; for (int i = 0; i < _tzPresets.Length; i++) { if (string.Equals(_tzPresets[i].Label, b, StringComparison.OrdinalIgnoreCase)) { num = i; break; } } num = (num + 1) % _tzPresets.Length; Plugin.TournamentTimezone.Value = _tzPresets[num].Label; dirty = true; } private static string _DateFormat() { string text = Plugin.TournamentDateFormat?.Value ?? "ISO"; if (text != "ISO" && text != "US" && text != "EU") { text = "ISO"; } return text; } private static void _CycleDateFormat() { string value = _DateFormat(); int num = Array.IndexOf(_dateFormats, value); if (num < 0) { num = 0; } num = (num + 1) % _dateFormats.Length; Plugin.TournamentDateFormat.Value = _dateFormats[num]; dirty = true; } private static string _FmtSlot(string iso, bool includeTz = true) { if (string.IsNullOrEmpty(iso)) { return "(TBD)"; } try { DateTime dateTime = DateTime.Parse(iso, _INV, DateTimeStyles.RoundtripKind).ToUniversalTime(); TimeZoneInfo destinationTimeZone = _ResolveTz(); DateTime dateTime2 = TimeZoneInfo.ConvertTimeFromUtc(dateTime, destinationTimeZone); string text = _DateFormat() switch { "ISO" => dateTime2.ToString("yyyy-MM-dd HH:mm", _INV), "US" => dateTime2.ToString("ddd MM/dd h:mm tt", _INV), "EU" => dateTime2.ToString("ddd dd/MM HH:mm", _INV), _ => dateTime2.ToString("yyyy-MM-dd HH:mm", _INV), }; return includeTz ? (text + " " + _TzLabel()) : text; } catch { return iso; } } private static void RenderVisualBracket(ApiClient.TournamentSnapshot t, bool blankNames, int blankSize, bool isAsync) { //IL_05e3: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_0664: Unknown result type (might be due to invalid IL or missing references) //IL_066b: Unknown result type (might be due to invalid IL or missing references) //IL_073d: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_06bb: Unknown result type (might be due to invalid IL or missing references) //IL_06c8: Unknown result type (might be due to invalid IL or missing references) //IL_06df: Unknown result type (might be due to invalid IL or missing references) //IL_06e1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)tBracketVisual == (Object)null) { return; } for (int num = tBracketVisual.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)tBracketVisual.transform.GetChild(num)).gameObject); } ApiClient.TournamentMatchRow[] array = t.matches; if (array == null || array.Length == 0) { if (blankSize < 4) { return; } array = SynthesizeBlankBracket(blankSize); } Dictionary>> dictionary = new Dictionary>>(); int num2 = 0; int num3 = 0; ApiClient.TournamentMatchRow[] array2 = array; foreach (ApiClient.TournamentMatchRow tournamentMatchRow in array2) { if (!dictionary.TryGetValue(tournamentMatchRow.bracket_side, out var value)) { value = new Dictionary>(); dictionary[tournamentMatchRow.bracket_side] = value; } if (!value.TryGetValue(tournamentMatchRow.round, out var value2)) { value2 = new List(); value[tournamentMatchRow.round] = value2; } value2.Add(tournamentMatchRow); if (tournamentMatchRow.bracket_side == "W" && tournamentMatchRow.round > num2) { num2 = tournamentMatchRow.round; } if (tournamentMatchRow.bracket_side == "L" && tournamentMatchRow.round > num3) { num3 = tournamentMatchRow.round; } } Dictionary> value3; List value4; int num4 = ((dictionary.TryGetValue("W", out value3) && value3.TryGetValue(1, out value4)) ? value4.Count : 0); Dictionary> value5; List value6; int num5 = ((dictionary.TryGetValue("L", out value5) && value5.TryGetValue(1, out value6)) ? value6.Count : 0); int num6 = Math.Max(num4 * 56, 56); int num7 = Math.Max(num5 * 56, 56); Dictionary dictionary2 = new Dictionary(); int num8 = 0; int num9 = 0; if (value3 != null) { foreach (KeyValuePair> item in value3) { int key = item.Key; foreach (ApiClient.TournamentMatchRow item2 in item.Value) { int slot_idx = item2.slot_idx; int num10 = 12 + (key - 1) * 194; float num11 = 56 * (1 << key - 1); float num12 = 12f + (float)slot_idx * num11 + (num11 - 56f) / 2f; dictionary2[item2.match_id] = new Vector2((float)num10, num12); if (num10 + 170 > num8) { num8 = num10 + 170; } if (num12 + 48f > (float)num9) { num9 = (int)(num12 + 48f); } } } } int num13 = 12 + num6 + 30; if (value5 != null) { foreach (KeyValuePair> item3 in value5) { int key2 = item3.Key; foreach (ApiClient.TournamentMatchRow item4 in item3.Value) { int slot_idx2 = item4.slot_idx; int num14 = 12 + (key2 - 1) * 194; int num15 = (key2 - 1) / 2; float num16 = 56 * (1 << num15); float num17 = ((key2 % 2 == 0) ? (num16 / 2f) : 0f); float num18 = (float)num13 + (float)slot_idx2 * num16 + num17; dictionary2[item4.match_id] = new Vector2((float)num14, num18); if (num14 + 170 > num8) { num8 = num14 + 170; } if (num18 + 48f > (float)num9) { num9 = (int)(num18 + 48f); } } } } int num19 = 12 + Math.Max(num2, num3) * 194; float num20 = 12f + (float)(num6 + 30) / 2f - 24f; int num21 = 0; string[] array3 = new string[3] { "GF", "GF_RESET", "TP" }; foreach (string key3 in array3) { if (!dictionary.TryGetValue(key3, out var value7)) { continue; } foreach (KeyValuePair> item5 in value7) { foreach (ApiClient.TournamentMatchRow item6 in item5.Value) { int num22 = num19; float num23 = num20 + (float)(num21 * 62); dictionary2[item6.match_id] = new Vector2((float)num22, num23); if (num22 + 170 > num8) { num8 = num22 + 170; } if (num23 + 48f > (float)num9) { num9 = (int)(num23 + 48f); } num21++; } } } int num24 = num8 + 12; int num25 = num9 + 12; RectTransform component = tBracketVisual.GetComponent(); component.sizeDelta = new Vector2((float)num24, (float)num25); GameObject go = tBracketVisual; float prefH = num25; float minH = num25; float prefW = num24; UIFactory.AddLE(go, num24, minH, prefW, prefH, 0f, 0f); ApiClient.TournamentMatchRow[] array4 = array; Vector2 toTopLeftPx = default(Vector2); Vector2 fromTopLeftPx = default(Vector2); foreach (ApiClient.TournamentMatchRow tournamentMatchRow2 in array4) { if (tournamentMatchRow2.prereq_match_ids == null || !dictionary2.TryGetValue(tournamentMatchRow2.match_id, out var value8)) { continue; } ((Vector2)(ref toTopLeftPx))..ctor(value8.x, value8.y + 24f); string[] prereq_match_ids = tournamentMatchRow2.prereq_match_ids; foreach (string text in prereq_match_ids) { if (!string.IsNullOrEmpty(text) && dictionary2.TryGetValue(text, out var value9)) { ((Vector2)(ref fromTopLeftPx))..ctor(value9.x + 170f, value9.y + 24f); DrawBracketConnector(tBracketVisual, fromTopLeftPx, toTopLeftPx); } } } ApiClient.TournamentMatchRow[] array5 = array; foreach (ApiClient.TournamentMatchRow tournamentMatchRow3 in array5) { if (dictionary2.TryGetValue(tournamentMatchRow3.match_id, out var value10)) { CreateBracketCell(tBracketVisual, tournamentMatchRow3, value10, blankNames, isAsync); } } } private static void DrawBracketConnector(GameObject host, Vector2 fromTopLeftPx, Vector2 toTopLeftPx) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) float num = (fromTopLeftPx.x + toTopLeftPx.x) / 2f; float num2 = 2f; Color c = default(Color); ((Color)(ref c))..ctor(1f, 0.85f, 0.3f, 0.55f); DrawLineSegment(host, fromTopLeftPx.x, fromTopLeftPx.y, num - fromTopLeftPx.x, num2, c); float y = Math.Min(fromTopLeftPx.y, toTopLeftPx.y); float h = Math.Abs(toTopLeftPx.y - fromTopLeftPx.y) + num2; DrawLineSegment(host, num - num2 / 2f, y, num2, h, c); DrawLineSegment(host, num, toTopLeftPx.y, toTopLeftPx.x - num, num2, c); } private static void DrawLineSegment(GameObject host, float x, float y, float w, float h, Color c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0031: 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_005d: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Conn"); val.transform.SetParent(host.transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0f, 1f); val2.anchorMax = new Vector2(0f, 1f); val2.pivot = new Vector2(0f, 1f); val2.anchoredPosition = new Vector2(x, 0f - y); val2.sizeDelta = new Vector2(Math.Max(1f, w), Math.Max(1f, h)); Component obj = val.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, c); UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, false); } private static void CreateBracketCell(GameObject host, ApiClient.TournamentMatchRow m, Vector2 topLeftPx, bool blankNames, bool isAsync) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_0071: 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) Color bgColor = (m.is_bye ? new Color(0.18f, 0.2f, 0.24f, 0.8f) : ((m.status == "completed") ? new Color(0.18f, 0.32f, 0.45f, 0.85f) : ((m.status == "active") ? new Color(0.2f, 0.42f, 0.2f, 0.9f) : ((m.status == "ready") ? new Color(0.45f, 0.38f, 0.15f, 0.9f) : new Color(0.16f, 0.17f, 0.21f, 0.85f))))); GameObject val = UIFactory.CreatePanel("M_" + m.match_id, host.transform, bgColor); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(topLeftPx.x, 0f - topLeftPx.y); component.sizeDelta = new Vector2(170f, 48f); string playerName = (blankNames ? "?" : (m.p1_display_name ?? (m.is_bye ? "BYE" : "TBD"))); string playerName2 = (blankNames ? "?" : (m.p2_display_name ?? (m.is_bye ? "BYE" : "TBD"))); string score = ""; string score2 = ""; if (m.status == "completed") { score = m.p1_series_wins.ToString(); score2 = m.p2_series_wins.ToString(); } else if (m.status == "forfeit" || m.status == "double_forfeit") { score = ((m.status == "forfeit") ? "FF" : "FF"); score2 = ((m.status == "forfeit") ? "FF" : "FF"); } int winnerSlot = 0; if (m.status == "completed") { winnerSlot = ((m.p1_series_wins > m.p2_series_wins) ? 1 : 2); } float num = 23f; CreateBracketCellRow(val, playerName, score, 1, winnerSlot, 0f, num, 170f); CreateBracketCellRow(val, playerName2, score2, 2, winnerSlot, num + 1f, num, 170f); } private static void CreateBracketCellRow(GameObject cell, string playerName, string score, int rowSlot, int winnerSlot, float yTop, float h, float cellW) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_003c: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"R{rowSlot}"); val.transform.SetParent(cell.transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0f, 1f); val2.anchorMax = new Vector2(0f, 1f); val2.pivot = new Vector2(0f, 1f); val2.anchoredPosition = new Vector2(0f, 0f - yTop); val2.sizeDelta = new Vector2(cellW, h); bool flag = winnerSlot == rowSlot; bool flag2 = winnerSlot != 0 && winnerSlot != rowSlot; Color color = (flag ? new Color(0.95f, 1f, 0.7f) : (flag2 ? new Color(0.55f, 0.55f, 0.55f) : new Color(0.92f, 0.95f, 1f))); string text = (flag ? ("" + playerName + "") : playerName); UIFactory.CreateText("N", val.transform, text, 13f, color, 513, (Vector2?)new Vector2(cellW - 36f, h), richText: true, raycastTarget: false); Transform val3 = val.transform.Find("N"); if ((Object)(object)val3 != (Object)null) { RectTransform component = ((Component)val3).GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(8f, 0f); } if (!string.IsNullOrEmpty(score)) { Color color2 = (flag ? new Color(1f, 0.95f, 0.4f) : new Color(0.7f, 0.7f, 0.7f)); UIFactory.CreateText("S", val.transform, score, 14f, color2, 516, (Vector2?)new Vector2(28f, h), richText: true, raycastTarget: false); Transform val4 = val.transform.Find("S"); if ((Object)(object)val4 != (Object)null) { RectTransform component2 = ((Component)val4).GetComponent(); component2.anchorMin = new Vector2(0f, 1f); component2.anchorMax = new Vector2(0f, 1f); component2.pivot = new Vector2(0f, 1f); component2.anchoredPosition = new Vector2(cellW - 32f, 0f); } } } private static ApiClient.TournamentMatchRow[] SynthesizeBlankBracket(int n) { List list = new List(); int num = 0; int num2 = n; while (num2 > 1) { num2 >>= 1; num++; } Dictionary<(int, int), string> dictionary = new Dictionary<(int, int), string>(); for (int i = 1; i <= num; i++) { int num3 = n / (1 << i); for (int j = 0; j < num3; j++) { string text = $"BLANK_W_{i}_{j}"; dictionary[(i, j)] = text; List list2 = new List(); if (i > 1) { if (dictionary.TryGetValue((i - 1, j * 2), out var value)) { list2.Add(value); } if (dictionary.TryGetValue((i - 1, j * 2 + 1), out var value2)) { list2.Add(value2); } } list.Add(new ApiClient.TournamentMatchRow { match_id = text, bracket_side = "W", round = i, slot_idx = j, status = "pending", prereq_match_ids = list2.ToArray() }); } } list.Add(new ApiClient.TournamentMatchRow { match_id = "BLANK_GF", bracket_side = "GF", round = 1, slot_idx = 0, status = "pending", prereq_match_ids = new string[0] }); return list.ToArray(); } private static void RefreshTournamentBets() { if ((Object)(object)tTournBetsBox == (Object)null || (Object)(object)tTournBetsContainer == (Object)null) { return; } foreach (GameObject item in tTournBetRowPool) { item.SetActive(false); } List cachedActiveSeries = ApiClient.CachedActiveSeries; List list = new List(); if (cachedActiveSeries != null) { foreach (ApiClient.ActiveSeriesEntry item2 in cachedActiveSeries) { if (item2.is_tournament && item2.phase == "pre_match") { list.Add(item2); } } } if (list.Count == 0) { tTournBetsBox.SetActive(false); return; } tTournBetsBox.SetActive(true); UIFactory.SetText(tTournBetsHeader, $"Upcoming Match Bets ({list.Count})"); int num = 0; foreach (ApiClient.ActiveSeriesEntry item3 in list) { GameObject orCreateTournBetRow = GetOrCreateTournBetRow(num++); ApplyHeaderRow(orCreateTournBetRow, item3); GameObject orCreateTournBetRow2 = GetOrCreateTournBetRow(num++); ApplyBetRow(orCreateTournBetRow2, item3, betOnP1: true); GameObject orCreateTournBetRow3 = GetOrCreateTournBetRow(num++); ApplyBetRow(orCreateTournBetRow3, item3, betOnP1: false); } } private static GameObject GetOrCreateTournBetRow(int idx) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown while (tTournBetRowPool.Count <= idx) { GameObject val = new GameObject($"tbet{tTournBetRowPool.Count}"); val.transform.SetParent(tTournBetsContainer.transform, false); val.AddComponent(); UIFactory.AddHLG(val); UIFactory.AddLE(val, -1f, -1f, -1f, 26f, -1f, 0f); tTournBetRowPool.Add(val); } GameObject val2 = tTournBetRowPool[idx]; for (int num = val2.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)val2.transform.GetChild(num)).gameObject); } val2.SetActive(true); return val2; } private static void RefreshTournaments() { //IL_0094: 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_017d: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_16da: Unknown result type (might be due to invalid IL or missing references) //IL_1646: Unknown result type (might be due to invalid IL or missing references) //IL_108e: Unknown result type (might be due to invalid IL or missing references) RefreshTournamentBets(); ApiClient.TournamentSnapshot cachedTournament = ApiClient.CachedTournament; if (cachedTournament == null) { UIFactory.SetText(txtTState, "Loading..."); UIFactory.SetText(txtTWhen, ""); if ((Object)(object)txtTSignupBtn != (Object)null) { txtTSignupBtn.SetActive(false); } if ((Object)(object)txtTUnsignupBtn != (Object)null) { txtTUnsignupBtn.SetActive(false); } if ((Object)(object)tMyMatchPanel != (Object)null) { tMyMatchPanel.SetActive(false); } return; } Color c = C_GOLD; string s; switch (cachedTournament.status) { case "voting": s = "VOTING / SIGNUPS OPEN"; ((Color)(ref c))..ctor(0.4f, 1f, 0.5f); break; case "locked": s = "LOCKED - STARTING SOON"; ((Color)(ref c))..ctor(1f, 0.85f, 0.3f); break; case "running": s = "LIVE"; ((Color)(ref c))..ctor(1f, 0.4f, 0.4f); break; case "completed": s = "COMPLETED"; c = C_DIM; break; case "cancelled": s = "CANCELLED (not enough players)"; c = C_DIM; break; default: s = "No active tournament"; break; } UIFactory.SetText(txtTState, s); UIFactory.SetColor(txtTState, c); if ((Object)(object)txtTTzButton != (Object)null) { UIFactory.SetText(UIFactory.GetButtonText(txtTTzButton), _TzLabel()); } if ((Object)(object)txtTDateFmtButton != (Object)null) { UIFactory.SetText(UIFactory.GetButtonText(txtTDateFmtButton), _DateFormat()); } bool flag = ApiClient.TournamentKind == "async"; _tInfoTitle = (flag ? "How It Works - Async (6-week)" : "How It Works - Sync (weekly)"); _tInfoInstructions = (flag ? "HOW IT WORKS (Async)\n 1. Sign up any time during the 7-day signup window (Discord must be linked)\n 2. On lock, bracket is built and first-round matches activate\n 3. Coordinate with your opponent via /dm-opponent on Discord\n 4. Both of you enable Ranked, join any private lobby in ROUNDS, play the BO3\n 5. Mod records the result automatically - no manual report, no room code needed\n 6. Winner advances in bracket; loser drops to LB (or is eliminated)\n\nAUTO-RECORDING REQUIREMENTS\n * Both players must have Ranked toggled ON in-game when playing\n * Any private ROUNDS lobby works - tournament doesn't force a specific room\n * Once you hit 2 BO3 wins, the mod advances the bracket and notifies you\n\nSCHEDULING\n * No fixed start time - self-paced, 7 days per match\n * Total tournament runs up to 6-9 weeks depending on how fast matches happen\n * Miss the deadline and you forfeit that match (tracked in penalty %)\n\nFORMAT\n * Double-elim BO3 - lose once, you drop to losers bracket\n * Grand Final: WB champ vs LB champ (bracket reset if LB wins first BO3)\n * All matches count toward ranked Elo\n\nPENALTY %\n * Grows when you sign up but forfeit a match by missing the 7-day deadline" : "HOW IT WORKS (Sync)\n 1. Pick every start time you can make, then sign up (Discord must be linked)\n 2. It locks when 8+ players agree on one time - decided 2 days before the default start, so you always get 24h+ notice; players who can't make the winning time are removed (no penalty)\n 3. Have ROUNDS open at start time (main menu is fine - no tab-sitting needed)\n 4. Mod auto-connects you to your opponent - no queue, no invites\n 5. Play BO3, bracket advances automatically - plan for a couple of hours total\n\nBETWEEN MATCHES\n * ~7 min breather before each of your matches after round 1\n * Both players press Play Now to skip the break and start early\n * Show up within 10 min of your match or forfeit\n * Bracket hidden until start (no scouting your first opponent)\n\nFORMAT\n * Double-elim BO3 (first to 2) - losing once drops you to the losers bracket\n * Matches run in parallel: your next match schedules the moment its players are known\n * Top seeds get byes when fewer than 16 sign up\n * Grand Final: WB champ vs LB champ (bracket reset if LB wins first BO3)\n * All matches count toward ranked Elo\n\nPENALTY %\n * Grows when you sign up but no-show at match time\n * Lower penalty = priority if more than 16 sign up"); if (cachedTournament.prize_gold_1 > 0) { int num = Math.Max(8, cachedTournament.prize_players); string text = ((!(cachedTournament.status == "voting")) ? "" : ((cachedTournament.prize_players < 16) ? $"\n Every signup past 8 grows the pot - 16 players doubles it! (now: {cachedTournament.prize_players})" : "\n Max pot - 16 players!")); _tInfoPrizes = string.Format("PRIZES (at {0} players{1})\n", num, (cachedTournament.status == "voting") ? ", live" : "") + $" * 1st - {cachedTournament.prize_gold_1}g / {cachedTournament.prize_xp_1} XP / Winner role\n" + $" * 2nd - {cachedTournament.prize_gold_2}g / {cachedTournament.prize_xp_2} XP / Runner Up role\n" + $" * 3rd - {cachedTournament.prize_gold_3}g / {cachedTournament.prize_xp_3} XP / 3rd Place role (loser of LB final)" + text; } else { _tInfoPrizes = ""; } if ((Object)(object)tSubTabSyncBtn != (Object)null) { UIFactory.SetImageColor(tSubTabSyncBtn, flag ? C_TAB : C_TABACT); UIFactory.SetColor(UIFactory.GetButtonText(tSubTabSyncBtn), flag ? C_LABEL : C_WHITE); UIFactory.SetBold(UIFactory.GetButtonText(tSubTabSyncBtn), !flag); } if ((Object)(object)tSubTabAsyncBtn != (Object)null) { UIFactory.SetImageColor(tSubTabAsyncBtn, flag ? C_TABACT : C_TAB); UIFactory.SetColor(UIFactory.GetButtonText(tSubTabAsyncBtn), flag ? C_WHITE : C_LABEL); UIFactory.SetBold(UIFactory.GetButtonText(tSubTabAsyncBtn), flag); } try { DateTime dateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, _ResolveTz()); UIFactory.SetText(s: "now: " + _DateFormat() switch { "ISO" => dateTime.ToString("yyyy-MM-dd HH:mm", _INV), "US" => dateTime.ToString("ddd MM/dd h:mm tt", _INV), "EU" => dateTime.ToString("ddd dd/MM HH:mm", _INV), _ => dateTime.ToString("yyyy-MM-dd HH:mm", _INV), } + "", t: txtTTzNow); } catch { UIFactory.SetText(txtTTzNow, ""); } string s2 = ""; if (!string.IsNullOrEmpty(cachedTournament.scheduled_start_ts)) { s2 = "Starts: " + _FmtSlot(cachedTournament.scheduled_start_ts) + ""; } else if (!string.IsNullOrEmpty(cachedTournament.default_start_ts)) { s2 = "Default start: " + _FmtSlot(cachedTournament.default_start_ts) + " Signups close: " + _FmtSlot(cachedTournament.lock_at); } UIFactory.SetText(txtTWhen, s2); bool flag2 = !string.IsNullOrEmpty(cachedTournament.my_signup_id); bool active = cachedTournament.status == "voting" && !flag2 && cachedTournament.my_discord_linked; if ((Object)(object)txtTSignupBtn != (Object)null) { txtTSignupBtn.SetActive(active); } if ((Object)(object)txtTUnsignupBtn != (Object)null) { txtTUnsignupBtn.SetActive(cachedTournament.status == "voting" && flag2); } UIFactory.SetText(txtTDiscordGate, cachedTournament.my_discord_linked ? "" : "Link Discord first (Home tab) to sign up."); UIFactory.SetText(txtTPenalty, $"Your no-show penalty: {cachedTournament.my_penalty_pct * 100f:0.0}%"); if ((Object)(object)tVoteBoxPanel != (Object)null) { tVoteBoxPanel.SetActive(!flag); } bool flag3 = !flag && cachedTournament.status == "voting"; string[] time_slot_options = cachedTournament.time_slot_options; int num2 = ((time_slot_options != null) ? time_slot_options.Length : 0); string text2 = string.Join("|", cachedTournament.time_slot_options ?? Array.Empty()); if (text2 != _tVoteSlotSig) { _tVoteSlotSig = text2; _tVoteLocalEdited = false; } HashSet hashSet = new HashSet(cachedTournament.my_votes ?? Array.Empty()); Dictionary dictionary = new Dictionary(); if (cachedTournament.time_slot_tallies != null) { ApiClient.TimeVoteTally[] time_slot_tallies = cachedTournament.time_slot_tallies; foreach (ApiClient.TimeVoteTally timeVoteTally in time_slot_tallies) { dictionary[timeVoteTally.slot_ts] = timeVoteTally.votes; } } if (txtTVoteHdr != null) { int num3 = 0; foreach (KeyValuePair item in dictionary) { if (item.Value > num3) { num3 = item.Value; } } UIFactory.SetText(txtTVoteHdr, (cachedTournament.status == "voting") ? ("Pick Your Start Times (multi-select, required to sign up) " + $"best time: {num3}/{cachedTournament.min_players} agreed") : "Pick Your Start Times (multi-select)"); } for (int j = 0; j < tSlotToggles.Count; j++) { if (j >= num2) { ((Component)tSlotToggles[j].transform.parent).gameObject.SetActive(false); continue; } ((Component)tSlotToggles[j].transform.parent).gameObject.SetActive(flag3); string text3 = cachedTournament.time_slot_options[j]; bool flag4 = hashSet.Contains(text3); if (j >= tSlotChecked.Count) { tSlotChecked.Add(flag4); } else if (!_tVoteLocalEdited) { tSlotChecked[j] = flag4; } UIFactory.SetText(UIFactory.GetButtonText(tSlotToggles[j]), tSlotChecked[j] ? "[X]" : "[ ]"); dictionary.TryGetValue(text3, out var value); string text4 = ((value > 0) ? $" ({value})" : ""); UIFactory.SetWordWrap(tSlotLabels[j], on: false); UIFactory.SetText(tSlotLabels[j], _FmtSlot(text3, includeTz: false) + text4); } for (int k = 0; k * 2 < tSlotToggles.Count; k++) { GameObject val = (((Object)(object)tSlotToggles[k * 2].transform.parent.parent != (Object)null) ? ((Component)tSlotToggles[k * 2].transform.parent.parent).gameObject : null); if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)tTimeVoteRow) { continue; } bool active2 = false; for (int l = 0; l < 2 && k * 2 + l < tSlotToggles.Count; l++) { if (((Component)tSlotToggles[k * 2 + l].transform.parent).gameObject.activeSelf) { active2 = true; break; } } val.SetActive(active2); } if ((Object)(object)tVoteSaveBtn != (Object)null) { tVoteSaveBtn.SetActive(flag3 && flag2); } int num4 = 0; if (cachedTournament.signups != null) { ApiClient.TournamentSignupRow[] signups = cachedTournament.signups; foreach (ApiClient.TournamentSignupRow tournamentSignupRow in signups) { if (!tournamentSignupRow.is_speculative) { num4++; } } } bool flag5 = !flag && flag3 && flag2 && num4 >= cachedTournament.min_players; UIFactory.SetText(txtTForceCount, (!(cachedTournament.status == "voting")) ? "" : (flag5 ? $"Force-start votes: {cachedTournament.force_vote_count}/{num4}" : ((!flag2) ? "Sign up to unlock force-start" : $"Force-start unlocks at {cachedTournament.min_players} signups ({num4}/{cachedTournament.min_players})"))); if ((Object)(object)txtTForceBtn != (Object)null) { txtTForceBtn.SetActive(flag5); } bool flag6 = false; bool active3 = false; bool flag7 = false; string s3 = ""; string text5 = ""; if (cachedTournament.status == "running" && flag2 && cachedTournament.matches != null) { ApiClient.TournamentMatchRow[] matches = cachedTournament.matches; foreach (ApiClient.TournamentMatchRow tournamentMatchRow in matches) { if (tournamentMatchRow.status != "scheduled" || (tournamentMatchRow.p1_signup_id != cachedTournament.my_signup_id && tournamentMatchRow.p2_signup_id != cachedTournament.my_signup_id)) { continue; } string text6 = ((tournamentMatchRow.p1_signup_id == cachedTournament.my_signup_id) ? tournamentMatchRow.p2_display_name : tournamentMatchRow.p1_display_name); string text7 = ""; bool flag8 = false; bool flag9 = false; List cachedMyActiveTournamentMatches = ApiClient.CachedMyActiveTournamentMatches; if (cachedMyActiveTournamentMatches != null) { foreach (ApiClient.ActiveTournamentMatch item2 in cachedMyActiveTournamentMatches) { if (!(item2.match_id == tournamentMatchRow.match_id)) { continue; } flag8 = item2.my_early_ok; flag9 = item2.opp_early_ok; if (item2.scheduled_seconds_left >= 0) { float num5 = (float)item2.scheduled_seconds_left - (Time.realtimeSinceStartup - item2.fetched_at_realtime); if (num5 < 0f) { num5 = 0f; } text7 = $" starts in {(int)(num5 / 60f)}:{(int)(num5 % 60f):00}"; } break; } } string text8 = ((!flag8) ? " (both press Play Now to skip the break)" : (flag9 ? "" : " (Play Now sent - waiting on opponent)")); s3 = string.Format("Next match (R{0}{1}): vs {2} -{3}{4}", tournamentMatchRow.round, (tournamentMatchRow.bracket_side == "TP") ? " 3rd Place" : "", text6 ?? "?", text7, text8); flag6 = true; flag7 = true; active3 = !flag8; break; } ApiClient.TournamentMatchRow[] matches2 = cachedTournament.matches; foreach (ApiClient.TournamentMatchRow tournamentMatchRow2 in matches2) { if ((tournamentMatchRow2.status != "ready" && tournamentMatchRow2.status != "active") || (tournamentMatchRow2.p1_signup_id != cachedTournament.my_signup_id && tournamentMatchRow2.p2_signup_id != cachedTournament.my_signup_id)) { continue; } if (!string.IsNullOrEmpty(tournamentMatchRow2.match_id)) { text5 = ((!string.IsNullOrEmpty(tournamentMatchRow2.photon_room_name)) ? tournamentMatchRow2.photon_room_name : ("sct-" + tournamentMatchRow2.match_id.Replace("-", "").Substring(0, 12))); } string text9 = ((tournamentMatchRow2.p1_signup_id == cachedTournament.my_signup_id) ? tournamentMatchRow2.p2_display_name : tournamentMatchRow2.p1_display_name); string text10 = ((tournamentMatchRow2.p1_signup_id == cachedTournament.my_signup_id) ? tournamentMatchRow2.p2_signup_id : tournamentMatchRow2.p1_signup_id); bool flag10 = false; if (cachedTournament.signups != null) { ApiClient.TournamentSignupRow[] signups2 = cachedTournament.signups; foreach (ApiClient.TournamentSignupRow tournamentSignupRow2 in signups2) { if (tournamentSignupRow2.signup_id == text10) { flag10 = tournamentSignupRow2.ready; break; } } } string text11 = ((!cachedTournament.my_ready) ? "press Ready Up" : (flag10 ? "both ready - connecting..." : "waiting on opponent to ready")); s3 = string.Format("Your match (R{0}{1}): vs {2} - {3}", tournamentMatchRow2.round, (tournamentMatchRow2.bracket_side == "TP") ? " 3rd Place" : "", text9 ?? "?", text11); flag6 = true; if (!flag && cachedTournament.my_ready && flag10 && !string.IsNullOrEmpty(tournamentMatchRow2.match_id)) { string text12 = ((!string.IsNullOrEmpty(tournamentMatchRow2.photon_room_name)) ? tournamentMatchRow2.photon_room_name : ("sct-" + tournamentMatchRow2.match_id.Replace("-", "").Substring(0, 12))); if (!_tournamentDispatchedMatches.Contains(tournamentMatchRow2.match_id) && Plugin.PendingRankedRoom != text12) { _tournamentDispatchedMatches.Add(tournamentMatchRow2.match_id); Plugin.SetPendingRoom(text12, cachedTournament.photon_region); Plugin.Log.LogInfo((object)("[TOURNAMENT] Auto-connecting to " + text12 + " in region '" + (cachedTournament.photon_region ?? "(client default)") + "' for match " + tournamentMatchRow2.match_id)); CompetitiveUI.ShowNotification("Tournament match starting vs " + text9, new Color(0.5f, 1f, 0.5f)); } } break; } } UIFactory.SetText(txtTMyMatch, s3); string text13 = (string.IsNullOrEmpty(cachedTournament.photon_region) ? "" : (" [" + cachedTournament.photon_region.ToUpper() + "]")); UIFactory.SetText(txtTRoomCode, string.IsNullOrEmpty(text5) ? "" : ("Room code: " + text5 + "" + text13 + " (if auto-connect fails, Reconnect or join via Private Lobby)")); if ((Object)(object)txtTReconnectBtn != (Object)null) { txtTReconnectBtn.SetActive(flag6 && !flag7); } if ((Object)(object)tPlayNowBtn != (Object)null) { tPlayNowBtn.SetActive(active3); } if ((Object)(object)txtTReadyBtn != (Object)null) { txtTReadyBtn.SetActive(flag6 && !flag7); } if ((Object)(object)tMyMatchPanel != (Object)null) { tMyMatchPanel.SetActive(flag6); } bool flag11 = cachedTournament.status == "running" || cachedTournament.status == "completed"; int num8 = 0; int num9 = 0; if (cachedTournament.signups != null) { for (int num10 = 0; num10 < cachedTournament.signups.Length; num10++) { if (num8 >= tSignupRowPool.Count) { break; } ApiClient.TournamentSignupRow tournamentSignupRow3 = cachedTournament.signups[num10]; GameObject val2 = tSignupRowPool[num8]; object[] array = tSignupRowTexts[num8]; string s4 = ((flag11 && tournamentSignupRow3.seed > 0) ? $"#{tournamentSignupRow3.seed}" : $"{num10 + 1}."); string text14 = tournamentSignupRow3.display_name ?? ""; if (tournamentSignupRow3.is_speculative) { text14 = "~ " + text14; } string s5 = ((tournamentSignupRow3.placed_rank == 1) ? "1st" : ((tournamentSignupRow3.placed_rank == 2) ? "2nd" : ((tournamentSignupRow3.placed_rank == 3) ? "3rd" : ((!string.IsNullOrEmpty(tournamentSignupRow3.progress_label)) ? (tournamentSignupRow3.progress_label.StartsWith("eliminated") ? ("" + tournamentSignupRow3.progress_label + "") : ((!(tournamentSignupRow3.progress_label == "CHAMPION")) ? ("" + tournamentSignupRow3.progress_label + "") : "CHAMPION")) : (tournamentSignupRow3.forfeited ? "FORFEIT" : ((!tournamentSignupRow3.ready) ? $"{tournamentSignupRow3.penalty_at_signup * 100f:0}% pen" : "ready")))))); UIFactory.SetText(array[0], s4); UIFactory.SetText(array[1], text14); UIFactory.SetText(array[2], s5); val2.SetActive(true); num8++; if (!tournamentSignupRow3.is_speculative) { num9++; } } } for (int num11 = num8; num11 < tSignupRowPool.Count; num11++) { tSignupRowPool[num11].SetActive(false); } int num12 = 0; bool flag12 = !flag && cachedTournament.status != "running" && cachedTournament.status != "completed"; bool flag13 = cachedTournament.matches != null && cachedTournament.matches.Length != 0; bool blankNames = flag12 && flag13; int num13 = 0; if (!flag13 && (cachedTournament.status == "voting" || cachedTournament.status == "locked")) { int num14 = 0; if (cachedTournament.signups != null) { ApiClient.TournamentSignupRow[] signups3 = cachedTournament.signups; foreach (ApiClient.TournamentSignupRow tournamentSignupRow4 in signups3) { if (!tournamentSignupRow4.is_speculative) { num14++; } } } int num16 = Math.Max(num14, 4); for (num13 = 1; num13 < num16; num13 *= 2) { } if (num13 > 16) { num13 = 16; } } if (flag13 || num13 > 0) { for (int num17 = 0; num17 < tBracketRowPool.Count; num17++) { tBracketRowPool[num17].SetActive(false); } if ((Object)(object)tBracketVisual != (Object)null) { tBracketVisual.SetActive(true); RenderVisualBracket(cachedTournament, blankNames, num13, flag); } _tBracketRowPurposes.Clear(); num12 = tBracketRowPool.Count; } else if (flag12 && !flag13) { if ((Object)(object)tBracketVisual != (Object)null) { tBracketVisual.SetActive(false); } if (num12 < tBracketRowPool.Count) { UIFactory.SetColor(tBracketRowTexts[num12], C_DIM); UIFactory.SetText(tBracketRowTexts[num12], "Bracket revealed when the tournament starts (" + _FmtSlot(cachedTournament.scheduled_start_ts) + ")."); tBracketRowPool[num12].SetActive(true); num12++; } } else { if ((Object)(object)tBracketVisual != (Object)null) { tBracketVisual.SetActive(false); } if (num12 < tBracketRowPool.Count) { UIFactory.SetColor(tBracketRowTexts[num12], C_DIM); UIFactory.SetText(tBracketRowTexts[num12], "Bracket appears once signups have rolled in."); tBracketRowPool[num12].SetActive(true); num12++; } } bool flag14 = false; for (int num18 = num12; num18 < tBracketRowPool.Count; num18++) { tBracketRowPool[num18].SetActive(false); } string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown" && ApiClient.CachedPlayerTournaments.TryGetValue(localSteamId, out var value2) && value2 != null && value2.participant_count > 0) { UIFactory.SetText(txtTMyHistory, $"Your placements: 1stx{value2.winner_count} 2ndx{value2.runner_up_count} 3rdx{value2.third_place_count} (played {value2.participant_count})"); } else { UIFactory.SetText(txtTMyHistory, "Your placements: no completed tournaments yet"); } ApiClient.PlayerTournamentEntry[] cachedSiteTournamentHistory = ApiClient.CachedSiteTournamentHistory; int num19 = 0; if (cachedSiteTournamentHistory != null) { for (int num20 = 0; num20 < cachedSiteTournamentHistory.Length; num20++) { if (num19 >= tHistoryRowPool.Count) { break; } ApiClient.PlayerTournamentEntry playerTournamentEntry = cachedSiteTournamentHistory[num20]; string text15 = playerTournamentEntry.ended_at; try { if (!string.IsNullOrEmpty(text15)) { text15 = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(playerTournamentEntry.ended_at, _INV, DateTimeStyles.RoundtripKind).ToUniversalTime(), _ResolveTz()).ToString((_DateFormat() == "EU") ? "dd/MM/yy" : "MM/dd/yy", _INV); } } catch { } string arg = (string.IsNullOrEmpty(playerTournamentEntry.winner_display_name) ? "-" : playerTournamentEntry.winner_display_name); UIFactory.SetText(tHistoryRowTexts[num19], $"{text15} Winner: {arg} ({playerTournamentEntry.signup_count}p)"); tHistoryRowPool[num19].SetActive(true); num19++; } } for (int num21 = num19; num21 < tHistoryRowPool.Count; num21++) { tHistoryRowPool[num21].SetActive(false); } } private static GameObject BuildTeamTab(Transform parent) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Expected O, but got Unknown //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Expected O, but got Unknown //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_048b: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Unknown result type (might be due to invalid IL or missing references) //IL_0457: Expected O, but got Unknown //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_04fc: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Expected O, but got Unknown //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_0579: Unknown result type (might be due to invalid IL or missing references) //IL_0592: Unknown result type (might be due to invalid IL or missing references) //IL_052e: Unknown result type (might be due to invalid IL or missing references) //IL_0533: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Expected O, but got Unknown //IL_05c0: Unknown result type (might be due to invalid IL or missing references) //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_05ec: Expected O, but got Unknown //IL_0658: Unknown result type (might be due to invalid IL or missing references) //IL_0671: Unknown result type (might be due to invalid IL or missing references) //IL_05ab: Unknown result type (might be due to invalid IL or missing references) //IL_05b0: Unknown result type (might be due to invalid IL or missing references) //IL_05b6: Expected O, but got Unknown //IL_069f: Unknown result type (might be due to invalid IL or missing references) //IL_06c9: Unknown result type (might be due to invalid IL or missing references) //IL_06e2: Unknown result type (might be due to invalid IL or missing references) //IL_068a: Unknown result type (might be due to invalid IL or missing references) //IL_068f: Unknown result type (might be due to invalid IL or missing references) //IL_0695: Expected O, but got Unknown //IL_0710: Unknown result type (might be due to invalid IL or missing references) //IL_073a: Unknown result type (might be due to invalid IL or missing references) //IL_074e: Unknown result type (might be due to invalid IL or missing references) //IL_076f: Unknown result type (might be due to invalid IL or missing references) //IL_07d6: Unknown result type (might be due to invalid IL or missing references) //IL_07ea: Unknown result type (might be due to invalid IL or missing references) //IL_0816: Unknown result type (might be due to invalid IL or missing references) //IL_082a: Unknown result type (might be due to invalid IL or missing references) //IL_06fb: Unknown result type (might be due to invalid IL or missing references) //IL_0700: Unknown result type (might be due to invalid IL or missing references) //IL_0706: Expected O, but got Unknown //IL_089d: Unknown result type (might be due to invalid IL or missing references) //IL_08a4: Expected O, but got Unknown //IL_0905: Unknown result type (might be due to invalid IL or missing references) //IL_096c: Unknown result type (might be due to invalid IL or missing references) //IL_0980: Unknown result type (might be due to invalid IL or missing references) //IL_09ac: Unknown result type (might be due to invalid IL or missing references) //IL_09c0: Unknown result type (might be due to invalid IL or missing references) //IL_0a33: Unknown result type (might be due to invalid IL or missing references) //IL_0a9a: Unknown result type (might be due to invalid IL or missing references) //IL_0aae: Unknown result type (might be due to invalid IL or missing references) //IL_0ada: Unknown result type (might be due to invalid IL or missing references) //IL_0aee: Unknown result type (might be due to invalid IL or missing references) //IL_0b83: Unknown result type (might be due to invalid IL or missing references) //IL_0b97: Unknown result type (might be due to invalid IL or missing references) //IL_0bb8: Unknown result type (might be due to invalid IL or missing references) //IL_0bbf: Expected O, but got Unknown //IL_0c19: Unknown result type (might be due to invalid IL or missing references) //IL_0c20: Expected O, but got Unknown //IL_0c8c: Unknown result type (might be due to invalid IL or missing references) //IL_0ca0: Unknown result type (might be due to invalid IL or missing references) //IL_0cbb: Unknown result type (might be due to invalid IL or missing references) //IL_0cc2: Expected O, but got Unknown //IL_0e98: Unknown result type (might be due to invalid IL or missing references) //IL_0eb1: Unknown result type (might be due to invalid IL or missing references) //IL_0ebe: Unknown result type (might be due to invalid IL or missing references) //IL_0ed1: Unknown result type (might be due to invalid IL or missing references) //IL_0ee0: Expected O, but got Unknown //IL_0e1b: Unknown result type (might be due to invalid IL or missing references) //IL_0fc4: Unknown result type (might be due to invalid IL or missing references) //IL_0fcb: Expected O, but got Unknown //IL_1026: Unknown result type (might be due to invalid IL or missing references) //IL_102d: Expected O, but got Unknown //IL_1099: Unknown result type (might be due to invalid IL or missing references) //IL_10ad: Unknown result type (might be due to invalid IL or missing references) //IL_10c8: Unknown result type (might be due to invalid IL or missing references) //IL_10cf: Expected O, but got Unknown //IL_1128: Unknown result type (might be due to invalid IL or missing references) //IL_1141: Unknown result type (might be due to invalid IL or missing references) //IL_0e3e: Unknown result type (might be due to invalid IL or missing references) //IL_116f: Unknown result type (might be due to invalid IL or missing references) //IL_1199: Unknown result type (might be due to invalid IL or missing references) //IL_11ad: Unknown result type (might be due to invalid IL or missing references) //IL_11d9: Unknown result type (might be due to invalid IL or missing references) //IL_11f2: Unknown result type (might be due to invalid IL or missing references) //IL_115a: Unknown result type (might be due to invalid IL or missing references) //IL_115f: Unknown result type (might be due to invalid IL or missing references) //IL_1165: Expected O, but got Unknown //IL_1220: Unknown result type (might be due to invalid IL or missing references) //IL_120b: Unknown result type (might be due to invalid IL or missing references) //IL_1210: Unknown result type (might be due to invalid IL or missing references) //IL_1216: Expected O, but got Unknown GameObject val = new GameObject("Team2v2Outer"); val.transform.SetParent(parent, false); val.AddComponent(); UIFactory.AddVLG(val, 0f); UIFactory.AddLE(val, -1f, -1f, -1f, -1f, -1f, 1f); MakeSubTabAnchor(8, val.transform, asFirst: true); UIFactory.ScrollViewRefs scrollViewRefs = UIFactory.CreateScrollView("Team2v2Scroll", val.transform, 6f); UIFactory.AddLE(scrollViewRefs.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); GameObject content = scrollViewRefs.content; GameObject val2 = new GameObject("Team2v2Inner"); val2.transform.SetParent(content.transform, false); val2.AddComponent(); UIFactory.AddVLG(val2, 6f, 10, 10, 8, 8); content = val2; GameObject val3 = new GameObject("THdrRow"); val3.transform.SetParent(content.transform, false); val3.AddComponent(); UIFactory.AddHLG(val3, 8f); UIFactory.AddLE(val3, -1f, -1f, -1f, 38f, -1f, 0f); txtTeamHeader = UIFactory.CreateText("THdr", val3.transform, "2v2 Ranked (separate Glicko, FF on, BO3 series)", 20f, C_GOLD, 513, (Vector2?)new Vector2(700f, 28f), richText: true, raycastTarget: false); GameObject val4 = new GameObject("THdrSp"); val4.transform.SetParent(val3.transform, false); val4.AddComponent(); UIFactory.AddLE(val4, -1f, -1f, -1f, -1f, 1f); Transform transform = val3.transform; Color c_WHITE = C_WHITE; Color c_BTN = C_BTN; object obj = <>c.<>9__855_0; if (obj == null) { UnityAction val5 = delegate { ShowInfoPopup("2v2 - How It Works", "Two teams of two play a best-of-3 series.\r\n\r\nHOW TO PLAY\r\n\r\n- Random queue uses an Elo band that widens as you wait.\r\n The server auto-balances the teams.\r\n- Custom lobbies have no Elo band.\r\n Joining the lobby is consent to play.\r\n- All 4 players have 120 seconds to ready up.\r\n If time expires, everyone returns to searching.\r\n- After an auto-queue game with a point margin of 3 or more,\r\n the weakest winner may swap with the strongest loser.\r\n\r\nSCORING\r\n\r\n- The first team to win 2 games wins the series.\r\n- 2v2 uses its own Glicko rating.\r\n It does not change your 1v1 rating.\r\n- Rating updates after the completed series.\r\n- W-L and WR count completed series, not individual games.\r\n\r\nREWARDS\r\n\r\n- Each game gives 600 base XP.\r\n A game win gets x1.5, for 900 base XP.\r\n- A series win gives 50 base Gold.\r\n A series loss gives 25 base Gold.\r\n- The opposing team's rating tier can multiply base rewards.\r\n- Game XP converts to Gold at 100 XP = 1 Gold.\r\n\r\nLEADERBOARD COLUMNS\r\n\r\nRank - Position in the currently selected sort.\r\nPlayer - The player's display name.\r\nRating - The player's separate 2v2 Glicko rating.\r\nW-L - Completed series won and lost.\r\nWR - Series wins divided by completed series.\r\nAvg Mate Elo - Average rating of past teammates.\r\n A teammate uses 2v2 rating after 5 completed series.\r\n Before that, their 1v1 rating is used, or 1500 if absent.\r\nGold - Lifetime Gold earned from 2v2 only.\r\nXP - Lifetime XP earned from 2v2 only.\r\n Gold and XP do not affect your rating-based rank.\r\n\r\nGOTCHAS\r\n\r\n- Leaving mid-game is recorded."); }; <>c.<>9__855_0 = val5; obj = (object)val5; } UIFactory.CreateButton("THdrInfo", transform, "Info", 18f, c_WHITE, c_BTN, (UnityAction)obj, (Vector2?)new Vector2(110f, 34f)); GameObject val6 = UIFactory.CreatePanel("TStat", content.transform, C_PANEL); UIFactory.AddVLG(val6, 6f, 12, 12, 8, 8); UIFactory.AddLE(val6, -1f, -1f, -1f, -1f, -1f, 0f); txtTeamStatus = UIFactory.CreateText("TS", val6.transform, "Click Search to start finding a 2v2.", 17f, C_WHITE, 513, (Vector2?)new Vector2(900f, 24f), richText: true, raycastTarget: false); txtTeamMembers = UIFactory.CreateText("TM", val6.transform, "", 15f, C_LABEL, 257, (Vector2?)new Vector2(900f, 60f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(txtTeamMembers, on: true); txtTeamDcGrace = UIFactory.CreateText("TDC", val6.transform, "", 16f, new Color(1f, 0.7f, 0.3f), 513, (Vector2?)new Vector2(900f, 26f), richText: true, raycastTarget: false); UIFactory.SetBold(txtTeamDcGrace, b: true); object obj2 = txtTeamDcGrace; object obj3 = ((obj2 is Component) ? obj2 : null); if (obj3 != null) { GameObject gameObject = ((Component)obj3).gameObject; if (gameObject != null) { gameObject.SetActive(false); } } GameObject val7 = new GameObject("TBR"); val7.transform.SetParent(val6.transform, false); val7.AddComponent(); UIFactory.AddHLG(val7, 8f); UIFactory.AddLE(val7, -1f, 32f, -1f, 32f, -1f, 0f); Transform transform2 = val7.transform; Color c_WHITE2 = C_WHITE; Color bgColor = new Color(0.2f, 0.55f, 0.3f, 0.95f); object obj4 = <>c.<>9__855_1; if (obj4 == null) { UnityAction val8 = delegate { //IL_0061: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)"[TEAM-QUEUE-UI] Search Random clicked"); string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { Plugin.Log.LogWarning((object)("[TEAM-QUEUE-UI] LocalSteamId='" + localSteamId + "' — Steam not ready yet, ignoring click")); CompetitiveUI.ShowNotification("Steam ID not ready yet — try again in a few seconds", new Color(1f, 0.6f, 0.2f), 4f); } else { string text = ""; try { text = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { } Plugin.Log.LogInfo((object)("[TEAM-QUEUE-UI] joining auto team queue sid=" + localSteamId + " region='" + text + "'")); ApiClient.JoinTeamQueue(localSteamId, MatchTracker.LocalDisplayName, text); } }; <>c.<>9__855_1 = val8; obj4 = (object)val8; } teamSearchBtn = UIFactory.CreateButton("TSB", transform2, "Search Random", 16f, c_WHITE2, bgColor, (UnityAction)obj4, (Vector2?)new Vector2(160f, 28f)); Transform transform3 = val7.transform; Color c_WHITE3 = C_WHITE; Color bgColor2 = new Color(0.4f, 0.3f, 0.55f, 0.95f); object obj5 = <>c.<>9__855_2; if (obj5 == null) { UnityAction val9 = delegate { //IL_0046: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)"[TEAM-QUEUE-UI] Find Custom Lobby clicked"); string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || localSteamId == "unknown") { CompetitiveUI.ShowNotification("Steam ID not ready yet — try again in a few seconds", new Color(1f, 0.6f, 0.2f), 4f); } else { string text = ""; try { text = PhotonNetwork.CloudRegion?.Replace("/*", "") ?? ""; } catch { } Plugin.Log.LogInfo((object)("[TEAM-QUEUE-UI] joining manual team queue sid=" + localSteamId + " region='" + text + "'")); ApiClient.JoinTeamQueue(localSteamId, MatchTracker.LocalDisplayName, text, "manual"); } }; <>c.<>9__855_2 = val9; obj5 = (object)val9; } teamSearchCustomBtn = UIFactory.CreateButton("TSC", transform3, "Find Custom Lobby", 16f, c_WHITE3, bgColor2, (UnityAction)obj5, (Vector2?)new Vector2(180f, 28f)); Transform transform4 = val7.transform; Color c_WHITE4 = C_WHITE; Color bgColor3 = new Color(0.55f, 0.2f, 0.2f, 0.95f); object obj6 = <>c.<>9__855_3; if (obj6 == null) { UnityAction val10 = delegate { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.LeaveTeamQueue(localSteamId); } }; <>c.<>9__855_3 = val10; obj6 = (object)val10; } teamLeaveBtn = UIFactory.CreateButton("TLB", transform4, "Leave Queue", 16f, c_WHITE4, bgColor3, (UnityAction)obj6, (Vector2?)new Vector2(160f, 28f)); teamLeaveBtn.SetActive(false); Transform transform5 = val7.transform; Color c_WHITE5 = C_WHITE; Color bgColor4 = new Color(0.2f, 0.55f, 0.3f, 0.95f); object obj7 = <>c.<>9__855_4; if (obj7 == null) { UnityAction val11 = delegate { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.ReadyUpTeam(localSteamId); } }; <>c.<>9__855_4 = val11; obj7 = (object)val11; } teamReadyBtn = UIFactory.CreateButton("TRB", transform5, "Ready Up", 16f, c_WHITE5, bgColor4, (UnityAction)obj7, (Vector2?)new Vector2(160f, 28f)); teamReadyBtn.SetActive(false); GameObject val12 = new GameObject("TPR"); val12.transform.SetParent(val6.transform, false); val12.AddComponent(); UIFactory.AddHLG(val12, 8f); UIFactory.AddLE(val12, -1f, 30f, -1f, 30f, -1f, 0f); Transform transform6 = val12.transform; Color c_WHITE6 = C_WHITE; Color bgColor5 = new Color(0.55f, 0.3f, 0.1f, 0.5f); object obj8 = <>c.<>9__855_5; if (obj8 == null) { UnityAction val13 = delegate { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.SetTeamPreferredTeam(localSteamId, 1); } }; <>c.<>9__855_5 = val13; obj8 = (object)val13; } teamPickT1Btn = UIFactory.CreateButton("TPT1", transform6, "Team 1 (Orange)", 14f, c_WHITE6, bgColor5, (UnityAction)obj8, (Vector2?)new Vector2(140f, 26f)); Transform transform7 = val12.transform; Color c_WHITE7 = C_WHITE; Color bgColor6 = new Color(0.1f, 0.3f, 0.55f, 0.5f); object obj9 = <>c.<>9__855_6; if (obj9 == null) { UnityAction val14 = delegate { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId)) { ApiClient.SetTeamPreferredTeam(localSteamId, 2); } }; <>c.<>9__855_6 = val14; obj9 = (object)val14; } teamPickT2Btn = UIFactory.CreateButton("TPT2", transform7, "Team 2 (Blue)", 14f, c_WHITE7, bgColor6, (UnityAction)obj9, (Vector2?)new Vector2(140f, 26f)); txtPickStatus = UIFactory.CreateText("TPS", val12.transform, "Custom lobby — claim Team 1 or Team 2.", 13f, C_LABEL, 513, (Vector2?)new Vector2(440f, 26f), richText: true, raycastTarget: false); GameObject val15 = UIFactory.CreatePanel("TLT", content.transform, C_PANEL); UIFactory.AddVLG(val15, 2f, 12, 12, 6, 6); UIFactory.AddLE(val15, -1f, -1f, -1f, -1f, -1f, 0f); txtTeamLiveHeader = UIFactory.CreateText("TLTH", val15.transform, "* Live 2v2 Now", 16f, C_SUB, 513, (Vector2?)new Vector2(900f, 22f), richText: true, raycastTarget: false); txtTeamLiveBody = UIFactory.CreateText("TLTB", val15.transform, "No live 2v2 right now.", 14f, C_LABEL, 257, (Vector2?)new Vector2(900f, 22f), richText: true, raycastTarget: false); object obj10 = txtTeamLiveBody; Component val16 = (Component)((obj10 is Component) ? obj10 : null); if ((Object)(object)val16 != (Object)null) { UIFactory.AddLE(val16.gameObject, -1f, 22f, -1f, 22f, -1f, 0f); } UIFactory.SetWordWrap(txtTeamLiveBody, on: false); teamLivePanel = val15; GameObject val17 = new GameObject("TQR"); val17.transform.SetParent(content.transform, false); val17.AddComponent(); UIFactory.AddHLG(val17, 8f); UIFactory.AddLE(val17, -1f, -1f, -1f, -1f, -1f, 0f); GameObject val18 = UIFactory.CreatePanel("TQL", val17.transform, C_PANEL); UIFactory.AddVLG(val18, 2f, 10, 10, 6, 6); UIFactory.AddLE(val18, -1f, -1f, -1f, -1f, 1f, 0f); txtTeamQueueListHeader = UIFactory.CreateText("TQLH", val18.transform, "Random Queue", 16f, C_SUB, 513, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); txtTeamQueueListBody = UIFactory.CreateText("TQLB", val18.transform, "Loading…", 14f, C_LABEL, 257, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); object obj11 = txtTeamQueueListBody; Component val19 = (Component)((obj11 is Component) ? obj11 : null); if ((Object)(object)val19 != (Object)null) { UIFactory.AddLE(val19.gameObject, -1f, 22f, -1f, 22f, -1f, 0f); } UIFactory.SetWordWrap(txtTeamQueueListBody, on: true); GameObject val20 = UIFactory.CreatePanel("TQM", val17.transform, C_PANEL); UIFactory.AddVLG(val20, 2f, 10, 10, 6, 6); UIFactory.AddLE(val20, -1f, -1f, -1f, -1f, 1f, 0f); txtTeamQueueManualHeader = UIFactory.CreateText("TQMH", val20.transform, "Custom Lobbies", 16f, C_SUB, 513, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); txtTeamQueueManualBody = UIFactory.CreateText("TQMB", val20.transform, "Loading…", 14f, C_LABEL, 257, (Vector2?)new Vector2(440f, 22f), richText: true, raycastTarget: false); object obj12 = txtTeamQueueManualBody; Component val21 = (Component)((obj12 is Component) ? obj12 : null); if ((Object)(object)val21 != (Object)null) { UIFactory.AddLE(val21.gameObject, -1f, 22f, -1f, 22f, -1f, 0f); } UIFactory.SetWordWrap(txtTeamQueueManualBody, on: true); disablePanelRaycast(val15); disablePanelRaycast(val18); disablePanelRaycast(val20); object t = UIFactory.CreateText("TSH", content.transform, "v Scroll down for leaderboard + recent series v", 13f, C_LABEL, 514, (Vector2?)new Vector2(900f, 18f), richText: true, raycastTarget: false); UIFactory.SetBold(t, b: false); GameObject val22 = new GameObject("TBot"); val22.transform.SetParent(content.transform, false); val22.AddComponent(); UIFactory.AddHLG(val22, 8f); UIFactory.AddLE(val22, -1f, 400f, -1f, 720f, -1f, 0f); GameObject val23 = new GameObject("TLBCol"); val23.transform.SetParent(val22.transform, false); val23.AddComponent(); UIFactory.AddVLG(val23, 4f); UIFactory.AddLE(val23, 700f, -1f, 770f, -1f, 0f, 1f); txtTeamLBHeader = UIFactory.CreateText("TLBH", val23.transform, "2v2 Leaderboard", 18f, C_SUB, 513, (Vector2?)new Vector2(560f, 24f), richText: true, raycastTarget: false); GameObject val24 = new GameObject("TLBHR"); val24.transform.SetParent(val23.transform, false); val24.AddComponent(); UIFactory.AddHLG(val24, 4f, 8, 8); UIFactory.AddLE(val24, -1f, 24f, -1f, 24f, -1f, 0f); string[] array = new string[8] { "#", "Player", "Rating", "W-L", "WR", "Avg Mate Elo", "Gold", "XP" }; string[] hdrSortKey = new string[8] { null, null, "rating", "wins", "win_rate", "avg_teammate_elo", "team_gold_earned", "team_xp_earned" }; teamLBSortBtns = new List(); teamLBSortKeys = hdrSortKey; teamLBHeaderTexts = new object[array.Length]; for (int num = 0; num < array.Length; num++) { int idx = num; if (hdrSortKey[num] == null) { object obj13 = UIFactory.CreateText($"TLBH_{num}", val24.transform, array[num], 13f, C_LABEL, (num == 0) ? 513 : 513, (Vector2?)new Vector2((float)TLB_COL_W[num], 24f), richText: true, raycastTarget: false); teamLBHeaderTexts[num] = obj13; teamLBSortBtns.Add(null); continue; } GameObject val25 = UIFactory.CreateButton("TLBS_" + hdrSortKey[num], val24.transform, array[num], 13f, C_LABEL, new Color(0.18f, 0.2f, 0.24f, 0.85f), (UnityAction)delegate { ApiClient.FetchTeamLeaderboard(200, hdrSortKey[idx]); }, (Vector2?)new Vector2((float)TLB_COL_W[num], 24f)); teamLBSortBtns.Add(val25); teamLBHeaderTexts[num] = UIFactory.GetButtonText(val25); } UIFactory.ScrollViewRefs scrollViewRefs2 = UIFactory.CreateScrollView("TLBSV", val23.transform, 1f); UIFactory.AddLE(scrollViewRefs2.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); teamLBContainer = scrollViewRefs2.content; teamLBScrollRect = scrollViewRefs2.scrollGO.GetComponent(UIFactory.tScrollRect); for (int num2 = 0; num2 < 100; num2++) { teamLBRows.Add(CreateTeamLBRow(teamLBContainer.transform, $"tlb{num2}")); } GameObject val26 = new GameObject("TH2Col"); val26.transform.SetParent(val22.transform, false); val26.AddComponent(); UIFactory.AddVLG(val26, 4f); UIFactory.AddLE(val26, -1f, -1f, -1f, -1f, 1f, 1f); GameObject val27 = new GameObject("THHR"); val27.transform.SetParent(val26.transform, false); val27.AddComponent(); UIFactory.AddHLG(val27, 6f); UIFactory.AddLE(val27, -1f, 26f, -1f, 26f, -1f, 0f); txtTeamHistHeader = UIFactory.CreateText("THH", val27.transform, "Recent 2v2 Series", 18f, C_SUB, 513, (Vector2?)new Vector2(280f, 26f), richText: true, raycastTarget: false); GameObject val28 = new GameObject("THSp"); val28.transform.SetParent(val27.transform, false); val28.AddComponent(); UIFactory.AddLE(val28, -1f, -1f, -1f, -1f, 1f); Transform transform8 = val27.transform; Color c_WHITE8 = C_WHITE; Color bgColor7 = new Color(0.22f, 0.25f, 0.3f, 0.95f); object obj14 = <>c.<>9__855_8; if (obj14 == null) { UnityAction val29 = delegate { teamSeriesPageReq = Math.Max(0, teamSeriesPageReq - 1); ApiClient.FetchAllSeriesPaged(teamSeriesPageReq, 10); }; <>c.<>9__855_8 = val29; obj14 = (object)val29; } teamHistPrevBtn = UIFactory.CreateButton("THPP", transform8, "<", 13f, c_WHITE8, bgColor7, (UnityAction)obj14, (Vector2?)new Vector2(28f, 22f)); txtTeamHistPageIndicator = UIFactory.CreateText("THPI", val27.transform, "1/1", 13f, C_LABEL, 514, (Vector2?)new Vector2(48f, 22f), richText: true, raycastTarget: false); Transform transform9 = val27.transform; Color c_WHITE9 = C_WHITE; Color bgColor8 = new Color(0.22f, 0.25f, 0.3f, 0.95f); object obj15 = <>c.<>9__855_9; if (obj15 == null) { UnityAction val30 = delegate { teamSeriesPageReq++; ApiClient.FetchAllSeriesPaged(teamSeriesPageReq, 10); }; <>c.<>9__855_9 = val30; obj15 = (object)val30; } teamHistNextBtn = UIFactory.CreateButton("THPN", transform9, ">", 13f, c_WHITE9, bgColor8, (UnityAction)obj15, (Vector2?)new Vector2(28f, 22f)); UIFactory.ScrollViewRefs scrollViewRefs3 = UIFactory.CreateScrollView("THSV", val26.transform); UIFactory.AddLE(scrollViewRefs3.scrollGO, -1f, -1f, -1f, -1f, -1f, 1f); teamHistContainer = scrollViewRefs3.content; teamHistScrollRect = scrollViewRefs3.scrollGO.GetComponent(UIFactory.tScrollRect); for (int num3 = 0; num3 < 80; num3++) { teamHistRows.Add(CreateTeamHistRow(teamHistContainer.transform, $"th{num3}")); } return val; static void disablePanelRaycast(GameObject p) { Component component = p.GetComponent(UIFactory.tImage); if ((Object)(object)component != (Object)null) { UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, false); } } } private static TeamHistRow CreateTeamHistRow(Transform parent, string name) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_00bc: 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_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Expected O, but got Unknown //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_053d: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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) //IL_0164: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_0613: Unknown result type (might be due to invalid IL or missing references) TeamHistRow row = new TeamHistRow(); row.root = new GameObject(name); row.root.transform.SetParent(parent, false); row.root.AddComponent(); UIFactory.AddVLG(row.root, 2f, 8, 6, 4, 4); UIFactory.AddLE(row.root, -1f, 30f, -1f, -1f, -1f, 0f); row.txtLine1 = UIFactory.CreateText("l1", row.root.transform, "", 17f, C_WHITE, 257, (Vector2?)new Vector2(1000f, 26f), richText: true, raycastTarget: false); object txtLine = row.txtLine1; Component val = (Component)((txtLine is Component) ? txtLine : null); if ((Object)(object)val != (Object)null) { row.btnId = UIFactory.CreateButton("id", val.transform, "[ID]", 12f, C_DIM, new Color(0.18f, 0.2f, 0.26f, 0.45f), (UnityAction)delegate { if (!string.IsNullOrEmpty(row.matchKey)) { CopyGameCode(row.matchKey); } }, (Vector2?)new Vector2(34f, 18f)); RectTransform component = row.btnId.GetComponent(); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0.5f); component.anchorMax = val2; component.anchorMin = val2; component.pivot = new Vector2(0f, 0.5f); component.anchoredPosition = new Vector2(260f, 0f); row.btnId.SetActive(false); } row.txtLine2 = UIFactory.CreateText("l2", row.root.transform, "", 14f, C_LABEL, 257, (Vector2?)new Vector2(1000f, 24f), richText: true, raycastTarget: false); row.teleRow = new GameObject("teleRow"); row.teleRow.transform.SetParent(row.root.transform, false); row.teleRow.AddComponent(); UIFactory.AddHLG(row.teleRow, 6f, 12); UIFactory.AddLE(row.teleRow, -1f, -1f, -1f, 20f, -1f, 0f); row.txtTeleLA = UIFactory.CreateText("ta", row.teleRow.transform, "", 13f, C_LABEL, 513, (Vector2?)new Vector2(245f, 20f), richText: true, raycastTarget: false); row.txtTeleLB = UIFactory.CreateText("tb", row.teleRow.transform, "", 13f, C_LABEL, 513, (Vector2?)new Vector2(245f, 20f), richText: true, raycastTarget: false); row.txtTeleRA = UIFactory.CreateText("tc", row.teleRow.transform, "", 13f, C_LABEL, 513, (Vector2?)new Vector2(245f, 20f), richText: true, raycastTarget: false); row.txtTeleRB = UIFactory.CreateText("td", row.teleRow.transform, "", 13f, C_LABEL, 513, (Vector2?)new Vector2(245f, 20f), richText: true, raycastTarget: false); row.teleRow.SetActive(false); row.cardsRow = new GameObject("cardsRow"); row.cardsRow.transform.SetParent(row.root.transform, false); row.cardsRow.AddComponent(); UIFactory.AddHLG(row.cardsRow, 4f, 12, 0, 6); UIFactory.AddLE(row.cardsRow, -1f, 24f, -1f, -1f, -1f, 0f); row.txtCardsLeft = UIFactory.CreateText("cl", row.cardsRow.transform, "", 14f, new Color(0.55f, 0.8f, 1f), 257, (Vector2?)new Vector2(300f, 200f), richText: true, raycastTarget: false); row.txtCardsRight = UIFactory.CreateText("cr", row.cardsRow.transform, "", 14f, new Color(1f, 0.69f, 0.53f), 257, (Vector2?)new Vector2(300f, 200f), richText: true, raycastTarget: false); UIFactory.SetWordWrap(row.txtCardsLeft, on: true); UIFactory.SetWordWrap(row.txtCardsRight, on: true); row.cardsRow.SetActive(false); if (UIFactory.tImage != null && (Object)(object)row.root.GetComponent(UIFactory.tImage) == (Object)null) { Component obj = row.root.AddComponent(UIFactory.tImage); UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, (object)new Color(1f, 1f, 1f, 0.01f)); UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public)?.SetValue(obj, true); } if ((Object)(object)row.root.GetComponent() == (Object)null) { ClickHandler clickHandler = row.root.AddComponent(); TeamHistRow capturedRow = row; clickHandler.onClick = delegate { if (ClickGuard.Claim(capturedRow.root) && capturedRow.isHeader && !string.IsNullOrEmpty(capturedRow.seriesKey)) { _teamSeriesExpanded.TryGetValue(capturedRow.seriesKey, out var value); _teamSeriesExpanded[capturedRow.seriesKey] = !value; dirty = true; } }; } row.root.SetActive(false); return row; } private static TeamLBRow CreateTeamLBRow(Transform parent, string name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0135: 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_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) TeamLBRow teamLBRow = new TeamLBRow(); teamLBRow.root = new GameObject(name); teamLBRow.root.transform.SetParent(parent, false); teamLBRow.root.AddComponent(); UIFactory.AddHLG(teamLBRow.root, 4f, 8, 8); UIFactory.AddLE(teamLBRow.root, -1f, 22f, -1f, 22f, -1f, 0f); teamLBRow.txtRank = UIFactory.CreateText("r", teamLBRow.root.transform, "", 15f, C_GOLD, 513, (Vector2?)new Vector2((float)TLB_COL_W[0], 22f), richText: true, raycastTarget: false); teamLBRow.txtName = UIFactory.CreateText("n", teamLBRow.root.transform, "", 15f, C_WHITE, 513, (Vector2?)new Vector2((float)TLB_COL_W[1], 22f), richText: true, raycastTarget: false); teamLBRow.txtRating = UIFactory.CreateText("rt", teamLBRow.root.transform, "", 15f, C_WHITE, 514, (Vector2?)new Vector2((float)TLB_COL_W[2], 22f), richText: true, raycastTarget: false); UIFactory.SetBold(teamLBRow.txtRating, b: true); teamLBRow.txtWL = UIFactory.CreateText("wl", teamLBRow.root.transform, "", 14f, C_LABEL, 514, (Vector2?)new Vector2((float)TLB_COL_W[3], 22f), richText: true, raycastTarget: false); teamLBRow.txtWR = UIFactory.CreateText("wr", teamLBRow.root.transform, "", 14f, C_LABEL, 514, (Vector2?)new Vector2((float)TLB_COL_W[4], 22f), richText: true, raycastTarget: false); teamLBRow.txtMate = UIFactory.CreateText("mt", teamLBRow.root.transform, "", 14f, C_LABEL, 514, (Vector2?)new Vector2((float)TLB_COL_W[5], 22f), richText: true, raycastTarget: false); teamLBRow.txtGold = UIFactory.CreateText("g", teamLBRow.root.transform, "", 14f, C_LABEL, 514, (Vector2?)new Vector2((float)TLB_COL_W[6], 22f), richText: true, raycastTarget: false); teamLBRow.txtXp = UIFactory.CreateText("xp", teamLBRow.root.transform, "", 14f, C_LABEL, 514, (Vector2?)new Vector2((float)TLB_COL_W[7], 22f), richText: true, raycastTarget: false); teamLBRow.root.SetActive(false); return teamLBRow; } private static float ReadTeamHistScrollY() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) try { GameObject obj = teamHistContainer; RectTransform val = ((obj != null) ? obj.GetComponent() : null); return ((Object)(object)val != (Object)null) ? val.anchoredPosition.y : (-1f); } catch { return -1f; } } private static void WriteTeamHistScrollY(float y) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00bb: 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_00d6: Unknown result type (might be due to invalid IL or missing references) try { if (teamHistScrollRect == null || y < 0f) { return; } GameObject obj = teamHistContainer; RectTransform val = ((obj != null) ? obj.GetComponent() : null); object obj2 = teamHistScrollRect; Component val2 = (Component)((obj2 is Component) ? obj2 : null); RectTransform val3 = (RectTransform)(((Object)(object)val2 != (Object)null && val2.transform.childCount > 0) ? /*isinst with value type is only supported in some contexts*/: null); if (!((Object)(object)val == (Object)null)) { float num; if (!((Object)(object)val3 != (Object)null)) { num = Mathf.Max(0f, y); } else { Rect rect = val.rect; float height = ((Rect)(ref rect)).height; rect = val3.rect; num = Mathf.Max(0f, height - ((Rect)(ref rect)).height); } float num2 = num; Vector2 anchoredPosition = val.anchoredPosition; anchoredPosition.y = Mathf.Clamp(y, 0f, num2); val.anchoredPosition = anchoredPosition; UIFactory.tScrollRect.GetMethod("StopMovement", BindingFlags.Instance | BindingFlags.Public)?.Invoke(teamHistScrollRect, null); } } catch { } } private static void PositionTeamHistIdButton(TeamHistRow row) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)row?.btnId == (Object)null || row.txtLine1 == null || row.isHeader) { return; } try { object txtLine = row.txtLine1; Component val = (Component)((txtLine is Component) ? txtLine : null); RectTransform val2 = ((val != null) ? val.GetComponent() : null); RectTransform component = row.btnId.GetComponent(); if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)component == (Object)null)) { float num = 0f; PropertyInfo property = ((object)val).GetType().GetProperty("preferredWidth", BindingFlags.Instance | BindingFlags.Public); if (property != null) { num = Convert.ToSingle(property.GetValue(val)); } if (num < 1f) { num = 260f; } Rect rect = val2.rect; float width = ((Rect)(ref rect)).width; rect = component.rect; float num2; if (!(width > ((Rect)(ref rect)).width)) { num2 = num + 4f; } else { rect = val2.rect; float width2 = ((Rect)(ref rect)).width; rect = component.rect; num2 = width2 - ((Rect)(ref rect)).width; } float num3 = num2; component.anchoredPosition = new Vector2(Mathf.Clamp(num + 4f, 0f, num3), 0f); } } catch { } } private static IEnumerator RestoreTeamHistScroll(float y) { yield return null; yield return (object)new WaitForEndOfFrame(); foreach (TeamHistRow row in teamHistRows) { if (row.root.activeSelf && !row.isHeader) { PositionTeamHistIdButton(row); } } WriteTeamHistScrollY(y); } private static void RefreshTeamTab() { //IL_05aa: Unknown result type (might be due to invalid IL or missing references) //IL_0592: Unknown result type (might be due to invalid IL or missing references) //IL_05af: Unknown result type (might be due to invalid IL or missing references) //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_05cd: Unknown result type (might be due to invalid IL or missing references) //IL_05ea: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Unknown result type (might be due to invalid IL or missing references) //IL_05fe: Unknown result type (might be due to invalid IL or missing references) //IL_0bb4: Unknown result type (might be due to invalid IL or missing references) //IL_0b9e: Unknown result type (might be due to invalid IL or missing references) //IL_0e45: Unknown result type (might be due to invalid IL or missing references) //IL_0e4a: Unknown result type (might be due to invalid IL or missing references) //IL_0b88: Unknown result type (might be due to invalid IL or missing references) //IL_0b72: Unknown result type (might be due to invalid IL or missing references) //IL_0c93: Unknown result type (might be due to invalid IL or missing references) //IL_0c8c: Unknown result type (might be due to invalid IL or missing references) //IL_0aa6: Unknown result type (might be due to invalid IL or missing references) //IL_0a8b: Unknown result type (might be due to invalid IL or missing references) float num = ReadTeamHistScrollY(); int cachedTeamQueueSearching = ApiClient.CachedTeamQueueSearching; string arg = ((cachedTeamQueueSearching > 0) ? "#88FF88" : "#888"); UIFactory.SetText(txtTeamHeader, $"2v2 Ranked ({cachedTeamQueueSearching} searching)"); ApiClient.TeamQueueState currentTeamQueueState = ApiClient.CurrentTeamQueueState; ApiClient.TeamQueuePollData lastTeamPollData = ApiClient.LastTeamPollData; string s = ""; string s2; switch (currentTeamQueueState) { case ApiClient.TeamQueueState.Idle: s2 = "Pick Search Random for matchmaking, or Find Custom Lobby to choose teams."; if ((Object)(object)teamSearchBtn != (Object)null) { teamSearchBtn.SetActive(true); } if ((Object)(object)teamSearchCustomBtn != (Object)null) { teamSearchCustomBtn.SetActive(true); } if ((Object)(object)teamLeaveBtn != (Object)null) { teamLeaveBtn.SetActive(false); } if ((Object)(object)teamReadyBtn != (Object)null) { teamReadyBtn.SetActive(false); } break; case ApiClient.TeamQueueState.Searching: { int num2 = ((lastTeamPollData == null || lastTeamPollData.queue_count <= 0) ? 1 : lastTeamPollData.queue_count); if (num2 < 1) { num2 = 1; } if (num2 > 4) { num2 = 4; } string arg2 = ((ApiClient.CurrentTeamQueueType == "manual") ? "custom 2v2 lobby" : "2v2"); s2 = $"Searching for {arg2}... {num2}/4"; if ((Object)(object)teamSearchBtn != (Object)null) { teamSearchBtn.SetActive(false); } if ((Object)(object)teamSearchCustomBtn != (Object)null) { teamSearchCustomBtn.SetActive(false); } if ((Object)(object)teamLeaveBtn != (Object)null) { teamLeaveBtn.SetActive(true); } if ((Object)(object)teamReadyBtn != (Object)null) { teamReadyBtn.SetActive(false); } break; } case ApiClient.TeamQueueState.Matched: s2 = "Match found! Click Ready Up."; if ((Object)(object)teamSearchBtn != (Object)null) { teamSearchBtn.SetActive(false); } if ((Object)(object)teamSearchCustomBtn != (Object)null) { teamSearchCustomBtn.SetActive(false); } if ((Object)(object)teamLeaveBtn != (Object)null) { teamLeaveBtn.SetActive(true); } if ((Object)(object)teamReadyBtn != (Object)null) { teamReadyBtn.SetActive(true); } s = BuildTeamMembersString(lastTeamPollData); break; case ApiClient.TeamQueueState.ReadySent: s2 = "Ready! Waiting for the other 3..."; if ((Object)(object)teamSearchBtn != (Object)null) { teamSearchBtn.SetActive(false); } if ((Object)(object)teamSearchCustomBtn != (Object)null) { teamSearchCustomBtn.SetActive(false); } if ((Object)(object)teamLeaveBtn != (Object)null) { teamLeaveBtn.SetActive(true); } if ((Object)(object)teamReadyBtn != (Object)null) { teamReadyBtn.SetActive(false); } s = BuildTeamMembersString(lastTeamPollData); break; case ApiClient.TeamQueueState.Leaving: s2 = "Leaving queue…"; if ((Object)(object)teamSearchBtn != (Object)null) { teamSearchBtn.SetActive(false); } if ((Object)(object)teamSearchCustomBtn != (Object)null) { teamSearchCustomBtn.SetActive(false); } if ((Object)(object)teamLeaveBtn != (Object)null) { teamLeaveBtn.SetActive(false); } if ((Object)(object)teamReadyBtn != (Object)null) { teamReadyBtn.SetActive(false); } break; default: s2 = ""; break; } UIFactory.SetText(txtTeamStatus, s2); UIFactory.SetText(txtTeamMembers, s); ApiClient.UpdateTeamSeriesStatePoll(force: false); int lastSeriesDcGraceSeconds = ApiClient.LastSeriesDcGraceSeconds; string lastSeriesStateStatus = ApiClient.LastSeriesStateStatus; object obj = txtTeamDcGrace; object obj2 = ((obj is Component) ? obj : null); GameObject val = ((obj2 != null) ? ((Component)obj2).gameObject : null); if ((Object)(object)val != (Object)null) { if (lastSeriesStateStatus == "dc_paused" && lastSeriesDcGraceSeconds > 0) { int num3 = lastSeriesDcGraceSeconds / 60; int num4 = lastSeriesDcGraceSeconds % 60; int lastSeriesT1Wins = ApiClient.LastSeriesT1Wins; int lastSeriesT2Wins = ApiClient.LastSeriesT2Wins; UIFactory.SetText(txtTeamDcGrace, $"Series paused — same 4 can re-queue to resume {num3}:{num4:D2} (score {lastSeriesT1Wins}-{lastSeriesT2Wins})"); val.SetActive(true); } else { val.SetActive(false); } } ApiClient.UpdateTeamQueueList(); List cachedTeamQueueAuto = ApiClient.CachedTeamQueueAuto; List cachedTeamQueueManual = ApiClient.CachedTeamQueueManual; int num5 = 0; bool flag = ApiClient.CurrentTeamQueueType == "manual" && (currentTeamQueueState == ApiClient.TeamQueueState.Searching || currentTeamQueueState == ApiClient.TeamQueueState.Matched); if (cachedTeamQueueManual != null) { foreach (ApiClient.TeamQueueListEntry item in cachedTeamQueueManual) { if (item.steam_id == MatchTracker.LocalSteamId) { num5 = item.preferred_team; break; } } } if ((Object)(object)teamPickT1Btn != (Object)null) { teamPickT1Btn.SetActive(flag); } if ((Object)(object)teamPickT2Btn != (Object)null) { teamPickT2Btn.SetActive(flag); } object obj3 = txtPickStatus; Component val2 = (Component)((obj3 is Component) ? obj3 : null); if ((Object)(object)val2 != (Object)null) { val2.gameObject.SetActive(flag); } if (flag) { float num6 = 0.95f; float num7 = 0.95f; Color c = ((num5 == 1) ? new Color(1f, 0.65f, 0.2f, num6) : new Color(0.4f, 0.25f, 0.1f, num6 * 0.7f)); Color c2 = ((num5 == 2) ? new Color(0.3f, 0.7f, 1f, num7) : new Color(0.1f, 0.25f, 0.45f, num7 * 0.7f)); UIFactory.SetImageColor(teamPickT1Btn, c); UIFactory.SetImageColor(teamPickT2Btn, c2); UIFactory.SetText(UIFactory.GetButtonText(teamPickT1Btn), (num5 == 1) ? "✓ Team 1 (Orange)" : "Team 1 (Orange)"); UIFactory.SetText(UIFactory.GetButtonText(teamPickT2Btn), (num5 == 2) ? "✓ Team 2 (Blue)" : "Team 2 (Blue)"); int num8 = 0; if (cachedTeamQueueManual != null) { foreach (ApiClient.TeamQueueListEntry item2 in cachedTeamQueueManual) { if (item2.status == "searching") { num8++; } } } string s3 = ((num5 == 0) ? $"Claim Team 1 or Team 2. ({num8}/4 in lobby)" : $"Locked in to Team {num5}. ({num8}/4 in lobby)"); UIFactory.SetText(txtPickStatus, s3); } RenderTeamQueueSection(cachedTeamQueueAuto, txtTeamQueueListHeader, txtTeamQueueListBody, "Random Queue"); RenderTeamQueueSection(cachedTeamQueueManual, txtTeamQueueManualHeader, txtTeamQueueManualBody, "Custom Lobbies"); List cachedActiveTeamSeries = ApiClient.CachedActiveTeamSeries; int num9 = cachedActiveTeamSeries?.Count ?? 0; if ((Object)(object)teamLivePanel != (Object)null) { teamLivePanel.SetActive(num9 > 0); } if (num9 > 0) { UIFactory.SetText(txtTeamLiveHeader, $"* Live 2v2 Now ({num9})"); StringBuilder stringBuilder = new StringBuilder(); foreach (ApiClient.ActiveTeamSeriesEntry item3 in cachedActiveTeamSeries) { stringBuilder.Append($"{Trunc(item3.t1a_name, 7)}({item3.t1a_rating})+{Trunc(item3.t1b_name, 7)}({item3.t1b_rating})"); stringBuilder.Append($" {item3.t1_wins}-{item3.t2_wins} "); stringBuilder.Append($"{Trunc(item3.t2a_name, 7)}({item3.t2a_rating})+{Trunc(item3.t2b_name, 7)}({item3.t2b_rating})\n"); } UIFactory.SetText(txtTeamLiveBody, stringBuilder.ToString().TrimEnd('\n')); int num10 = Math.Max(22, num9 * 18 + 4); object obj4 = txtTeamLiveBody; Component val3 = (Component)((obj4 is Component) ? obj4 : null); if ((Object)(object)val3 != (Object)null) { Component component = val3.gameObject.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)num10); UIFactory.tLE.GetProperty("minHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)num10); } } } List list = ApiClient.CachedTeamLeaderboard ?? new List(); string text = ApiClient.CachedTeamLeaderboardSort ?? "rating"; if (teamLBSortKeys != null && teamLBHeaderTexts != null && teamLBSortBtns != null) { for (int i = 0; i < teamLBSortKeys.Length; i++) { bool flag2 = teamLBSortKeys[i] != null && teamLBSortKeys[i] == text; string text2 = i switch { 0 => "#", 1 => "Player", 2 => "Rating", 3 => "W-L", 4 => "WR", 5 => "Avg Mate Elo", 6 => "Gold", 7 => "XP", _ => "", }; if (flag2) { text2 += " v"; } UIFactory.SetText(teamLBHeaderTexts[i], text2); if ((Object)(object)teamLBSortBtns[i] != (Object)null) { UIFactory.SetImageColor(teamLBSortBtns[i], flag2 ? new Color(0.3f, 0.4f, 0.55f, 0.95f) : new Color(0.18f, 0.2f, 0.24f, 0.85f)); } } } for (int j = 0; j < teamLBRows.Count; j++) { TeamLBRow teamLBRow = teamLBRows[j]; if (j >= list.Count) { teamLBRow.root.SetActive(false); continue; } ApiClient.TeamLeaderboardEntry teamLeaderboardEntry = list[j]; bool flag3 = teamLeaderboardEntry.steam_id == MatchTracker.LocalSteamId; UIFactory.SetText(teamLBRow.txtRank, $"#{teamLeaderboardEntry.rank}"); UIFactory.SetColor(teamLBRow.txtRank, (Color)((teamLeaderboardEntry.rank == 1) ? new Color(1f, 0.84f, 0f) : ((teamLeaderboardEntry.rank == 2) ? new Color(0.75f, 0.75f, 0.75f) : ((teamLeaderboardEntry.rank == 3) ? new Color(0.8f, 0.5f, 0.2f) : C_GOLD)))); string text3 = Trunc(teamLeaderboardEntry.display_name, 14); if (!string.IsNullOrEmpty(teamLeaderboardEntry.title)) { string text4 = (string.IsNullOrEmpty(teamLeaderboardEntry.title_color) ? "#FFD94D" : teamLeaderboardEntry.title_color); text3 = (IsPodiumTitle(teamLeaderboardEntry.title) ? (text3 + " " + PodiumSparkleSpan(teamLeaderboardEntry.title, text4, 0u)) : (text3 + " [" + Trunc(teamLeaderboardEntry.title, 12) + "]")); } UIFactory.SetText(teamLBRow.txtName, text3); UIFactory.SetColor(teamLBRow.txtName, flag3 ? C_GREEN : C_WHITE); if (teamLeaderboardEntry.rd > 0) { UIFactory.SetText(teamLBRow.txtRating, $"{teamLeaderboardEntry.rating} ±{teamLeaderboardEntry.rd}"); } else { UIFactory.SetText(teamLBRow.txtRating, $"{teamLeaderboardEntry.rating}"); } UIFactory.SetText(teamLBRow.txtWL, $"{teamLeaderboardEntry.series_wins}-{teamLeaderboardEntry.series_losses}"); UIFactory.SetText(teamLBRow.txtWR, $"{teamLeaderboardEntry.win_rate * 100f:F0}%"); UIFactory.SetText(teamLBRow.txtMate, (teamLeaderboardEntry.avg_teammate_elo > 0) ? $"{teamLeaderboardEntry.avg_teammate_elo}" : "—"); UIFactory.SetText(teamLBRow.txtGold, $"{teamLeaderboardEntry.team_gold_earned}"); UIFactory.SetText(teamLBRow.txtXp, $"{teamLeaderboardEntry.team_xp_earned}"); teamLBRow.root.SetActive(true); } try { Component obj5 = teamLBScrollRect; Behaviour val4 = (Behaviour)(object)((obj5 is Behaviour) ? obj5 : null); if ((Object)(object)val4 != (Object)null) { float num11 = 0f; Transform transform = ((Component)val4).transform; RectTransform val5 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val5 != (Object)null) { Rect rect = val5.rect; num11 = ((Rect)(ref rect)).height; } int num12 = Math.Min(list.Count, teamLBRows.Count); bool flag4 = num11 > 1f && (float)num12 * 23f > num11; if (val4.enabled != flag4) { val4.enabled = flag4; } } } catch { } if (list.Count == 0) { UIFactory.SetText(txtTeamLBHeader, "2v2 Leaderboard — no completed series yet"); } else { UIFactory.SetText(txtTeamLBHeader, $"2v2 Leaderboard ({list.Count} ranked)"); } List list2 = ApiClient.CachedTeamSeriesPaged ?? new List(); string localSteamId = MatchTracker.LocalSteamId; int num13 = 0; CompetitiveUI.ClearCardHoverRegions(); foreach (ApiClient.TeamSeriesPagedEntry item4 in list2) { if (num13 >= teamHistRows.Count) { break; } ApiClient.TeamSeriesSlot teamSeriesSlot = null; int num14 = 0; if (item4.t1a?.steam_id == localSteamId) { teamSeriesSlot = item4.t1a; num14 = 1; } else if (item4.t1b?.steam_id == localSteamId) { teamSeriesSlot = item4.t1b; num14 = 1; } else if (item4.t2a?.steam_id == localSteamId) { teamSeriesSlot = item4.t2a; num14 = 2; } else if (item4.t2b?.steam_id == localSteamId) { teamSeriesSlot = item4.t2b; num14 = 2; } bool flag5 = teamSeriesSlot != null; int num15 = ((flag5 && num14 == 2) ? item4.t2_series_wins : item4.t1_series_wins); int num16 = ((flag5 && num14 == 2) ? item4.t1_series_wins : item4.t2_series_wins); bool flag6 = flag5 && item4.winner_team == num14; string text5 = ((!flag5) ? "·" : (flag6 ? "W" : "L")); string text6 = ""; if (teamSeriesSlot != null && Mathf.Abs(teamSeriesSlot.rating_change) > 0.01f) { string arg3 = ((teamSeriesSlot.rating_change > 0f) ? "#00FF00" : "#FF6666"); text6 = string.Format(" {1}{2:F0} elo", arg3, (teamSeriesSlot.rating_change > 0f) ? "+" : "", teamSeriesSlot.rating_change); } string text7 = ""; if (teamSeriesSlot != null && (teamSeriesSlot.gold_earned > 0 || teamSeriesSlot.xp_earned > 0)) { text7 = $" +{teamSeriesSlot.gold_earned}g +{teamSeriesSlot.xp_earned}xp"; } string text8 = ""; try { if (!string.IsNullOrEmpty(item4.completed_at) && item4.completed_at.Length >= 10) { text8 = DateTime.Parse(item4.completed_at).ToString("M/d"); } } catch { } ApiClient.TeamSeriesSlot teamSeriesSlot2; ApiClient.TeamSeriesSlot teamSeriesSlot3; ApiClient.TeamSeriesSlot teamSeriesSlot4; ApiClient.TeamSeriesSlot teamSeriesSlot5; if (flag5 && num14 == 2) { teamSeriesSlot2 = item4.t2a; teamSeriesSlot3 = item4.t2b; teamSeriesSlot4 = item4.t1a; teamSeriesSlot5 = item4.t1b; } else { teamSeriesSlot2 = item4.t1a; teamSeriesSlot3 = item4.t1b; teamSeriesSlot4 = item4.t2a; teamSeriesSlot5 = item4.t2b; } string text9 = (flag5 ? " (you)" : ""); string s4 = FormatTeamSide(teamSeriesSlot2, teamSeriesSlot3, "#6FB7FF") + text9 + " vs " + FormatTeamSide(teamSeriesSlot4, teamSeriesSlot5, "#FFA864"); _teamSeriesExpanded.TryGetValue(item4.series_id ?? "", out var value); string text10 = (value ? "[-]" : "[+]"); string text11; if (flag5) { text11 = (flag6 ? $"WON {num15}-{num16}" : $"LOST {num15}-{num16}"); } else { string arg4 = ((item4.winner_team == 1) ? "Blue" : "Orange"); int num17 = Math.Max(num15, num16); int num18 = Math.Min(num15, num16); text11 = $"{arg4} won {num17}-{num18}"; } TeamHistRow teamHistRow = teamHistRows[num13++]; teamHistRow.isHeader = true; teamHistRow.seriesKey = item4.series_id ?? ""; UIFactory.SetText(teamHistRow.txtLine1, text10 + " " + text5 + " " + text11 + " " + text8 + "" + text6 + text7); UIFactory.SetText(teamHistRow.txtLine2, s4); object txtLine = teamHistRow.txtLine2; object obj8 = ((txtLine is Component) ? txtLine : null); GameObject val6 = ((obj8 != null) ? ((Component)obj8).gameObject : null); if ((Object)(object)val6 != (Object)null) { val6.SetActive(true); } if ((Object)(object)teamHistRow.cardsRow != (Object)null) { teamHistRow.cardsRow.SetActive(false); } if ((Object)(object)teamHistRow.teleRow != (Object)null) { teamHistRow.teleRow.SetActive(false); } teamHistRow.matchKey = null; if ((Object)(object)teamHistRow.btnId != (Object)null) { teamHistRow.btnId.SetActive(false); } SetTeamHistRowPrefH(teamHistRow, 60, 0); teamHistRow.root.SetActive(true); if (!value) { continue; } int num19 = 0; foreach (ApiClient.TeamSeriesMatch match in item4.matches) { if (num13 >= teamHistRows.Count) { break; } num19++; int num20 = ((flag5 && num14 == 2) ? match.t2_rounds_won : match.t1_rounds_won); int num21 = ((flag5 && num14 == 2) ? match.t1_rounds_won : match.t2_rounds_won); string text12 = ((!flag5) ? "·" : ((num20 > num21) ? "W" : "L")); string text13 = BuildTeamCardsColumnChips(match, teamSeriesSlot2, teamSeriesSlot3); string text14 = BuildTeamCardsColumnChips(match, teamSeriesSlot4, teamSeriesSlot5); TeamHistRow teamHistRow2 = teamHistRows[num13++]; teamHistRow2.isHeader = false; teamHistRow2.seriesKey = item4.series_id ?? ""; teamHistRow2.matchKey = match.match_id; string text15 = ((match.duration_seconds > 0) ? $" {match.duration_seconds / 60}:{match.duration_seconds % 60:00}" : ""); UIFactory.SetText(teamHistRow2.txtLine1, $" Game {num19}: {text12} {num20}-{num21}{text15}"); if ((Object)(object)teamHistRow2.btnId != (Object)null) { teamHistRow2.btnId.SetActive(!string.IsNullOrEmpty(match.match_id)); PositionTeamHistIdButton(teamHistRow2); } object txtLine2 = teamHistRow2.txtLine2; object obj9 = ((txtLine2 is Component) ? txtLine2 : null); GameObject val7 = ((obj9 != null) ? ((Component)obj9).gameObject : null); if ((Object)(object)val7 != (Object)null) { val7.SetActive(false); } bool flag7 = (match.telemetry_by_player != null && match.telemetry_by_player.Count > 0) || (match.fps_by_player != null && match.fps_by_player.Count > 0); if ((Object)(object)teamHistRow2.teleRow != (Object)null) { teamHistRow2.teleRow.SetActive(flag7); } int num22 = (flag7 ? 22 : 0); if (flag7) { FillTeleCell(teamHistRow2.txtTeleLA, match, teamSeriesSlot2, right: false); FillTeleCell(teamHistRow2.txtTeleLB, match, teamSeriesSlot3, right: false); FillTeleCell(teamHistRow2.txtTeleRA, match, teamSeriesSlot4, right: true); FillTeleCell(teamHistRow2.txtTeleRB, match, teamSeriesSlot5, right: true); } UIFactory.SetText(teamHistRow2.txtCardsLeft, string.IsNullOrEmpty(text13) ? "—" : text13); UIFactory.SetText(teamHistRow2.txtCardsRight, string.IsNullOrEmpty(text14) ? "—" : text14); if ((Object)(object)teamHistRow2.cardsRow != (Object)null) { teamHistRow2.cardsRow.SetActive(true); } RegisterHoverRectFor(teamHistRow2.txtCardsLeft, BuildTeamCardsFullLine(match, teamSeriesSlot2, teamSeriesSlot3), isOpponent: false, "", BuildTeamCardsTooltipBody(match, teamSeriesSlot2, teamSeriesSlot3)); RegisterHoverRectFor(teamHistRow2.txtCardsRight, BuildTeamCardsFullLine(match, teamSeriesSlot4, teamSeriesSlot5), isOpponent: true, "", BuildTeamCardsTooltipBody(match, teamSeriesSlot4, teamSeriesSlot5)); int val8 = CountCardChipLines(match, teamSeriesSlot2, teamSeriesSlot3); int val9 = CountCardChipLines(match, teamSeriesSlot4, teamSeriesSlot5); int num23 = Math.Max(2, Math.Max(val8, val9)); int num24 = num23 * 22 + 8; SetTeamHistRowPrefH(teamHistRow2, 42 + num22 + num24, num24); teamHistRow2.root.SetActive(true); } } for (int k = num13; k < teamHistRows.Count; k++) { teamHistRows[k].root.SetActive(false); } int cachedTeamSeriesTotal = ApiClient.CachedTeamSeriesTotal; int cachedTeamSeriesTotalPages = ApiClient.CachedTeamSeriesTotalPages; int cachedTeamSeriesPage = ApiClient.CachedTeamSeriesPage; if (cachedTeamSeriesTotal == 0) { UIFactory.SetText(txtTeamHistHeader, "Recent 2v2 Series — none yet"); if (txtTeamHistPageIndicator != null) { UIFactory.SetText(txtTeamHistPageIndicator, "—"); } if ((Object)(object)teamHistPrevBtn != (Object)null) { teamHistPrevBtn.SetActive(false); } if ((Object)(object)teamHistNextBtn != (Object)null) { teamHistNextBtn.SetActive(false); } } else { UIFactory.SetText(txtTeamHistHeader, $"Recent 2v2 Series ({cachedTeamSeriesTotal} total)"); if (txtTeamHistPageIndicator != null) { UIFactory.SetText(txtTeamHistPageIndicator, $"{cachedTeamSeriesPage + 1}/{Math.Max(1, cachedTeamSeriesTotalPages)}"); } if ((Object)(object)teamHistPrevBtn != (Object)null) { teamHistPrevBtn.SetActive(cachedTeamSeriesPage > 0); } if ((Object)(object)teamHistNextBtn != (Object)null) { teamHistNextBtn.SetActive(cachedTeamSeriesPage + 1 < cachedTeamSeriesTotalPages); } } if (num >= 0f && (Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(RestoreTeamHistScroll(num)); } } private static string FormatTitleName(ApiClient.TeamSeriesSlot s) { if (s == null) { return "?"; } string text = Trunc(s.name ?? "?", 12); if (string.IsNullOrEmpty(s.title)) { return text; } string text2 = (string.IsNullOrEmpty(s.title_color) ? "#FFD94D" : s.title_color); return text + " [" + Trunc(s.title, 10) + "]"; } private static string FormatTeamSide(ApiClient.TeamSeriesSlot a, ApiClient.TeamSeriesSlot b, string sideColor) { return FormatPlayerToken(a, sideColor) + " + " + FormatPlayerToken(b, sideColor); } private static string FormatPlayerToken(ApiClient.TeamSeriesSlot s, string sideColor) { if (s == null) { return "?"; } string text = "" + Trunc(s.name ?? "?", 12) + ""; string text2 = ""; if (!string.IsNullOrEmpty(s.title)) { string text3 = (string.IsNullOrEmpty(s.title_color) ? "#FFD94D" : s.title_color); text2 = " [" + Trunc(s.title, 10) + "]"; } string text4 = ((s.rating > 0) ? $" {s.rating}" : ""); return text + text2 + text4; } private static string BuildTeamCardsColumnChips(ApiClient.TeamSeriesMatch m, ApiClient.TeamSeriesSlot a, ApiClient.TeamSeriesSlot b) { if (m == null || m.cards_by_player == null) { return ""; } bool flag = false; ApiClient.TeamSeriesSlot[] array = new ApiClient.TeamSeriesSlot[2] { a, b }; foreach (ApiClient.TeamSeriesSlot teamSeriesSlot in array) { if (teamSeriesSlot != null && !string.IsNullOrEmpty(teamSeriesSlot.steam_id) && m.cards_by_player.TryGetValue(teamSeriesSlot.steam_id, out var value) && value != null && value.Count > 0) { flag = true; break; } } if (!flag) { return "(card data not recorded)"; } StringBuilder sb = new StringBuilder(); appendFor(a); appendFor(b); return sb.ToString(); void appendFor(ApiClient.TeamSeriesSlot s) { if (s != null && !string.IsNullOrEmpty(s.steam_id)) { if (sb.Length > 0) { sb.Append("\n"); } List value2; bool flag2 = m.cards_by_player.TryGetValue(s.steam_id, out value2) && value2 != null && value2.Count > 0; sb.Append("").Append(Trunc(s.name ?? "?", 14)).Append(""); if (!flag2) { sb.Append("\n —"); } else { sb.Append("\n ").Append(CardsToChips(value2)); } } } } private static string BuildTeamCardsFullLine(ApiClient.TeamSeriesMatch m, ApiClient.TeamSeriesSlot a, ApiClient.TeamSeriesSlot b) { if (m == null || m.cards_by_player == null) { return ""; } List parts = new List(); addFor(a); addFor(b); return string.Join(", ", parts); void addFor(ApiClient.TeamSeriesSlot s) { if (s == null || string.IsNullOrEmpty(s.steam_id) || !m.cards_by_player.TryGetValue(s.steam_id, out var value) || value == null) { return; } foreach (string item in value) { if (!string.IsNullOrEmpty(item)) { parts.Add(item.Trim()); } } } } private static string BuildTeamCardsTooltipBody(ApiClient.TeamSeriesMatch m, ApiClient.TeamSeriesSlot a, ApiClient.TeamSeriesSlot b) { if (m == null || m.cards_by_player == null) { return ""; } StringBuilder sb = new StringBuilder(); addFor(a); addFor(b); return sb.ToString(); void addFor(ApiClient.TeamSeriesSlot s) { if (s != null && !string.IsNullOrEmpty(s.steam_id)) { if (sb.Length > 0) { sb.Append('\n'); } sb.Append("").Append(Trunc(s.name ?? "?", 16)).Append(""); if (m.cards_by_player.TryGetValue(s.steam_id, out var value) && value != null && value.Count > 0) { foreach (string item in value) { string text = (item ?? "").Trim(); if (text.Length != 0) { int num = text.IndexOf('>'); if (num >= 0 && num < text.Length - 1) { text = text.Substring(num + 1); } int num2 = text.IndexOf('<'); if (num2 > 0) { text = text.Substring(0, num2); } text = text.Trim(); if (text.Length != 0) { sb.Append("\n • ").Append(text); } } } return; } sb.Append("\n (no cards)"); } } } private static string CardsToChips(List cards) { if (cards == null || cards.Count == 0) { return ""; } StringBuilder stringBuilder = new StringBuilder(); foreach (string card in cards) { string text = (card ?? "").Trim(); if (text.Length != 0) { int num = text.IndexOf('>'); if (num >= 0 && num < text.Length - 1) { text = text.Substring(num + 1); } int num2 = text.IndexOf('<'); if (num2 > 0) { text = text.Substring(0, num2); } text = text.Trim(); if (text.Length != 0) { string value = ((text.Length >= 2) ? text.Substring(0, 2).ToUpperInvariant() : text.ToUpperInvariant()); stringBuilder.Append('[').Append(value).Append("] "); } } } return stringBuilder.ToString().TrimEnd(); } private static int CountCardChipLines(ApiClient.TeamSeriesMatch m, ApiClient.TeamSeriesSlot a, ApiClient.TeamSeriesSlot b) { int lines = 0; countFor(a); countFor(b); return lines; void countFor(ApiClient.TeamSeriesSlot s) { if (s != null && !string.IsNullOrEmpty(s.steam_id)) { lines++; if (m != null && m.cards_by_player != null && m.cards_by_player.TryGetValue(s.steam_id, out var value) && value != null && value.Count > 0) { lines += Math.Max(1, (value.Count + 7) / 8); } else { lines++; } } } } private static void SetTeamHistRowPrefH(TeamHistRow row, int prefH, int cardContentH) { try { Component component = row.root.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)prefH); } int contentH; if ((Object)(object)row.cardsRow != (Object)null && row.cardsRow.activeSelf) { contentH = Math.Max(40, cardContentH); resizeText(row.txtCardsLeft); resizeText(row.txtCardsRight); } void resizeText(object t) { //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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) Component val = (Component)((t is Component) ? t : null); if (!((Object)(object)val == (Object)null)) { RectTransform component2 = val.GetComponent(); if (!((Object)(object)component2 == (Object)null)) { Vector2 sizeDelta = component2.sizeDelta; component2.sizeDelta = new Vector2(sizeDelta.x, (float)contentH); UIFactory.SetPrefH(val.gameObject, contentH); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2-HIST] row size update failed: " + ex.Message)); } } private static string BuildTeamCardsColumn(ApiClient.TeamSeriesMatch m, ApiClient.TeamSeriesSlot a, ApiClient.TeamSeriesSlot b) { if (m == null || m.cards_by_player == null) { return ""; } bool flag = false; ApiClient.TeamSeriesSlot[] array = new ApiClient.TeamSeriesSlot[2] { a, b }; foreach (ApiClient.TeamSeriesSlot teamSeriesSlot in array) { if (teamSeriesSlot != null && !string.IsNullOrEmpty(teamSeriesSlot.steam_id) && m.cards_by_player.TryGetValue(teamSeriesSlot.steam_id, out var value) && value != null && value.Count > 0) { flag = true; break; } } if (!flag) { return "(card data not recorded)"; } StringBuilder sb = new StringBuilder(); appendFor(a); appendFor(b); return sb.ToString(); void appendFor(ApiClient.TeamSeriesSlot s) { if (s != null && !string.IsNullOrEmpty(s.steam_id)) { if (sb.Length > 0) { sb.Append("\n"); } List value2; bool flag2 = m.cards_by_player.TryGetValue(s.steam_id, out value2) && value2 != null && value2.Count > 0; sb.Append("").Append(Trunc(s.name ?? "?", 14)).Append(""); if (!flag2) { sb.Append("\n —"); } else { for (int j = 0; j < value2.Count; j += 2) { sb.Append("\n ").Append(value2[j]); if (j + 1 < value2.Count) { sb.Append(", ").Append(value2[j + 1]); } } } } } } private static int CountCardLines(ApiClient.TeamSeriesMatch m, ApiClient.TeamSeriesSlot a, ApiClient.TeamSeriesSlot b) { int lines = 0; countFor(a); countFor(b); return lines; void countFor(ApiClient.TeamSeriesSlot s) { if (s != null && !string.IsNullOrEmpty(s.steam_id)) { lines++; if (m != null && m.cards_by_player != null && m.cards_by_player.TryGetValue(s.steam_id, out var value) && value != null && value.Count > 0) { lines += (value.Count + 1) / 2; } else { lines++; } } } } private static void RenderTeamQueueSection(List list, object header, object body, string label) { //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) int num = list?.Count ?? 0; float num2 = 18f; int num3; if (num == 0) { UIFactory.SetText(header, "" + label + " (empty)"); UIFactory.SetText(body, "No one in " + label.ToLower() + " right now."); num3 = 22; } else { UIFactory.SetText(header, $"{label} ({num})"); StringBuilder stringBuilder = new StringBuilder(); foreach (ApiClient.TeamQueueListEntry item in list) { string text = ((item.steam_id == MatchTracker.LocalSteamId) ? "" : ""); string text2 = (item.using_fallback_rating ? $"{item.balance_rating} 1v1" : $"{item.rating}"); string text3 = ((item.status == "searching") ? "searching" : ((item.status == "matched") ? "matched" : ("" + item.status + ""))); int num4 = item.wait_seconds / 60; int num5 = item.wait_seconds % 60; string text4 = ((num4 > 0) ? $"{num4}m{num5:D2}s" : $"{num5}s"); string text5 = ""; if (item.preferred_team == 1) { text5 = " T1"; } else if (item.preferred_team == 2) { text5 = " T2"; } stringBuilder.Append(" " + text + Trunc(item.display_name, 18) + " " + text2 + " " + text3 + " " + text4 + "" + text5 + "\n"); } UIFactory.SetText(body, stringBuilder.ToString()); num3 = (int)((float)num * num2 + 6f); } Component val = (Component)((body is Component) ? body : null); if ((Object)(object)val != (Object)null) { Component component = val.gameObject.GetComponent(UIFactory.tLE); if ((Object)(object)component != (Object)null) { UIFactory.tLE.GetProperty("preferredHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)num3); UIFactory.tLE.GetProperty("minHeight", BindingFlags.Instance | BindingFlags.Public)?.SetValue(component, (float)num3); } RectTransform component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sizeDelta = new Vector2(component2.sizeDelta.x, (float)num3); } } } private static string JoinTeamCards(ApiClient.TeamMatchHistoryEntry m, int team) { if (m.cards_by_player == null || m.cards_by_player.Count == 0) { return ""; } string key = ((team == 1) ? m.t1a_steam_id : m.t2a_steam_id); string key2 = ((team == 1) ? m.t1b_steam_id : m.t2b_steam_id); string s = ((team == 1) ? m.t1a_name : m.t2a_name); string s2 = ((team == 1) ? m.t1b_name : m.t2b_name); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(Trunc(s, 8)).Append(": "); if (m.cards_by_player.TryGetValue(key, out var value) && value.Count > 0) { stringBuilder.Append(string.Join(", ", value.GetRange(0, Math.Min(value.Count, 6)).ToArray())); } else { stringBuilder.Append("(no cards)"); } stringBuilder.Append(" | "); stringBuilder.Append(Trunc(s2, 8)).Append(": "); if (m.cards_by_player.TryGetValue(key2, out var value2) && value2.Count > 0) { stringBuilder.Append(string.Join(", ", value2.GetRange(0, Math.Min(value2.Count, 6)).ToArray())); } else { stringBuilder.Append("(no cards)"); } return stringBuilder.ToString(); } private static string BuildTeamMembersString(ApiClient.TeamQueuePollData poll) { if (poll == null) { return ""; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("Your Team: "); stringBuilder.Append(ReadyTag(poll.my_ready) + "YOU"); if (poll.teammates != null) { foreach (ApiClient.TeamQueueMember teammate in poll.teammates) { stringBuilder.Append(", " + ReadyTag(teammate.ready) + Trunc(teammate.display_name, 16) + " " + FmtMemberRating(teammate)); } } stringBuilder.Append("\nOpponents: "); if (poll.opponents != null) { bool flag = true; foreach (ApiClient.TeamQueueMember opponent in poll.opponents) { if (!flag) { stringBuilder.Append(", "); } stringBuilder.Append(ReadyTag(opponent.ready) + Trunc(opponent.display_name, 16) + " " + FmtMemberRating(opponent)); flag = false; } } return stringBuilder.ToString(); } private static string ReadyTag(bool isReady) { return isReady ? "[R] " : "[ ] "; } private static string FmtMemberRating(ApiClient.TeamQueueMember m) { if (m.using_fallback_rating && m.balance_rating > 0) { return $"({m.balance_rating} 1v1, {m.completed_series}/10 2v2 series)"; } return $"({m.rating})"; } [CompilerGenerated] internal static int g__rank|534_9(string sku) { if (sku.StartsWith("nametag_neon_", StringComparison.OrdinalIgnoreCase)) { return 2; } return NametagStyler.GetSubgroup(sku) switch { null => 0, "color" => 1, "glow" => 3, "size" => 4, _ => 5, }; } [CompilerGenerated] internal static int g__TierRank|692_0(string tier) { if (string.IsNullOrEmpty(tier)) { return 99; } return tier switch { "S" => 0, "A" => 1, "B" => 2, "C" => 3, "D" => 4, "E" => 5, "F" => 6, _ => 99, }; } } internal static class PerfGate { private static readonly Dictionary _counts = new Dictionary(); private static readonly Dictionary _lifetime = new Dictionary(); private static readonly HashSet _firstFireLogged = new HashSet(); public static bool Check(ConfigEntry perPatch) { ConfigEntry perfOptimizations = Plugin.PerfOptimizations; if (perfOptimizations != null && !perfOptimizations.Value) { return false; } if (perPatch != null && !perPatch.Value) { return false; } return true; } public static void Hit(string patch) { try { _counts.TryGetValue(patch, out var value); _counts[patch] = value + 1; _lifetime.TryGetValue(patch, out var value2); _lifetime[patch] = value2 + 1; if (_firstFireLogged.Add(patch)) { Plugin.Log.LogInfo((object)$"[PERF] {patch} FIRST FIRE (frame {Time.frameCount})"); } } catch { } } public static void DumpAndReset() { try { if (_counts.Count == 0) { Plugin.Log.LogInfo((object)"[PERF] No perf patches fired this match (toggles off, or none triggered)."); return; } StringBuilder stringBuilder = new StringBuilder("[PERF] Per-match patch hits: "); foreach (KeyValuePair count in _counts) { stringBuilder.Append(count.Key).Append('=').Append(count.Value) .Append(" "); } Plugin.Log.LogInfo((object)stringBuilder.ToString()); _counts.Clear(); } catch { } } public static Dictionary LifetimeSnapshot() { try { return new Dictionary(_lifetime); } catch { return new Dictionary(); } } } [HarmonyPatch(typeof(PlayerManager), "SetInputActive")] internal class PlayerManagerSetInputActiveNullGuard { private static bool Prefix(PlayerManager __instance, bool inputActive) { try { List list = (((Object)(object)__instance != (Object)null) ? __instance.players : null); if (list == null) { return false; } for (int i = 0; i < list.Count; i++) { Player val = list[i]; try { if (!((Object)(object)val == (Object)null)) { CharacterData data = val.data; if (!((Object)(object)data == (Object)null) && !((Object)(object)data.view == (Object)null) && data.playerActions != null && data.view.IsMine) { ((PlayerActionSet)data.playerActions).Enabled = inputActive; } } } catch { } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[INPUTFIX] SetInputActive guard error: " + ex.Message)); } return false; } } [HarmonyPatch(typeof(EscapeMenuHandler), "ToggleEsc")] internal class EscapeMenuToggleEscFinalizer { private static Exception Finalizer(Exception __exception) { if (__exception != null) { Plugin.Log.LogWarning((object)("[INPUTFIX] EscapeMenuHandler.ToggleEsc threw (swallowed): " + __exception.Message)); } return null; } } [HarmonyPatch(typeof(StunPlayer), "Go")] internal class StunPlayerGoNullGuard { private static bool Prefix(StunPlayer __instance) { if (!PerfGate.Check(Plugin.PerfStunPlayerNullGuard)) { return true; } bool flag = (Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponentInParent() != (Object)null; if (!flag) { PerfGate.Hit("StunPlayerGoNullGuard"); } return flag; } } [HarmonyPatch(typeof(ProjectileHit), "Update")] internal class ProjectileHitOutOfBoundsCleanup { private static readonly Dictionary _lastChecked = new Dictionary(64); private const float CHECK_INTERVAL = 0.5f; private const float X_MIN = -0.25f; private const float X_MAX = 1.25f; private const float Y_MIN = -1f; private static void Prefix(ProjectileHit __instance) { if (!PerfGate.Check(Plugin.PerfDespawnOffscreenBullets) || (Object)(object)__instance == (Object)null) { return; } int instanceID; try { instanceID = ((Object)__instance).GetInstanceID(); } catch { return; } float time = Time.time; if (_lastChecked.TryGetValue(instanceID, out var value) && time < value + 0.5f) { return; } _lastChecked[instanceID] = time; if (_lastChecked.Count > 512) { List list = new List(); foreach (KeyValuePair item in _lastChecked) { if (time - item.Value > 30f) { list.Add(item.Key); } } foreach (int item2 in list) { _lastChecked.Remove(item2); } } try { if (IsOutOfBounds(((Component)__instance).transform) && !((Object)(object)__instance.ownPlayer == (Object)null) && !((Object)(object)__instance.ownPlayer.data == (Object)null) && !((Object)(object)__instance.ownPlayer.data.view == (Object)null) && __instance.ownPlayer.data.view.IsMine && (Object)(object)((Component)__instance).gameObject != (Object)null) { PhotonNetwork.Destroy(((Component)__instance).gameObject); PerfGate.Hit("DespawnOffscreenBullets"); } } catch { } } private static bool IsOutOfBounds(Transform t) { //IL_0037: 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_0051: 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_005c: 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) try { MainCam instance = MainCam.instance; object obj; if (instance == null) { obj = null; } else { Transform transform = ((Component)instance).transform; obj = ((transform != null) ? ((Component)transform).GetComponent() : null); } Camera val = (Camera)obj; if ((Object)(object)val == (Object)null) { return false; } Vector3 val2 = val.WorldToScreenPoint(new Vector3(t.position.x, t.position.y, 0f)); float num = val2.x / Mathf.Max(1f, (float)Screen.width); float num2 = val2.y / Mathf.Max(1f, (float)Screen.height); return num <= -0.25f || num >= 1.25f || num2 <= -1f; } catch { return false; } } } [HarmonyPatch(typeof(RayHitBulletSound), "DoHitEffect")] internal class RayHitBulletSoundDoHitEffectFinalizer { private static Exception Finalizer(Exception __exception) { if (!PerfGate.Check(Plugin.PerfSwallowHitSoundNREs)) { return __exception; } if (__exception is NullReferenceException || __exception is MissingReferenceException) { PerfGate.Hit("SwallowHitSoundNRE"); return null; } return __exception; } } [HarmonyPatch(typeof(ScreenEdgeBounce), "DoHit")] internal class ScreenEdgeBounceDoHitFinalizer { private static Exception Finalizer(ScreenEdgeBounce __instance, Exception __exception) { if (!PerfGate.Check(Plugin.PerfSwallowEdgeBounceNREs)) { return __exception; } return _PerfHelpers.SwallowAndDestroy((MonoBehaviour)(object)__instance, __exception); } } [HarmonyPatch(typeof(ScreenEdgeBounce), "Update")] internal class ScreenEdgeBounceUpdateFinalizer { private static Exception Finalizer(ScreenEdgeBounce __instance, Exception __exception) { if (!PerfGate.Check(Plugin.PerfSwallowEdgeBounceNREs)) { return __exception; } return _PerfHelpers.SwallowAndDestroy((MonoBehaviour)(object)__instance, __exception); } } internal static class _PerfHelpers { internal static Exception SwallowAndDestroy(MonoBehaviour mb, Exception ex) { if (ex is NullReferenceException || ex is MissingReferenceException) { PerfGate.Hit("SwallowEdgeBounceNRE"); return null; } return ex; } } internal static class _PerfHelpersAlias { public static Exception _SwallowAndDestroy(ScreenEdgeBounce mb, Exception ex) { return _PerfHelpers.SwallowAndDestroy((MonoBehaviour)(object)mb, ex); } } [HarmonyPatch(typeof(DynamicParticles), "PlayBulletHit")] internal class DynamicParticlesPlayBulletHitCap { private const int MAX_PER_FRAME = 2; private static int _lastFrame = -1; private static int _countThisFrame; private static bool Prefix() { if (!PerfGate.Check(Plugin.PerfBulletHitParticleCap)) { return true; } int frameCount = Time.frameCount; if (frameCount != _lastFrame) { _lastFrame = frameCount; _countThisFrame = 0; } if (_countThisFrame >= 2) { PerfGate.Hit("BulletHitParticleCap"); return false; } _countThisFrame++; return true; } } [HarmonyPatch] internal class ObjectPoolInitClamp { private static MethodBase TargetMethod() { try { Type typeFromHandle = typeof(ObjectPool); ConstructorInfo[] constructors = typeFromHandle.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (ConstructorInfo constructorInfo in constructors) { ParameterInfo[] parameters = constructorInfo.GetParameters(); if (parameters.Length >= 2 && parameters[0].ParameterType == typeof(GameObject) && parameters[1].ParameterType == typeof(int)) { return constructorInfo; } } } catch { } return null; } private static void Prefix(ref int initSpawn) { if (!PerfGate.Check(Plugin.PerfClampObjectPoolInit)) { return; } try { if (!GameStateWatcher.IsInMatch) { return; } } catch { return; } if (initSpawn > 4) { initSpawn = 4; PerfGate.Hit("ClampObjectPoolInit"); } } } [HarmonyPatch(typeof(MenuControllerHandler), "Update")] [HarmonyPriority(800)] internal class MenuControllerHandlerUpdateBail { private static bool _wasSkipping; private static bool Prefix() { if (!PerfGate.Check(Plugin.PerfSkipMenuUpdateInMatch)) { _wasSkipping = false; return true; } try { bool isInMatch = GameStateWatcher.IsInMatch; bool flag = false; try { flag = EscapeMenuHandler.isEscMenu; } catch { } bool flag2 = !isInMatch || flag; if (!flag2 && !_wasSkipping) { PerfGate.Hit("SkipMenuUpdateInMatch"); } _wasSkipping = !flag2; return flag2; } catch { _wasSkipping = false; return true; } } } [HarmonyPatch(typeof(Screenshaker))] internal static class ScreenshakerDisablePatch { internal static string Level { get { string a = ((Plugin.ScreenShakeStrength != null) ? (Plugin.ScreenShakeStrength.Value ?? "") : ""); if (string.Equals(a, "Off", StringComparison.OrdinalIgnoreCase)) { return "Off"; } if (string.Equals(a, "Reduced", StringComparison.OrdinalIgnoreCase)) { return "Reduced"; } return "Full"; } } internal static void Cycle() { if (Plugin.ScreenShakeStrength != null) { Plugin.ScreenShakeStrength.Value = ((Level == "Full") ? "Reduced" : ((Level == "Reduced") ? "Off" : "Full")); } } private static bool Scale(ref Vector2 feelDirection) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) string level = Level; if (level == "Full") { return true; } if (level == "Off") { PerfGate.Hit("ScreenShakeBlocked"); return false; } feelDirection *= 0.35f; PerfGate.Hit("ScreenShakeReduced"); return true; } [HarmonyPrefix] [HarmonyPatch("OnGameFeel")] private static bool PreOnGameFeel(ref Vector2 feelDirection) { return Scale(ref feelDirection); } [HarmonyPrefix] [HarmonyPatch("OnUIGameFeel")] private static bool PreOnUIGameFeel(ref Vector2 feelDirection) { return Scale(ref feelDirection); } } internal static class PlayerColorCosmetic { private class AnimState { public string sku; public Color baseColor; public Color teamBaseline; public bool baselineCaptured; public List tintedSkins = new List(); public List skinColorFields = new List(); public List originalSkinColors = new List(); public List tintedSprites = new List(); public List originalSpriteColors = new List(); public List tintedParticles = new List(); public List originalParticleColors = new List(); public bool staticFrameApplied; } private const string PROP_SKU = "cr_pcolor_sku"; private const string PROP_COLOR = "cr_pcolor_color"; private static readonly Dictionary animByActor = new Dictionary(); private static Coroutine animLoop; private static readonly HashSet _pendingInactiveApplies = new HashSet(); private static readonly Dictionary _applyGen = new Dictionary(); public static void PublishLocalProps() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown try { if (PhotonNetwork.IsConnected && PhotonNetwork.LocalPlayer != null) { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; Hashtable val = new Hashtable(); val[(object)"cr_pcolor_sku"] = cachedPlayerStats?.active_player_color_sku ?? ""; val[(object)"cr_pcolor_color"] = cachedPlayerStats?.active_player_color_hex ?? ""; PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)string.Format("[PCOLOR] Published sku={0} color={1}", val[(object)"cr_pcolor_sku"], val[(object)"cr_pcolor_color"])); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PCOLOR] PublishLocalProps failed: " + ex.Message)); } } public static void OnMatchStart() { if (Plugin.ShowPlayerColors != null && !Plugin.ShowPlayerColors.Value) { return; } try { ((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedApplyAll()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PCOLOR] OnMatchStart error: " + ex.Message)); } } public static void OnRoundStart() { if (Plugin.ShowPlayerColors != null && !Plugin.ShowPlayerColors.Value) { return; } try { ((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedApplyAll()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PCOLOR] OnRoundStart error: " + ex.Message)); } } public static void OnMatchEnd() { foreach (KeyValuePair item in animByActor) { try { RevertOnState(item.Value); } catch { } } animByActor.Clear(); if (animLoop != null && (Object)(object)Plugin.Instance != (Object)null) { try { ((MonoBehaviour)Plugin.Instance).StopCoroutine(animLoop); } catch { } animLoop = null; } } public static void RevertPlayer(int actor) { if (animByActor.TryGetValue(actor, out var value)) { try { RevertOnState(value); } catch { } animByActor.Remove(actor); } } public static void OnShowPlayerColorsToggled() { if (Plugin.ShowPlayerColors == null) { return; } if (!Plugin.ShowPlayerColors.Value) { foreach (KeyValuePair item in animByActor) { try { RevertOnState(item.Value); } catch { } } animByActor.Clear(); if (animLoop != null && (Object)(object)Plugin.Instance != (Object)null) { try { ((MonoBehaviour)Plugin.Instance).StopCoroutine(animLoop); } catch { } animLoop = null; } try { PlayerManager instance = PlayerManager.instance; if (!((Object)(object)instance != (Object)null) || instance.players == null) { return; } foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null)) { Component componentInChildren = ((Component)player).GetComponentInChildren(typeof(PlayerSkinHandler), true); if (!((Object)(object)componentInChildren == (Object)null)) { typeof(PlayerSkinHandler).GetMethod("Init", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(componentInChildren, null); } } } return; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PCOLOR] re-bake on toggle-off failed: " + ex.Message)); return; } } if (GameStateWatcher.IsInMatch) { OnMatchStart(); } } private static void RevertOnState(AnimState st) { //IL_0033: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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 (st == null) { return; } for (int i = 0; i < st.tintedSkins.Count && i < st.originalSkinColors.Count; i++) { try { st.skinColorFields[i].SetValue(st.tintedSkins[i], st.originalSkinColors[i]); } catch { } } for (int j = 0; j < st.tintedSprites.Count && j < st.originalSpriteColors.Count; j++) { try { if ((Object)(object)st.tintedSprites[j] != (Object)null) { st.tintedSprites[j].color = st.originalSpriteColors[j]; } } catch { } } for (int k = 0; k < st.tintedParticles.Count && k < st.originalParticleColors.Count; k++) { try { ParticleSystem val = st.tintedParticles[k]; if (!((Object)(object)val == (Object)null)) { MainModule main = val.main; ((MainModule)(ref main)).startColor = new MinMaxGradient(st.originalParticleColors[k]); } } catch { } } } public static void OnPlayerPropertiesChanged(Player target, Hashtable changed) { if (target != null && changed != null && (((Dictionary)(object)changed).ContainsKey((object)"cr_pcolor_sku") || ((Dictionary)(object)changed).ContainsKey((object)"cr_pcolor_color")) && (PhotonNetwork.LocalPlayer == null || target.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)) { ReapplyForActor(target.ActorNumber); } } public static void ReapplyForActor(int actor) { try { PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null) { return; } Player val = null; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val2 in playerList) { if (val2 != null && val2.ActorNumber == actor) { val = val2; break; } } if (val == null || val.CustomProperties == null) { return; } Hashtable customProperties = val.CustomProperties; string text = ((!((Dictionary)(object)customProperties).ContainsKey((object)"cr_pcolor_sku")) ? "" : (customProperties[(object)"cr_pcolor_sku"]?.ToString() ?? "")); string colorHex = ((!((Dictionary)(object)customProperties).ContainsKey((object)"cr_pcolor_color")) ? "" : (customProperties[(object)"cr_pcolor_color"]?.ToString() ?? "")); if (string.IsNullOrEmpty(text)) { return; } foreach (Player player in instance.players) { if ((Object)(object)player == (Object)null) { continue; } PhotonView component = ((Component)player).GetComponent(); if ((Object)(object)component == (Object)null || component.OwnerActorNr != actor) { continue; } if (ApplyOrDefer(((Component)player).transform, actor, text, colorHex)) { Plugin.Log.LogInfo((object)$"[PCOLOR] Re-applied for actor={actor} (late props) sku={text}"); } break; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PCOLOR] ReapplyForActor failed: " + ex.Message)); } } private static bool ApplyOrDefer(Transform playerRoot, int actor, string sku, string colorHex) { if ((Object)(object)playerRoot == (Object)null) { return false; } _applyGen.TryGetValue(actor, out var value); value++; _applyGen[actor] = value; if (((Component)playerRoot).gameObject.activeInHierarchy) { ApplyToPlayer(playerRoot, actor, sku, colorHex); return true; } if (_pendingInactiveApplies.Add(actor)) { Plugin.Log.LogInfo((object)$"[PCOLOR] deferred (player inactive) actor={actor}"); try { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ApplyWhenActive(playerRoot, actor, sku, colorHex, value)); } catch (Exception ex) { _pendingInactiveApplies.Remove(actor); Plugin.Log.LogWarning((object)("[PCOLOR] defer failed: " + ex.Message)); } } return false; } private static IEnumerator ApplyWhenActive(Transform playerRoot, int actor, string sku, string colorHex, int gen) { float deadline = Time.realtimeSinceStartup + 10f; while ((Object)(object)playerRoot != (Object)null && !((Component)playerRoot).gameObject.activeInHierarchy && Time.realtimeSinceStartup < deadline) { yield return null; } _pendingInactiveApplies.Remove(actor); if (_applyGen.TryGetValue(actor, out var cur) && cur != gen) { Plugin.Log.LogInfo((object)$"[PCOLOR] deferred apply superseded actor={actor}"); } else if (!((Object)(object)playerRoot == (Object)null) && ((Component)playerRoot).gameObject.activeInHierarchy) { ApplyToPlayer(playerRoot, actor, sku, colorHex); } } private static IEnumerator DelayedApplyAll() { for (int i = 0; i < 30; i++) { yield return null; } PlayerManager pm = PlayerManager.instance; if ((Object)(object)pm == (Object)null || pm.players == null) { yield break; } animByActor.Clear(); foreach (Player p in pm.players) { if ((Object)(object)p == (Object)null) { continue; } PhotonView pv = ((Component)p).GetComponent(); if ((Object)(object)pv == (Object)null) { continue; } int actor = pv.OwnerActorNr; Player photonPlayer = null; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player pp in playerList) { if (pp != null && pp.ActorNumber == actor) { photonPlayer = pp; break; } } string sku = ""; string colorHex = ""; if (pv.IsMine) { ApiClient.PlayerStatsData s = ApiClient.CachedPlayerStats; sku = s?.active_player_color_sku ?? ""; colorHex = s?.active_player_color_hex ?? ""; } else if (photonPlayer != null && photonPlayer.CustomProperties != null) { Hashtable cp = photonPlayer.CustomProperties; if (((Dictionary)(object)cp).ContainsKey((object)"cr_pcolor_sku")) { sku = cp[(object)"cr_pcolor_sku"]?.ToString() ?? ""; } if (((Dictionary)(object)cp).ContainsKey((object)"cr_pcolor_color")) { colorHex = cp[(object)"cr_pcolor_color"]?.ToString() ?? ""; } } if (!string.IsNullOrEmpty(sku)) { ApplyOrDefer(((Component)p).transform, actor, sku, colorHex); } } bool needTick = false; foreach (AnimState st in animByActor.Values) { if (IsAnimatedSku(st.sku)) { needTick = true; break; } } if (needTick && animLoop == null) { animLoop = ((MonoBehaviour)Plugin.Instance).StartCoroutine(AnimTickLoop()); } } private static bool IsAnimatedSku(string sku) { return sku == "pcolor_prismatic" || sku == "pcolor_chrome"; } private static void ApplyToPlayer(Transform playerRoot, int actor, string sku, string colorHex) { //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_0593: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_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_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Expected O, but got Unknown //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)playerRoot == (Object)null) { return; } if (Plugin.ShowPlayerColors != null && !Plugin.ShowPlayerColors.Value) { RevertPlayer(actor); return; } Color val = ParseHex(colorHex, Color.white); Color val2 = default(Color); bool flag = false; if (animByActor.TryGetValue(actor, out var value)) { val2 = value.teamBaseline; flag = value.baselineCaptured; RevertOnState(value); } AnimState animState = new AnimState { sku = sku, baseColor = val }; Color val3 = (Color)(flag ? val2 : new Color(1f, 0.5f, 0.2f)); if (!flag) { try { MonoBehaviour[] componentsInChildren = ((Component)playerRoot).GetComponentsInChildren(true); MonoBehaviour[] array = componentsInChildren; foreach (MonoBehaviour val4 in array) { if ((Object)(object)val4 == (Object)null) { continue; } Type type = ((object)val4).GetType(); if (type.Name != "PlayerSkin" && type.Name != "PlayerSkinHandler") { continue; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Color val5 = val3; float num = -1f; FieldInfo[] array2 = fields; foreach (FieldInfo fieldInfo in array2) { if (fieldInfo.FieldType != typeof(Color)) { continue; } try { Color val6 = (Color)fieldInfo.GetValue(val4); float num2 = ColorSaturation(val6); if (num2 > num) { num = num2; val5 = val6; } } catch { } } if (num > 0.2f) { val3 = val5; break; } } } catch { } } animState.teamBaseline = val3; animState.baselineCaptured = true; try { MonoBehaviour[] componentsInChildren2 = ((Component)playerRoot).GetComponentsInChildren(true); MonoBehaviour[] array3 = componentsInChildren2; foreach (MonoBehaviour val7 in array3) { if ((Object)(object)val7 == (Object)null) { continue; } Type type2 = ((object)val7).GetType(); if (type2.Name != "PlayerSkin" && type2.Name != "PlayerSkinHandler") { continue; } FieldInfo[] fields2 = type2.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array4 = fields2; foreach (FieldInfo fieldInfo2 in array4) { if (fieldInfo2.FieldType != typeof(Color)) { continue; } Color val8; try { val8 = (Color)fieldInfo2.GetValue(val7); if (!IsTeamLike(val8, val3)) { continue; } } catch { continue; } fieldInfo2.SetValue(val7, val); animState.tintedSkins.Add((Component)(object)val7); animState.skinColorFields.Add(fieldInfo2); animState.originalSkinColors.Add(val8); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PCOLOR] PlayerSkin tint failed: " + ex.Message)); } try { ParticleSystem[] componentsInChildren3 = ((Component)playerRoot).GetComponentsInChildren(true); ParticleSystem[] array5 = componentsInChildren3; foreach (ParticleSystem val9 in array5) { if ((Object)(object)val9 == (Object)null) { continue; } MainModule main = val9.main; MinMaxGradient startColor = ((MainModule)(ref main)).startColor; Color color = ((MinMaxGradient)(ref startColor)).color; if (IsTeamLike(color, val3)) { ((MainModule)(ref main)).startColor = new MinMaxGradient(val); ColorOverLifetimeModule colorOverLifetime = val9.colorOverLifetime; if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled) { Gradient val10 = new Gradient(); val10.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(val, 0f), new GradientColorKey(val, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[2] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val10); } animState.tintedParticles.Add(val9); animState.originalParticleColors.Add(color); } } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[PCOLOR] ParticleSystem tint failed: " + ex2.Message)); } try { SpriteRenderer[] componentsInChildren4 = ((Component)playerRoot).GetComponentsInChildren(true); SpriteRenderer[] array6 = componentsInChildren4; foreach (SpriteRenderer val11 in array6) { if (!((Object)(object)val11 == (Object)null)) { Color color2 = val11.color; if (!(color2.a < 0.3f) && IsTeamLike(color2, val3)) { val11.color = val; animState.tintedSprites.Add(val11); animState.originalSpriteColors.Add(color2); } } } } catch { } animByActor[actor] = animState; Plugin.Log.LogInfo((object)$"[PCOLOR] Applied actor={actor} sku={sku} hex={colorHex} baseline=({val3.r:F2},{val3.g:F2},{val3.b:F2}) skins={animState.tintedSkins.Count} particles={animState.tintedParticles.Count} sprites={animState.tintedSprites.Count}"); try { if (IsAnimatedSku(sku) && animLoop == null && (Object)(object)Plugin.Instance != (Object)null) { animLoop = ((MonoBehaviour)Plugin.Instance).StartCoroutine(AnimTickLoop()); Plugin.Log.LogInfo((object)$"[PCOLOR] Started anim tick loop (triggered by actor={actor} sku={sku})"); } } catch (Exception ex3) { Plugin.Log.LogWarning((object)("[PCOLOR] anim loop start failed: " + ex3.Message)); } } private static bool IsTeamLike(Color c, Color baseline) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_008c: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (c.a < 0.2f) { return false; } float num = ColorSaturation(c); float num2 = ColorSaturation(baseline); if (num < 0.18f) { return false; } float num3 = Mathf.Max(new float[3] { c.r, c.g, c.b }); if (num3 < 0.18f) { return false; } bool flag = baseline.r > baseline.b; bool flag2 = c.r > c.b; if (flag != flag2 && num2 > 0.2f) { return false; } float num4 = c.r - baseline.r; float num5 = c.g - baseline.g; float num6 = c.b - baseline.b; float num7 = Mathf.Sqrt(num4 * num4 + num5 * num5 + num6 * num6); return num7 < 0.55f; } private static float ColorSaturation(Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0024: 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) float num = Mathf.Max(c.r, Mathf.Max(c.g, c.b)); float num2 = Mathf.Min(c.r, Mathf.Min(c.g, c.b)); return (num <= 0.001f) ? 0f : ((num - num2) / num); } private static IEnumerator AnimTickLoop() { WaitForSeconds wait = new WaitForSeconds(1f / 30f); while (animByActor.Count > 0) { bool animationsEnabled = Plugin.AnimatedCosmetics == null || Plugin.AnimatedCosmetics.Value; float now = (animationsEnabled ? Time.time : 0f); foreach (KeyValuePair item in animByActor) { AnimState st = item.Value; if (!IsAnimatedSku(st.sku) || (!animationsEnabled && st.staticFrameApplied)) { continue; } Color c = st.baseColor; if (st.sku == "pcolor_prismatic") { float h = now * 0.25f % 1f; c = Color.HSVToRGB(h, 0.85f, 1f); } else if (st.sku == "pcolor_chrome") { float t = (Mathf.Sin(now * 0.7f) + 1f) * 0.5f; c = Color.Lerp(new Color(0.78f, 0.78f, 0.86f), new Color(0.92f, 0.92f, 0.96f), t); } for (int i = 0; i < st.tintedSkins.Count; i++) { st.skinColorFields[i].SetValue(st.tintedSkins[i], c); } foreach (SpriteRenderer sr in st.tintedSprites) { if ((Object)(object)sr != (Object)null) { sr.color = c; } } foreach (ParticleSystem ps in st.tintedParticles) { if (!((Object)(object)ps == (Object)null)) { MainModule main = ps.main; ((MainModule)(ref main)).startColor = new MinMaxGradient(c); main = default(MainModule); } } st.staticFrameApplied = !animationsEnabled; } yield return wait; } animLoop = null; } private static Color ParseHex(string hex, Color fallback) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(hex)) { return fallback; } if (hex.StartsWith("#")) { hex = hex.Substring(1); } if (hex.Length != 6) { return fallback; } try { int num = Convert.ToInt32(hex.Substring(0, 2), 16); int num2 = Convert.ToInt32(hex.Substring(2, 2), 16); int num3 = Convert.ToInt32(hex.Substring(4, 2), 16); return new Color((float)num / 255f, (float)num2 / 255f, (float)num3 / 255f, 1f); } catch { return fallback; } } } internal static class PlayerEffectCosmetic { private struct PreviewCfg { public float life; public float speed; public float size; public float rate; public float rise; public float gravity; public float orbital; public float radius; public Color start; public Color start2; public Color fadeFrom; public Color fadeTo; public bool twoStart; public bool fade; public bool rainbow; public bool spin; public string shape; } private struct SimParticle { public Vector2 pos; public Vector2 vel; public float born; public float life; public float size; public float spinSpeed; public float startLerp; } private const string PROP_SKU = "cr_effect_sku"; private static readonly Dictionary auraByActor = new Dictionary(); private static readonly Dictionary skuByActor = new Dictionary(); private static readonly Dictionary _texCache = new Dictionary(); private static Material _baseParticleMat; private static bool _baseMatSearched; private static readonly HashSet _pendingInactiveApplies = new HashSet(); private static readonly Dictionary _applyGen = new Dictionary(); private static string _previewSku = ""; private const int PREVIEW_MAX_PARTICLES = 220; private static readonly List _simParticles = new List(); private static PreviewCfg _cfg; private static float _emitAcc; private static Random _rng = new Random(); private const int TEX = 32; public static string PreviewSku => _previewSku; public static void PublishLocalProps() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown try { if (PhotonNetwork.IsConnected && PhotonNetwork.LocalPlayer != null) { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; Hashtable val = new Hashtable(); val[(object)"cr_effect_sku"] = cachedPlayerStats?.active_player_effect_sku ?? ""; PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)string.Format("[EFFECT] Published sku={0}", val[(object)"cr_effect_sku"])); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[EFFECT] PublishLocalProps failed: " + ex.Message)); } } public static void OnMatchStart() { if (Plugin.ShowPlayerColors != null && !Plugin.ShowPlayerColors.Value) { return; } try { ((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedApplyAll()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[EFFECT] OnMatchStart error: " + ex.Message)); } } public static void OnRoundStart() { if (Plugin.ShowPlayerColors != null && !Plugin.ShowPlayerColors.Value) { return; } try { ((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedApplyAll()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[EFFECT] OnRoundStart error: " + ex.Message)); } } public static void OnMatchEnd() { foreach (KeyValuePair item in auraByActor) { try { if ((Object)(object)item.Value != (Object)null) { Object.Destroy((Object)(object)item.Value); } } catch { } } auraByActor.Clear(); skuByActor.Clear(); } public static void OnShowPlayerColorsToggled() { if (Plugin.ShowPlayerColors != null) { if (!Plugin.ShowPlayerColors.Value) { OnMatchEnd(); } else if (GameStateWatcher.IsInMatch) { OnMatchStart(); } } } public static void OnAnimatedCosmeticsToggled() { bool animate = Plugin.AnimatedCosmetics == null || Plugin.AnimatedCosmetics.Value; foreach (KeyValuePair item in auraByActor) { try { ParticleSystem val = (((Object)(object)item.Value != (Object)null) ? item.Value.GetComponent() : null); if (!((Object)(object)val == (Object)null)) { ApplyAnimationState(val, animate); } } catch { } } } private static void ApplyAnimationState(ParticleSystem ps, bool animate) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ps == (Object)null)) { ps.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = ps.main; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)(animate ? 1 : 0); if (animate) { ps.Play(true); return; } ps.Simulate(0.75f, true, true); ps.Pause(true); } } public static void OnPlayerPropertiesChanged(Player target, Hashtable changed) { if (target == null || changed == null || !((Dictionary)(object)changed).ContainsKey((object)"cr_effect_sku") || (PhotonNetwork.LocalPlayer != null && target.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber)) { return; } try { ReapplyForActor(target.ActorNumber); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[EFFECT] propchange failed: " + ex.Message)); } } public static void ReapplyForActor(int actor) { if (Plugin.ShowPlayerColors != null && !Plugin.ShowPlayerColors.Value) { return; } PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null) { return; } Player val = null; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val2 in playerList) { if (val2 != null && val2.ActorNumber == actor) { val = val2; break; } } if (val == null || val.CustomProperties == null) { return; } string sku = ((!((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_effect_sku")) ? "" : (val.CustomProperties[(object)"cr_effect_sku"]?.ToString() ?? "")); foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null)) { PhotonView component = ((Component)player).GetComponent(); if (!((Object)(object)component == (Object)null) && component.OwnerActorNr == actor) { ApplyOrDefer(((Component)player).transform, actor, sku); break; } } } } private static int BumpGen(int actor) { _applyGen.TryGetValue(actor, out var value); value++; _applyGen[actor] = value; return value; } private static void ApplyOrDefer(Transform playerRoot, int actor, string sku) { if ((Object)(object)playerRoot == (Object)null) { return; } int gen = BumpGen(actor); if (string.IsNullOrEmpty(sku) || ((Component)playerRoot).gameObject.activeInHierarchy) { ApplyToPlayer(playerRoot, actor, sku); } else if (_pendingInactiveApplies.Add(actor)) { Plugin.Log.LogInfo((object)$"[EFFECT] deferred (player inactive) actor={actor}"); try { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ApplyWhenActive(playerRoot, actor, sku, gen)); } catch (Exception ex) { _pendingInactiveApplies.Remove(actor); Plugin.Log.LogWarning((object)("[EFFECT] defer failed: " + ex.Message)); } } } private static IEnumerator ApplyWhenActive(Transform playerRoot, int actor, string sku, int gen) { float deadline = Time.realtimeSinceStartup + 10f; while ((Object)(object)playerRoot != (Object)null && !((Component)playerRoot).gameObject.activeInHierarchy && Time.realtimeSinceStartup < deadline) { yield return null; } _pendingInactiveApplies.Remove(actor); if (_applyGen.TryGetValue(actor, out var cur) && cur != gen) { Plugin.Log.LogInfo((object)$"[EFFECT] deferred apply superseded actor={actor}"); } else if (!((Object)(object)playerRoot == (Object)null) && ((Component)playerRoot).gameObject.activeInHierarchy) { ApplyToPlayer(playerRoot, actor, sku); } } private static IEnumerator DelayedApplyAll() { for (int i = 0; i < 30; i++) { yield return null; } PlayerManager pm = PlayerManager.instance; if ((Object)(object)pm == (Object)null || pm.players == null) { yield break; } foreach (Player p in pm.players) { if ((Object)(object)p == (Object)null) { continue; } PhotonView pv = ((Component)p).GetComponent(); if ((Object)(object)pv == (Object)null) { continue; } int actor = pv.OwnerActorNr; string sku = ""; if (pv.IsMine) { sku = ApiClient.CachedPlayerStats?.active_player_effect_sku ?? ""; } else { Player photonPlayer = null; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player pp in playerList) { if (pp != null && pp.ActorNumber == actor) { photonPlayer = pp; break; } } if (photonPlayer != null && photonPlayer.CustomProperties != null && ((Dictionary)(object)photonPlayer.CustomProperties).ContainsKey((object)"cr_effect_sku")) { sku = photonPlayer.CustomProperties[(object)"cr_effect_sku"]?.ToString() ?? ""; } } ApplyOrDefer(((Component)p).transform, actor, sku); } } private static void ApplyToPlayer(Transform playerRoot, int actor, string sku) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)playerRoot == (Object)null) { return; } if (auraByActor.TryGetValue(actor, out var value)) { try { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } catch { } auraByActor.Remove(actor); } skuByActor.Remove(actor); if (string.IsNullOrEmpty(sku) || (Plugin.ShowPlayerColors != null && !Plugin.ShowPlayerColors.Value)) { return; } try { GameObject val = new GameObject("cr_effect"); val.transform.SetParent(playerRoot, false); val.transform.localPosition = Vector3.zero; ParticleSystem val2 = val.AddComponent(); val2.Stop(true, (ParticleSystemStopBehavior)0); ConfigureForSku(val2, sku); ParticleSystemRenderer component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Material val3 = BuildMaterialForSku(playerRoot, sku); if ((Object)(object)val3 != (Object)null) { ((Renderer)component).material = val3; } component.sortingFudge = -2f; component.renderMode = (ParticleSystemRenderMode)0; } ApplyAnimationState(val2, Plugin.AnimatedCosmetics == null || Plugin.AnimatedCosmetics.Value); auraByActor[actor] = val; skuByActor[actor] = sku; Plugin.Log.LogInfo((object)$"[EFFECT] Applied actor={actor} sku={sku}"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[EFFECT] ApplyToPlayer failed: " + ex.Message)); } } private static PreviewCfg CfgFor(string sku) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_059c: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Unknown result type (might be due to invalid IL or missing references) //IL_05bc: Unknown result type (might be due to invalid IL or missing references) //IL_05c1: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Unknown result type (might be due to invalid IL or missing references) //IL_0634: Unknown result type (might be due to invalid IL or missing references) //IL_064a: Unknown result type (might be due to invalid IL or missing references) //IL_064f: Unknown result type (might be due to invalid IL or missing references) //IL_0533: Unknown result type (might be due to invalid IL or missing references) //IL_0538: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_0507: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_0522: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) PreviewCfg result = new PreviewCfg { life = 1.2f, speed = 1f, size = 0.5f, rate = 14f, rise = 0f, gravity = 0f, orbital = 0f, radius = 1f, start = new Color(1f, 1f, 1f, 0.6f), shape = "dot" }; switch (sku) { case "effect_smoke": result.start = new Color(0.55f, 0.55f, 0.6f, 0.5f); result.life = 2.2f; result.speed = 0.6f; result.size = 0.9f; result.rate = 10f; result.rise = 0.8f; result.fade = true; result.fadeFrom = new Color(0.55f, 0.55f, 0.6f); result.fadeTo = new Color(0.7f, 0.7f, 0.75f); break; case "effect_clover": result.start = new Color(0.25f, 0.72f, 0.32f, 1f); result.life = 1.8f; result.speed = 0.9f; result.size = 0.4f; result.rate = 12f; result.gravity = 0.35f; result.spin = true; result.shape = "clover"; break; case "effect_hearts": result.start = new Color(0.95f, 0.36f, 0.58f, 1f); result.life = 1.8f; result.speed = 0.7f; result.size = 0.5f; result.rate = 9f; result.rise = 1.1f; result.fade = true; result.fadeFrom = new Color(0.95f, 0.36f, 0.58f); result.fadeTo = new Color(1f, 0.55f, 0.72f); result.shape = "heart"; break; case "effect_bubbles": result.start = new Color(0.5f, 0.78f, 0.94f, 0.7f); result.life = 2f; result.speed = 0.6f; result.size = 0.45f; result.rate = 11f; result.rise = 1f; break; case "effect_embers": result.start = new Color(0.94f, 0.47f, 0.16f, 1f); result.life = 1.4f; result.speed = 1.1f; result.size = 0.25f; result.rate = 22f; result.rise = 1.5f; result.fade = true; result.fadeFrom = new Color(1f, 0.6f, 0.2f); result.fadeTo = new Color(0.7f, 0.15f, 0.05f); break; case "effect_sparks": result.start = new Color(0.96f, 0.88f, 0.29f, 1f); result.life = 0.7f; result.speed = 2.4f; result.size = 0.18f; result.rate = 30f; result.radius = 0.4f; result.fade = true; result.fadeFrom = new Color(1f, 0.95f, 0.5f); result.fadeTo = new Color(1f, 0.6f, 0.1f); break; case "effect_rainbow": result.start = Color.white; result.life = 1.6f; result.speed = 0.9f; result.size = 0.4f; result.rate = 24f; result.rise = 0.7f; result.rainbow = true; break; case "effect_void": result.start = new Color(0.6f, 0.36f, 0.88f, 1f); result.start2 = new Color(0.2f, 0.78f, 0.9f, 1f); result.twoStart = true; result.life = 2f; result.speed = 0.5f; result.size = 0.45f; result.rate = 20f; result.radius = 0.9f; result.orbital = 1.4f; result.fade = true; result.fadeFrom = new Color(0.6f, 0.36f, 0.88f); result.fadeTo = new Color(0.12f, 0.05f, 0.2f); break; default: result.rise = 0.8f; break; } return result; } public static void TogglePreview(string sku) { if (!string.IsNullOrEmpty(_previewSku) && _previewSku == sku) { StopPreview(); return; } StopPreview(); if (!string.IsNullOrEmpty(sku)) { _cfg = CfgFor(sku); _previewSku = sku; _emitAcc = 0f; Plugin.Log.LogInfo((object)("[EFFECT] preview started: " + sku + " (IMGUI sim)")); } } public static void StopPreview() { _previewSku = ""; _simParticles.Clear(); _emitAcc = 0f; } public static void DrawPreview() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0136: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //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_0161: 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_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0563: Unknown result type (might be due to invalid IL or missing references) //IL_056b: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04d5: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Unknown result type (might be due to invalid IL or missing references) //IL_050d: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_052c: Unknown result type (might be due to invalid IL or missing references) //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(_previewSku)) { return; } if (!NativeUI.IsOpen) { StopPreview(); } else { if (Event.current == null || (int)Event.current.type != 7) { return; } try { float num = Mathf.Clamp(Time.unscaledDeltaTime, 0f, 0.05f); float num2 = (float)Screen.height / 40f; Vector3 mousePosition = Input.mousePosition; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(mousePosition.x, (float)Screen.height - mousePosition.y); _emitAcc += _cfg.rate * num; int num3 = (int)_emitAcc; _emitAcc -= num3; Vector2 val2 = default(Vector2); for (int i = 0; i < num3; i++) { if (_simParticles.Count >= 220) { break; } double num4 = _rng.NextDouble() * Math.PI * 2.0; float num5 = (float)Math.Sqrt(_rng.NextDouble()) * _cfg.radius; ((Vector2)(ref val2))..ctor((float)Math.Cos(num4), (float)Math.Sin(num4)); _simParticles.Add(new SimParticle { pos = val + val2 * num5 * num2, vel = val2 * _cfg.speed * num2, born = Time.unscaledTime, life = _cfg.life, size = _cfg.size, spinSpeed = (_cfg.spin ? ((float)(_rng.NextDouble() * 6.0 - 3.0)) : 0f), startLerp = (_cfg.twoStart ? ((float)_rng.NextDouble()) : 0f) }); } Texture2D textureForSku = GetTextureForSku(_previewSku); Color color = GUI.color; Matrix4x4 matrix = GUI.matrix; int depth = GUI.depth; GUI.depth = -1000; Rect val6 = default(Rect); for (int num6 = _simParticles.Count - 1; num6 >= 0; num6--) { SimParticle value = _simParticles[num6]; float num7 = Time.unscaledTime - value.born; if (num7 >= value.life) { _simParticles.RemoveAt(num6); } else { float num8 = num7 / value.life; value.vel.y += _cfg.gravity * 9.81f * num2 * num; Vector2 val3 = value.vel + new Vector2(0f, (0f - _cfg.rise) * num2); if (_cfg.orbital != 0f) { Vector2 val4 = value.pos - val; val3 += new Vector2(val4.y, 0f - val4.x) * _cfg.orbital; } ref Vector2 pos = ref value.pos; pos += val3 * num; _simParticles[num6] = value; Color val5; float num9; if (_cfg.rainbow) { val5 = RainbowAt(num8); num9 = 1f - num8; } else if (_cfg.fade) { val5 = Color.Lerp(_cfg.fadeFrom, _cfg.fadeTo, num8); num9 = ((num8 < 0.3f) ? Mathf.Lerp(1f, 0.9f, num8 / 0.3f) : Mathf.Lerp(0.9f, 0f, (num8 - 0.3f) / 0.7f)); num9 *= _cfg.start.a; } else { val5 = (_cfg.twoStart ? Color.Lerp(_cfg.start, _cfg.start2, value.startLerp) : _cfg.start); num9 = _cfg.start.a; } float num10 = value.size * 2f * num2; ((Rect)(ref val6))..ctor(value.pos.x - num10 / 2f, value.pos.y - num10 / 2f, num10, num10); GUI.color = new Color(val5.r, val5.g, val5.b, num9); if (value.spinSpeed != 0f) { Matrix4x4 matrix2 = GUI.matrix; GUIUtility.RotateAroundPivot(value.spinSpeed * num7 * 57.29578f, value.pos); GUI.DrawTexture(val6, (Texture)(object)textureForSku); GUI.matrix = matrix2; } else { GUI.DrawTexture(val6, (Texture)(object)textureForSku); } } } GUI.color = color; GUI.matrix = matrix; GUI.depth = depth; } catch { } } } private static Color RainbowAt(float t) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0038: 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_0069: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00d9: 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_00e1: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[6] { new Color(1f, 0.2f, 0.2f), new Color(1f, 0.8f, 0.2f), new Color(0.3f, 1f, 0.3f), new Color(0.2f, 0.8f, 1f), new Color(0.5f, 0.3f, 1f), new Color(1f, 0.3f, 0.9f) }; float num = Mathf.Clamp01(t) * (float)(array.Length - 1); int num2 = Mathf.Min((int)num, array.Length - 2); return Color.Lerp(array[num2], array[num2 + 1], num - (float)num2); } private static void ConfigureForSku(ParticleSystem ps, string sku) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_069f: Unknown result type (might be due to invalid IL or missing references) //IL_06b8: Unknown result type (might be due to invalid IL or missing references) //IL_06bd: Unknown result type (might be due to invalid IL or missing references) //IL_06cf: Unknown result type (might be due to invalid IL or missing references) //IL_06e1: Unknown result type (might be due to invalid IL or missing references) //IL_06f3: Unknown result type (might be due to invalid IL or missing references) //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_0734: Unknown result type (might be due to invalid IL or missing references) //IL_0748: Unknown result type (might be due to invalid IL or missing references) //IL_0619: Unknown result type (might be due to invalid IL or missing references) //IL_061e: Unknown result type (might be due to invalid IL or missing references) //IL_0630: Unknown result type (might be due to invalid IL or missing references) //IL_0642: Unknown result type (might be due to invalid IL or missing references) //IL_0654: Unknown result type (might be due to invalid IL or missing references) //IL_0666: Unknown result type (might be due to invalid IL or missing references) //IL_04d0: Unknown result type (might be due to invalid IL or missing references) //IL_04d5: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_0558: Unknown result type (might be due to invalid IL or missing references) //IL_076b: Unknown result type (might be due to invalid IL or missing references) //IL_0770: Unknown result type (might be due to invalid IL or missing references) //IL_057e: Unknown result type (might be due to invalid IL or missing references) //IL_0583: Unknown result type (might be due to invalid IL or missing references) //IL_0595: Unknown result type (might be due to invalid IL or missing references) //IL_05a7: Unknown result type (might be due to invalid IL or missing references) //IL_05b9: Unknown result type (might be due to invalid IL or missing references) //IL_05cb: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Unknown result type (might be due to invalid IL or missing references) //IL_0607: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_047a: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Unknown result type (might be due to invalid IL or missing references) //IL_049e: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).playOnAwake = false; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)1; ((MainModule)(ref main)).maxParticles = 200; EmissionModule emission = ps.emission; ((EmissionModule)(ref emission)).enabled = true; ShapeModule shape = ps.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.7f; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1.2f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(1f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.5f); ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(14f); VelocityOverLifetimeModule velocityOverLifetime = ps.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = false; ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = false; switch (sku) { case "effect_smoke": ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.55f, 0.55f, 0.6f, 0.5f)); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(2.2f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.6f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.9f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(10f); EnableRise(ps, 0.8f); FadeOut(ps, new Color(0.55f, 0.55f, 0.6f), new Color(0.7f, 0.7f, 0.75f)); break; case "effect_clover": { ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.25f, 0.72f, 0.32f, 1f)); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1.8f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.9f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.4f); ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0.35f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(12f); RotationOverLifetimeModule rotationOverLifetime = ps.rotationOverLifetime; ((RotationOverLifetimeModule)(ref rotationOverLifetime)).enabled = true; ((RotationOverLifetimeModule)(ref rotationOverLifetime)).z = new MinMaxCurve(-3f, 3f); break; } case "effect_hearts": ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.95f, 0.36f, 0.58f, 1f)); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1.8f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.7f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.5f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(9f); EnableRise(ps, 1.1f); FadeOut(ps, new Color(0.95f, 0.36f, 0.58f), new Color(1f, 0.55f, 0.72f)); break; case "effect_bubbles": ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.5f, 0.78f, 0.94f, 0.7f)); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(2f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.6f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.45f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(11f); EnableRise(ps, 1f); break; case "effect_embers": ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.94f, 0.47f, 0.16f, 1f)); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1.4f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(1.1f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.25f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(22f); EnableRise(ps, 1.5f); FadeOut(ps, new Color(1f, 0.6f, 0.2f), new Color(0.7f, 0.15f, 0.05f)); break; case "effect_sparks": ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.96f, 0.88f, 0.29f, 1f)); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.7f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(2.4f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.18f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(30f); ((ShapeModule)(ref shape)).radius = 0.4f; FadeOut(ps, new Color(1f, 0.95f, 0.5f), new Color(1f, 0.6f, 0.1f)); break; case "effect_rainbow": ((MainModule)(ref main)).startColor = new MinMaxGradient(Color.white); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1.6f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.9f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.4f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(24f); EnableRise(ps, 0.7f); RainbowOverLifetime(ps); break; case "effect_void": ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.6f, 0.36f, 0.88f, 1f), new Color(0.2f, 0.78f, 0.9f, 1f)); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(2f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.5f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.45f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(20f); ((ShapeModule)(ref shape)).radius = 0.9f; OrbitSwirl(ps); FadeOut(ps, new Color(0.6f, 0.36f, 0.88f), new Color(0.12f, 0.05f, 0.2f)); break; default: ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(1f, 1f, 1f, 0.6f)); EnableRise(ps, 0.8f); break; } } private static void EnableRise(ParticleSystem ps, float speed) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) VelocityOverLifetimeModule velocityOverLifetime = ps.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)1; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y = new MinMaxCurve(speed); } private static void OrbitSwirl(ParticleSystem ps) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) VelocityOverLifetimeModule velocityOverLifetime = ps.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)0; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalZ = new MinMaxCurve(1.4f); } private static void FadeOut(ParticleSystem ps, Color from, Color to) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0020: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val = new Gradient(); val.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(from, 0f), new GradientColorKey(to, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[3] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(0.9f, 0.3f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val); } private static void RainbowOverLifetime(ParticleSystem ps) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0137: Unknown result type (might be due to invalid IL or missing references) ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val = new Gradient(); val.SetKeys((GradientColorKey[])(object)new GradientColorKey[6] { new GradientColorKey(new Color(1f, 0.2f, 0.2f), 0f), new GradientColorKey(new Color(1f, 0.8f, 0.2f), 0.2f), new GradientColorKey(new Color(0.3f, 1f, 0.3f), 0.4f), new GradientColorKey(new Color(0.2f, 0.8f, 1f), 0.6f), new GradientColorKey(new Color(0.5f, 0.3f, 1f), 0.8f), new GradientColorKey(new Color(1f, 0.3f, 0.9f), 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[2] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val); } private static Material BuildMaterialForSku(Transform playerRoot, string sku) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) try { Material val = FindBaseParticleMaterial(playerRoot); Material val2 = ((!((Object)(object)val != (Object)null)) ? ((Material)null) : new Material(val)); if ((Object)(object)val2 == (Object)null) { return BuildUnlitPreviewMaterial(sku); } val2.mainTexture = (Texture)(object)GetTextureForSku(sku); return val2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[EFFECT] material build failed: " + ex.Message)); return null; } } private static Material BuildUnlitPreviewMaterial(string sku) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown try { Shader val = Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Legacy Shaders/Particles/Alpha Blended") ?? Shader.Find("Sprites/Default"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val); val2.mainTexture = (Texture)(object)GetTextureForSku(sku); return val2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[EFFECT] unlit material build failed: " + ex.Message)); return null; } } private static Material FindBaseParticleMaterial(Transform playerRoot) { if (_baseMatSearched && (Object)(object)_baseParticleMat != (Object)null) { return _baseParticleMat; } _baseMatSearched = true; try { if ((Object)(object)playerRoot != (Object)null) { ParticleSystemRenderer componentInChildren = ((Component)playerRoot).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Renderer)componentInChildren).sharedMaterial != (Object)null) { _baseParticleMat = ((Renderer)componentInChildren).sharedMaterial; return _baseParticleMat; } } ParticleSystemRenderer[] array = Object.FindObjectsOfType(); foreach (ParticleSystemRenderer val in array) { if ((Object)(object)val != (Object)null && (Object)(object)((Renderer)val).sharedMaterial != (Object)null) { _baseParticleMat = ((Renderer)val).sharedMaterial; return _baseParticleMat; } } } catch { } return _baseParticleMat; } private static Texture2D GetTextureForSku(string sku) { string text = ((sku == "effect_hearts") ? "heart" : ((sku == "effect_clover") ? "clover" : "dot")); if (_texCache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null) { return value; } Texture2D val = ((text == "heart") ? BuildHeartTex() : ((text == "clover") ? BuildCloverTex() : BuildDotTex())); _texCache[text] = val; return val; } private static Texture2D NewTex() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; ((Object)val).hideFlags = (HideFlags)61; return val; } private static Texture2D BuildDotTex() { //IL_0075: 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) Texture2D val = NewTex(); Color[] array = (Color[])(object)new Color[1024]; float num = 15.5f; float num2 = num; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num3 = Mathf.Sqrt(((float)j - num) * ((float)j - num) + ((float)i - num) * ((float)i - num)) / num2; float num4 = Mathf.Clamp01(1f - num3); num4 *= num4; array[i * 32 + j] = new Color(1f, 1f, 1f, num4); } } val.SetPixels(array); val.Apply(); return val; } private static Texture2D BuildHeartTex() { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) Texture2D val = NewTex(); Color[] array = (Color[])(object)new Color[1024]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = (float)j / 31f * 2f - 1f; float num2 = 1f - (float)i / 31f * 2f; num *= 1.25f; num2 = num2 * 1.25f + 0.15f; float num3 = Mathf.Pow(num * num + num2 * num2 - 1f, 3f) - num * num * num2 * num2 * num2; float num4 = ((num3 <= 0f) ? 1f : 0f); array[i * 32 + j] = new Color(1f, 1f, 1f, num4); } } val.SetPixels(array); val.Apply(); return val; } private static Texture2D BuildCloverTex() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_009c: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) Texture2D val = NewTex(); Color[] array = (Color[])(object)new Color[1024]; float num = 15.5f; float num2 = 8.32f; float num3 = 6.4f; Vector2[] array2 = (Vector2[])(object)new Vector2[4] { new Vector2(num - num3, num), new Vector2(num + num3, num), new Vector2(num, num - num3), new Vector2(num, num + num3) }; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num4 = 1f; Vector2[] array3 = array2; foreach (Vector2 val2 in array3) { float num5 = Mathf.Sqrt(((float)j - val2.x) * ((float)j - val2.x) + ((float)i - val2.y) * ((float)i - val2.y)) / num2; if (num5 < num4) { num4 = num5; } } float num6 = ((num4 <= 1f) ? Mathf.Clamp01(1.2f - num4) : 0f); array[i * 32 + j] = new Color(1f, 1f, 1f, num6); } } val.SetPixels(array); val.Apply(); return val; } } [BepInPlugin("com.competitiverounds.mod", "Competitive ROUNDS", "1.35.5")] [BepInProcess("Rounds.exe")] public class Plugin : BaseUnityPlugin { public const string ModId = "com.competitiverounds.mod"; public const string ModName = "Competitive ROUNDS"; public const string ModVersion = "1.35.5"; public const string RequiredGameVersion = "1.1.2"; internal const string LegacyApiUrl = "http://competitive-rounds.duckdns.org:8443"; internal const string DefaultApiUrl = "https://competitive-rounds.duckdns.org:8444"; internal static ManualLogSource Log; internal static CompetitiveRoundsBehaviour Instance; internal static Harmony HarmonyInstance; internal static ConfigEntry ApiBaseUrl; internal static ConfigEntry AdminHmacSecret; internal static ConfigEntry HttpsMigrationDone; internal static ConfigEntry RankedEnabled; internal static ConfigEntry RankedDisabledByConsent; internal static ConfigEntry ShowNotifications; internal static ConfigEntry ShowFps; internal static ConfigEntry ShowRegionPing; internal static ConfigEntry ShowIngameChat; internal static ConfigEntry ShowTrails; internal static ConfigEntry ShowBlockDebug; internal static ConfigEntry ShowPlayerColors; internal static ConfigEntry ShowInputOverlay; internal static ConfigEntry ScreenShakeEnabled; internal static ConfigEntry ScreenShakeStrength; internal static ConfigEntry MapLightingEnabled; internal static ConfigEntry MapShadowsEnabled; internal static ConfigEntry AnimatedCosmetics; internal static ConfigEntry ChromaticAberrationEnabled; internal static ConfigEntry BloomStrength; internal static ConfigEntry AutoRequeueOnMatchmakingBug; internal static ConfigEntry PerfOptimizations; internal static ConfigEntry PerfStunPlayerNullGuard; internal static ConfigEntry PerfDespawnOffscreenBullets; internal static ConfigEntry PerfSwallowHitSoundNREs; internal static ConfigEntry PerfSwallowEdgeBounceNREs; internal static ConfigEntry PerfSkipMenuUpdateInMatch; internal static ConfigEntry PerfBulletHitParticleCap; internal static ConfigEntry PerfClampObjectPoolInit; internal static ConfigEntry TournamentTimezone; internal static ConfigEntry TournamentDateFormat; internal static ConfigEntry MutedChatNames; internal static ConfigEntry DataConsent; private static bool spawned = false; internal static bool modDisabled = false; private static string pendingRankedRoom = null; private static string pendingRankedRegion = null; private static bool pendingRoomLeaving = false; private static float pendingRoomLogTimer = 0f; private static int pending2v2Slot = -1; private static int pendingOvtSlot = -1; private static int pendingFfaSlot = -1; private static int pendingFfaCount = 0; public static bool DataConsentGranted => DataConsent != null && DataConsent.Value == "granted"; public static bool DataConsentAsked => DataConsent != null && !string.IsNullOrEmpty(DataConsent.Value); public static string PendingRankedRoom => pendingRankedRoom; public static string PendingRankedRegion => pendingRankedRegion; public static int Pending2v2Slot => pending2v2Slot; public static int PendingOvtSlot => pendingOvtSlot; public static int PendingFfaSlot => pendingFfaSlot; public static int PendingFfaCount => pendingFfaCount; public static void SetPendingRoom(string roomName, string region = null) { pendingRankedRoom = roomName; pendingRankedRegion = region; Log.LogInfo((object)("[QUEUE] Pending ranked room set: " + roomName + " (region: " + (region ?? "auto") + ")")); } public static void ClearPendingRoom() { pendingRankedRoom = null; pendingRankedRegion = null; pendingRoomLeaving = false; } public static void SetPending2v2Slot(int slot) { pending2v2Slot = slot; Log.LogInfo((object)$"[2v2] Pending slot set: {slot} (team={((slot < 2) ? 1 : 2)})"); } public static void ClearPending2v2Slot() { if (pending2v2Slot >= 0) { Log.LogInfo((object)"[2v2] Pending slot cleared"); } pending2v2Slot = -1; } public static void SetPendingOvtSlot(int slot) { pendingOvtSlot = slot; Log.LogInfo((object)string.Format("[1v2] Pending slot set: {0} ({1})", slot, (slot == 0) ? "solo/team0" : "duo/team1")); } public static void ClearPendingOvtSlot() { if (pendingOvtSlot >= 0) { Log.LogInfo((object)"[1v2] Pending slot cleared"); } pendingOvtSlot = -1; } public static void SetPendingFfaSlot(int slot, int playerCount) { pendingFfaSlot = slot; pendingFfaCount = playerCount; Log.LogInfo((object)$"[FFA] Pending slot set: {slot} of {playerCount}"); } public static void ClearPendingFfaSlot() { if (pendingFfaSlot >= 0) { Log.LogInfo((object)"[FFA] Pending slot cleared"); } pendingFfaSlot = -1; pendingFfaCount = 0; } private void Awake() { //IL_082a: Unknown result type (might be due to invalid IL or missing references) //IL_0830: Expected O, but got Unknown //IL_084c: Unknown result type (might be due to invalid IL or missing references) //IL_0852: Expected O, but got Unknown //IL_07b9: Unknown result type (might be due to invalid IL or missing references) //IL_07c0: Expected O, but got Unknown //IL_06a4: Unknown result type (might be due to invalid IL or missing references) //IL_06ae: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; try { Application.quitting += delegate { try { string text2 = CompetitiveUI.BepInExLogPathPublic(); string text3 = CompetitiveUI.BepInExLogPreviousPath(); if (!string.IsNullOrEmpty(text2) && !string.IsNullOrEmpty(text3) && File.Exists(text2)) { File.Copy(text2, text3, overwrite: true); Log.LogInfo((object)("[BUG-REPORT] log snapshot saved: " + text3)); } } catch (Exception ex7) { Log.LogWarning((object)("[BUG-REPORT] quit-time log copy failed: " + ex7.Message)); } }; } catch (Exception ex) { Log.LogWarning((object)("[BUG-REPORT] quit hook bind failed: " + ex.Message)); } ApiBaseUrl = ((BaseUnityPlugin)this).Config.Bind("API", "BaseUrl", "https://competitive-rounds.duckdns.org:8444", "Base URL of the Competitive ROUNDS API server"); AdminHmacSecret = ((BaseUnityPlugin)this).Config.Bind("API", "AdminSecret", "", "Admin HMAC secret. Leave empty unless you are a server admin - admins receive the value out-of-band and it must match the server's ADMIN_HMAC_SECRET. Admin menu actions are rejected without it."); HttpsMigrationDone = ((BaseUnityPlugin)this).Config.Bind("API", "HttpsMigrationDone", false, "Internal: set once the one-time HTTPS endpoint migration has run. Clear it only if you also want BaseUrl re-migrated on next launch."); try { if (!HttpsMigrationDone.Value) { string a = (ApiBaseUrl.Value ?? "").Trim().TrimEnd('/'); if (string.Equals(a, "http://competitive-rounds.duckdns.org:8443", StringComparison.OrdinalIgnoreCase)) { ApiBaseUrl.Value = "https://competitive-rounds.duckdns.org:8444"; Log.LogInfo((object)"[API] BaseUrl migrated to HTTPS: https://competitive-rounds.duckdns.org:8444"); } HttpsMigrationDone.Value = true; } } catch (Exception ex2) { Log.LogWarning((object)("[API] BaseUrl migration skipped: " + ex2.Message)); } try { ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; } catch (Exception ex3) { Log.LogWarning((object)("[API] TLS 1.2 enable failed: " + ex3.Message)); } RankedEnabled = ((BaseUnityPlugin)this).Config.Bind("Ranked", "Enabled", true, "Whether ranked tracking is active"); RankedDisabledByConsent = ((BaseUnityPlugin)this).Config.Bind("Ranked", "DisabledByConsentRevoke", false, "Internal: ranked was auto-disabled by a data-consent revoke, not by the user"); ShowNotifications = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowNotifications", true, "Show in-game notifications for match results"); ShowFps = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowFps", true, "Show FPS counter in the top-left corner"); ShowRegionPing = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowRegionPing", true, "Show Photon ping and region alongside FPS when in a room"); ShowIngameChat = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowIngameChat", true, "Show the in-game chat overlay while outside the F5 menu"); ShowTrails = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowTrails", true, "Show cosmetic trails behind players during matches (including your own and opponents')"); ShowBlockDebug = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowBlockDebug", false, "Show the Block Debug overlay (top-right corner) during matches. Displays live counts of block activations vs successful absorbs, dedup drops, and per-hit timing ('too early' / 'too slow') so you can see why a block didn't land."); ShowPlayerColors = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowPlayerColors", true, "Render custom player body colors (purchased from the Body Color shop tab) — your own and other modded players'. Off = everyone falls back to the default orange/blue team colors."); ShowInputOverlay = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowInputOverlay", false, "Show a bottom-left WASD + Space + L/R-click input visualizer during matches. Keys glow red when pressed."); ScreenShakeEnabled = ((BaseUnityPlugin)this).Config.Bind("UI", "ScreenShakeEnabled", true, "(Legacy — superseded by ScreenShakeStrength.) Camera screen shake on hits/deaths/shots."); ScreenShakeStrength = ((BaseUnityPlugin)this).Config.Bind("UI", "ScreenShakeStrength", "Full", "Camera screen shake on hits/deaths/shots. Full = vanilla. Reduced = softer. Off = none. Local only — opponents still see theirs. Valid values: Full, Reduced, Off."); try { if (!ScreenShakeEnabled.Value && string.Equals(ScreenShakeStrength.Value, "Full", StringComparison.OrdinalIgnoreCase)) { ScreenShakeStrength.Value = "Off"; ScreenShakeEnabled.Value = true; Log.LogInfo((object)"[SETTINGS] migrated ScreenShakeEnabled=false -> ScreenShakeStrength=Off"); } } catch (Exception ex4) { Log.LogWarning((object)("[SETTINGS] shake migration: " + ex4.Message)); } MapLightingEnabled = ((BaseUnityPlugin)this).Config.Bind("UI", "MapLightingEnabled", true, "The map lighting pass (SFSS). Turn OFF for a flat, full-bright scene — skips the whole per-frame lightmap render for extra FPS."); MapShadowsEnabled = ((BaseUnityPlugin)this).Config.Bind("UI", "MapShadowsEnabled", true, "Soft shadow beams cast by map lighting. Turn OFF to skip the shadow render pass (lighting stays) for extra FPS."); AnimatedCosmetics = ((BaseUnityPlugin)this).Config.Bind("UI", "AnimatedCosmetics", true, "Animated cosmetics (prismatic/chrome body colors, prism trail hue cycle, player effects, map-skin sparkle shimmer, animated face items). Turn OFF to freeze them all to a static frame instantly."); ChromaticAberrationEnabled = ((BaseUnityPlugin)this).Config.Bind("UI", "ChromaticAberrationEnabled", true, "The RGB color-fringing distortion that pulses on shots/hits/deaths. Turn OFF for crisp edges and a tiny FPS gain (local only)."); BloomStrength = ((BaseUnityPlugin)this).Config.Bind("UI", "BloomStrength", "Full", "Strength of the post-processing GLOW (bloom) — the soft halo around bright cosmetics, map art and effects. Full = vanilla. Reduced = smaller, dimmer halo. Off = no halo at all. Local only, and it never hides anything: the cosmetic/map itself still renders exactly the same, only the halo around it changes. Note that a few cosmetics have their glow PAINTED INTO the artwork (energy orbs, shooting star) — that part is pixels, not an effect, so it stays visible at any setting. Valid values: Full, Reduced, Off."); AutoRequeueOnMatchmakingBug = ((BaseUnityPlugin)this).Config.Bind("UI", "AutoRequeueOnMatchmakingBug", true, "When the vanilla 'Press Jump to Join over a dead connection' matchmaking bug is detected, automatically restart and put you back in the quickplay queue (OFF = fast return to menu instead)."); PerfOptimizations = ((BaseUnityPlugin)this).Config.Bind("Performance", "Enabled", true, "Master switch for the v1.26.8 performance pass. Turn OFF to disable ALL patches below in one click. Individual patches below also have their own toggle for granular control."); PerfStunPlayerNullGuard = ((BaseUnityPlugin)this).Config.Bind("Performance", "StunPlayerNullGuard", true, "Null-guard StunPlayer.Go so a destroyed parent Player reference doesn't NRE every frame. Pure error suppression, no visual change."); PerfDespawnOffscreenBullets = ((BaseUnityPlugin)this).Config.Bind("Performance", "DespawnOffscreenBullets", true, "Host of each projectile despawns it once it flies outside the camera viewport (0.5s throttle). Without this, missed bullets keep ticking physics + RPC handlers indefinitely. Slight bandwidth savings, no gameplay difference."); PerfSwallowHitSoundNREs = ((BaseUnityPlugin)this).Config.Bind("Performance", "SwallowHitSoundNREs", true, "Catch the NullReferenceException that fires from RayHitBulletSound.DoHitEffect when its parent is destroyed mid-frame, and destroy the now-dead instance. Reduces BepInEx log spam, no visual change."); PerfSwallowEdgeBounceNREs = ((BaseUnityPlugin)this).Config.Bind("Performance", "SwallowEdgeBounceNREs", true, "Catch NullReferenceExceptions from ScreenEdgeBounce.DoHit and ScreenEdgeBounce.Update when a parent bullet was destroyed mid-frame. Reduces log spam, no visual change."); PerfSkipMenuUpdateInMatch = ((BaseUnityPlugin)this).Config.Bind("Performance", "SkipMenuUpdateInMatch", true, "Skip MenuControllerHandler.Update during an active match (menu controller input routing isn't needed during gameplay). Modest CPU win, no visible change."); PerfBulletHitParticleCap = ((BaseUnityPlugin)this).Config.Bind("Performance", "BulletHitParticleCap", true, "Cap bullet-hit particle explosions at 2 per frame. In a heavy firefight (BombsAway / Echo / Mayhem) a single frame can spawn 20+ explosion bursts — the cap drops GC and render cost noticeably. Missed bursts are silent: the damage already registered, you just don't see every visual."); PerfClampObjectPoolInit = ((BaseUnityPlugin)this).Config.Bind("Performance", "ClampObjectPoolInit", true, "Clamp ObjectPool initial-spawn to 4 instances while in a match (lazy growth instead of pre-allocating 30+ up-front). Reduces frame stutter when new pools are constructed mid-game."); TournamentTimezone = ((BaseUnityPlugin)this).Config.Bind("Tournaments", "Timezone", "Local", "Timezone used to display tournament times. One of: Local, UTC, PT, MT, CT, ET, UK, CET, EET, MSK, JST, AEST, or a system timezone ID."); TournamentDateFormat = ((BaseUnityPlugin)this).Config.Bind("Tournaments", "DateFormat", "ISO", "Date/time display format: ISO (2026-04-24 14:30), US (Sat 04/24 2:30 PM), or EU (Sat 24/04 14:30). All formats emit ASCII-only so any locale renders cleanly."); MutedChatNames = ((BaseUnityPlugin)this).Config.Bind("UI", "MutedChatNames", "", "Pipe-delimited list of display names whose chat messages are hidden from your in-game chat log. Use /mute name and /unmute name in chat."); DataConsent = ((BaseUnityPlugin)this).Config.Bind("Privacy", "DataConsent", "", "Consent to report match data to the leaderboard. Values: \"\" (unset — you'll be asked at launch), \"granted\", or \"denied\"."); Log.LogInfo((object)("Competitive ROUNDS v1.35.5 initializing (consent=" + (string.IsNullOrEmpty(DataConsent.Value) ? "unset" : DataConsent.Value) + ")...")); string text = Application.version ?? ""; if (!text.StartsWith("1.1.2")) { Log.LogError((object)("[COMPAT] ROUNDS version " + text + " is NOT supported! This mod requires vanilla ROUNDS v1.1.2.")); Log.LogError((object)"[COMPAT] Please switch to the 'Default Public Version' in Steam → ROUNDS → Properties → Betas."); Log.LogError((object)"[COMPAT] Mod DISABLED."); return; } Log.LogInfo((object)("[COMPAT] Game version OK: " + text)); try { HarmonyInstance = new Harmony("com.competitiverounds.mod"); int num = 0; int num2 = 0; Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in types) { object[] customAttributes = type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true); if (customAttributes != null && customAttributes.Length != 0) { try { HarmonyInstance.CreateClassProcessor(type).Patch(); num++; } catch (Exception ex5) { num2++; Log.LogError((object)("[HARMONY] Failed to patch " + type.Name + ": " + ex5.Message)); } } } Log.LogInfo((object)$"[HARMONY] Patches applied: {num} ok, {num2} failed"); } catch (Exception ex6) { Log.LogWarning((object)("Harmony patching bootstrap failed (mod will work without it): " + ex6.Message)); } if (!spawned) { GameObject val = new GameObject("CompetitiveRounds_Persistent"); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); Instance = val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); spawned = true; Log.LogInfo((object)"Created persistent GameObject with DontDestroyOnLoad"); } Log.LogInfo((object)"Competitive ROUNDS v1.35.5 loaded!"); GameObject val2 = new GameObject("CR_QueueJoiner"); ((Object)val2).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val2); val2.AddComponent(); GameObject val3 = new GameObject("CR_TaskbarFlash"); ((Object)val3).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val3); val3.AddComponent(); } } public class QueueRoomJoiner : MonoBehaviour { private enum JoinState { Idle, LeavingRoom, Connecting, WaitingForRoom } private JoinState state = JoinState.Idle; private float stateTimer = 0f; private bool joinInitiated = false; private string targetRoom; private string targetRegion; private int joinAttempts = 0; private void Awake() { Plugin.Log.LogInfo((object)"[QUEUE-JOINER] Awake, DontDestroyOnLoad set"); } private void Update() { //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Expected O, but got Unknown string pendingRankedRoom = Plugin.PendingRankedRoom; if (string.IsNullOrEmpty(pendingRankedRoom)) { joinInitiated = false; state = JoinState.Idle; stateTimer = 0f; joinAttempts = 0; return; } stateTimer += Time.deltaTime; if (state != JoinState.Idle && !string.IsNullOrEmpty(targetRoom) && !string.Equals(pendingRankedRoom, targetRoom, StringComparison.Ordinal)) { Plugin.Log.LogWarning((object)("[QUEUE-JOINER] pending room replaced mid-run ('" + targetRoom + "' -> '" + pendingRankedRoom + "') — restarting joiner for the new room")); if (state != JoinState.LeavingRoom) { try { GameStateWatcher.LeavingForRanked = false; } catch { } } joinInitiated = false; state = JoinState.Idle; stateTimer = 0f; joinAttempts = 0; targetRoom = null; targetRegion = null; return; } if (state != JoinState.Idle && stateTimer > 30f) { joinAttempts++; if (joinAttempts <= 1) { Plugin.Log.LogWarning((object)$"[QUEUE-JOINER] Join attempt {joinAttempts} timed out (state={state}, target='{targetRoom}') — retrying once"); bool flag = state == JoinState.LeavingRoom; joinInitiated = false; state = JoinState.Idle; stateTimer = 0f; if (!flag) { try { GameStateWatcher.LeavingForRanked = false; } catch { } } CompetitiveUI.ShowNotification("Slow connection — retrying ranked room join...", new Color(1f, 0.8f, 0.3f), 6f); return; } Plugin.Log.LogWarning((object)$"[QUEUE-JOINER] Timed out waiting for room join after {joinAttempts} attempts (state={state}, target='{targetRoom}'), resetting all queue state"); bool flag2 = (targetRoom ?? "").StartsWith("ovt_") || (pendingRankedRoom ?? "").StartsWith("ovt_"); bool flag3 = (targetRoom ?? "").StartsWith("ffa_") || (pendingRankedRoom ?? "").StartsWith("ffa_"); bool flag4 = state == JoinState.LeavingRoom; Plugin.ClearPendingRoom(); joinInitiated = false; state = JoinState.Idle; stateTimer = 0f; joinAttempts = 0; targetRoom = null; targetRegion = null; if (!flag4) { try { GameStateWatcher.LeavingForRanked = false; } catch { } } if (flag2) { try { ApiClient.OvtLeaveQueue(); } catch { } CompetitiveUI.ShowNotification("Failed to join the 1v2 room — lobby dissolved, please requeue", new Color(1f, 0.4f, 0.4f), 8f); } else if (flag3) { try { ApiClient.FfaLeaveQueue(); } catch { } CompetitiveUI.ShowNotification("Failed to join the FFA room — lobby dissolved, please requeue", new Color(1f, 0.4f, 0.4f), 8f); } else { CompetitiveUI.ShowNotification("Failed to join ranked room — please requeue", new Color(1f, 0.4f, 0.4f), 8f); } return; } switch (state) { case JoinState.Idle: if (joinInitiated) { break; } if (PhotonNetwork.InRoom) { Room currentRoom2 = PhotonNetwork.CurrentRoom; string text2 = ((currentRoom2 != null) ? currentRoom2.Name : null) ?? ""; if (text2 == pendingRankedRoom) { OnJoinedRankedRoom(text2); break; } if (!string.Equals(pendingRankedRoom, targetRoom, StringComparison.Ordinal)) { joinAttempts = 0; } targetRoom = pendingRankedRoom; targetRegion = Plugin.PendingRankedRegion; joinInitiated = true; GameStateWatcher.LeavingForRanked = true; try { Hashtable val = new Hashtable(); val[(object)"cr_lv_rk"] = "1"; Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer != null) { localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } catch { } PhotonNetwork.LeaveRoom(true); Plugin.Log.LogInfo((object)"[QUEUE-JOINER] Leaving current room before ranked join..."); state = JoinState.LeavingRoom; stateTimer = 0f; } else { if (!string.Equals(pendingRankedRoom, targetRoom, StringComparison.Ordinal)) { joinAttempts = 0; } targetRoom = pendingRankedRoom; targetRegion = Plugin.PendingRankedRegion; StartNCHConnect(); } break; case JoinState.LeavingRoom: if (!PhotonNetwork.InRoom) { Plugin.Log.LogInfo((object)"[QUEUE-JOINER] Left room, starting NCH connect..."); StartNCHConnect(); } break; case JoinState.Connecting: if (PhotonNetwork.InRoom) { Room currentRoom3 = PhotonNetwork.CurrentRoom; string text3 = ((currentRoom3 != null) ? currentRoom3.Name : null) ?? ""; if (text3 == targetRoom) { OnJoinedRankedRoom(text3); } } break; case JoinState.WaitingForRoom: if (PhotonNetwork.InRoom) { Room currentRoom = PhotonNetwork.CurrentRoom; string text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; if (text == targetRoom) { OnJoinedRankedRoom(text); } } break; } } private void StartNCHConnect() { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) joinInitiated = true; NetworkConnectionHandler instance = NetworkConnectionHandler.instance; if ((Object)(object)instance == (Object)null) { Plugin.Log.LogError((object)"[QUEUE-JOINER] NetworkConnectionHandler.instance is null!"); return; } try { if (PhotonNetwork.IsConnected) { PhotonNetwork.Disconnect(); Plugin.Log.LogInfo((object)"[QUEUE-JOINER] Disconnecting from Photon..."); } try { CharacterCreatorHandler instance2 = CharacterCreatorHandler.instance; if (instance2 != null) { instance2.CloseMenus(); } } catch { } try { MainMenuHandler instance3 = MainMenuHandler.instance; if (instance3 != null) { instance3.Close(); } } catch { } if (!string.IsNullOrEmpty(targetRegion)) { RegionSelector.region = targetRegion; Plugin.Log.LogInfo((object)("[QUEUE-JOINER] Set RegionSelector.region = " + targetRegion)); } instance.m_ForceRegion = true; Plugin.Log.LogInfo((object)"[QUEUE-JOINER] Set m_ForceRegion = true"); try { instance.m_searchingType = (SearchingType)0; } catch { } try { TimeHandler.instance.gameStartTime = 1f; } catch { } try { LoadingScreen instance4 = LoadingScreen.instance; if (instance4 != null) { instance4.StartLoading(false); } } catch { } string capturedRoom = targetRoom; ((MonoBehaviour)instance).StartCoroutine(instance.DoActionWhenConnected((Action)delegate { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0116: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Expected O, but got Unknown try { if (!string.Equals(Plugin.PendingRankedRoom, capturedRoom, StringComparison.Ordinal)) { bool flag = string.IsNullOrEmpty(Plugin.PendingRankedRoom); Plugin.Log.LogWarning((object)string.Format("[QUEUE-JOINER] pending room changed/cleared since capture ('{0}' -> '{1}') — aborting join (cleared={2})", capturedRoom, Plugin.PendingRankedRoom ?? "(none)", flag)); if (flag) { try { NetworkConnectionHandler.instance.NetworkRestart(); return; } catch { return; } } } else { Plugin.Log.LogInfo((object)("[QUEUE-JOINER] Connected! JoinOrCreate: " + capturedRoom)); bool flag2 = capturedRoom != null && capturedRoom.StartsWith("team_"); bool flag3 = capturedRoom != null && capturedRoom.StartsWith("ovt_"); bool flag4 = capturedRoom != null && capturedRoom.StartsWith("ffa_"); int num = ((Plugin.PendingFfaCount > 0) ? Plugin.PendingFfaCount : 10); Hashtable val = new Hashtable(); ((Dictionary)val).Add((object)"C2", (object)capturedRoom); Hashtable val2 = val; if (flag2) { val2[(object)"cr_ff"] = true; } if (flag3 && ApiClient.OvtSoloExtraPick) { val2[(object)"cr_ovt_xp"] = true; } if (flag4) { val2[(object)"cr_ffa_n"] = num; } RoomOptions val3 = new RoomOptions(); val3.MaxPlayers = (byte)(flag2 ? 4 : (flag3 ? 3 : (flag4 ? num : 2))); val3.IsOpen = true; val3.IsVisible = true; val3.CustomRoomProperties = val2; val3.CustomRoomPropertiesForLobby = new string[1] { "C2" }; RoomOptions val4 = val3; TypedLobby val5 = new TypedLobby("RoomCodeLobby", (LobbyType)2); PhotonNetwork.JoinOrCreateRoom(capturedRoom, val4, val5, (string[])null); } } catch (Exception ex2) { Plugin.Log.LogError((object)("[QUEUE-JOINER] JoinOrCreate failed: " + ex2.Message)); } })); Plugin.Log.LogInfo((object)("[QUEUE-JOINER] Started NCH connection sequence for room: " + targetRoom)); state = JoinState.Connecting; stateTimer = 0f; } catch (Exception ex) { Plugin.Log.LogError((object)("[QUEUE-JOINER] StartNCHConnect failed: " + ex.Message)); joinInitiated = false; } } private void OnJoinedRankedRoom(string roomName) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)("[QUEUE] In ranked room: " + roomName + "!")); Plugin.ClearPendingRoom(); joinInitiated = false; state = JoinState.Idle; stateTimer = 0f; joinAttempts = 0; try { GameStateWatcher.LeavingForRanked = false; } catch { } try { NetworkConnectionHandler instance = NetworkConnectionHandler.instance; if ((Object)(object)instance != (Object)null) { instance.m_ForceRegion = false; } } catch { } CompetitiveUI.ShowNotification("In ranked match room!", Color.green); CompetitiveRoundsBehaviour.HideMainMenu(); string localSteamId = GameStateWatcher.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { ApiClient.LeaveQueue(localSteamId); } if (roomName != null && roomName.StartsWith("ovt_")) { ApiClient.OvtQueueStatus = ""; } if (roomName != null && roomName.StartsWith("ffa_")) { ApiClient.FfaQueueStatus = ""; } if (Plugin.Pending2v2Slot >= 0 || Plugin.PendingOvtSlot >= 0 || Plugin.PendingFfaSlot >= 0) { ((MonoBehaviour)this).StartCoroutine(Auto2v2SpawnCoroutine()); } } private IEnumerator Auto2v2SpawnCoroutine() { float deadline = Time.realtimeSinceStartup + 12f; int tickLogCount = 0; while (Time.realtimeSinceStartup < deadline) { if (Plugin.Pending2v2Slot < 0 && Plugin.PendingOvtSlot < 0 && Plugin.PendingFfaSlot < 0) { Plugin.Log.LogInfo((object)"[2v2] Auto-spawn aborted — pending slot cleared mid-wait"); yield break; } if (!PhotonNetwork.InRoom) { Plugin.Log.LogInfo((object)"[2v2] Auto-spawn aborted — not in Photon room mid-wait"); yield break; } PlayerAssigner pa = PlayerAssigner.instance; if ((Object)(object)pa != (Object)null && !pa.hasCreatedLocalPlayer) { InputDevice device = null; try { if (InputManager.ActiveDevices != null && InputManager.ActiveDevices.Count > 0) { device = InputManager.ActiveDevices[0]; } } catch { } Plugin.Log.LogInfo((object)string.Format("[2v2] Auto-spawning local player (slot={0}, device={1})", Diag2v2.PendingSlot(), (device != null) ? "keyboard" : "null")); bool ok = false; try { pa.CreatePlayer(device, false); ok = true; } catch (Exception ex) { Plugin.Log.LogError((object)("[2v2] Auto-spawn CreatePlayer failed: " + ex.Message)); } if (ok) { try { string sid = MatchTracker.LocalSteamId; string seriesId = ApiClient.ActiveTeamSeriesId; if (!string.IsNullOrEmpty(sid) && !string.IsNullOrEmpty(seriesId)) { ApiClient.SendTeamSpawnConfirm(seriesId, sid); } yield break; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[2v2] spawn-confirm send error: " + ex2.Message)); yield break; } } } else if (tickLogCount < 6) { string reason = (((Object)(object)pa == (Object)null) ? "PlayerAssigner.instance == null" : (pa.hasCreatedLocalPlayer ? "local player already exists" : "?")); Plugin.Log.LogInfo((object)$"[2v2] Auto-spawn waiting: {reason} (tick {tickLogCount})"); tickLogCount++; } yield return (object)new WaitForSeconds(0.5f); } if ((Object)(object)PlayerAssigner.instance == (Object)null || !PlayerAssigner.instance.hasCreatedLocalPlayer) { Plugin.Log.LogWarning((object)"[2v2] Auto-spawn timed out — PlayerAssigner never initialized or local player never spawned"); } } } public class CompetitiveRoundsBehaviour : MonoBehaviour { private bool initialized = false; private float startupTimer = 0f; private bool startupComplete = false; private static bool _initSteamRanFired; private void Awake() { ((Object)this).hideFlags = (HideFlags)61; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); Plugin.Log.LogInfo((object)"[PERSIST] Behaviour Awake, DontDestroyOnLoad set"); } private void Update() { if (Plugin.modDisabled) { return; } try { MainMenuInjector.TryInject(); } catch { } if (!startupComplete) { startupTimer += Time.deltaTime; if (startupTimer >= 3f) { startupComplete = true; DoInitialize(); } } else { if (!initialized) { return; } try { CompetitiveUI.Tick(); } catch { } if (Input.GetKeyDown((KeyCode)286)) { CompetitiveUI.ToggleOverlay(); } try { GameStateWatcher.TickFrame(); } catch { } try { GameStateWatcher.Poll(); } catch (Exception ex) { Plugin.Log.LogError((object)("Poll error: " + ex.Message)); } if (ApiClient.IsQueuePolling) { try { ApiClient.UpdateQueuePoll(GameStateWatcher.LocalSteamId); } catch { } } if (ApiClient.IsTeamQueuePolling) { try { ApiClient.UpdateTeamQueuePoll(GameStateWatcher.LocalSteamId); } catch { } } try { ApiClient.TickLeaveRecovery(); } catch { } try { PoisonSync.Hook(); PoisonSync.EnsureCapabilityPublished(); } catch { } if (ApiClient.IsOvtQueuePolling) { try { ApiClient.UpdateOvtQueuePoll(force: false); } catch { } } if (ApiClient.IsFfaQueuePolling) { try { ApiClient.UpdateFfaQueuePoll(force: false); } catch { } } if (NativeUI.IsOpen) { try { ApiClient.UpdateQueueCount(); } catch { } try { ApiClient.UpdateTeamQueueCount(); } catch { } try { NativeUI.MaybeRefreshLiveSeries(); } catch { } } } } private void DoInitialize() { Plugin.Log.LogInfo((object)"[PERSIST] Delayed initialization starting..."); try { Dictionary pluginInfos = Chainloader.PluginInfos; if (pluginInfos != null && pluginInfos.Count > 1) { List list = new List(); foreach (KeyValuePair item in pluginInfos) { if (item.Key != "com.competitiverounds.mod") { list.Add(item.Value.Metadata.Name + " (" + item.Key + ")"); } } if (list.Count > 0) { Plugin.Log.LogError((object)$"[COMPAT] {list.Count} other mod(s) detected! This mod requires vanilla ROUNDS with no other plugins."); foreach (string item2 in list) { Plugin.Log.LogError((object)("[COMPAT] - " + item2)); } Plugin.Log.LogError((object)"[COMPAT] Mod DISABLED to ensure competitive integrity."); Plugin.modDisabled = true; return; } } Plugin.Log.LogInfo((object)"[COMPAT] No other mods detected — OK"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[COMPAT] Could not check other mods: " + ex.Message)); } ApiClient.Initialize(Plugin.ApiBaseUrl.Value); GameStateWatcher.Initialize(); CardImageLoader.Initialize(); try { CustomCosmetics.Initialize(); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[COSMETIC] init failed: " + ex2.Message)); } CompetitiveUI.CacheRaycasters(); initialized = true; try { UIFactory.InitTypes(); UIFactory.InitFont(); } catch (Exception ex3) { Plugin.Log.LogWarning((object)("[UI] Type init deferred: " + ex3.Message)); } ((MonoBehaviour)Plugin.Instance).StartCoroutine(InitWhenSteamReady()); ChatClient.OnMessage = NativeUI.OnChatMessage; if (Plugin.DataConsentGranted) { ChatClient.Connect(); } try { NametagFontRenderer.LogAvailableTmpFonts(); } catch { } Plugin.Log.LogInfo((object)"[PERSIST] All systems active! Press F5 for overlay."); } private IEnumerator InitWhenSteamReady() { float deadline = Time.unscaledTime + 30f; int tries = 0; while (!_initSteamRanFired && Time.unscaledTime < deadline) { tries++; string sid = GameStateWatcher.LocalSteamId; if (!string.IsNullOrEmpty(sid) && sid != "unknown") { _initSteamRanFired = true; Plugin.Log.LogInfo((object)$"[INIT] Steam resolved on try {tries} (sid={sid}); firing one-shot init"); try { ApiClient.ToggleRanked(sid, Plugin.RankedEnabled.Value); } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogWarning((object)("[INIT] ToggleRanked failed: " + ex2.Message)); } try { ApiClient.FetchPlayerStats(sid); } catch { } try { ApiClient.FetchMatchHistory(sid); } catch { } try { ApiClient.FetchBlockedPlayers(sid); } catch { } try { ApiClient.CheckAdminStatus(sid); } catch { } try { ApiClient.FetchShopItems(sid); yield break; } catch { yield break; } } yield return (object)new WaitForSeconds(0.5f); } if (!_initSteamRanFired) { Plugin.Log.LogWarning((object)$"[INIT] Steam ID never resolved after {tries} tries / 30s. Server-side ranked_enabled may be stale until next launch."); } } private void OnGUI() { if (initialized && !Plugin.modDisabled) { CompetitiveUI.DrawUI(); } } internal static void HideMainMenu() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) try { for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); Plugin.Log.LogInfo((object)$"[QUEUE] Loaded scene: {((Scene)(ref sceneAt)).name} (index {((Scene)(ref sceneAt)).buildIndex})"); } MainMenuHandler val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); Plugin.Log.LogInfo((object)"[QUEUE] Disabled MainMenuHandler"); } ListMenu[] array = Object.FindObjectsOfType(); ListMenu[] array2 = array; foreach (ListMenu val2 in array2) { ((Component)val2).gameObject.SetActive(false); } if (array.Length != 0) { Plugin.Log.LogInfo((object)$"[QUEUE] Disabled {array.Length} ListMenu objects"); } CharacterSelectionInstance val3 = Object.FindObjectOfType(); if ((Object)(object)val3 != (Object)null) { ((Component)((Component)val3).transform.root).gameObject.SetActive(false); Plugin.Log.LogInfo((object)"[QUEUE] Disabled character selection"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[QUEUE] HideMainMenu error: " + ex.Message)); } } private void OnDestroy() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown Plugin.Log.LogWarning((object)"[PERSIST] Destroyed! Attempting respawn..."); MainMenuInjector.Reset(); try { GameObject val = new GameObject("CompetitiveRounds_Respawn"); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); CompetitiveRoundsBehaviour instance = val.AddComponent(); Plugin.Instance = instance; Plugin.Log.LogInfo((object)"[PERSIST] Respawned with DontDestroyOnLoad!"); } catch (Exception ex) { Plugin.Log.LogError((object)("[PERSIST] Respawn failed: " + ex.Message)); } } } [HarmonyPatch(typeof(GM_ArmsRace), "Awake")] internal class GMArmsRaceAwakePatch { private static void Postfix(GM_ArmsRace __instance) { Plugin.Log.LogInfo((object)"[HARMONY] GM_ArmsRace.Awake fired! Harmony is WORKING!"); CardRarityLookup.ScanAll(); if (CardRarityLookup.Count == 0) { Plugin.Log.LogInfo((object)"[HARMONY] No cards found yet — will retry on match start"); } } } [HarmonyPatch(typeof(GM_ArmsRace), "OnEnable")] internal class GMArmsRaceOnEnable_4Player_Patch { private static void Postfix(GM_ArmsRace __instance) { try { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; string text = PhotonNetwork.CurrentRoom.Name ?? ""; bool flag = text.StartsWith("ovt_"); bool flag2 = text.StartsWith("ffa_") && FfaMode.EngineActive(); bool flag3 = ((Dictionary)(object)customProperties)?.ContainsKey((object)"cr_ff") ?? false; if (flag || flag3 || flag2) { int num = (__instance.playersNeededToStart = (flag2 ? Diag2v2.PlayersNeeded() : (flag ? 3 : 4))); if ((Object)(object)PlayerAssigner.instance != (Object)null) { PlayerAssigner.instance.maxPlayers = num; } Plugin.Log.LogInfo((object)string.Format("[MODE] Forced playersNeededToStart={0} ({1} room)", num, flag2 ? "ffa_ FFA" : (flag ? "ovt_ 1v2" : "cr_ff 2v2"))); } } catch (Exception ex) { Plugin.Log.LogError((object)("[2v2] OnEnable patch error: " + ex.Message)); } } } [HarmonyPatch(typeof(CharacterSelectionMenu), "PlayerJoined")] internal class CharacterSelectionMenu_PlayerJoined_2v2_Patch { private static bool Prefix(CharacterSelectionMenu __instance) { try { if ((Object)(object)__instance == (Object)null || ((Component)__instance).transform.childCount == 0) { return true; } int num = (((Object)(object)PlayerManager.instance != (Object)null && PlayerManager.instance.players != null) ? (PlayerManager.instance.players.Count - 1) : (-1)); Transform child = ((Component)__instance).transform.GetChild(0); if (num < 0 || num >= child.childCount) { Plugin.Log.LogInfo((object)$"[2v2] CharacterSelectionMenu skipped (slot={num} >= children={child.childCount})"); return false; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2] CharacterSelectionMenu prefix error: " + ex.Message)); } return true; } } [HarmonyPatch(typeof(PlayerAssigner), "CreatePlayer")] internal class PlayerAssigner_CreatePlayer_2v2_Patch { private static float _lastSpawnGuardLog = -999f; private static float _suppressEpisodeStart = -1f; private static bool Prefix(PlayerAssigner __instance, InputDevice inputDevice, bool isAI) { //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown if (!PhotonNetwork.OfflineMode && (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)) { try { if (Time.unscaledTime - _lastSpawnGuardLog > 2f) { _lastSpawnGuardLog = Time.unscaledTime; Plugin.Log.LogWarning((object)("[SPAWN-GUARD] CreatePlayer suppressed — client not in a room " + $"(state={PhotonNetwork.NetworkClientState}). Will retry when connected.")); } if (_suppressEpisodeStart < 0f) { _suppressEpisodeStart = Time.unscaledTime; } else if (Time.unscaledTime - _suppressEpisodeStart > 30f) { _suppressEpisodeStart = -1f; Plugin.Log.LogWarning((object)"[SPAWN-GUARD] stuck >30s with no room — NetworkRestart back to menu"); try { CompetitiveUI.ShowNotification("Connection was lost — returning to menu.", new Color(1f, 0.8f, 0.3f), 6f); } catch { } try { NetworkConnectionHandler.instance.NetworkRestart(); } catch { } } } catch { } return false; } _suppressEpisodeStart = -1f; if (PhotonNetwork.OfflineMode) { return true; } if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return true; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; bool flag = (PhotonNetwork.CurrentRoom.Name ?? "").StartsWith("ovt_"); bool flag2 = (PhotonNetwork.CurrentRoom.Name ?? "").StartsWith("ffa_"); bool flag3 = ((Dictionary)(object)customProperties)?.ContainsKey((object)"cr_ff") ?? false; int num = (flag ? Plugin.PendingOvtSlot : (flag2 ? Plugin.PendingFfaSlot : (flag3 ? Plugin.Pending2v2Slot : (-1)))); if (num < 0) { return true; } if (__instance.hasCreatedLocalPlayer) { return false; } int num2 = Diag2v2.SlotToTeam(num); int num3 = num; try { typeof(PlayerAssigner).GetField("m_playerId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(__instance, num); __instance.hasCreatedLocalPlayer = true; Hashtable val = new Hashtable(); val[(object)Player.VAR_PLAYERID] = num3; val[(object)Player.VAR_TEAMID] = num2; try { string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && localSteamId != "unknown") { val[(object)"u_id"] = localSteamId; } } catch { } PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); Vector3 val2 = Vector3.up * 100f; CharacterData component = PhotonNetwork.Instantiate(((Object)__instance.playerPrefab).name, val2, Quaternion.identity, (byte)0, (object[])null).GetComponent(); component.input.inputType = (InputType)1; component.playerActions = PlayerActions.CreateWithKeyboardBindings(); ((PlayerActionSet)component.playerActions).Device = inputDevice; __instance.players.Add(component); int num4 = num3; PlayerManager.RegisterPlayer(component.player, num4); component.player.AssignPlayerID(num3); component.player.AssignTeamID(num2); try { Type typeFromHandle = typeof(Player); (string, object)[] array = new(string, object)[3] { ("AssignPlatform", null), ("AssignUserID", null), ("AssignUnityID", null) }; for (int i = 0; i < array.Length; i++) { (string, object) tuple = array[i]; string item = tuple.Item1; object item2 = tuple.Item2; MethodInfo method = typeFromHandle.GetMethod(item); if (method != null && item2 != null) { method.Invoke(component.player, new object[1] { item2 }); } } } catch { } try { PlayerSkinHandler componentInChildren = ((Component)component).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { for (int num5 = ((Component)componentInChildren).transform.childCount - 1; num5 >= 0; num5--) { Transform child = ((Component)componentInChildren).transform.GetChild(num5); if ((Object)(object)child != (Object)null) { Object.Destroy((Object)(object)((Component)child).gameObject); } } componentInChildren.inited = false; typeof(PlayerSkinHandler).GetMethod("Init", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(componentInChildren, null); Plugin.Log.LogInfo((object)$"[2v2] Re-baked local PlayerSkin for slot={num} (post-AssignPlayerID)"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2] PlayerSkin re-bake failed: " + ex.Message)); } Plugin.Log.LogInfo((object)string.Format("[{0}] CreatePlayer override: slot={1} team={2} pid={3}", flag2 ? "FFA" : (flag ? "1v2" : "2v2"), num, num2, num3)); return false; } catch (Exception ex2) { Plugin.Log.LogError((object)("[2v2] CreatePlayer override failed: " + ex2.Message + " — falling back to vanilla")); return true; } } } [HarmonyPatch(typeof(NetworkConnectionHandler), "OnPlayerEnteredRoom")] internal class QuickplayChurnFreezePatch { private static void Postfix() { try { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.PlayerCount >= 2) { NetworkConnectionHandler instance = NetworkConnectionHandler.instance; if (!((Object)(object)instance == (Object)null)) { instance.untilTryOtherRegionCounter = float.MaxValue; Plugin.Log.LogInfo((object)"[QUICKPLAY-GUARD] opponent joined — region-churn timer frozen"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[QUICKPLAY-GUARD] freeze failed: " + ex.Message)); } } } [HarmonyPatch(typeof(NetworkConnectionHandler), "PlayOnBestActiveRegion")] internal class QuickplayChurnAbandonGuardPatch { internal static volatile bool SweepActive; internal static volatile bool AbortSweep; private static bool Prefix(ref IEnumerator __result) { try { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.PlayerCount >= 2) { Plugin.Log.LogWarning((object)"[QUICKPLAY-GUARD] PlayOnBestActiveRegion suppressed — match already found in this room"); try { NetworkConnectionHandler.instance.untilTryOtherRegionCounter = 15f; } catch { } __result = EmptyRoutine(); return false; } } catch { } return true; } private static void Postfix(ref IEnumerator __result) { __result = Track(__result); } private static IEnumerator Track(IEnumerator orig) { SweepActive = true; AbortSweep = false; try { while (!AbortSweep && orig.MoveNext()) { yield return orig.Current; } } finally { SweepActive = false; if (AbortSweep) { Plugin.Log.LogWarning((object)"[QUICKPLAY-GUARD] region sweep aborted by requeue watchdog"); } } } private static IEnumerator EmptyRoutine() { yield break; } } internal static class Diag2v2 { public static bool IsActive() { if (Plugin.Pending2v2Slot >= 0 || Plugin.PendingOvtSlot >= 0 || Plugin.PendingFfaSlot >= 0) { return true; } try { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null) { Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (customProperties != null && ((Dictionary)(object)customProperties).ContainsKey((object)"cr_ff")) { return true; } string text = PhotonNetwork.CurrentRoom.Name ?? ""; if (text.StartsWith("ovt_")) { return true; } if (text.StartsWith("ffa_") && FfaMode.EngineActive()) { return true; } } } catch { } return false; } public static bool IsOvt() { try { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null) { return (PhotonNetwork.CurrentRoom.Name ?? "").StartsWith("ovt_"); } } catch { } return Plugin.PendingOvtSlot >= 0; } public static bool IsFfa() { try { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null) { return FfaMode.EngineActive(); } } catch { } return Plugin.PendingFfaSlot >= 0; } public static int SlotToTeam(int slot) { if (IsFfa()) { return slot; } return (!IsOvt()) ? (slot / 2) : ((slot != 0) ? 1 : 0); } public static int PlayersNeeded() { if (IsFfa()) { try { object obj; if (!PhotonNetwork.InRoom) { obj = null; } else { Room currentRoom = PhotonNetwork.CurrentRoom; obj = ((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null); } Hashtable val = (Hashtable)obj; if (val != null && ((Dictionary)(object)val).ContainsKey((object)"cr_ffa_n")) { int num = Convert.ToInt32(val[(object)"cr_ffa_n"]); if (num >= 2 && num <= 10) { return num; } } } catch { } return (Plugin.PendingFfaCount > 0) ? Plugin.PendingFfaCount : 10; } return IsOvt() ? 3 : 4; } public static int PendingSlot() { if (Plugin.PendingFfaSlot >= 0) { return Plugin.PendingFfaSlot; } if (Plugin.PendingOvtSlot >= 0) { return Plugin.PendingOvtSlot; } return Plugin.Pending2v2Slot; } public static string ShortStack() { try { StackTrace stackTrace = new StackTrace(2, fNeedFileInfo: false); StringBuilder stringBuilder = new StringBuilder(); int num = Math.Min(stackTrace.FrameCount, 8); for (int i = 0; i < num; i++) { MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod(); if (!(methodBase == null)) { stringBuilder.Append(methodBase.DeclaringType?.Name ?? "?").Append('.').Append(methodBase.Name); if (i < num - 1) { stringBuilder.Append(" <- "); } } } return stringBuilder.ToString(); } catch { return ""; } } public static string DescribeRoom() { try { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return "(not in room)"; } Room currentRoom = PhotonNetwork.CurrentRoom; int playerCount = currentRoom.PlayerCount; int maxPlayers = currentRoom.MaxPlayers; return $"room={currentRoom.Name} players={playerCount}/{maxPlayers}"; } catch { return "(room-describe failed)"; } } } public class Cr2v2DiagCallbacks : MonoBehaviour, IInRoomCallbacks, IConnectionCallbacks, IMatchmakingCallbacks { private void OnEnable() { try { PhotonNetwork.AddCallbackTarget((object)this); } catch { } } private void OnDisable() { try { PhotonNetwork.RemoveCallbackTarget((object)this); } catch { } } public void OnPlayerEnteredRoom(Player p) { try { if (CompetitiveRoomDetect.IsCompetitiveRoom()) { FacePublisher.PublishLocal(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POPUP] PlayerEntered face republish: " + ex.Message)); } if (!Diag2v2.IsActive()) { return; } try { int result = -1; int result2 = -1; if (p.CustomProperties != null) { if (((Dictionary)(object)p.CustomProperties).ContainsKey((object)"p_id")) { int.TryParse(p.CustomProperties[(object)"p_id"].ToString(), out result); } if (((Dictionary)(object)p.CustomProperties).ContainsKey((object)"t_id")) { int.TryParse(p.CustomProperties[(object)"t_id"].ToString(), out result2); } } Plugin.Log.LogInfo((object)$"[2v2-DIAG] PlayerEntered: nick='{p.NickName}' actor={p.ActorNumber} p_id={result} t_id={result2} {Diag2v2.DescribeRoom()}"); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[2v2-DIAG] PlayerEntered log error: " + ex2.Message)); } } public void OnPlayerLeftRoom(Player p) { try { GameStateWatcher.NotifyPlayerLeftRoom(p); } catch { } if (!Diag2v2.IsActive()) { return; } try { Plugin.Log.LogInfo((object)$"[2v2-DIAG] PlayerLeft: nick='{((p != null) ? p.NickName : null)}' actor={((p != null) ? new int?(p.ActorNumber) : ((int?)null))} {Diag2v2.DescribeRoom()}"); } catch { } if (Diag2v2.IsOvt() || Diag2v2.IsFfa()) { return; } try { if (p == null) { return; } string activeTeamSeriesId = ApiClient.ActiveTeamSeriesId; if (string.IsNullOrEmpty(activeTeamSeriesId)) { return; } if (!GameStateWatcher.IsInMatch) { Plugin.Log.LogInfo((object)("[2v2-DC] suppressed during assembly phase " + $"(IsInMatch=false), leaver='{((p != null) ? p.NickName : null)}' actor={((p != null) ? new int?(p.ActorNumber) : ((int?)null))}")); return; } string text = null; if (p.CustomProperties != null) { if (((Dictionary)(object)p.CustomProperties).ContainsKey((object)"u_id")) { text = p.CustomProperties[(object)"u_id"]?.ToString(); } if (string.IsNullOrEmpty(text) && ((Dictionary)(object)p.CustomProperties).ContainsKey((object)"unity_id")) { text = p.CustomProperties[(object)"unity_id"]?.ToString(); } } if (string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(p.UserId)) { text = p.UserId; } if (string.IsNullOrEmpty(text) || text.StartsWith("photon_")) { return; } string localSteamId = MatchTracker.LocalSteamId; if (string.IsNullOrEmpty(localSteamId) || !long.TryParse(localSteamId, out var result)) { return; } bool flag = true; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if (val != null && val.ActorNumber != p.ActorNumber && !val.IsLocal) { string text2 = null; if (val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).ContainsKey((object)"u_id")) { text2 = val.CustomProperties[(object)"u_id"]?.ToString(); } if (!string.IsNullOrEmpty(text2) && !text2.StartsWith("photon_") && long.TryParse(text2, out var result2) && result2 < result) { flag = false; break; } } } if (flag) { int lastP1Points = GameStateWatcher.LastP1Points; int lastP2Points = GameStateWatcher.LastP2Points; ApiClient.ReportTeamSeriesDc(activeTeamSeriesId, localSteamId, text, lastP1Points, lastP2Points); Plugin.Log.LogInfo((object)$"[2v2-DC] reporter={localSteamId} dc={text} series={activeTeamSeriesId} pts={lastP1Points}/{lastP2Points}"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2-DC] report error: " + ex.Message)); } } public void OnPlayerPropertiesUpdate(Player target, Hashtable changedProps) { } public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { } public void OnMasterClientSwitched(Player newMasterClient) { if (!Diag2v2.IsActive()) { return; } try { Plugin.Log.LogInfo((object)$"[2v2-DIAG] MasterClientSwitched: new='{((newMasterClient != null) ? newMasterClient.NickName : null)}' actor={((newMasterClient != null) ? new int?(newMasterClient.ActorNumber) : ((int?)null))}"); } catch { } } public void OnConnected() { } public void OnConnectedToMaster() { } public void OnDisconnected(DisconnectCause cause) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (Diag2v2.PendingSlot() < 0) { return; } try { Plugin.Log.LogWarning((object)$"[2v2-DIAG] Disconnected: cause={cause} stack={Diag2v2.ShortStack()}"); } catch { } } public void OnRegionListReceived(RegionHandler regionHandler) { } public void OnCustomAuthenticationResponse(Dictionary data) { } public void OnCustomAuthenticationFailed(string debugMessage) { } public void OnFriendListUpdate(List friendList) { } public void OnCreatedRoom() { } public void OnCreateRoomFailed(short returnCode, string message) { if (Diag2v2.PendingSlot() >= 0) { Plugin.Log.LogWarning((object)$"[2v2-DIAG] CreateRoomFailed: code={returnCode} msg={message}"); } } public void OnJoinedRoom() { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown try { Room currentRoom = PhotonNetwork.CurrentRoom; string text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; Room currentRoom2 = PhotonNetwork.CurrentRoom; bool flag = ((Dictionary)(object)((currentRoom2 != null) ? ((RoomInfo)currentRoom2).CustomProperties : null))?.ContainsKey((object)"cr_ff") ?? false; if (Plugin.Pending2v2Slot >= 0 && !flag && !text.StartsWith("team_")) { Plugin.ClearPending2v2Slot(); } if (Plugin.PendingOvtSlot >= 0 && !text.StartsWith("ovt_")) { Plugin.ClearPendingOvtSlot(); } if (Plugin.PendingFfaSlot >= 0 && !text.StartsWith("ffa_")) { Plugin.ClearPendingFfaSlot(); } } catch { } try { CompetitiveUI.ClearLeaverBanner(); } catch { } try { Player localPlayer = PhotonNetwork.LocalPlayer; Hashtable val = ((localPlayer != null) ? localPlayer.CustomProperties : null); if (val != null && ((Dictionary)(object)val).ContainsKey((object)"cr_lv_rk")) { Hashtable val2 = new Hashtable(); val2[(object)"cr_lv_rk"] = "0"; PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); } } catch { } if (CompetitiveRoomDetect.IsCompetitiveRoom()) { try { FacePublisher.PublishLocal(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POPUP] Face publish hook error: " + ex.Message)); } if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(RepeatedCompetitiveCosmeticReapply()); } } if (!Diag2v2.IsActive()) { return; } try { ManualLogSource log = Plugin.Log; string arg = Diag2v2.DescribeRoom(); Player localPlayer2 = PhotonNetwork.LocalPlayer; log.LogInfo((object)$"[2v2-DIAG] JoinedRoom: {arg} masterClient={localPlayer2 != null && localPlayer2.IsMasterClient}"); } catch { } try { GM_ArmsRace val3 = Object.FindObjectOfType(true); if ((Object)(object)val3 != (Object)null && !((Component)val3).gameObject.activeInHierarchy) { ((Component)val3).gameObject.SetActive(true); Plugin.Log.LogInfo((object)"[2v2] Force-activated GM_ArmsRace.gameObject (vanilla path missed late joiner)"); } } catch (Exception ex2) { Plugin.Log.LogError((object)("[2v2] GM_ArmsRace activate failed: " + ex2.Message)); } try { LoadingScreen instance = LoadingScreen.instance; if ((Object)(object)instance != (Object)null) { try { GeneralParticleSystem searchingSystem = instance.searchingSystem; if (searchingSystem != null) { searchingSystem.Stop(); } } catch { } try { GeneralParticleSystem matchFoundSystem = instance.matchFoundSystem; if (matchFoundSystem != null) { matchFoundSystem.Stop(); } } catch { } if (instance.playerNamesSystem != null) { GeneralParticleSystem[] playerNamesSystem = instance.playerNamesSystem; foreach (GeneralParticleSystem val4 in playerNamesSystem) { try { if (val4 != null) { val4.Stop(); } } catch { } } } try { if ((Object)(object)instance.m_cancelText != (Object)null) { instance.m_cancelText.SetActive(false); } } catch { } typeof(LoadingScreen).GetField("m_isLoading", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(instance, false); Plugin.Log.LogInfo((object)"[2v2] Cleared LoadingScreen searching overlay (late joiner)"); } } catch (Exception ex3) { Plugin.Log.LogWarning((object)("[2v2] LoadingScreen clear failed: " + ex3.Message)); } if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(Force2v2StartGameWhenReady()); ((MonoBehaviour)Plugin.Instance).StartCoroutine(Setup4PlayerCardBarsWhenReady()); ((MonoBehaviour)Plugin.Instance).StartCoroutine(PollAssemblyStateLoop()); } } private static IEnumerator PollAssemblyStateLoop() { yield return (object)new WaitForSeconds(3f); float deadline = Time.realtimeSinceStartup + 22f; while (Time.realtimeSinceStartup < deadline) { if (Plugin.Pending2v2Slot < 0 || !PhotonNetwork.InRoom) { break; } string sid = ApiClient.ActiveTeamSeriesId; if (string.IsNullOrEmpty(sid)) { break; } bool gotResponse = false; ApiClient.PollTeamSeriesState(sid, delegate(string status, string reason, int conf) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) gotResponse = true; if (status == "canceled" && reason == "assembly_timeout") { Plugin.Log.LogWarning((object)$"[2v2] Server canceled series (assembly_timeout, {conf}/4 confirmed) — leaving room"); try { CompetitiveUI.ShowNotification($"Match couldn't assemble — only {conf} of 4 connected. Returning to menu.", new Color(1f, 0.55f, 0.2f), 6f); } catch { } try { Plugin.ClearPending2v2Slot(); if (PhotonNetwork.InRoom) { PhotonNetwork.LeaveRoom(true); } return; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2] LeaveRoom on assembly cancel failed: " + ex.Message)); return; } } if (status == "active" && conf < 4) { } }); float waitUntil = Time.realtimeSinceStartup + 1.5f; while (!gotResponse && Time.realtimeSinceStartup < waitUntil) { yield return null; } if (ApiClient.LastSeriesStateStatus == "canceled" || (ApiClient.LastSeriesStateStatus == "active" && ApiClient.LastSeriesStateConfirmations >= 4)) { break; } yield return (object)new WaitForSeconds(2f); } } private static IEnumerator RepeatedCompetitiveCosmeticReapply() { yield return (object)new WaitForSeconds(2f); float deadline = Time.realtimeSinceStartup + 12f; while (Time.realtimeSinceStartup < deadline && CompetitiveRoomDetect.IsCompetitiveRoom() && PhotonNetwork.InRoom) { try { Player[] list = PhotonNetwork.PlayerList; if (list != null) { Player[] array = list; foreach (Player pp in array) { if (pp != null && (PhotonNetwork.LocalPlayer == null || pp.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)) { PlayerColorCosmetic.ReapplyForActor(pp.ActorNumber); TrailCosmetic.ReattachForActor(pp.ActorNumber); try { PlayerEffectCosmetic.ReapplyForActor(pp.ActorNumber); } catch { } } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POPUP] cosmetic reapply tick error: " + ex.Message)); } yield return (object)new WaitForSeconds(2f); } } private static IEnumerator Setup4PlayerCardBarsWhenReady() { float deadline = Time.realtimeSinceStartup + 15f; while (Time.realtimeSinceStartup < deadline) { if (Diag2v2.IsFfa() || Diag2v2.PendingSlot() < 0 || !PhotonNetwork.InRoom) { yield break; } CardBarHandler cbh = CardBarHandler.instance; if ((Object)(object)cbh == (Object)null || cbh.cardBars == null || cbh.cardBars.Length < 2) { yield return (object)new WaitForSeconds(0.5f); continue; } if (cbh.cardBars.Length >= (Diag2v2.IsOvt() ? 3 : 4)) { Plugin.Log.LogInfo((object)$"[2v2] CardBars already {cbh.cardBars.Length} — no extension needed"); yield break; } try { CardBar[] allInTree = ((Component)cbh).GetComponentsInChildren(true); if (allInTree != null && allInTree.Length >= 4) { CardBar[] array = allInTree; foreach (CardBar b in array) { if ((Object)(object)b != (Object)null && !((Component)b).gameObject.activeSelf) { ((Component)b).gameObject.SetActive(true); } } cbh.cardBars = allInTree; Plugin.Log.LogInfo((object)$"[2v2] CardBars: found {allInTree.Length} in tree (incl. inactive), activated all"); yield break; } CardBar bar0 = cbh.cardBars[0]; CardBar bar1 = cbh.cardBars[1]; if ((Object)(object)bar0 == (Object)null || (Object)(object)bar1 == (Object)null) { Plugin.Log.LogWarning((object)"[2v2] CardBars: original bar0/bar1 is null, skipping extension"); yield break; } if (Diag2v2.IsOvt()) { GameObject cloneObj = Object.Instantiate(((Component)bar1).gameObject, ((Component)bar1).transform.parent); ((Object)cloneObj).name = ((Object)((Component)bar1).gameObject).name + "_1v2_duoB"; OffsetBar(cloneObj.transform, new Vector2(0f, -180f)); CardBar cloneCB = cloneObj.GetComponent(); if ((Object)(object)cloneCB == (Object)null) { Plugin.Log.LogWarning((object)"[1v2] CardBars: clone missing CardBar component"); yield break; } cbh.cardBars = (CardBar[])(object)new CardBar[3] { bar0, bar1, cloneCB }; Plugin.Log.LogInfo((object)"[1v2] CardBars: extended to 3 entries [solo_left, duoA_right, duoB_right_low]"); yield break; } GameObject clone0Obj = Object.Instantiate(((Component)bar0).gameObject, ((Component)bar0).transform.parent); GameObject clone1Obj = Object.Instantiate(((Component)bar1).gameObject, ((Component)bar1).transform.parent); ((Object)clone0Obj).name = ((Object)((Component)bar0).gameObject).name + "_2v2_p1"; ((Object)clone1Obj).name = ((Object)((Component)bar1).gameObject).name + "_2v2_p3"; OffsetBar(clone0Obj.transform, new Vector2(0f, -180f)); OffsetBar(clone1Obj.transform, new Vector2(0f, -180f)); CardBar clone0CB = clone0Obj.GetComponent(); CardBar clone1CB = clone1Obj.GetComponent(); if ((Object)(object)clone0CB == (Object)null || (Object)(object)clone1CB == (Object)null) { Plugin.Log.LogWarning((object)"[2v2] CardBars: clone missing CardBar component"); yield break; } cbh.cardBars = (CardBar[])(object)new CardBar[4] { bar0, clone0CB, bar1, clone1CB }; Plugin.Log.LogInfo((object)"[2v2] CardBars: cloned to 4 entries [team0_p0, team0_p1, team1_p2, team1_p3]"); yield break; } catch (Exception ex) { Plugin.Log.LogError((object)("[2v2] CardBar extension failed: " + ex.Message)); yield break; } } Plugin.Log.LogWarning((object)"[2v2] CardBar setup timed out — CardBarHandler.instance never appeared"); } private static void OffsetBar(Transform t, Vector2 offset) { //IL_002a: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null); if ((Object)(object)val != (Object)null) { val.anchoredPosition += offset; } else { t.localPosition += new Vector3(offset.x, offset.y, 0f); } } private static IEnumerator Force2v2StartGameWhenReady() { float deadline = Time.realtimeSinceStartup + 30f; while (Time.realtimeSinceStartup < deadline) { if (Diag2v2.PendingSlot() < 0 || !PhotonNetwork.InRoom) { yield break; } try { if ((Object)(object)GameManager.instance != (Object)null && GameManager.instance.isPlaying) { yield break; } } catch { } int need = Diag2v2.PlayersNeeded(); GM_ArmsRace gm = GM_ArmsRace.instance; if ((Object)(object)gm != (Object)null && ((Component)gm).gameObject.activeInHierarchy && (Object)(object)PlayerManager.instance != (Object)null) { int counted = 0; foreach (Player p in PlayerManager.instance.players) { if ((Object)(object)p != (Object)null) { counted++; } } if (counted >= need) { Plugin.Log.LogInfo((object)$"[2v2] Force-invoking GM_ArmsRace.StartGame (counted={counted}/{need})"); try { gm.StartGame(); yield break; } catch (Exception ex) { Exception ex2 = ex; Plugin.Log.LogError((object)("[2v2] StartGame invoke failed: " + ex2.Message)); yield break; } } } yield return (object)new WaitForSeconds(0.5f); } Plugin.Log.LogWarning((object)$"[2v2] Force-StartGame timed out — never reached {Diag2v2.PlayersNeeded()} spawned players"); } public void OnJoinRoomFailed(short returnCode, string message) { if (Diag2v2.PendingSlot() >= 0) { Plugin.Log.LogWarning((object)$"[2v2-DIAG] JoinRoomFailed: code={returnCode} msg={message}"); } } public void OnJoinRandomFailed(short returnCode, string message) { } public void OnLeftRoom() { if (Diag2v2.PendingSlot() < 0) { return; } try { Plugin.Log.LogWarning((object)("[2v2-DIAG] LeftRoom (Photon callback) stack=" + Diag2v2.ShortStack())); } catch { } } } [HarmonyPatch(typeof(NetworkConnectionHandler), "OnJoinedRoom")] internal class NetworkConnectionHandler_OnJoinedRoom_RestyleNick_Patch { private static void Postfix() { try { if (CompetitiveRoomDetect.IsCompetitiveRoom()) { NametagStyler.PublishToPhoton(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POPUP] OnJoinedRoom restyle failed: " + ex.Message)); } } } [HarmonyPatch(typeof(NetworkConnectionHandler), "NetworkRestart")] internal class NetworkConnectionHandler_NetworkRestart_Diag_Patch { private static void Prefix() { try { if (!CompetitiveRoomDetect.IsCompetitiveRoom()) { return; } } catch { return; } try { NetworkConnectionHandler instance = NetworkConnectionHandler.instance; bool flag = (Object)(object)instance != (Object)null && instance.m_restarting; Plugin.Log.LogWarning((object)$"[NCH-DIAG] NetworkRestart() entered (already_restarting={flag}) {Diag2v2.DescribeRoom()} stack={Diag2v2.ShortStack()}"); } catch { } } } [HarmonyPatch(typeof(PhotonNetwork), "LeaveRoom", new Type[] { typeof(bool) })] internal class PhotonNetwork_LeaveRoom_Diag_Patch { private static void Prefix(bool becomeInactive) { try { if (!CompetitiveRoomDetect.IsCompetitiveRoom()) { return; } } catch { return; } try { Plugin.Log.LogWarning((object)$"[NCH-DIAG] PhotonNetwork.LeaveRoom(becomeInactive={becomeInactive}) {Diag2v2.DescribeRoom()} stack={Diag2v2.ShortStack()}"); } catch { } } } [HarmonyPatch(typeof(GM_ArmsRace), "PlayerJoined")] internal class GMArmsRace_PlayerJoined_Diag_Patch { private static void Prefix(GM_ArmsRace __instance, Player player) { if (!Diag2v2.IsActive()) { return; } try { int num = 0; int num2 = 0; if ((Object)(object)PlayerManager.instance != (Object)null && PlayerManager.instance.players != null) { num2 = PlayerManager.instance.players.Count; foreach (Player player2 in PlayerManager.instance.players) { if ((Object)(object)player2 != (Object)null) { num++; } } } int playersNeededToStart = __instance.playersNeededToStart; Plugin.Log.LogInfo((object)$"[2v2-DIAG] GM_ArmsRace.PlayerJoined fired: counted={num} listSize={num2} playersNeededToStart={playersNeededToStart}"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2-DIAG] GM_ArmsRace.PlayerJoined log error: " + ex.Message)); } } } [HarmonyPatch(typeof(GM_ArmsRace), "StartGame")] internal class GMArmsRace_StartGame_Diag_Patch { private static void Prefix() { if (!Diag2v2.IsActive()) { return; } try { Plugin.Log.LogInfo((object)("[2v2-DIAG] GM_ArmsRace.StartGame() fired " + Diag2v2.DescribeRoom())); } catch { } } } [HarmonyPatch(typeof(Player), "Start")] internal class Player_Start_Diag_Patch { private static void Postfix(Player __instance) { if (!Diag2v2.IsActive()) { return; } try { bool flag = false; int num = -1; try { CharacterData data = __instance.data; bool? obj; if (data == null) { obj = null; } else { PhotonView view = data.view; obj = ((view != null) ? new bool?(view.IsMine) : ((bool?)null)); } bool? flag2 = obj; flag = flag2 == true; } catch { } try { CharacterData data2 = __instance.data; int? obj3; if (data2 == null) { obj3 = null; } else { PhotonView view2 = data2.view; obj3 = ((view2 != null) ? new int?(view2.OwnerActorNr) : ((int?)null)); } num = obj3 ?? (-1); } catch { } Plugin.Log.LogInfo((object)$"[2v2-DIAG] Player.Start: pid={__instance.PlayerID} team={__instance.TeamID} isLocal={flag} actor={num}"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2-DIAG] Player.Start log error: " + ex.Message)); } } } internal static class FacePublisher { public const string PROP_FACE = "cr_face"; public static void PublishLocal() { //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Expected O, but got Unknown try { CharacterCreatorHandler instance = CharacterCreatorHandler.instance; if ((Object)(object)instance == (Object)null) { Plugin.Log.LogInfo((object)"[POPUP-DIAG] PublishLocal skipped: CharacterCreatorHandler.instance is null (game state not ready)"); return; } if (instance.selectedPlayerFaces == null || instance.selectedPlayerFaces.Length == 0) { Plugin.Log.LogInfo((object)"[POPUP-DIAG] PublishLocal skipped: selectedPlayerFaces empty"); return; } PlayerFace val = instance.selectedPlayerFaces[0]; if (val == null) { Plugin.Log.LogInfo((object)"[POPUP-DIAG] PublishLocal skipped: face[0] is null"); return; } if (PhotonNetwork.LocalPlayer == null) { Plugin.Log.LogInfo((object)"[POPUP-DIAG] PublishLocal skipped: LocalPlayer is null"); return; } if (val.eyeID == 0 && val.mouthID == 0 && val.detailID == 0 && val.detail2ID == 0) { Plugin.Log.LogInfo((object)"[2v2] FacePublisher: skipping publish (face is all-zero defaults — let vanilla RPC handle it)"); return; } string text = string.Join("|", val.eyeID.ToString(CultureInfo.InvariantCulture), val.eyeOffset.x.ToString("F3", CultureInfo.InvariantCulture), val.eyeOffset.y.ToString("F3", CultureInfo.InvariantCulture), val.mouthID.ToString(CultureInfo.InvariantCulture), val.mouthOffset.x.ToString("F3", CultureInfo.InvariantCulture), val.mouthOffset.y.ToString("F3", CultureInfo.InvariantCulture), val.detailID.ToString(CultureInfo.InvariantCulture), val.detailOffset.x.ToString("F3", CultureInfo.InvariantCulture), val.detailOffset.y.ToString("F3", CultureInfo.InvariantCulture), val.detail2ID.ToString(CultureInfo.InvariantCulture), val.detail2Offset.x.ToString("F3", CultureInfo.InvariantCulture), val.detail2Offset.y.ToString("F3", CultureInfo.InvariantCulture)); Hashtable val2 = new Hashtable(); val2[(object)"cr_face"] = text; PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)("[2v2] Published local face to Photon: " + text)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2] Face publish failed: " + ex.Message)); } } public static bool TryReadAndApply(int pickerActorNumber, GameObject visualizerRoot) { //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) try { Player val = null; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val2 in playerList) { if (val2 != null && val2.ActorNumber == pickerActorNumber) { val = val2; break; } } if (val == null || val.CustomProperties == null) { Plugin.Log.LogInfo((object)string.Format("[POPUP-DIAG] Face apply skipped actor={0}: photonPlayer={1} props={2}", pickerActorNumber, (val == null) ? "null" : "found", (((val != null) ? val.CustomProperties : null) == null) ? "null" : "ok")); return false; } if (!((Dictionary)(object)val.CustomProperties).ContainsKey((object)"cr_face")) { Plugin.Log.LogInfo((object)$"[POPUP-DIAG] Face apply skipped actor={pickerActorNumber}: cr_face property not set on remote player (their client never published, or property not yet replicated)"); return false; } string text = val.CustomProperties[(object)"cr_face"]?.ToString() ?? ""; if (string.IsNullOrEmpty(text)) { Plugin.Log.LogInfo((object)$"[POPUP-DIAG] Face apply skipped actor={pickerActorNumber}: cr_face value is empty string"); return false; } string[] array = text.Split('|'); if (array.Length < 12) { Plugin.Log.LogInfo((object)$"[POPUP-DIAG] Face apply skipped actor={pickerActorNumber}: cr_face has {array.Length} parts (expected 12) — likely truncated"); return false; } CultureInfo invariantCulture = CultureInfo.InvariantCulture; int num = int.Parse(array[0], invariantCulture); float num2 = float.Parse(array[1], invariantCulture); float num3 = float.Parse(array[2], invariantCulture); int num4 = int.Parse(array[3], invariantCulture); float num5 = float.Parse(array[4], invariantCulture); float num6 = float.Parse(array[5], invariantCulture); int num7 = int.Parse(array[6], invariantCulture); float num8 = float.Parse(array[7], invariantCulture); float num9 = float.Parse(array[8], invariantCulture); int num10 = int.Parse(array[9], invariantCulture); float num11 = float.Parse(array[10], invariantCulture); float num12 = float.Parse(array[11], invariantCulture); if (num == 0 && num4 == 0 && num7 == 0 && num10 == 0) { return false; } PlayerFace val3 = PlayerFace.CreateFace(num, new Vector2(num2, num3), num4, new Vector2(num5, num6), num7, new Vector2(num8, num9), num10, new Vector2(num11, num12)); CharacterCreatorItemEquipper val4 = ((visualizerRoot != null) ? visualizerRoot.GetComponentInChildren(true) : null); if ((Object)(object)val4 == (Object)null) { return false; } val4.EquipFace(val3); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2] Face read+apply failed: " + ex.Message)); return false; } } } internal static class CardPickBodyTinter { private static Color teamColor0 = new Color(0.95f, 0.45f, 0.32f); private static Color teamColor1 = new Color(0.45f, 0.62f, 0.95f); private static bool teamColorsResolved = false; public static Color TeamColor0 => teamColor0; public static Color TeamColor1 => teamColor1; public static void EnsureTeamColors() { TryResolveTeamColors(); } private static void TryResolveTeamColors() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_00d7: 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) if (teamColorsResolved) { return; } try { Color? val = ResolveTeamColor(0); Color? val2 = ResolveTeamColor(1); if (val.HasValue && ColorSat(val.Value) > 0.12f) { teamColor0 = val.Value; } if (val2.HasValue && ColorSat(val2.Value) > 0.12f) { teamColor1 = val2.Value; } teamColorsResolved = true; Plugin.Log.LogInfo((object)("[CARDPICK-TINT] resolved team colors: t0=" + ColorHex(teamColor0) + " t1=" + ColorHex(teamColor1) + " (raw c0=" + (val.HasValue ? ColorHex(val.Value) : "null") + " c1=" + (val2.HasValue ? ColorHex(val2.Value) : "null") + ")")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CARDPICK-TINT] resolve failed: " + ex.Message)); } } private static float ColorSat(Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0024: 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) float num = Math.Max(c.r, Math.Max(c.g, c.b)); float num2 = Math.Min(c.r, Math.Min(c.g, c.b)); return (num <= 0.001f) ? 0f : ((num - num2) / num); } private static Color? ResolveTeamColor(int team) { //IL_0170: Unknown result type (might be due to invalid IL or missing references) try { Type typeFromHandle = typeof(PlayerSkinBank); MethodInfo method = typeFromHandle.GetMethod("GetPlayerSkinColors", BindingFlags.Static | BindingFlags.Public); object obj = null; if (method != null) { try { obj = method.Invoke(null, new object[1] { team }); } catch { } } if (obj == null) { PlayerSkinBank instance = PlayerSkinBank.instance; if ((Object)(object)instance == (Object)null) { return null; } if (!(typeFromHandle.GetField("skins", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance) is Array array) || array.Length <= team) { return null; } object value = array.GetValue(team); obj = (value?.GetType().GetField("currentPlayerSkin", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(value); } if (obj == null) { return null; } FieldInfo field = obj.GetType().GetField("color", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != typeof(Color)) { return null; } return (Color)field.GetValue(obj); } catch { return null; } } private static string ColorHex(Color c) { //IL_0005: 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_0029: Unknown result type (might be due to invalid IL or missing references) return $"#{(int)(c.r * 255f):X2}{(int)(c.g * 255f):X2}{(int)(c.b * 255f):X2}"; } public static IEnumerator RetintAfterChildrenSpawn(GameObject visualizer, int pickerTeamID, int pickerID, int pickerActor = -1) { for (int i = 0; i < 10; i++) { if ((Object)(object)visualizer == (Object)null) { yield break; } yield return null; } if ((Object)(object)visualizer == (Object)null) { yield break; } TryResolveTeamColors(); Color desired = ((pickerTeamID == 1) ? teamColor1 : teamColor0); Color wrongTeam = ((pickerTeamID == 1) ? teamColor0 : teamColor1); bool hasCustom = false; try { if (pickerActor > 0 && PhotonNetwork.PlayerList != null) { Player[] playerList = PhotonNetwork.PlayerList; Color cc = default(Color); foreach (Player pl in playerList) { if (pl == null || pl.ActorNumber != pickerActor) { continue; } if (pl.CustomProperties != null && ((Dictionary)(object)pl.CustomProperties).ContainsKey((object)"cr_pcolor_color")) { string hex = pl.CustomProperties[(object)"cr_pcolor_color"] as string; if (!string.IsNullOrEmpty(hex) && ColorUtility.TryParseHtmlString(hex, ref cc)) { desired = cc; hasCustom = true; } } break; } } } catch { } int sprites = 0; int particles = 0; int skinFields = 0; try { Func looksWrong = (Color a) => (!hasCustom) ? IsCloseHue(a, wrongTeam) : (IsCloseHue(a, teamColor0) || IsCloseHue(a, teamColor1)); SpriteRenderer[] sprs = visualizer.GetComponentsInChildren(true); SpriteRenderer[] array = sprs; foreach (SpriteRenderer sr in array) { if (!((Object)(object)sr == (Object)null) && looksWrong(sr.color)) { sr.color = new Color(desired.r, desired.g, desired.b, sr.color.a); sprites++; } } ParticleSystem[] pss = visualizer.GetComponentsInChildren(true); ParticleSystem[] array2 = pss; foreach (ParticleSystem ps in array2) { if (!((Object)(object)ps == (Object)null)) { MainModule main = ps.main; MinMaxGradient sc = ((MainModule)(ref main)).startColor; Color current = ((MinMaxGradient)(ref sc)).color; if (looksWrong(current)) { ((MinMaxGradient)(ref sc)).color = new Color(desired.r, desired.g, desired.b, current.a); ((MainModule)(ref main)).startColor = sc; particles++; } main = default(MainModule); sc = default(MinMaxGradient); } } MonoBehaviour[] comps = visualizer.GetComponentsInChildren(true); MonoBehaviour[] array3 = comps; foreach (MonoBehaviour c in array3) { if ((Object)(object)c == (Object)null) { continue; } Type t = ((object)c).GetType(); if (t.Name != "PlayerSkin" && t.Name != "PlayerSkinHandler") { continue; } FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo f in fields) { if (f.FieldType != typeof(Color)) { continue; } try { Color v = (Color)f.GetValue(c); if (looksWrong(v)) { f.SetValue(c, (object)new Color(desired.r, desired.g, desired.b, v.a)); skinFields++; } } catch { } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CARDPICK-TINT] retint failed: " + ex.Message)); } if (sprites > 0 || particles > 0 || skinFields > 0) { Plugin.Log.LogInfo((object)$"[CARDPICK-TINT] pickerID={pickerID} team={pickerTeamID} custom={hasCustom} retinted: sprites={sprites} particles={particles} skinFields={skinFields}"); } try { ParticleSystem bodyPs = visualizer.GetComponent() ?? visualizer.GetComponentInChildren(true); if ((Object)(object)bodyPs != (Object)null) { bool wasPlaying = bodyPs.isPlaying; if (!wasPlaying) { bodyPs.Play(true); } Plugin.Log.LogInfo((object)$"[CARDPICK-BODY] pickerID={pickerID} ps={((Object)((Component)bodyPs).gameObject).name} wasPlaying={wasPlaying} count={bodyPs.particleCount} activeInHierarchy={((Component)bodyPs).gameObject.activeInHierarchy} worldPos={((Component)bodyPs).transform.position}"); } else { Plugin.Log.LogWarning((object)$"[CARDPICK-BODY] pickerID={pickerID} NO ParticleSystem found on visualizer — body cannot render"); } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[CARDPICK-BODY] check failed: " + ex2.Message)); } } private static bool IsCloseHue(Color a, Color b) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) float num = a.r - b.r; float num2 = a.g - b.g; float num3 = a.b - b.b; return Mathf.Sqrt(num * num + num2 * num2 + num3 * num3) < 0.35f; } } [HarmonyPatch(typeof(CardChoiceVisuals), "Show")] internal class CardChoiceVisuals_Show_Competitive_Patch { internal static int LastShownPickerIndex = -1; private static void Prefix(ref int pickerID) { try { if (PhotonNetwork.OfflineMode || !Diag2v2.IsActive() || Diag2v2.IsFfa()) { return; } CardChoice instance = CardChoice.instance; if ((Object)(object)instance == (Object)null || !instance.IsPicking) { return; } int pickrID = instance.pickrID; if (pickrID < 0) { return; } PlayerManager instance2 = PlayerManager.instance; if ((Object)(object)instance2 == (Object)null || instance2.players == null) { return; } int num = -1; for (int i = 0; i < instance2.players.Count; i++) { if ((Object)(object)instance2.players[i] != (Object)null && instance2.players[i].PlayerID == pickrID) { num = i; break; } } if (num >= 0 && num != pickerID) { Player val = instance2.players[num]; if (!((Object)(object)val.data == (Object)null) && !((Object)(object)val.data.view == (Object)null)) { Plugin.Log.LogInfo((object)$"[CARDPICK-BODY] retargeted a late Show({pickerID}) to the active picker idx={num} pid={pickrID}"); pickerID = num; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CARDPICK-BODY] Show retarget failed: " + ex.Message)); } } private static void Postfix(CardChoiceVisuals __instance, int pickerID) { //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0161: 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_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) LastShownPickerIndex = pickerID; try { if (!CompetitiveRoomDetect.IsCompetitiveRoom()) { return; } PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null || pickerID < 0 || pickerID >= instance.players.Count) { return; } Player val = instance.players[pickerID]; if ((Object)(object)val == (Object)null) { return; } PhotonView component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null || component.Owner == null) { return; } if (val.IsLocal) { FacePublisher.PublishLocal(); } CardPickSelectionTracker.CurrentPickerIsLocal = val.IsLocal; if (FacePublisher.TryReadAndApply(component.Owner.ActorNumber, ((Component)__instance).gameObject)) { Plugin.Log.LogInfo((object)$"[POPUP] CardChoiceVisuals: applied picker face from Photon (pickerID={pickerID}, actor={component.Owner.ActorNumber})"); } try { object? obj = typeof(CardChoiceVisuals).GetField("currentSkin", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance); GameObject val2 = (GameObject)((obj is GameObject) ? obj : null); string text; if ((Object)(object)val2 == (Object)null) { text = "(null)"; } else { Vector3 localPosition = val2.transform.localPosition; Vector3 localScale = val2.transform.localScale; int childCount = val2.transform.childCount; text = $"name={((Object)val2).name} active={val2.activeInHierarchy} layer={val2.layer} children={childCount} localPos=({localPosition.x:F1},{localPosition.y:F1},{localPosition.z:F1}) localScale=({localScale.x:F2},{localScale.y:F2},{localScale.z:F2})"; if ((Object)(object)Plugin.Instance != (Object)null && (Object)(object)val2 != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(CardPickBodyTinter.RetintAfterChildrenSpawn(val2, val.TeamID, pickerID, component.Owner.ActorNumber)); } } Plugin.Log.LogInfo((object)$"[CARDPICK-DIAG] pickerID={pickerID} actor={component.Owner.ActorNumber} pid={val.PlayerID} team={val.TeamID} isLocal={val.IsLocal} currentSkin: {text}"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CARDPICK-DIAG] log error: " + ex.Message)); } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[POPUP] CardChoiceVisuals.Show postfix error: " + ex2.Message)); } } } internal static class CardPickSelectionTracker { public static bool CurrentPickerIsLocal; } [HarmonyPatch(typeof(AbyssalCountdown), "RPCA_Activate")] internal class AbyssalCountdown_Activate_DeepEnd_Patch { private static void Postfix(AbyssalCountdown __instance) { try { CharacterData componentInParent = ((Component)__instance).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.view != (Object)null && componentInParent.view.IsMine) { GameStateWatcher.OnAbyssalActivatedLocal(); } } catch { } } } [HarmonyPatch(typeof(CardChoiceVisuals), "RPCA_SetCurrentSelected")] internal class CardChoiceVisuals_SetSelected_Instinct_Patch { private static void Postfix(int toSet) { try { if (CompetitiveRoomDetect.IsCompetitiveRoom() && CardPickSelectionTracker.CurrentPickerIsLocal && toSet != 0 && !GameStateWatcher.achLeftmostViolated) { GameStateWatcher.achLeftmostViolated = true; Plugin.Log.LogInfo((object)"[ACH] Instinct run broken — selection moved off the left-most card"); } } catch { } } } [HarmonyPatch(typeof(GameCrownHandler), "LateUpdate")] internal class GameCrownHandler2v2Patch { private static GameObject mateCrown; private static bool Prefix(GameCrownHandler __instance) { //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_044f: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_046c: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Unknown result type (might be due to invalid IL or missing references) if (!Diag2v2.IsActive()) { return true; } try { GM_ArmsRace val = (((Object)(object)__instance.gm != (Object)null) ? __instance.gm : ((Component)__instance).GetComponentInParent()); if ((Object)(object)val == (Object)null || (Object)(object)PlayerManager.instance == (Object)null || PlayerManager.instance.players == null) { return false; } GameObject val2 = ((((Component)__instance).transform.childCount > 0) ? ((Component)((Component)__instance).transform.GetChild(0)).gameObject : null); if (Diag2v2.IsFfa()) { if ((Object)(object)val2 == (Object)null) { return false; } Player val3 = FfaMode.CurrentLeader(); if ((Object)(object)mateCrown != (Object)null && mateCrown.activeSelf) { mateCrown.SetActive(false); } if ((Object)(object)val3 == (Object)null || !((Component)val3).gameObject.activeInHierarchy) { if (val2.activeSelf) { val2.SetActive(false); } return false; } if (!val2.activeSelf) { val2.SetActive(true); } ((Component)__instance).transform.position = val3.data.GetCrownPos(); return false; } int num = -1; if (val.p1Rounds != val.p2Rounds) { num = ((val.p1Rounds <= val.p2Rounds) ? 1 : 0); } else if (val.p1Points != val.p2Points) { num = ((val.p1Points <= val.p2Points) ? 1 : 0); } GameObject val4 = ((((Component)__instance).transform.childCount > 0) ? ((Component)((Component)__instance).transform.GetChild(0)).gameObject : null); if ((Object)(object)val4 == (Object)null) { return false; } if (num == -1) { if (val4.activeSelf) { val4.SetActive(false); } if ((Object)(object)mateCrown != (Object)null && mateCrown.activeSelf) { mateCrown.SetActive(false); } return false; } Player val5 = null; Player val6 = null; foreach (Player player in PlayerManager.instance.players) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player.data == (Object)null) && player.TeamID == num) { if ((Object)(object)val5 == (Object)null) { val5 = player; } else if ((Object)(object)val6 == (Object)null) { val6 = player; break; } } } if ((Object)(object)val5 == (Object)null) { if (val4.activeSelf) { val4.SetActive(false); } if ((Object)(object)mateCrown != (Object)null && mateCrown.activeSelf) { mateCrown.SetActive(false); } return false; } bool activeInHierarchy = ((Component)val5).gameObject.activeInHierarchy; if (val4.activeSelf != activeInHierarchy) { val4.SetActive(activeInHierarchy); } if (activeInHierarchy) { ((Component)__instance).transform.position = val5.data.GetCrownPos(); } if ((Object)(object)val6 != (Object)null) { if ((Object)(object)mateCrown == (Object)null) { mateCrown = Object.Instantiate(val4, ((Component)__instance).transform.parent); ((Object)mateCrown).name = "cr_mate_crown"; mateCrown.transform.localScale = Vector3.Scale(((Component)__instance).transform.localScale, val4.transform.localScale); Plugin.Log.LogInfo((object)"[2v2-CROWN] mate crown cloned"); } bool activeInHierarchy2 = ((Component)val6).gameObject.activeInHierarchy; if (mateCrown.activeSelf != activeInHierarchy2) { mateCrown.SetActive(activeInHierarchy2); } if (activeInHierarchy2) { Vector3 val7 = val4.transform.position - ((Component)__instance).transform.position; mateCrown.transform.position = val6.data.GetCrownPos() + val7; } } else if ((Object)(object)mateCrown != (Object)null && mateCrown.activeSelf) { mateCrown.SetActive(false); } return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2-CROWN] prefix error: " + ex.Message)); return true; } } } internal static class CompetitiveRoomDetect { public static bool IsCompetitiveRoom() { try { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return false; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (customProperties != null && ((Dictionary)(object)customProperties).ContainsKey((object)"cr_ff")) { return true; } string text = PhotonNetwork.CurrentRoom.Name ?? ""; return text.StartsWith("ranked_") || text.StartsWith("team_") || text.StartsWith("sct-") || text.StartsWith("ovt_") || (text.StartsWith("ffa_") && FfaMode.EngineActive()); } catch { return false; } } } [HarmonyPatch(typeof(Player), "FullReset")] internal class Player_FullReset_CardBaseline_Patch { private static void Postfix(Player __instance) { try { TabStatsOverlay.RecordCardBaseline(__instance); } catch { } } } [HarmonyPatch(typeof(PopUpHandler), "StartPicking")] internal class PopUpHandler_StartPicking_Competitive_Patch { private static bool Prefix(Player player, Action functionToCall) { try { if (!CompetitiveRoomDetect.IsCompetitiveRoom()) { return true; } Plugin.Log.LogInfo((object)"[POPUP] Auto-confirming Continue prompt (competitive room bypass)"); try { functionToCall?.Invoke((YesNo)0); } catch (Exception ex) { Plugin.Log.LogError((object)("[POPUP] Continue auto-invoke failed: " + ex.Message)); } return false; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[POPUP] StartPicking prefix error: " + ex2.Message)); return true; } } } [HarmonyPatch(typeof(MapManager), "GetSpawnPoints")] internal class MapManager_GetSpawnPoints_2v2_Patch { private static void Postfix(ref SpawnPoint[] __result) { try { if (__result == null || __result.Length < 2 || !Diag2v2.IsActive()) { return; } Array.Sort(__result, (SpawnPoint a, SpawnPoint b) => (((Object)(object)a == (Object)null) ? 0f : a.localStartPos.x).CompareTo(((Object)(object)b == (Object)null) ? 0f : b.localStartPos.x)); if (Diag2v2.IsOvt() && __result.Length >= 4) { SpawnPoint[] array = __result; __result = (SpawnPoint[])(object)new SpawnPoint[4] { array[0], array[2], array[3], array[1] }; } if (!Diag2v2.IsFfa()) { return; } int num = Diag2v2.PlayersNeeded(); if (__result.Length < num) { SpawnPoint[] array2 = (SpawnPoint[])(object)new SpawnPoint[num]; for (int num2 = 0; num2 < num; num2++) { array2[num2] = __result[num2 % __result.Length]; } __result = array2; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2] SpawnPoint sort failed: " + ex.Message)); } } } [HarmonyPatch(typeof(PlayerSkinBank), "GetPlayerSkinColors")] internal class PlayerSkinBank_GetPlayerSkinColors_2v2_Patch { private static readonly HashSet _bodyCallers = new HashSet { "PlayerSkinHandler", "Player", "PlayerAssigner", "HealthHandler", "CharacterData", "Holdable", "DeathEffect", "PlayerSkinParticle", "DamageHandler", "CardChoiceVisuals" }; private static readonly HashSet _loggedKeys = new HashSet(); private static float _lastClear; private static void Prefix(ref int team) { try { if (!Diag2v2.IsActive()) { return; } if (Diag2v2.IsFfa()) { if (team > 3) { team = (team % 4 + 4) % 4; } } else { if (team < 0 || team > 3) { return; } bool flag = false; try { StackTrace stackTrace = new StackTrace(1, fNeedFileInfo: false); int num = Math.Min(stackTrace.FrameCount, 6); for (int i = 0; i < num; i++) { MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod(); if (!(methodBase == null)) { string item = methodBase.DeclaringType?.Name ?? ""; if (_bodyCallers.Contains(item)) { flag = true; break; } } } } catch { } if (flag) { int num2 = team; team = Diag2v2.SlotToTeam(team); if (Time.realtimeSinceStartup - _lastClear > 5f) { _loggedKeys.Clear(); _lastClear = Time.realtimeSinceStartup; } string text = $"{num2}→{team}"; if (_loggedKeys.Add(text)) { Plugin.Log.LogInfo((object)("[2v2-COLOR] body-call mapped " + text)); } } } } catch { } } } [HarmonyPatch(typeof(PlayerSkinHandler), "Init")] internal class PlayerSkinHandlerInitRebakeGuard { private static void Postfix(PlayerSkinHandler __instance) { try { if (Diag2v2.IsActive() && !((Object)(object)__instance == (Object)null) && !((Object)(object)Plugin.Instance == (Object)null)) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(VerifyAndRebake(__instance)); } } catch { } } private static IEnumerator VerifyAndRebake(PlayerSkinHandler psh) { for (int i = 0; i < 8; i++) { yield return null; } if ((Object)(object)psh == (Object)null) { yield break; } try { object data = typeof(PlayerSkinHandler).GetField("data", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(psh); if (data == null) { yield break; } object pPlayer = data.GetType().GetField("player", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(data); if (pPlayer == null) { yield break; } PropertyInfo pidProp = pPlayer.GetType().GetProperty("PlayerID", BindingFlags.Instance | BindingFlags.Public); if (pidProp == null) { yield break; } int playerID = (int)pidProp.GetValue(pPlayer); if (playerID < 0 || playerID > 3) { yield break; } int expectedTeam = Diag2v2.SlotToTeam(playerID); SpriteRenderer sr = ((Component)psh).GetComponentInChildren(true); if ((Object)(object)sr == (Object)null) { yield break; } CardPickBodyTinter.EnsureTeamColors(); Color c0 = CardPickBodyTinter.TeamColor0; Color c1 = CardPickBodyTinter.TeamColor1; Color want = ((expectedTeam == 1) ? c1 : c0); Color other = ((expectedTeam == 1) ? c0 : c1); float dWant = ColorDist(sr.color, want); float dOther = ColorDist(sr.color, other); if (!(dOther + 0.08f < dWant)) { yield break; } FieldInfo fInited = typeof(PlayerSkinHandler).GetField("inited", BindingFlags.Instance | BindingFlags.NonPublic); for (int i2 = ((Component)psh).transform.childCount - 1; i2 >= 0; i2--) { Transform ch = ((Component)psh).transform.GetChild(i2); if ((Object)(object)ch != (Object)null) { Object.Destroy((Object)(object)((Component)ch).gameObject); } } fInited?.SetValue(psh, false); typeof(PlayerSkinHandler).GetMethod("Init", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(psh, null); Plugin.Log.LogInfo((object)$"[2v2-COLOR] Re-baked skin for PlayerID={playerID} (expectedTeam={expectedTeam}, body matched wrong team)"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[2v2-COLOR] rebake guard error: " + ex.Message)); } } private static float ColorDist(Color a, Color b) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) float num = a.r - b.r; float num2 = a.g - b.g; float num3 = a.b - b.b; return (float)Math.Sqrt(num * num + num2 * num2 + num3 * num3); } } [HarmonyPatch(typeof(MapManager), "UnloadAfterSeconds")] internal class MapManager_UnloadAfterSeconds_Diag_Patch { private static Exception Finalizer(Exception __exception) { if (__exception != null && Diag2v2.IsActive()) { try { Plugin.Log.LogError((object)("[2v2-DIAG] MapManager.UnloadAfterSeconds threw: " + __exception.GetType().Name + ": " + __exception.Message)); } catch { } } return __exception; } } [HarmonyPatch(typeof(CardChoice), "StartPick")] internal class MultiPickerShowVisualsPatch { private static void Prefix(int pickerIDToSet) { try { if (PhotonNetwork.OfflineMode || !Diag2v2.IsActive() || Diag2v2.IsFfa()) { return; } CardChoiceVisuals instance = CardChoiceVisuals.instance; PlayerManager instance2 = PlayerManager.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || instance2.players == null) { return; } int num = -1; for (int i = 0; i < instance2.players.Count; i++) { if ((Object)(object)instance2.players[i] != (Object)null && instance2.players[i].PlayerID == pickerIDToSet) { num = i; break; } } if (num >= 0 && CardChoiceVisuals_Show_Competitive_Patch.LastShownPickerIndex != num) { Player val = instance2.players[num]; if (!((Object)(object)val.data == (Object)null) && !((Object)(object)val.data.view == (Object)null)) { instance.Show(num, true); Plugin.Log.LogInfo((object)$"[CARDPICK-BODY] re-Show for sequential picker idx={num} pid={pickerIDToSet}"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CARDPICK-BODY] re-Show failed: " + ex.Message)); } } } [HarmonyPatch(typeof(CardChoice), "StartPick")] internal class OvtExtraPickPatch { internal static int ActivePickerId = -1; private static void Prefix(ref int picksToSet, int pickerIDToSet) { ActivePickerId = -1; try { if (picksToSet != 1 || PhotonNetwork.OfflineMode || !PhotonNetwork.InRoom) { return; } Room currentRoom = PhotonNetwork.CurrentRoom; string text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; if (!text.StartsWith("ovt_")) { return; } bool flag = false; Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (!((customProperties == null || !((Dictionary)(object)customProperties).ContainsKey((object)"cr_ovt_xp")) ? ApiClient.OvtSoloExtraPick : ((customProperties[(object)"cr_ovt_xp"] is bool flag2) ? flag2 : (customProperties[(object)"cr_ovt_xp"]?.ToString() == "True")))) { return; } GM_ArmsRace instance = GM_ArmsRace.instance; if ((Object)(object)instance == (Object)null || instance.p1Points != 0 || instance.p2Points != 0 || instance.p1Rounds != 0 || instance.p2Rounds != 0) { return; } PlayerManager instance2 = PlayerManager.instance; Player val = ((instance2 != null) ? instance2.GetPlayerWithID(pickerIDToSet) : null); if ((Object)(object)val == (Object)null) { return; } int num = 0; foreach (Player player in PlayerManager.instance.players) { if ((Object)(object)player != (Object)null && player.TeamID == val.TeamID) { num++; } } if (num == 1) { picksToSet = 2; ActivePickerId = pickerIDToSet; Plugin.Log.LogInfo((object)$"[1v2-EXTRAPICK] solo picker {pickerIDToSet} (team {val.TeamID}) gets 2 initial picks"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[1v2-EXTRAPICK] prefix failed: " + ex.Message)); } } } [HarmonyPatch(typeof(CardChoice), "ReplaceCards")] internal class OvtExtraPickRestorePickerPatch { private static void Prefix(CardChoice __instance) { try { if (OvtExtraPickPatch.ActivePickerId >= 0) { if (__instance.picks <= 0) { OvtExtraPickPatch.ActivePickerId = -1; } else if (__instance.pickrID == -1) { __instance.pickrID = OvtExtraPickPatch.ActivePickerId; Plugin.Log.LogInfo((object)($"[1v2-EXTRAPICK] restored pickrID={__instance.pickrID} for the extra deal " + $"(vanilla cleared it to -1 on pick; picks left={__instance.picks})")); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[1v2-EXTRAPICK] restore failed: " + ex.Message)); } } } [HarmonyPatch(typeof(CardChoice), "Pick")] internal class CardChoicePickPatch { private static void Prefix(GameObject pickedCard, bool clear) { try { if ((Object)(object)pickedCard == (Object)null) { return; } CardInfo val = pickedCard.GetComponent(); if ((Object)(object)val == (Object)null) { val = pickedCard.GetComponentInChildren(); } if ((Object)(object)val == (Object)null) { return; } string text = null; try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = typeof(CardInfo).GetField("cardName", bindingAttr); if (field != null) { text = field.GetValue(val) as string; } } catch { } if (string.IsNullOrEmpty(text)) { text = ((Object)pickedCard).name.Replace("(Clone)", "").Trim(); } if (!string.IsNullOrEmpty(text)) { int num = -1; try { num = CardChoice.instance.pickrID; } catch { } Plugin.Log.LogInfo((object)$"[HARMONY-CARD] Local Pick: card={text}, pickerID={num}"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[HARMONY-CARD] Pick hook error: " + ex.Message)); } } } [HarmonyPatch(typeof(CardChoice), "RPCA_DoEndPick")] internal class CardChoiceEndPickPatch { private struct PendingPick { public string CardName; public string Rarity; public int PickId; } private static List pendingPicks = new List(); public static void FlushPendingPicks(int localTeam) { if (pendingPicks.Count == 0) { return; } foreach (PendingPick pendingPick in pendingPicks) { if (pendingPick.PickId != localTeam && !string.IsNullOrEmpty(pendingPick.CardName)) { Plugin.Log.LogInfo((object)("[HARMONY-CARD] Flushing pre-match opp card: " + pendingPick.CardName + " (" + pendingPick.Rarity + ")")); GameStateWatcher.OnOpponentCardPicked(pendingPick.CardName, pendingPick.Rarity); } } pendingPicks.Clear(); } public static void ClearPending() { pendingPicks.Clear(); } private static void Prefix(int[] cardIDs, int targetCardID, int theInt, int pickId) { try { try { if (theInt != 0 && CompetitiveRoomDetect.IsCompetitiveRoom()) { Player val = (((Object)(object)PlayerManager.instance != (Object)null) ? PlayerManager.instance.GetPlayerWithID(pickId) : null); if ((Object)(object)val != (Object)null && (Object)(object)val.data != (Object)null && (Object)(object)val.data.view != (Object)null && val.data.view.IsMine && !GameStateWatcher.achLeftmostViolated) { GameStateWatcher.achLeftmostViolated = true; Plugin.Log.LogInfo((object)$"[ACH] Instinct run broken — took card slot {theInt} (not the left-most)"); } } } catch { } int localTeamId = GameStateWatcher.LocalTeamId; string text = null; string text2 = "Unknown"; try { PhotonView val2 = PhotonView.Find(targetCardID); if ((Object)(object)val2 != (Object)null) { CardInfo val3 = ((Component)val2).GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)val2).GetComponentInChildren(); } if ((Object)(object)val3 != (Object)null) { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = typeof(CardInfo).GetField("cardName", bindingAttr); if (field != null) { text = field.GetValue(val3) as string; } FieldInfo field2 = typeof(CardInfo).GetField("rarity", bindingAttr); if (field2 != null) { text2 = field2.GetValue(val3)?.ToString() ?? "Unknown"; } } if (string.IsNullOrEmpty(text)) { text = ((Object)((Component)val2).gameObject).name.Replace("(Clone)", "").Trim(); } } } catch { } if (!string.IsNullOrEmpty(text)) { text = CardRarityLookup.GetCanonicalName(text); } if (!string.IsNullOrEmpty(text) && text2 == "Unknown") { text2 = CardRarityLookup.GetRarity(text); } if (localTeamId < 0) { if (!string.IsNullOrEmpty(text)) { pendingPicks.Add(new PendingPick { CardName = text, Rarity = text2, PickId = pickId }); Plugin.Log.LogInfo((object)$"[HARMONY-CARD] Buffered pick: card={text}, pickId={pickId} (localTeam unknown)"); } return; } bool flag = pickId != localTeamId; Plugin.Log.LogInfo((object)string.Format("[HARMONY-CARD] EndPick: card={0}, pickId(player)={1}, localTeam={2}, isOpp={3}", text ?? "(unresolved)", pickId, localTeamId, flag)); if (flag && !string.IsNullOrEmpty(text)) { Plugin.Log.LogInfo((object)("[HARMONY-CARD] Opponent picked: " + text + " (" + text2 + ")")); GameStateWatcher.OnOpponentCardPicked(text, text2); } if (flag || cardIDs == null || cardIDs.Length == 0) { return; } int currentRound = GameStateWatcher.CurrentRound; int localOffersCount = GameStateWatcher.LocalOffersCount; BindingFlags bindingAttr2 = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field3 = typeof(CardInfo).GetField("cardName", bindingAttr2); foreach (int num in cardIDs) { try { PhotonView val4 = PhotonView.Find(num); if ((Object)(object)val4 == (Object)null) { continue; } string text3 = null; CardInfo val5 = ((Component)val4).GetComponent(); if ((Object)(object)val5 == (Object)null) { val5 = ((Component)val4).GetComponentInChildren(); } if ((Object)(object)val5 != (Object)null && field3 != null) { text3 = field3.GetValue(val5) as string; } if (string.IsNullOrEmpty(text3)) { text3 = ((Object)((Component)val4).gameObject).name.Replace("(Clone)", "").Trim(); } text3 = CardRarityLookup.GetCanonicalName(text3); if (!string.IsNullOrEmpty(text3)) { bool flag2 = num == targetCardID; GameStateWatcher.OnLocalCardOffered(text3, flag2, currentRound); if (flag2) { Plugin.Log.LogInfo((object)$"[HARMONY-CARD] offer marked picked: card={text3} cid={num} target={targetCardID} round={currentRound}"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)$"[HARMONY-CARD] offer loop error on cid={num}: {ex.Message}"); } } int num2 = GameStateWatcher.LocalOffersCount - localOffersCount; if (!GameStateWatcher.LocalOffersPickedIn(localOffersCount)) { string lastLocalPickedCardName = GameStateWatcher.LastLocalPickedCardName; if (!string.IsNullOrEmpty(lastLocalPickedCardName)) { GameStateWatcher.OnLocalCardOffered(lastLocalPickedCardName, wasPicked: true, currentRound); Plugin.Log.LogInfo((object)$"[HARMONY-CARD] offer fallback picked: card={lastLocalPickedCardName} round={currentRound} (newOffers={num2}, no picked row in cardIDs[])"); } } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[HARMONY-CARD] EndPick error: " + ex2.Message)); } } } public static class MainMenuInjector { private static bool injected = false; private static float checkTimer = 0f; private static GameObject injectedButton = null; private static int retryCount = 0; private static int maxRetries = 30; private static bool loggedFirstInjection = false; private static bool wasInRoomLastCheck = false; private static bool loggedBudgetExhausted = false; private static Type cachedTmpType = null; public static void Reset() { injected = false; injectedButton = null; retryCount = 0; } public static void TryInject() { checkTimer += Time.deltaTime; if (checkTimer < 1f) { return; } checkTimer = 0f; bool flag = false; try { flag = PhotonNetwork.InRoom; } catch { } if (flag) { wasInRoomLastCheck = true; return; } if (wasInRoomLastCheck) { wasInRoomLastCheck = false; retryCount = 0; loggedBudgetExhausted = false; } if (injected && (Object)(object)injectedButton != (Object)null) { return; } if (injected && (Object)(object)injectedButton == (Object)null) { injected = false; retryCount = 0; } if (retryCount >= maxRetries) { if (!loggedBudgetExhausted) { loggedBudgetExhausted = true; Plugin.Log.LogWarning((object)$"[MENU] Injection still failing after {maxRetries} attempts — dropping to slow retry (10s)"); } if (retryCount % 10 != 0) { retryCount++; return; } } retryCount++; try { DoInject(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MENU] Injection failed: " + ex.Message)); } } private static void DoInject() { if (cachedTmpType == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { cachedTmpType = assembly.GetType("TMPro.TMP_Text"); if (cachedTmpType != null) { break; } } if (cachedTmpType == null) { Plugin.Log.LogWarning((object)"[MENU] TMPro.TMP_Text not found"); return; } } PropertyInfo property = cachedTmpType.GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (property == null) { return; } ListMenuButton[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return; } ListMenuButton val = null; ListMenuButton[] array2 = array; foreach (ListMenuButton val2 in array2) { try { Component componentInChildren = ((Component)val2).GetComponentInChildren(cachedTmpType, true); if (!((Object)(object)componentInChildren == (Object)null)) { string text = ((property.GetValue(componentInChildren) as string) ?? "").Trim().ToUpper(); if (text == "QUIT") { val = val2; break; } } } catch { } } if ((Object)(object)val == (Object)null) { if (!loggedFirstInjection) { Plugin.Log.LogWarning((object)"[MENU] Could not find QUIT button in main menu"); } return; } Transform transform = ((Component)val).transform; Transform parent = transform.parent; if (!loggedFirstInjection) { Plugin.Log.LogInfo((object)("[MENU] Found QUIT button at " + ((Object)transform).name + ", parent: " + ((Object)parent).name)); } GameObject val3 = Object.Instantiate(((Component)transform).gameObject, parent); ((Object)val3).name = "CompetitiveRoundsButton"; val3.transform.SetSiblingIndex(transform.GetSiblingIndex()); bool flag = false; try { Component componentInChildren2 = val3.GetComponentInChildren(cachedTmpType); if ((Object)(object)componentInChildren2 != (Object)null) { property.SetValue(componentInChildren2, "SID'S COMPETITIVE ROUNDS"); flag = true; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MENU] TMP text change failed: " + ex.Message)); } if (!flag) { Plugin.Log.LogWarning((object)"[MENU] Could not set button text"); } try { QuitButton component = val3.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } catch { } try { GoBack component2 = val3.GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } } catch { } val3.AddComponent(); injectedButton = val3; injected = true; if (!loggedFirstInjection) { Plugin.Log.LogInfo((object)"[MENU] Competitive button injected into main menu!"); loggedFirstInjection = true; } } } public class CompetitiveMenuButton : MonoBehaviour { private const string BUTTON_TEXT = "SID'S COMPETITIVE ROUNDS"; private object cachedTmpComponent = null; private PropertyInfo cachedTextProp = null; private bool textEnforcementReady = false; private void Start() { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown CacheTmpReferences(); try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("UnityEngine.UI.Button"); if (type != null) { break; } } if (!(type != null)) { return; } Component component = ((Component)this).GetComponent(type); if (!((Object)(object)component != (Object)null)) { return; } PropertyInfo property = type.GetProperty("onClick", BindingFlags.Instance | BindingFlags.Public); if (property != null) { object value = property.GetValue(component); MethodInfo method = value.GetType().GetMethod("RemoveAllListeners"); if (method != null) { method.Invoke(value, null); } MethodInfo method2 = value.GetType().GetMethod("AddListener"); if (method2 != null) { UnityAction val = new UnityAction(OnButtonClick); method2.Invoke(value, new object[1] { val }); Plugin.Log.LogInfo((object)"[MENU] Button onClick wired successfully"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MENU] Button wiring failed: " + ex.Message)); } } private void CacheTmpReferences() { try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("TMPro.TMP_Text"); if (type != null) { break; } } if (!(type == null)) { cachedTmpComponent = ((Component)this).GetComponentInChildren(type); if (cachedTmpComponent != null) { cachedTextProp = type.GetProperty("text", BindingFlags.Instance | BindingFlags.Public); textEnforcementReady = cachedTextProp != null; } } } catch { } } private void LateUpdate() { if (!textEnforcementReady) { return; } try { string text = cachedTextProp.GetValue(cachedTmpComponent) as string; if (text != "SID'S COMPETITIVE ROUNDS") { cachedTextProp.SetValue(cachedTmpComponent, "SID'S COMPETITIVE ROUNDS"); } } catch { } } private void OnButtonClick() { Plugin.Log.LogInfo((object)"[MENU] Competitive button clicked!"); CompetitiveUI.ToggleOverlay(); } } public static class CardRarityLookup { private static readonly Dictionary lookup = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary canonical = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary hardAliases = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Leach", "Leech" }, { "Riccochet", "Ricochet" }, { "BombsAway", "Bombs Away" }, { "Glasscannon", "Glass Cannon" }, { "ShieldCharge", "Shield Charge" }, { "AbyssalCountdown", "Abyssal Countdown" }, { "ChillingPresence", "Chilling Presence" }, { "DrillAmmo", "Drill Ammo" }, { "RadarShot", "Radar Shot" }, { "TargetBounce", "Target Bounce" }, { "TasteOfBlood", "Taste Of Blood" }, { "Fastball", "Fast Ball" }, { "Poison Bullets", "Poison" }, { "PoisonBullets", "Poison" }, { "Prisitne Perseverence", "Pristine Perseverance" }, { "Pristine Perseverence", "Pristine Perseverance" }, { "PristinePerseverance", "Pristine Perseverance" }, { "PristinePerseverence", "Pristine Perseverance" } }; public static int Count => lookup.Count; public static void Register(string cardName, string rarity) { if (!string.IsNullOrEmpty(cardName)) { lookup[cardName] = rarity; if (!canonical.ContainsKey(cardName)) { canonical[cardName] = cardName; } } } public static string GetRarity(string cardName) { if (string.IsNullOrEmpty(cardName)) { return "Unknown"; } if (lookup.TryGetValue(cardName, out var value)) { return value; } string canonicalName = GetCanonicalName(cardName); if (canonicalName != cardName && lookup.TryGetValue(canonicalName, out value)) { return value; } return "Unknown"; } public static string GetCanonicalName(string name) { if (string.IsNullOrEmpty(name)) { return name; } if (hardAliases.TryGetValue(name, out var value)) { name = value; } if (canonical.TryGetValue(name, out var value2)) { return ToTitleCase(value2); } return name; } private static string ToTitleCase(string input) { if (string.IsNullOrEmpty(input)) { return input; } string[] array = input.ToLower().Split(' '); for (int i = 0; i < array.Length; i++) { if (array[i].Length > 0) { array[i] = char.ToUpper(array[i][0]) + array[i].Substring(1); } } return string.Join(" ", array); } public static void ScanAll() { if (lookup.Count > 0) { return; } try { Type typeFromHandle = typeof(CardInfo); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = typeFromHandle.GetField("cardName", bindingAttr); FieldInfo field2 = typeFromHandle.GetField("rarity", bindingAttr); PropertyInfo property = typeFromHandle.GetProperty("CardName", bindingAttr); CardInfo[] array = Resources.FindObjectsOfTypeAll(); CardInfo[] array2 = array; foreach (CardInfo val in array2) { try { string text = null; if (field != null) { text = field.GetValue(val) as string; } else if (property != null) { text = property.GetValue(val) as string; } if (string.IsNullOrEmpty(text)) { text = ((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim(); } if (!string.IsNullOrEmpty(text)) { string text2 = "Unknown"; if (field2 != null) { text2 = field2.GetValue(val)?.ToString() ?? "Unknown"; } Register(text, text2); string text3 = ((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim(); if (!string.IsNullOrEmpty(text3)) { lookup[text3] = text2; canonical[text3] = text; } } } catch { } } foreach (KeyValuePair hardAlias in hardAliases) { if (lookup.TryGetValue(hardAlias.Value, out var value)) { lookup[hardAlias.Key] = value; canonical[hardAlias.Key] = hardAlias.Value; } } if (lookup.Count > 0) { Plugin.Log.LogInfo((object)$"[RARITY] Card rarity lookup built: {lookup.Count} entries ({array.Length} CardInfo objects scanned)"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[RARITY] Card scan failed: " + ex.Message)); } } public static string GetSampleEntries(int max) { List list = new List(); int num = 0; foreach (KeyValuePair item in lookup) { list.Add(item.Key + "=" + item.Value); if (++num >= max) { break; } } return string.Join(", ", list.ToArray()); } } public class TaskbarFlash : MonoBehaviour { private struct FLASHWINFO { public uint cbSize; public IntPtr hwnd; public uint dwFlags; public uint uCount; public uint dwTimeout; } private const uint FLASHW_STOP = 0u; private const uint FLASHW_ALL = 3u; private const uint FLASHW_TIMERNOFG = 12u; private bool shouldFlash = false; private bool isFlashing = false; private IntPtr gameWindowHandle = IntPtr.Zero; private static TaskbarFlash instance; [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool FlashWindowEx(ref FLASHWINFO pwfi); [DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); private void Awake() { if ((Object)(object)instance != (Object)null && (Object)(object)instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); } else { instance = this; } } private void Update() { if (gameWindowHandle == IntPtr.Zero) { try { gameWindowHandle = Process.GetCurrentProcess().MainWindowHandle; } catch { } if (gameWindowHandle == IntPtr.Zero) { try { gameWindowHandle = FindWindow("UnityWndClass", null); } catch { } } if (gameWindowHandle == IntPtr.Zero) { return; } Plugin.Log.LogInfo((object)$"[FLASH] Window handle resolved: {gameWindowHandle}"); } bool isFocused = Application.isFocused; if (shouldFlash && !isFlashing && !isFocused) { StartFlashing(); } if (shouldFlash && isFocused) { shouldFlash = false; } if (isFlashing && (!shouldFlash || isFocused)) { StopFlashing(); } } public static void Flash() { if ((Object)(object)instance != (Object)null) { instance.shouldFlash = true; Plugin.Log.LogInfo((object)$"[FLASH] Flash requested (focused={Application.isFocused}, handle={instance.gameWindowHandle})"); } else { Plugin.Log.LogWarning((object)"[FLASH] Flash requested but no instance"); } } private void StartFlashing() { if (!isFlashing) { FLASHWINFO pwfi = default(FLASHWINFO); pwfi.cbSize = (uint)Marshal.SizeOf(pwfi); pwfi.hwnd = gameWindowHandle; pwfi.dwFlags = 15u; pwfi.uCount = uint.MaxValue; pwfi.dwTimeout = 0u; bool flag = FlashWindowEx(ref pwfi); isFlashing = true; shouldFlash = true; Plugin.Log.LogInfo((object)$"[FLASH] Started flashing (result={flag})"); } } private void StopFlashing() { if (isFlashing) { FLASHWINFO pwfi = default(FLASHWINFO); pwfi.cbSize = (uint)Marshal.SizeOf(pwfi); pwfi.hwnd = gameWindowHandle; pwfi.dwFlags = 0u; pwfi.uCount = 0u; pwfi.dwTimeout = 0u; FlashWindowEx(ref pwfi); isFlashing = false; shouldFlash = false; } } } [HarmonyPatch(typeof(Gun), "Attack")] internal class GunAttackBlockOnF5Patch { private static bool _postfixFirstFireLogged; private static bool _postfixFirstPvRejectLogged; private static bool _postfixFirstIsMineRejectLogged; private static bool _postfixFirstFalseRejectLogged; private static bool _postfixFirstForcedRejectLogged; private static bool Prefix(Gun __instance) { if (!NativeUI.IsOpen) { return true; } try { PhotonView val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent() : null); if ((Object)(object)val == (Object)null || !val.IsMine) { return true; } } catch { return true; } return false; } private static void Postfix(Gun __instance, bool __result, float charge, bool forceAttack) { if (!_postfixFirstFireLogged) { _postfixFirstFireLogged = true; Plugin.Log.LogInfo((object)$"[GUN-POST] Attack Postfix first invocation (gun={((__instance != null) ? ((Object)__instance).name : null)}, uiOpen={NativeUI.IsOpen})"); } if (NativeUI.IsOpen) { return; } if (!__result) { if (!_postfixFirstFalseRejectLogged) { _postfixFirstFalseRejectLogged = true; Plugin.Log.LogInfo((object)"[GUN-POST] first __result=false reject (reload/cooldown phantom)"); } return; } if (forceAttack) { if (!_postfixFirstForcedRejectLogged) { _postfixFirstForcedRejectLogged = true; Plugin.Log.LogInfo((object)"[GUN-POST] first forceAttack reject (card-driven attack)"); } return; } try { PhotonView val = null; try { Player val2 = __instance?.player; if ((Object)(object)val2 != (Object)null) { val = val2.data?.view ?? ((Component)val2).GetComponent(); } } catch { } if ((Object)(object)val == (Object)null) { val = ((__instance != null) ? ((Component)__instance).GetComponentInParent() : null); } if ((Object)(object)val == (Object)null) { if (!_postfixFirstPvRejectLogged) { _postfixFirstPvRejectLogged = true; Plugin.Log.LogInfo((object)("[GUN-POST] first pv-null reject on gun=" + ((__instance != null) ? ((Object)__instance).name : null))); } return; } if (!val.IsMine) { if (!_postfixFirstIsMineRejectLogged) { _postfixFirstIsMineRejectLogged = true; ManualLogSource log = Plugin.Log; Player owner = val.Owner; log.LogInfo((object)("[GUN-POST] first !IsMine reject (pv.owner=" + ((owner != null) ? owner.NickName : null) + ")")); } return; } int num = 1; try { num = Math.Max(1, __instance.numberOfProjectiles); } catch { } try { int num2 = Math.Max(1, __instance.bursts); int num3 = 1; if (!__instance.lockGunToDefault && charge > 0f && __instance.attackSpeed > 0f) { num3 = Mathf.Clamp(Mathf.RoundToInt(0.5f * charge / __instance.attackSpeed), 1, 10); } num *= num2 * num3; } catch { } GameStateWatcher.OnLocalBulletFired(num); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[GUN-POST] exception: " + ex.Message)); } } } [HarmonyPatch(typeof(Block), "TryBlock")] internal class BlockTryBlockOnF5Patch { private static bool Prefix(Block __instance) { if (!NativeUI.IsOpen) { return true; } try { PhotonView val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent() : null); if ((Object)(object)val == (Object)null || !val.IsMine) { return true; } } catch { return true; } return false; } } [HarmonyPatch] internal class HealthHandlerTakeDamageCounterPatch { private static int _ffDiagRemaining = 8; private static MethodBase TargetMethod() { Type typeFromHandle = typeof(HealthHandler); MethodInfo result = null; int num = -1; MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "TakeDamage")) { int num2 = methodInfo.GetParameters().Length; if (num2 > num) { num = num2; result = methodInfo; } } } return result; } private static void Postfix(HealthHandler __instance, Vector2 damage, GameObject damagingWeapon, Player damagingPlayer) { try { if ((Object)(object)damagingPlayer == (Object)null || ((Vector2)(ref damage)).magnitude <= 0.01f) { return; } try { if (Plugin.ShowBlockDebug != null && Plugin.ShowBlockDebug.Value && PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties != null && ((Dictionary)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).ContainsKey((object)"cr_ff") && _ffDiagRemaining > 0) { CharacterData val = (((Object)(object)damagingPlayer != (Object)null) ? ((Component)damagingPlayer).GetComponent() : null); CharacterData val2 = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent() : null); FieldInfo field = typeof(CharacterData).GetField("teamID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = (((Object)(object)val != (Object)null && field != null) ? ((int)field.GetValue(val)) : (-1)); int num2 = (((Object)(object)val2 != (Object)null && field != null) ? ((int)field.GetValue(val2)) : (-1)); bool flag = num >= 0 && num == num2; _ffDiagRemaining--; Plugin.Log.LogInfo((object)string.Format("[FF-DIAG] dmg={0:F1} src_team={1} tgt_team={2} same_team={3} weapon='{4}'", ((Vector2)(ref damage)).magnitude, num, num2, flag, ((Object)(object)damagingWeapon != (Object)null) ? ((Object)damagingWeapon).name : "(null)")); } } catch { } PhotonView val3 = damagingPlayer.data?.view ?? ((Component)damagingPlayer).GetComponent(); PhotonView val4 = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent() : null); try { if ((Object)(object)val4 != (Object)null && val4.IsMine && (Object)(object)val3 != (Object)null && !val3.IsMine) { GameStateWatcher.OnLocalPlayerHit(((Vector2)(ref damage)).magnitude); } } catch { } if (!((Object)(object)val3 == (Object)null) && val3.IsMine && (Object)(object)val4 != (Object)null && !val4.IsMine) { } } catch { } } } [HarmonyPatch(typeof(ProjectileHit), "RPCA_DoHit")] internal class ProjectileHit_DirectHitCounter_Patch { private static void Prefix(ProjectileHit __instance, int viewID, bool wasBlocked) { try { if (wasBlocked || viewID == -1) { return; } Player val = (((Object)(object)__instance != (Object)null) ? __instance.ownPlayer : null); if ((Object)(object)val == (Object)null || (Object)(object)val.data == (Object)null || (Object)(object)val.data.view == (Object)null || !val.data.view.IsMine) { return; } PhotonView photonView = PhotonNetwork.GetPhotonView(viewID); if (!((Object)(object)photonView == (Object)null)) { Player val2 = ((Component)photonView).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)photonView).GetComponentInParent(); } if (!((Object)(object)val2 == (Object)null) && val2.TeamID != val.TeamID) { GameStateWatcher.OnLocalBulletHit(); } } } catch { } } } internal static class BlockChain { internal static bool InTryBlock; internal static float LastUserWindowTime = -999f; internal static float LastUserDefaultTime = -999f; internal static void Reset() { InTryBlock = false; LastUserWindowTime = (LastUserDefaultTime = -999f); } internal static bool AbsorbIsUserChain() { return Time.time - LastUserWindowTime <= 0.8f; } } [HarmonyPatch(typeof(Block), "RPCA_DoBlock")] internal class BlockRpcaDoBlockChainClassifierPatch { private static void Prefix(Block __instance, bool firstBlock, BlockTriggerType triggerType, bool onlyBlockEffects) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected I4, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) try { PhotonView val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent() : null); if ((Object)(object)val == (Object)null || !val.IsMine || onlyBlockEffects) { return; } bool flag; switch ((int)triggerType) { case 0: flag = firstBlock && BlockChain.InTryBlock; if (flag) { BlockChain.LastUserDefaultTime = Time.time; } break; case 3: flag = Time.time - BlockChain.LastUserDefaultTime <= 1.5f; break; case 2: flag = Time.time - BlockChain.LastUserWindowTime <= 3f; break; default: flag = false; break; } if (flag) { BlockChain.LastUserWindowTime = Time.time; } if (GameStateWatcher.IsTracking && Plugin.ShowBlockDebug != null && Plugin.ShowBlockDebug.Value) { Plugin.Log.LogInfo((object)$"[BLOCK-DBG] WINDOW type={triggerType} first={firstBlock} user={flag}"); } } catch { } } } [HarmonyPatch(typeof(Block), "TryBlock")] internal class BlockTryBlockCounterPatch { private static float _lastDiagLogTime; private static void Prefix(Block __instance, out bool __state) { __state = false; try { __state = !(__instance.counter < __instance.Cooldown()); } catch { __state = true; } BlockChain.InTryBlock = true; } private static Exception Finalizer(Exception __exception) { BlockChain.InTryBlock = false; return __exception; } private static void Postfix(Block __instance, bool __state) { if (NativeUI.IsOpen) { return; } try { PhotonView val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent() : null); if ((Object)(object)val == (Object)null || !val.IsMine) { return; } try { if (Plugin.ShowBlockDebug != null && Plugin.ShowBlockDebug.Value && CompetitiveRoomDetect.IsCompetitiveRoom() && !_diagThrottled()) { Player componentInParent = ((Component)__instance).GetComponentInParent(); int num = -1; int num2 = -1; try { num = (((Object)(object)componentInParent != (Object)null) ? componentInParent.TeamID : (-1)); } catch { } try { num2 = (((Object)(object)componentInParent != (Object)null) ? componentInParent.PlayerID : (-1)); } catch { } int num3 = -1; bool flag = false; try { num3 = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); } catch { } try { flag = PhotonNetwork.IsMasterClient; } catch { } Plugin.Log.LogInfo((object)$"[BLOCK-TEAM] tryBlock ready={__state} team={num} playerID={num2} actor={num3} isMaster={flag}"); } } catch { } if (__state) { GameStateWatcher.OnLocalBlockActivated(); } } catch { } } private static bool _diagThrottled() { float unscaledTime = Time.unscaledTime; if (unscaledTime - _lastDiagLogTime < 0.5f) { return true; } _lastDiagLogTime = unscaledTime; return false; } } [HarmonyPatch] internal class BlockDoBlockCounterPatch { private static bool _firstEntry; private static MethodBase TargetMethod() { Type typeFromHandle = typeof(Block); MethodInfo result = null; int num = -1; MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "DoBlock")) { int num2 = methodInfo.GetParameters().Length; if (num2 > num) { num = num2; result = methodInfo; } } } return result; } private static void Postfix(Block __instance) { if (!_firstEntry) { _firstEntry = true; Plugin.Log.LogInfo((object)"[BLOCK] DoBlock Postfix first invocation (patch attached)"); } try { PhotonView val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInParent() : null); if (!((Object)(object)val == (Object)null) && val.IsMine) { GameStateWatcher.OnLocalBlockSuccessful(BlockChain.AbsorbIsUserChain()); } } catch { } } } internal class NCHConnectToRegionDiagPatch { private static IEnumerable TargetMethods() { HashSet seen = new HashSet(); Type[] array = new Type[2] { typeof(NetworkConnectionHandler), typeof(PhotonNetwork) }; foreach (Type t in array) { if (t == null) { continue; } List methods; try { methods = AccessTools.GetDeclaredMethods(t); } catch { methods = null; } if (methods == null) { continue; } foreach (MethodInfo m in methods) { if (m != null && m.Name == "ConnectToRegion" && seen.Add(m)) { yield return m; } } } } private static void Prefix(object[] __args) { try { if (!CompetitiveRoomDetect.IsCompetitiveRoom()) { return; } string text = "?"; if (__args != null) { foreach (object obj in __args) { if (obj is string text2) { text = text2; break; } } } string arg = "(none)"; try { Room currentRoom = PhotonNetwork.CurrentRoom; arg = ((currentRoom != null) ? currentRoom.Name : null) ?? "(none)"; } catch { } StackTrace stackTrace = new StackTrace(1, fNeedFileInfo: false); StringBuilder stringBuilder = new StringBuilder(); int num = Math.Min(stackTrace.FrameCount, 12); for (int j = 0; j < num; j++) { MethodBase methodBase = stackTrace.GetFrame(j)?.GetMethod(); if (!(methodBase == null)) { stringBuilder.Append(" at ").Append(methodBase.DeclaringType?.FullName ?? "?").Append('.') .Append(methodBase.Name) .Append('\n'); } } Plugin.Log.LogWarning((object)("[NCH-DIAG] ConnectToRegion('" + text + "') called " + $"while in comp room='{arg}'. Stack:\n{stringBuilder}")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[NCH-DIAG] log error: " + ex.Message)); } } } [HarmonyPatch(typeof(BlockTrigger), "DoBlock")] internal class BlockTriggerDoBlockNullSafetyPatch { private static bool Prefix(BlockTrigger __instance, BlockTriggerType triggerType) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { string arg = "?"; try { arg = "(GameObject destroyed)"; } catch { } Plugin.Log.LogWarning((object)($"[BLOCK-SAFETY] DoBlock skipped: triggerType={triggerType} owner={arg}. " + "If a player's block isn't proccing this round, this is the cause — main BlockTrigger was destroyed.")); return false; } return true; } private static Exception Finalizer(Exception __exception, BlockTrigger __instance, BlockTriggerType triggerType) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (__exception is NullReferenceException || __exception is MissingReferenceException) { string arg = "alive"; try { if ((Object)(object)__instance == (Object)null) { arg = "destroyed"; } } catch { arg = "introspection-failed"; } Plugin.Log.LogWarning((object)("[BLOCK-SAFETY] NRE inside vanilla DoBlock " + $"(triggerType={triggerType} instance={arg}) — swallowed so iterator continues. " + "Stack: " + (__exception.StackTrace ?? "(none)").Replace("\n", " | "))); return null; } return __exception; } } internal static class BlockReflect { private static FieldInfo _fCounter; private static FieldInfo _fCooldown; private static bool _resolved; private static readonly Dictionary _delFieldCache = new Dictionary(); private static void Resolve() { if (!_resolved) { try { Type typeFromHandle = typeof(Block); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; _fCounter = typeFromHandle.GetField("counter", bindingAttr); _fCooldown = typeFromHandle.GetField("cooldown", bindingAttr); } catch { } _resolved = true; } } public static int ScrubDeadDelegateFields(Component c) { if ((Object)(object)c == (Object)null) { return 0; } int num = 0; try { Type type = ((object)c).GetType(); if (!_delFieldCache.TryGetValue(type, out var value)) { List list = new List(); BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; Type type2 = type; while (type2 != null && type2 != typeof(MonoBehaviour) && type2 != typeof(Behaviour) && type2 != typeof(object)) { FieldInfo[] fields = type2.GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { if (typeof(Delegate).IsAssignableFrom(fieldInfo.FieldType)) { list.Add(fieldInfo); } } type2 = type2.BaseType; } value = list.ToArray(); _delFieldCache[type] = value; } FieldInfo[] array = value; foreach (FieldInfo fieldInfo2 in array) { if (!(fieldInfo2.GetValue(c) is Delegate obj)) { continue; } Delegate[] invocationList = obj.GetInvocationList(); Delegate obj2 = null; int num2 = 0; Delegate[] array2 = invocationList; foreach (Delegate obj3 in array2) { object? target = obj3.Target; Object val = (Object)((target is Object) ? target : null); if (val != null && val == (Object)null) { num2++; } else { obj2 = Delegate.Combine(obj2, obj3); } } if (num2 > 0) { fieldInfo2.SetValue(c, obj2); num += num2; } } } catch { } return num; } public static int ScrubChildRpcDictionaries(Component rpc) { if ((Object)(object)rpc == (Object)null) { return 0; } int num = 0; try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo[] fields = ((object)rpc).GetType().GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { if (!(fieldInfo.GetValue(rpc) is IDictionary { Count: not 0 } dictionary)) { continue; } List list = null; foreach (DictionaryEntry item in dictionary) { if (!(item.Value is Delegate obj)) { continue; } bool flag = false; bool flag2 = false; Delegate[] invocationList = obj.GetInvocationList(); foreach (Delegate obj2 in invocationList) { object? target = obj2.Target; Object val = (Object)((target is Object) ? target : null); if (val != null && val == (Object)null) { flag2 = true; } else { flag = true; } } if (flag2 && !flag) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list == null) { continue; } foreach (object item2 in list) { dictionary.Remove(item2); num++; Plugin.Log.LogWarning((object)$"[BLOCK-RESET] removed stale ChildRPC key '{item2}' (dead card handler — aborted OnDestroy)"); } } } catch { } return num; } public static int ScrubPlayerDelegates(Player p) { int num = 0; try { if ((Object)(object)p == (Object)null || (Object)(object)p.data == (Object)null) { return 0; } num += ScrubDeadDelegateFields((Component)(object)p.data); num += ScrubDeadDelegateFields((Component)(object)p.data.block); num += ScrubDeadDelegateFields((Component)(object)p.data.healthHandler); num += ScrubDeadDelegateFields((Component)(object)p.data.stats); if ((Object)(object)p.data.weaponHandler != (Object)null) { num += ScrubDeadDelegateFields((Component)(object)p.data.weaponHandler.gun); } num += ScrubDeadDelegateFields((Component)(object)((Component)p).GetComponent()); num += ScrubDeadDelegateFields((Component)(object)((Component)p).GetComponent()); Component rpc = (Component)(object)(((Component)p).GetComponentInChildren(true) ?? ((Component)p).GetComponentInParent()); num += ScrubChildRpcDictionaries(rpc); } catch { } return num; } public static void ForceReady(Block b) { if ((Object)(object)b == (Object)null) { return; } Resolve(); try { if (_fCounter != null && _fCooldown != null) { float num = (float)_fCooldown.GetValue(b); _fCounter.SetValue(b, num); } } catch { } } } [HarmonyPatch(typeof(Block), "RPCA_DoBlock")] internal class BlockRpcaDoBlockZombieScrubPatch { private static void Prefix(Block __instance) { int num = BlockReflect.ScrubDeadDelegateFields((Component)(object)__instance); try { CharacterData component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { if ((Object)(object)component.weaponHandler != (Object)null) { num += BlockReflect.ScrubDeadDelegateFields((Component)(object)component.weaponHandler.gun); } num += BlockReflect.ScrubDeadDelegateFields((Component)(object)component.healthHandler); } } catch { } if (num > 0) { Plugin.Log.LogWarning((object)$"[BLOCK-DBG] ZOMBIE-SCRUB removed {num} dead delegate entry(ies) at block time (an earlier card OnDestroy aborted mid-teardown)"); } } } [HarmonyPatch(typeof(GM_ArmsRace), "StartGame")] internal class GMArmsRaceStartGameBlockResetPatch { internal static void RunSweep(string source) { try { int num = 0; int num2 = 0; PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance != (Object)null && instance.players != null) { foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null)) { num += BlockReflect.ScrubPlayerDelegates(player); num2++; } } } bool flag = CompetitiveRoomDetect.IsCompetitiveRoom(); if (flag) { Block[] array = Object.FindObjectsOfType(); if (array != null) { Block[] array2 = array; foreach (Block b in array2) { BlockReflect.ForceReady(b); } } } Plugin.Log.LogInfo((object)$"[BLOCK-RESET] {source}: scrubbed {num} zombie delegate entry(ies) across {num2} player(s) (competitive={flag})"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BLOCK-RESET] error: " + ex.Message)); } } private static void Prefix(out bool __state) { bool flag = false; try { flag = (Object)(object)GameManager.instance != (Object)null && GameManager.instance.isPlaying; } catch { } __state = !flag; } private static void Postfix(bool __state) { RunSweep("StartGame v2"); if (!__state) { return; } try { PoisonSync.LatchForGame("StartGame"); } catch { } } } [HarmonyPatch(typeof(PlayerManager), "ResetCharacters")] internal class PlayerManagerResetCharactersBlockResetPatch { private static void Postfix() { try { ((MonoBehaviour)Plugin.Instance).StartCoroutine(SweepNextFrame()); } catch { GMArmsRaceStartGameBlockResetPatch.RunSweep("ResetCharacters (rematch, immediate fallback)"); } } private static IEnumerator SweepNextFrame() { yield return null; GMArmsRaceStartGameBlockResetPatch.RunSweep("ResetCharacters (rematch, post-destroy)"); try { PoisonSync.LatchForGame("ResetCharacters"); } catch { } } } [HarmonyPatch(typeof(ArtHandler), "Awake")] internal class ArtHandlerAwakePatch { private static void Postfix(ArtHandler __instance) { try { if (__instance.arts == null) { return; } FieldInfo field = typeof(ArtInstance).GetField("profile", BindingFlags.Instance | BindingFlags.Public); for (int i = 0; i < __instance.arts.Length; i++) { ArtInstance val = __instance.arts[i]; if (val != null) { object obj = field?.GetValue(val); string arg = ""; Object val2 = (Object)((obj is Object) ? obj : null); if (val2 != null) { arg = val2.name; } Plugin.Log.LogInfo((object)$"[MAPCOLOR] arts[{i}] profile.name = '{arg}'"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MAPCOLOR] Awake log failed: " + ex.Message)); } try { MapPhysicalColorPatch.ChromaticAberrationSetting.Apply(); } catch { } try { MapPhysicalColorPatch.BloomStrengthSetting.Apply(); } catch { } } } internal static class MapColorState { public static string CurrentSku; public static string ToastText = ""; public static float ToastUntil = -999f; public static void ShowToast(string name) { try { ToastText = name ?? ""; ToastUntil = Time.unscaledTime + 2.5f; } catch { } } } [HarmonyPatch(typeof(Map), "Start")] internal class MapPhysicalColorPatch { internal struct TwinkleEntry { public ParticleSystem ps; public Color baseColor; public Color glintColor; } internal static class RenderPerfSettings { private static readonly Dictionary _vanillaShadows = new Dictionary(); private static readonly Dictionary _vanillaEnabled = new Dictionary(); private static readonly Color FLAT_BACKDROP = new Color(0.09f, 0.1f, 0.13f, 1f); private static bool _flatBackdropActive = false; internal static void Apply() { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) try { bool flag = Plugin.MapLightingEnabled == null || Plugin.MapLightingEnabled.Value; bool flag2 = Plugin.MapShadowsEnabled == null || Plugin.MapShadowsEnabled.Value; SFRenderer[] array = Object.FindObjectsOfType(); foreach (SFRenderer val in array) { if (!((Object)(object)val == (Object)null)) { int instanceID = ((Object)val).GetInstanceID(); if (!_vanillaShadows.ContainsKey(instanceID)) { _vanillaShadows[instanceID] = val._shadows; } if (!_vanillaEnabled.ContainsKey(instanceID)) { _vanillaEnabled[instanceID] = ((Behaviour)val).enabled; } val._shadows = flag2 && _vanillaShadows[instanceID]; ((Behaviour)val).enabled = flag && _vanillaEnabled[instanceID]; } } if (!flag) { Shader.SetGlobalColor("_SFAmbientLight", Color.white); Shader.SetGlobalFloat("_SFExposure", 1f); Shader.SetGlobalTexture("_SFLightMap", (Texture)(object)Texture2D.whiteTexture); Shader.SetGlobalTexture("_SFLightMapWithShadows", (Texture)(object)Texture2D.whiteTexture); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[RENDERPERF] apply failed: " + ex.Message)); } } internal static void ApplyBackdrop() { try { if (Plugin.MapLightingEnabled != null && !Plugin.MapLightingEnabled.Value) { PaintFlatBackdrop(); _flatBackdropActive = true; } else if (_flatBackdropActive) { RestoreVanillaSky(); string currentSku = MapColorState.CurrentSku; if (!string.IsNullOrEmpty(currentSku) && CustomMapColors.IsCustomSku(currentSku)) { TintArtBackground(currentSku); } _flatBackdropActive = false; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[RENDERPERF] backdrop failed: " + ex.Message)); } } private static void PaintFlatBackdrop() { //IL_00ac: 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_0075: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) ArtHandler instance = ArtHandler.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.m_background : null); if ((Object)(object)val == (Object)null) { return; } SpriteRenderer[] componentsInChildren = val.GetComponentsInChildren(true); foreach (SpriteRenderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { int instanceID = ((Object)val2).GetInstanceID(); if (!_vanillaSkyColors.TryGetValue(instanceID, out var value)) { value = val2.color; _vanillaSkyColors[instanceID] = value; } val2.color = new Color(FLAT_BACKDROP.r, FLAT_BACKDROP.g, FLAT_BACKDROP.b, value.a); } } ParticleSystem[] componentsInChildren2 = val.GetComponentsInChildren(true); Color val4 = default(Color); foreach (ParticleSystem val3 in componentsInChildren2) { if (!((Object)(object)val3 == (Object)null)) { Color cachedVanillaColor = GetCachedVanillaColor(val3); ((Color)(ref val4))..ctor(FLAT_BACKDROP.r, FLAT_BACKDROP.g, FLAT_BACKDROP.b, cachedVanillaColor.a); MainModule main = val3.main; ((MainModule)(ref main)).startColor = new MinMaxGradient(val4); RetintLiveParticles(val3, val4); } } } } internal static class ChromaticAberrationSetting { private static bool _caLogged; internal static void Apply() { try { bool flag = Plugin.ChromaticAberrationEnabled == null || Plugin.ChromaticAberrationEnabled.Value; int num = 0; PostProcessVolume[] array = Object.FindObjectsOfType(); foreach (PostProcessVolume val in array) { if (!((Object)(object)val == (Object)null) && Set(val.profile, flag)) { num++; } } ArtHandler instance = ArtHandler.instance; if ((Object)(object)instance != (Object)null) { try { if (Set(((Object)(object)instance.volume != (Object)null) ? instance.volume.profile : null, flag)) { num++; } } catch { } try { if (Set((instance.menuArt != null) ? instance.menuArt.profile : null, flag)) { num++; } } catch { } try { if (instance.arts != null) { ArtInstance[] arts = instance.arts; for (int j = 0; j < arts.Length; j++) { if (Set(arts[j]?.profile, flag)) { num++; } } } } catch { } } foreach (PostProcessProfile cachedClone in CustomMapColors.CachedClones) { if (Set(cachedClone, flag)) { num++; } } if (!_caLogged) { _caLogged = true; Plugin.Log.LogInfo((object)$"[CA-TOGGLE] on={flag}; {num} profile(s) carrying a ChromaticAberration found"); if (num == 0) { Plugin.Log.LogWarning((object)"[CA-TOGGLE] no ChromaticAberration found on any profile — the toggle will do nothing"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[CA-TOGGLE] apply failed: " + ex.Message)); } } private static bool Set(PostProcessProfile p, bool on) { if ((Object)(object)p == (Object)null) { return false; } try { ChromaticAberration val = default(ChromaticAberration); if (p.TryGetSettings(ref val) && (Object)(object)val != (Object)null) { ((PostProcessEffectSettings)val).active = on; return true; } } catch { } return false; } } internal static class BloomStrengthSetting { private struct Authored { public bool active; public float intensity; public float threshold; public float diffusion; public bool oIntensity; public bool oThreshold; public bool oDiffusion; } private static readonly Dictionary _authored = new Dictionary(); private static bool _logged; internal static string Level { get { string text = ((Plugin.BloomStrength != null) ? (Plugin.BloomStrength.Value ?? "") : ""); text = text.Trim(); if (string.Equals(text, "Off", StringComparison.OrdinalIgnoreCase)) { return "Off"; } if (string.Equals(text, "Reduced", StringComparison.OrdinalIgnoreCase)) { return "Reduced"; } return "Full"; } } internal static void Cycle() { string value = ((Level == "Full") ? "Reduced" : ((Level == "Reduced") ? "Off" : "Full")); if (Plugin.BloomStrength != null) { Plugin.BloomStrength.Value = value; } Apply(); } internal static void Apply() { try { string level = Level; int num = 0; PostProcessVolume[] array = Object.FindObjectsOfType(); foreach (PostProcessVolume val in array) { if (!((Object)(object)val == (Object)null) && Set(val.profile, level, ((Object)val).name)) { num++; } } foreach (PostProcessProfile cachedClone in CustomMapColors.CachedClones) { if (Set(cachedClone, level, "cr-clone")) { num++; } } if (!_logged) { _logged = true; Plugin.Log.LogInfo((object)$"[BLOOM] level={level}; {num} profile(s) carrying a Bloom found"); if (num == 0) { Plugin.Log.LogWarning((object)"[BLOOM] no Bloom settings found on any volume — the strength setting will do nothing"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[BLOOM] apply failed: " + ex.Message)); } } private static bool Set(PostProcessProfile p, string lvl, string who) { if ((Object)(object)p == (Object)null) { return false; } try { Bloom val = default(Bloom); if (!p.TryGetSettings(ref val) || (Object)(object)val == (Object)null) { return false; } int instanceID = ((Object)p).GetInstanceID(); if (!_authored.ContainsKey(instanceID)) { _authored[instanceID] = new Authored { active = ((PostProcessEffectSettings)val).active, intensity = ((ParameterOverride)(object)val.intensity).value, threshold = ((ParameterOverride)(object)val.threshold).value, diffusion = ((ParameterOverride)(object)val.diffusion).value, oIntensity = ((ParameterOverride)val.intensity).overrideState, oThreshold = ((ParameterOverride)val.threshold).overrideState, oDiffusion = ((ParameterOverride)val.diffusion).overrideState }; if (((PostProcessEffectSettings)val).active) { Plugin.Log.LogInfo((object)("[BLOOM] live bloom on '" + ((Object)p).name + "' (volume " + who + "): " + $"intensity={((ParameterOverride)(object)val.intensity).value:F1} threshold={((ParameterOverride)(object)val.threshold).value:F2} " + $"diffusion={((ParameterOverride)(object)val.diffusion).value:F1}")); } } Authored authored = _authored[instanceID]; if (lvl == "Off") { ((PostProcessEffectSettings)val).active = false; return authored.active; } ((PostProcessEffectSettings)val).active = authored.active; if (lvl == "Reduced") { ((ParameterOverride)(object)val.intensity).Override(authored.intensity * 0.6f); ((ParameterOverride)(object)val.threshold).Override(Mathf.Max(authored.threshold, 1.5f)); ((ParameterOverride)(object)val.diffusion).Override(Mathf.Max(1f, authored.diffusion - 2f)); } else { ((ParameterOverride)(object)val.intensity).value = authored.intensity; ((ParameterOverride)val.intensity).overrideState = authored.oIntensity; ((ParameterOverride)(object)val.threshold).value = authored.threshold; ((ParameterOverride)val.threshold).overrideState = authored.oThreshold; ((ParameterOverride)(object)val.diffusion).value = authored.diffusion; ((ParameterOverride)val.diffusion).overrideState = authored.oDiffusion; } return authored.active; } catch { return false; } } } private static readonly Dictionary _matCache = new Dictionary(); private static bool _loggedTypes; private static readonly Dictionary _vanillaPSColorCache = new Dictionary(512); public static float LastMapStartTime = -999f; public const float MapTransitionGuardSec = 2f; private static Particle[] _retintBuf; private static bool _loggedScenePaths; private static readonly Dictionary _vanillaCamClears = new Dictionary(); private static bool _loggedCams; internal static readonly List _twinkleSystems = new List(); private static bool _twinkleLoopRunning; private static uint _twinkleTick; private static readonly Dictionary _vanillaLightColors = new Dictionary(); private static readonly Dictionary _vanillaAmbient = new Dictionary(); private static bool _loggedLights; private static readonly Dictionary _vanillaQuadColors = new Dictionary(); private static readonly HashSet _loggedQuads = new HashSet(); private static readonly Dictionary _vanillaSkyColors = new Dictionary(); private static Color GetCachedVanillaColor(ParticleSystem ps) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0067: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_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) int instanceID; try { instanceID = ((Object)ps).GetInstanceID(); } catch { return Color.white; } if (_vanillaPSColorCache.TryGetValue(instanceID, out var value)) { return value; } Color val; try { MainModule main = ps.main; MinMaxGradient startColor = ((MainModule)(ref main)).startColor; val = ((MinMaxGradient)(ref startColor)).color; } catch { val = Color.white; } _vanillaPSColorCache[instanceID] = val; return val; } private static void RetintLiveParticles(ParticleSystem ps, Color tinted, Color? sparkle = null, uint tick = 0u) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) try { int particleCount = ps.particleCount; if (particleCount > 0) { if (_retintBuf == null || _retintBuf.Length < particleCount) { _retintBuf = (Particle[])(object)new Particle[Mathf.Max(particleCount, 256)]; } int particles = ps.GetParticles(_retintBuf); Color32 val = default(Color32); ((Color32)(ref val))..ctor((byte)Mathf.Clamp(Mathf.RoundToInt(tinted.r * 255f), 0, 255), (byte)Mathf.Clamp(Mathf.RoundToInt(tinted.g * 255f), 0, 255), (byte)Mathf.Clamp(Mathf.RoundToInt(tinted.b * 255f), 0, 255), (byte)0); Color32 val2 = val; bool hasValue = sparkle.HasValue; if (hasValue) { Color value = sparkle.Value; ((Color32)(ref val2))..ctor((byte)Mathf.Clamp(Mathf.RoundToInt(value.r * 255f), 0, 255), (byte)Mathf.Clamp(Mathf.RoundToInt(value.g * 255f), 0, 255), (byte)Mathf.Clamp(Mathf.RoundToInt(value.b * 255f), 0, 255), (byte)0); } for (int i = 0; i < particles; i++) { Color32 startColor = ((Particle)(ref _retintBuf[i])).startColor; Color32 val3 = ((hasValue && (((Particle)(ref _retintBuf[i])).randomSeed + tick) % 3 == 0) ? val2 : val); ((Particle)(ref _retintBuf[i])).startColor = new Color32(val3.r, val3.g, val3.b, startColor.a); } if (particles > 0) { ps.SetParticles(_retintBuf, particles); } } } catch { } } private static Color CapBrightness(Color c, float maxChannel = 1.15f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(c.r, Mathf.Max(c.g, c.b)); if (num <= maxChannel || num <= 0f) { return c; } float num2 = maxChannel / num; return new Color(c.r * num2, c.g * num2, c.b * num2, c.a); } private static Color SaturateColor(Color c, float mult) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) float num = c.r * 0.299f + c.g * 0.587f + c.b * 0.114f; return new Color(Mathf.Clamp01(num + (c.r - num) * mult), Mathf.Clamp01(num + (c.g - num) * mult), Mathf.Clamp01(num + (c.b - num) * mult), c.a); } private static void Postfix(Map __instance) { LastMapStartTime = Time.time; RenderPerfSettings.Apply(); ChromaticAberrationSetting.Apply(); BloomStrengthSetting.Apply(); string text = MapColorState.CurrentSku; if (string.IsNullOrEmpty(text)) { text = ApiClient.CachedPlayerStats?.active_color_sku; } if (string.IsNullOrEmpty(text) || !CustomMapColors.IsCustomSku(text)) { RestoreVanillaSky(); RestoreCameraBackground(); RestoreBackdropQuads(); RestoreLighting(); _twinkleSystems.Clear(); RenderPerfSettings.ApplyBackdrop(); } else { ScheduleDeferredTints(text); RenderPerfSettings.ApplyBackdrop(); } } public static void ScheduleDeferredTints(string sku) { if (!string.IsNullOrEmpty(sku) && CustomMapColors.IsCustomSku(sku)) { CompetitiveRoundsBehaviour instance = Plugin.Instance; if ((Object)(object)instance != (Object)null) { ((MonoBehaviour)instance).StartCoroutine(DelayedApplyTints(sku)); } } } private static IEnumerator DelayedApplyTints(string sku) { yield return (object)new WaitForSeconds(2f); if (!string.Equals(MapColorState.CurrentSku, sku, StringComparison.OrdinalIgnoreCase)) { Plugin.Log.LogInfo((object)("[MAPCOLOR] skipped stale deferred tint for " + sku + " (current=" + MapColorState.CurrentSku + ")")); } else { ApplyPhysicalTintsForSku(null, sku); } } public static void ApplyPhysicalTintsForSku(Map mapInstance, string sku) { //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0357: 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_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_04a3: Unknown result type (might be due to invalid IL or missing references) //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mapInstance == (Object)null) { mapInstance = Object.FindObjectOfType(); if ((Object)(object)mapInstance == (Object)null) { return; } } try { if (string.IsNullOrEmpty(sku) || !CustomMapColors.IsCustomSku(sku)) { return; } Color? mapBlockColor = CustomMapColors.GetMapBlockColor(sku); if (!mapBlockColor.HasValue) { Plugin.Log.LogInfo((object)("[MAPCOLOR] Map.Start sku=" + sku + " but no MapBlockColor → SpriteRenderer-only path")); } Color val = (Color)(((??)mapBlockColor) ?? Color.white); if (!mapBlockColor.HasValue) { return; } int num = 0; _twinkleSystems.Clear(); try { Color secondaryColor = CustomMapColors.GetSecondaryColor(sku); string baseArt = CustomMapColors.GetBaseArt(sku); ArtHandler instance = ArtHandler.instance; if ((Object)(object)instance != (Object)null && instance.arts != null) { FieldInfo field = typeof(ArtInstance).GetField("parts", BindingFlags.Instance | BindingFlags.Public); FieldInfo field2 = typeof(ArtInstance).GetField("profile", BindingFlags.Instance | BindingFlags.Public); ArtInstance[] arts = instance.arts; foreach (ArtInstance val2 in arts) { if (val2 == null || !(field?.GetValue(val2) is ParticleSystem[] array)) { continue; } bool flag = false; try { object? obj = field2?.GetValue(val2); Object val3 = (Object)((obj is Object) ? obj : null); flag = val3 != (Object)null && !string.IsNullOrEmpty(baseArt) && string.Equals(val3.name, baseArt, StringComparison.OrdinalIgnoreCase); } catch { } if (!flag) { try { val2.TogglePart(false); } catch { } continue; } Color? sparkleColor = CustomMapColors.GetSparkleColor(sku); for (int j = 0; j < array.Length; j++) { ParticleSystem val4 = array[j]; if ((Object)(object)val4 == (Object)null) { continue; } try { Color cachedVanillaColor = GetCachedVanillaColor(val4); float num2 = cachedVanillaColor.r * 0.299f + cachedVanillaColor.g * 0.587f + cachedVanillaColor.b * 0.114f; MainModule main = val4.main; if (sparkleColor.HasValue) { Color val5 = SaturateColor(val, 1.15f); float num3 = 0.62f + 0.28f * Mathf.Clamp01(num2); Color val6 = CapBrightness(new Color(val5.r * num3, val5.g * num3, val5.b * num3, cachedVanillaColor.a), 0.85f); Color val7 = Color.Lerp(val6, SaturateColor(sparkleColor.Value, 1f), 0.5f); Color val8 = CapBrightness(new Color(val7.r * 1.15f, val7.g * 1.15f, val7.b * 1.15f, cachedVanillaColor.a), 0.95f); ((MainModule)(ref main)).startColor = new MinMaxGradient(val6, val8); RetintLiveParticles(val4, val6, val8); _twinkleSystems.Add(new TwinkleEntry { ps = val4, baseColor = val6, glintColor = val8 }); } else { Color c = ((j % 2 == 0) ? val : secondaryColor); Color val9 = SaturateColor(c, 1.3f); float num4 = 0.7f + 0.3f * Mathf.Clamp01(num2); Color val10 = CapBrightness(new Color(val9.r * num4, val9.g * num4, val9.b * num4, cachedVanillaColor.a), 1f); ((MainModule)(ref main)).startColor = new MinMaxGradient(val10); RetintLiveParticles(val4, val10); } try { ParticleSystemRenderer component = ((Component)val4).GetComponent(); Vector3 val11; if (!((Object)(object)component != (Object)null)) { val11 = Vector3.zero; } else { Bounds bounds = ((Renderer)component).bounds; val11 = ((Bounds)(ref bounds)).size; } Vector3 val12 = val11; MainModule main2 = val4.main; MinMaxGradient startColor = ((MainModule)(ref main2)).startColor; Color color = ((MinMaxGradient)(ref startColor)).color; Plugin.Log.LogInfo((object)$"[MAPCOLOR-ART] part='{((Object)((Component)val4).gameObject).name}' vanilla=#{(int)(cachedVanillaColor.r * 255f):X2}{(int)(cachedVanillaColor.g * 255f):X2}{(int)(cachedVanillaColor.b * 255f):X2} applied=#{(int)(Mathf.Clamp01(color.r) * 255f):X2}{(int)(Mathf.Clamp01(color.g) * 255f):X2}{(int)(Mathf.Clamp01(color.b) * 255f):X2} size={val12.x:F0}x{val12.y:F0}"); } catch { } } catch { } num++; } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MAPCOLOR] art-particle tint failed: " + ex.Message)); } int num5 = TintArtBackground(sku); ApplyCameraBackground(sku); int num6 = TintBackdropQuads(sku); if (num6 > 0) { Plugin.Log.LogInfo((object)$"[MAPCOLOR] tinted {num6} backdrop quad(s) for {sku}"); } ApplyLighting(sku); EnsureTwinkleLoop(); Plugin.Log.LogInfo((object)$"[MAPCOLOR] sku={sku}: {num} two-tone wall slab system(s) + {num5} sky renderer(s) + lighting; OOB player-warning effects untouched (vanilla)"); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[MAPCOLOR] Map tint failed: " + ex2.Message)); } } public static void ApplyCameraBackground(string sku) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Invalid comparison between Unknown and I4 //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Invalid comparison between Unknown and I4 //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Invalid comparison between Unknown and I4 //IL_01cf: Unknown result type (might be due to invalid IL or missing references) try { Color? val = CustomMapColors.GetBackgroundColor(sku) ?? CustomMapColors.GetMapBlockColor(sku); if (!val.HasValue) { return; } Color value = val.Value; Camera[] array = Object.FindObjectsOfType(); Camera[] array2 = array; foreach (Camera val2 in array2) { if ((Object)(object)val2 == (Object)null) { continue; } if (!_loggedCams) { Plugin.Log.LogInfo((object)$"[MAPCOLOR-CAMS] '{((Object)((Component)val2).gameObject).name}' depth={val2.depth} flags={val2.clearFlags} bg={val2.backgroundColor} rt={(Object)(object)val2.targetTexture != (Object)null} mask={val2.cullingMask}"); } bool flag = (Object)(object)val2.targetTexture != (Object)null || ((Object)((Component)val2).gameObject).name.IndexOf("Light", StringComparison.OrdinalIgnoreCase) >= 0; int instanceID = ((Object)val2).GetInstanceID(); if (flag) { if (_vanillaCamClears.TryGetValue(instanceID, out var value2)) { val2.backgroundColor = value2; _vanillaCamClears.Remove(instanceID); Plugin.Log.LogInfo((object)$"[MAPCOLOR-CAMS] restored off-screen camera '{((Object)((Component)val2).gameObject).name}' clear to {value2}"); } } else if ((int)val2.clearFlags == 2 || (int)val2.clearFlags == 1) { if (!_vanillaCamClears.ContainsKey(instanceID)) { _vanillaCamClears[instanceID] = val2.backgroundColor; } val2.backgroundColor = new Color(Mathf.Clamp01(value.r * 1.15f), Mathf.Clamp01(value.g * 1.15f), Mathf.Clamp01(value.b * 1.15f), 1f); if ((int)val2.clearFlags == 1) { val2.clearFlags = (CameraClearFlags)2; } } } _loggedCams = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MAPCOLOR] camera bg failed: " + ex.Message)); } } public static void RestoreCameraBackground() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) try { Camera[] array = Object.FindObjectsOfType(); foreach (Camera val in array) { if (!((Object)(object)val == (Object)null) && _vanillaCamClears.TryGetValue(((Object)val).GetInstanceID(), out var value)) { val.backgroundColor = value; } } } catch { } } internal static void EnsureTwinkleLoop() { if (!_twinkleLoopRunning && !((Object)(object)Plugin.Instance == (Object)null)) { _twinkleLoopRunning = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(TwinkleLoop()); } } private static IEnumerator TwinkleLoop() { WaitForSeconds wait = new WaitForSeconds(1.6f); while (true) { yield return wait; if (_twinkleSystems.Count == 0 || (Plugin.AnimatedCosmetics != null && !Plugin.AnimatedCosmetics.Value)) { continue; } _twinkleTick++; for (int i = 0; i < _twinkleSystems.Count; i++) { TwinkleEntry e = _twinkleSystems[i]; try { if (!((Object)(object)e.ps == (Object)null)) { RetintLiveParticles(e.ps, e.baseColor, e.glintColor, _twinkleTick); } } catch { } } } } public static void ApplyLighting(string sku) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0063: 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_009b: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) try { Color? val = CustomMapColors.GetBackgroundColor(sku) ?? CustomMapColors.GetMapBlockColor(sku); if (!val.HasValue) { return; } Color val2 = SaturateColor(val.Value, 1.1f); float num = 0.299f * val2.r + 0.587f * val2.g + 0.114f * val2.b; float num2 = Mathf.Lerp(0.04f, 0.22f, Mathf.InverseLerp(0.04f, 0.25f, num)); Color color = CapBrightness(new Color(num2 + val2.r * 0.95f, num2 + val2.g * 0.95f, num2 + val2.b * 0.95f, 1f), 1f); Color ambientLight = default(Color); ((Color)(ref ambientLight))..ctor(val2.r * 0.45f, val2.g * 0.45f, val2.b * 0.45f, 0.85f); SFRenderer[] array = Object.FindObjectsOfType(); foreach (SFRenderer val3 in array) { if (!((Object)(object)val3 == (Object)null)) { int instanceID = ((Object)val3).GetInstanceID(); if (!_vanillaAmbient.ContainsKey(instanceID)) { _vanillaAmbient[instanceID] = val3.ambientLight; Plugin.Log.LogInfo((object)$"[MAPCOLOR-LIGHT] SFRenderer '{((Object)((Component)val3).gameObject).name}' vanilla ambient={val3.ambientLight}"); } val3.ambientLight = ambientLight; } } if (SFLight._lights != null) { foreach (SFLight light in SFLight._lights) { if ((Object)(object)light == (Object)null) { continue; } if (!_loggedLights) { Plugin.Log.LogInfo((object)$"[MAPCOLOR-LIGHT] SFLight '{((Object)((Component)light).gameObject).name}' color={light._color} intensity={light._intensity} radius={light._radius} parallax={light._parallaxLight}"); } if (light._parallaxLight || !(light._intensity < 5f)) { int instanceID2 = ((Object)light).GetInstanceID(); if (!_vanillaLightColors.ContainsKey(instanceID2)) { _vanillaLightColors[instanceID2] = light._color; } light._color = color; } } } _loggedLights = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MAPCOLOR] lighting tint failed: " + ex.Message)); } } public static void RestoreLighting() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) try { SFRenderer[] array = Object.FindObjectsOfType(); foreach (SFRenderer val in array) { if (!((Object)(object)val == (Object)null) && _vanillaAmbient.TryGetValue(((Object)val).GetInstanceID(), out var value)) { val.ambientLight = value; } } if (SFLight._lights == null) { return; } foreach (SFLight light in SFLight._lights) { if (!((Object)(object)light == (Object)null) && _vanillaLightColors.TryGetValue(((Object)light).GetInstanceID(), out var value2)) { light._color = value2; } } } catch { } } private static int TintBackdropQuads(string sku) { //IL_0038: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0203: 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) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) int num = 0; try { Color? val = CustomMapColors.GetBackgroundColor(sku) ?? CustomMapColors.GetMapBlockColor(sku); if (!val.HasValue) { return 0; } Color val2 = SaturateColor(val.Value, 1.1f); Renderer[] array = Object.FindObjectsOfType(); foreach (Renderer val3 in array) { if ((Object)(object)val3 == (Object)null || val3 is ParticleSystemRenderer) { continue; } SpriteRenderer val4 = (SpriteRenderer)(object)((val3 is SpriteRenderer) ? val3 : null); if ((Object)(object)val4 == (Object)null || ((Object)((Component)val3).gameObject).name.IndexOf("STENCIL", StringComparison.OrdinalIgnoreCase) >= 0) { continue; } Bounds bounds = val3.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (!(size.x < 60f) && !(size.y < 25f)) { int instanceID = ((Object)val3).GetInstanceID(); if (_loggedQuads.Add(instanceID)) { Plugin.Log.LogInfo((object)$"[MAPCOLOR-BG] backdrop candidate: '{GetTransformPath(((Component)val3).transform)}' type={((object)val3).GetType().Name} size={size.x:F0}x{size.y:F0}"); } if (!_vanillaQuadColors.TryGetValue(instanceID, out var value)) { value = val4.color; _vanillaQuadColors[instanceID] = value; } float num2 = value.r * 0.299f + value.g * 0.587f + value.b * 0.114f; float num3 = 0.5f + 0.6f * Mathf.Clamp01(num2); val4.color = new Color(Mathf.Clamp01(val2.r * num3), Mathf.Clamp01(val2.g * num3), Mathf.Clamp01(val2.b * num3), value.a); num++; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MAPCOLOR] backdrop quad tint failed: " + ex.Message)); } return num; } private static void RestoreBackdropQuads() { //IL_0059: 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) try { Renderer[] array = Object.FindObjectsOfType(); foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null) && _vanillaQuadColors.TryGetValue(((Object)val).GetInstanceID(), out var value)) { SpriteRenderer val2 = (SpriteRenderer)(object)((val is SpriteRenderer) ? val : null); if ((Object)(object)val2 != (Object)null) { val2.color = value; } else if ((Object)(object)val.material != (Object)null && val.material.HasProperty("_Color")) { val.material.color = value; } } } } catch { } } private static int TintArtBackground(string sku) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) int num = 0; try { ArtHandler instance = ArtHandler.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.m_background : null); if ((Object)(object)val == (Object)null) { return 0; } Color? val2 = CustomMapColors.GetBackgroundColor(sku) ?? CustomMapColors.GetMapBlockColor(sku); if (!val2.HasValue) { return 0; } Color val3 = SaturateColor(val2.Value, 1.15f); SpriteRenderer[] componentsInChildren = val.GetComponentsInChildren(true); foreach (SpriteRenderer val4 in componentsInChildren) { if (!((Object)(object)val4 == (Object)null)) { int instanceID = ((Object)val4).GetInstanceID(); if (!_vanillaSkyColors.TryGetValue(instanceID, out var value)) { value = val4.color; _vanillaSkyColors[instanceID] = value; } float num2 = value.r * 0.299f + value.g * 0.587f + value.b * 0.114f; float num3 = 0.45f + 0.6f * Mathf.Clamp01(num2); val4.color = new Color(val3.r * num3, val3.g * num3, val3.b * num3, value.a); num++; } } Color? sparkleColor = CustomMapColors.GetSparkleColor(sku); ParticleSystem[] componentsInChildren2 = val.GetComponentsInChildren(true); Color val6 = default(Color); foreach (ParticleSystem val5 in componentsInChildren2) { if (!((Object)(object)val5 == (Object)null)) { Color cachedVanillaColor = GetCachedVanillaColor(val5); float num4 = cachedVanillaColor.r * 0.299f + cachedVanillaColor.g * 0.587f + cachedVanillaColor.b * 0.114f; float num5 = 0.45f + 0.6f * Mathf.Clamp01(num4); ((Color)(ref val6))..ctor(val3.r * num5, val3.g * num5, val3.b * num5, cachedVanillaColor.a); MainModule main = val5.main; if (sparkleColor.HasValue) { Color val7 = CapBrightness(Color.Lerp(val6, sparkleColor.Value, 0.5f) * 1.1f, 1f); val7.a = cachedVanillaColor.a; ((MainModule)(ref main)).startColor = new MinMaxGradient(val6, val7); RetintLiveParticles(val5, val6, val7); } else { ((MainModule)(ref main)).startColor = new MinMaxGradient(val6); RetintLiveParticles(val5, val6); } num++; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MAPCOLOR] sky tint failed: " + ex.Message)); } return num; } public static void RestoreVanillaSky() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_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) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) try { if (_vanillaSkyColors.Count == 0) { return; } ArtHandler instance = ArtHandler.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.m_background : null); if ((Object)(object)val == (Object)null) { return; } int num = 0; SpriteRenderer[] componentsInChildren = val.GetComponentsInChildren(true); foreach (SpriteRenderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && _vanillaSkyColors.TryGetValue(((Object)val2).GetInstanceID(), out var value)) { val2.color = value; num++; } } ParticleSystem[] componentsInChildren2 = val.GetComponentsInChildren(true); foreach (ParticleSystem val3 in componentsInChildren2) { if (!((Object)(object)val3 == (Object)null)) { Color cachedVanillaColor = GetCachedVanillaColor(val3); MainModule main = val3.main; ((MainModule)(ref main)).startColor = new MinMaxGradient(cachedVanillaColor); RetintLiveParticles(val3, cachedVanillaColor); num++; } } if (num > 0) { Plugin.Log.LogInfo((object)$"[MAPCOLOR] restored vanilla sky ({num} renderer(s))"); } } catch { } } private static int StablePathParity(string s) { uint num = 2166136261u; for (int i = 0; i < s.Length; i++) { num ^= s[i]; num *= 16777619; } return (int)(num & 1); } private static string GetTransformPath(Transform t) { if ((Object)(object)t == (Object)null) { return ""; } StringBuilder stringBuilder = new StringBuilder(((Object)t).name); Transform parent = t.parent; while ((Object)(object)parent != (Object)null) { stringBuilder.Insert(0, ((Object)parent).name + "/"); parent = parent.parent; } return stringBuilder.ToString(); } } [HarmonyPatch(typeof(ArtHandler), "NextArt")] internal class ArtHandlerNextArtPatch { private static readonly Dictionary SKU_TO_ART = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "mapcolor_default", "" }, { "mapcolor_sweden", "Sweden" }, { "mapcolor_sky", "Sky" }, { "mapcolor_poison", "Poison" }, { "mapcolor_gold", "Gold" }, { "mapcolor_soviet", "Soviet" }, { "mapcolor_rainbow", "Rainbow" } }; private static int _cycleIndex = 0; private static int _cycleLastListHash = 0; private static List _lastEquippedFiltered; private static bool Prefix(ArtHandler __instance) { try { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; List list = cachedPlayerStats?.active_color_skus; List list2 = null; if (list != null && list.Count > 0) { list2 = new List(list.Count); for (int i = 0; i < list.Count; i++) { string text = list[i]; if (!string.IsNullOrEmpty(text)) { list2.Add(text); } } } if ((list2 == null || list2.Count == 0) && _lastEquippedFiltered != null) { list2 = _lastEquippedFiltered; Plugin.Log.LogInfo((object)$"[MAPCOLOR] Live equipped empty/null, reusing last-known list ({list2.Count} skus)"); } else if (list2 != null && list2.Count > 0) { _lastEquippedFiltered = list2; } string text2 = null; if (list2 != null && list2.Count > 0) { int num = 0; for (int j = 0; j < list2.Count; j++) { num = num * 31 + (list2[j]?.GetHashCode() ?? 0); } if (num != _cycleLastListHash) { _cycleIndex = 0; _cycleLastListHash = num; } bool flag = false; try { flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); } catch { } if (flag) { _cycleIndex = (_cycleIndex + 1) % list2.Count; } text2 = list2[_cycleIndex % list2.Count]; Plugin.Log.LogInfo((object)string.Format("[MAPCOLOR] {0} → {1} (index {2}/{3})", flag ? "Shift cycle" : "auto-keep", text2, _cycleIndex, list2.Count)); if (flag) { MapColorState.ShowToast(CustomMapColors.FriendlyName(text2)); } } if (string.IsNullOrEmpty(text2)) { text2 = cachedPlayerStats?.active_color_sku; } if (string.IsNullOrEmpty(text2)) { Plugin.Log.LogInfo((object)"[MAPCOLOR] No custom sku resolved — falling through to vanilla NextArt"); return true; } MapColorState.CurrentSku = text2; if (CustomMapColors.IsCustomSku(text2)) { string baseArt = CustomMapColors.GetBaseArt(text2); if (string.IsNullOrEmpty(baseArt)) { return true; } try { if (__instance.arts != null) { ArtInstance[] arts = __instance.arts; foreach (ArtInstance val in arts) { if (val != null) { val.TogglePart(false); } } } } catch { } __instance.SetSpecificArt(baseArt); PostProcessProfile val2 = (((Object)(object)__instance.volume != (Object)null) ? __instance.volume.profile : null); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)("[MAPCOLOR] sku=" + text2 + " — volume.profile null after SetSpecificArt(" + baseArt + ")")); return false; } PostProcessProfile val3 = CustomMapColors.BuildOrGetClone(text2, val2); if ((Object)(object)val3 == (Object)null) { Plugin.Log.LogWarning((object)("[MAPCOLOR] sku=" + text2 + " — clone build failed, leaving base art active")); return false; } __instance.ApplyPost(val3); MapPhysicalColorPatch.ApplyCameraBackground(text2); MapPhysicalColorPatch.ApplyLighting(text2); MapPhysicalColorPatch.RenderPerfSettings.Apply(); MapPhysicalColorPatch.ChromaticAberrationSetting.Apply(); MapPhysicalColorPatch.BloomStrengthSetting.Apply(); try { if ((Object)(object)__instance.volume != (Object)null) { __instance.volume.weight = 1f; } } catch { } bool flag2 = Time.time - MapPhysicalColorPatch.LastMapStartTime < 2f; if (flag2) { MapPhysicalColorPatch.ScheduleDeferredTints(text2); } else { MapPhysicalColorPatch.ApplyPhysicalTintsForSku(null, text2); } Plugin.Log.LogInfo((object)$"[MAPCOLOR] applied custom sku={text2} on base='{baseArt}' (deferParticles={flag2})"); return false; } if (!SKU_TO_ART.TryGetValue(text2, out var value)) { Plugin.Log.LogWarning((object)("[MAPCOLOR] Unknown sku '" + text2 + "' — not in CustomMapColors presets, not in vanilla SKU_TO_ART. Equipped but not renderable; falling through to vanilla.")); return true; } if (string.IsNullOrEmpty(value)) { return true; } bool flag3 = false; if (__instance.arts != null) { FieldInfo field = typeof(ArtInstance).GetField("profile", BindingFlags.Instance | BindingFlags.Public); ArtInstance[] arts2 = __instance.arts; foreach (ArtInstance val4 in arts2) { if (val4 != null) { object? obj4 = field?.GetValue(val4); Object val5 = (Object)((obj4 is Object) ? obj4 : null); if (val5 != (Object)null && val5.name == value) { flag3 = true; break; } } } } if (!flag3) { Plugin.Log.LogWarning((object)("[MAPCOLOR] sku=" + text2 + " mapped to art='" + value + "' but no matching art on this ArtHandler — falling through to vanilla random")); return true; } __instance.SetSpecificArt(value); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MAPCOLOR] NextArt prefix failed: " + ex.Message)); return true; } } } internal static class PoisonSync { internal static bool ProtocolEnabled = false; internal const string CapabilityProp = "cr_pois1"; private const byte EventCode = 47; private const byte Protocol = 1; internal const string RoomModeProp = "cr_poismode"; private static int _nextStream = 1; private static readonly HashSet _applied = new HashSet(); private static readonly Dictionary _streamTally = new Dictionary(); private static bool _hooked; private static MethodInfo _playMi; private static object _soundManager; private static string _publishedFor = ""; private static readonly Dictionary _lifeGen = new Dictionary(); internal static bool Authoritative { get { try { if (!ProtocolEnabled) { return false; } if (!PhotonNetwork.InRoom || PhotonNetwork.OfflineMode) { return false; } int epoch; bool auth; return ReadRoomMode(out epoch, out auth) && auth; } catch { return false; } } } internal static int Epoch { get { ReadRoomMode(out var epoch, out var _); return epoch; } } private static bool ReadRoomMode(out int epoch, out bool auth) { epoch = 0; auth = false; try { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = ((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null); if (val == null) { return false; } if (!((Dictionary)(object)val).TryGetValue((object)"cr_poismode", out object value)) { return false; } if (!(value is object[] array) || array.Length < 2) { return false; } epoch = (int)array[0]; auth = (byte)array[1] == 1; return true; } catch { return false; } } private static void PlayTick(object sound, Transform at) { try { if (sound == null || (Object)(object)at == (Object)null) { return; } if (_playMi == null) { Type type = AccessTools.TypeByName("Sonigon.SoundManager"); if (type == null) { return; } PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); _soundManager = ((property != null) ? property.GetValue(null) : null); MethodInfo[] methods = type.GetMethods(); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "Play")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 2 && parameters[1].ParameterType == typeof(Transform)) { _playMi = methodInfo; break; } } } } if (!(_playMi == null) && _soundManager != null) { _playMi.Invoke(_soundManager, new object[2] { sound, at }); } } catch { } } internal static IEnumerator LocalTickSound(DamageOverTime host, CharacterData data, object sound, float magnitude, float total, float interval) { if (sound == null || interval <= 0f || total <= 0f) { yield break; } float dealt = 0f; float dpt = magnitude / total * interval; if (dpt <= 0f) { yield break; } while (dealt < magnitude && !((Object)(object)host == (Object)null) && !((Object)(object)data == (Object)null)) { dealt += dpt; if (data.isPlaying && !data.dead) { PlayTick(sound, ((Component)host).transform); } yield return (object)new WaitForSeconds(interval / TimeHandler.timeScale); } } internal static void EnsureCapabilityPublished() { //IL_0059: 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_006f: Expected O, but got Unknown //IL_0071: Expected O, but got Unknown try { if (ProtocolEnabled && PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode) { Room currentRoom = PhotonNetwork.CurrentRoom; string text = ((currentRoom != null) ? currentRoom.Name : null) ?? ""; if (!(text == _publishedFor)) { Hashtable val = new Hashtable(); ((Dictionary)val).Add((object)"cr_pois1", (object)1); Hashtable val2 = val; PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); _publishedFor = text; Plugin.Log.LogInfo((object)string.Format("[POISON-MODE] advertised {0}={1} for room {2}", "cr_pois1", (byte)1, text)); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POISON-MODE] publish failed: " + ex.Message)); } } private static bool EveryoneCapable(out string detail) { detail = ""; try { Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null || playerList.Length == 0) { detail = "no players"; return false; } List list = new List(); bool result = true; Player[] array = playerList; foreach (Player val in array) { object value = null; bool flag = val != null && val.CustomProperties != null && ((Dictionary)(object)val.CustomProperties).TryGetValue((object)"cr_pois1", out value) && value is int && (int)value >= 1; list.Add(string.Format("{0}:{1}", (val != null) ? val.ActorNumber : (-1), flag ? "y" : "n")); if (!flag) { result = false; } } detail = string.Join(",", list.ToArray()); return result; } catch (Exception ex) { detail = "error " + ex.Message; return false; } } internal static void LatchForGame(string source) { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown try { if (ProtocolEnabled) { _applied.Clear(); _streamTally.Clear(); _lifeGen.Clear(); if (!PhotonNetwork.InRoom || PhotonNetwork.OfflineMode) { Plugin.Log.LogInfo((object)("[POISON-MODE] OFFLINE-VANILLA (" + source + ") — vanilla block behaviour, untouched")); return; } if (!PhotonNetwork.IsMasterClient) { ReadRoomMode(out var epoch, out var auth); Plugin.Log.LogInfo((object)($"[POISON-MODE] adopting master decision epoch={epoch} " + "mode=" + (auth ? "AUTH" : "FALLBACK") + " (" + source + ")")); return; } string detail; bool flag = EveryoneCapable(out detail); int epoch2 = 0; ReadRoomMode(out epoch2, out var _); epoch2++; Hashtable val = new Hashtable(); ((Dictionary)(object)val).Add((object)"cr_poismode", (object)new object[2] { epoch2, (byte)(flag ? 1u : 0u) }); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)($"[POISON-MODE] MASTER published epoch={epoch2} " + "mode=" + (flag ? "AUTH" : "FALLBACK") + " caps=" + detail + " (" + source + ")")); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POISON-MODE] latch failed: " + ex.Message)); } } internal static int LifeGen(int viewId) { int value; return _lifeGen.TryGetValue(viewId, out value) ? value : 0; } internal static void BumpLife(int viewId) { _lifeGen[viewId] = LifeGen(viewId) + 1; } internal static void Hook() { if (_hooked) { return; } try { PhotonNetwork.NetworkingClient.EventReceived += OnEvent; _hooked = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POISON-SYNC] hook failed: " + ex.Message)); } } private static long DedupKey(int epoch, int viewId, int stream, int tick) { return ((long)epoch << 44) ^ ((long)viewId << 24) ^ ((long)stream << 10) ^ (uint)tick; } private static bool Raise(object[] payload) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown try { return PhotonNetwork.RaiseEvent((byte)47, (object)payload, new RaiseEventOptions { Receivers = (ReceiverGroup)1 }, SendOptions.SendReliable); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POISON-AUTH] raise threw: " + ex.Message)); return false; } } private static void OnEvent(EventData e) { //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) if (e.Code != 47) { return; } try { if (!(e.CustomData is object[] array) || array.Length < 17 || (byte)array[0] != 1) { return; } int num = (int)array[1]; int num2 = (int)array[2]; int num3 = (int)array[3]; int num4 = (int)array[4]; bool flag = (bool)array[5]; int num5 = (int)array[15]; int num6 = (int)array[16]; PhotonView val = PhotonView.Find(num2); if ((Object)(object)val == (Object)null) { return; } if (val.Owner == null || val.Owner.ActorNumber != e.Sender) { Plugin.Log.LogWarning((object)($"[POISON-SYNC] REJECT forged tick: sender={e.Sender} " + $"owner={((val.Owner != null) ? val.Owner.ActorNumber : (-1))} view={num2}")); } else { if (num != Epoch) { return; } if (num5 != LifeGen(num2)) { Plugin.Log.LogInfo((object)($"[POISON-SYNC] stale-life drop v{num2}/s{num3}/t{num4} " + $"(tick life={num5}, now={LifeGen(num2)})")); return; } long item = DedupKey(num, num2, num3, num4); if (!_applied.Add(item)) { return; } long key = ((long)num2 << 24) ^ (uint)num3; if (!_streamTally.TryGetValue(key, out var value)) { value = new int[3]; _streamTally[key] = value; } value[flag ? 1 : 0]++; if (flag) { return; } HealthHandler component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { return; } Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)array[6], (float)array[7]); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor((float)array[8], (float)array[9]); Color val4 = default(Color); ((Color)(ref val4))..ctor((float)array[10], (float)array[11], (float)array[12], 1f); int num7 = (int)array[13]; bool flag2 = (bool)array[14]; Player val5 = null; GameObject val6 = null; try { if (num7 >= 0) { foreach (Player player in PlayerManager.instance.players) { if ((Object)(object)player != (Object)null && player.PlayerID == num7) { val5 = player; break; } } if ((Object)(object)val5 != (Object)null && (Object)(object)val5.data != (Object)null && (Object)(object)val5.data.weaponHandler != (Object)null && (Object)(object)val5.data.weaponHandler.gun != (Object)null) { val6 = ((Component)val5.data.weaponHandler.gun).gameObject; } } } catch { } float num8 = 0f; try { CharacterData component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { num8 = component2.health; } } catch { } component.DoDamage(val2, val3, val4, val6, val5, true, flag2, true, (DamageSource)num6); try { CharacterData component3 = ((Component)val).GetComponent(); if ((Object)(object)component3 != (Object)null && component3.health < num8 - 0.0001f) { value[2]++; } return; } catch { return; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POISON-SYNC] apply failed: " + ex.Message)); } } internal static IEnumerator AuthoritativeDot(DamageOverTime host, HealthHandler health, CharacterData data, PhotonView view, Vector2 damage, Vector2 position, float time, float interval, Color color, Player damagingPlayer, bool lethal, int damageSource) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) int stream = _nextStream++; int epoch = Epoch; int viewId = view.ViewID; int lifeGen = LifeGen(viewId); int attackerId = (((Object)(object)damagingPlayer != (Object)null) ? damagingPlayer.PlayerID : (-1)); float damageDealt = 0f; float damageToDeal = ((Vector2)(ref damage)).magnitude; float dpt = damageToDeal / time * interval; int tick = 0; int blockedCount = 0; int failedSends = 0; while (damageDealt < damageToDeal) { damageDealt += dpt; bool blocked = false; float sinceBlock = -1f; try { Block block = (((Object)(object)data != (Object)null) ? data.block : null); if ((Object)(object)block != (Object)null) { blocked = block.IsBlocking(); sinceBlock = block.sinceBlock; } } catch { } if (blocked) { blockedCount++; } Vector2 slice = ((Vector2)(ref damage)).normalized * dpt; if (!Raise(new object[17] { (byte)1, epoch, viewId, stream, tick, blocked, slice.x, slice.y, position.x, position.y, color.r, color.g, color.b, attackerId, lethal, lifeGen, damageSource })) { failedSends++; Plugin.Log.LogWarning((object)("[POISON-AUTH] SEND FAILED e" + epoch + "/v" + viewId + "/s" + stream + "/t" + tick + " - tick lost for everyone")); } if (blocked) { Plugin.Log.LogInfo((object)($"[POISON-AUTH] BLOCK e{epoch}/v{viewId}/s{stream}/t{tick} " + $"sinceBlock={sinceBlock:F3} dmg={dpt:F2}")); } tick++; yield return (object)new WaitForSeconds(interval / TimeHandler.timeScale); } long tkey = ((long)viewId << 24) ^ (uint)stream; _streamTally.TryGetValue(tkey, out var tally); Plugin.Log.LogInfo((object)($"[POISON-SYNC] COMPLETE e{epoch}/v{viewId}/s{stream} life={lifeGen} " + $"sent={tick} blocked={blockedCount} failedSends={failedSends} " + $"recvAccepted={((tally != null) ? tally[0] : (-1))} " + $"recvBlocked={((tally != null) ? tally[1] : (-1))} " + $"hpApplied={((tally != null) ? tally[2] : (-1))}")); } } [HarmonyPatch(typeof(HealthHandler))] internal static class HealthHandlerLifeGenPatch { [HarmonyPostfix] [HarmonyPatch("RPCA_Die")] private static void AfterDie(HealthHandler __instance) { Bump(__instance); } [HarmonyPostfix] [HarmonyPatch("RPCA_Die_Phoenix")] private static void AfterPhoenix(HealthHandler __instance) { Bump(__instance); } private static void Bump(HealthHandler hh) { try { PhotonView val = (((Object)(object)hh != (Object)null) ? ((Component)hh).GetComponent() : null); if ((Object)(object)val != (Object)null) { PoisonSync.BumpLife(val.ViewID); } } catch { } } } [HarmonyPatch(typeof(DamageOverTime), "TakeDamageOverTime")] internal static class DamageOverTimeAuthoritativePatch { private static bool Prefix(DamageOverTime __instance, Vector2 damage, Vector2 position, float time, float interval, Color color, Player damagingPlayer, bool lethal, DamageSource damageSource, object[] __args) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected I4, but got Unknown try { if (!PoisonSync.Authoritative) { return true; } if (time <= 0f || interval <= 0f) { return true; } PhotonView component = ((Component)__instance).GetComponent(); HealthHandler component2 = ((Component)__instance).GetComponent(); CharacterData component3 = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null) { return true; } object obj = ((__args != null && __args.Length > 5) ? __args[5] : null); if (obj != null) { ((MonoBehaviour)__instance).StartCoroutine(PoisonSync.LocalTickSound(__instance, component3, obj, ((Vector2)(ref damage)).magnitude, time, interval)); } if (!component.IsMine) { return false; } ((MonoBehaviour)__instance).StartCoroutine(PoisonSync.AuthoritativeDot(__instance, component2, component3, component, damage, position, time, interval, color, damagingPlayer, lethal, (int)damageSource)); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[POISON-SYNC] scheduler failed, using vanilla: " + ex.Message)); return true; } } } internal static class SteamAuth { private static float _sessionExpiresAt = -1f; private static Callback _webTicketCb; private static bool _requestInFlight; private static float _requestStartedAt = -999f; private static float _lastAttemptAt = -999f; private static bool _loggedUnavailable; public static string SessionToken { get; private set; } public static bool HasFreshToken => !string.IsNullOrEmpty(SessionToken) && Time.realtimeSinceStartup < _sessionExpiresAt - 3600f; public static void MaybeRefresh() { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) try { if (_requestInFlight && Time.realtimeSinceStartup - _requestStartedAt > 30f) { _requestInFlight = false; } if (HasFreshToken || _requestInFlight) { return; } float num = (string.IsNullOrEmpty(SessionToken) ? 4f : 60f); if (Time.realtimeSinceStartup - _lastAttemptAt < num) { return; } string localSteamId = MatchTracker.LocalSteamId; if (!string.IsNullOrEmpty(localSteamId) && !(localSteamId == "unknown") && !localSteamId.StartsWith("photon_")) { _lastAttemptAt = Time.realtimeSinceStartup; if (_webTicketCb == null) { _webTicketCb = Callback.Create((DispatchDelegate)OnWebTicket); } SteamUser.GetAuthTicketForWebApi("competitive-rounds"); _requestInFlight = true; _requestStartedAt = Time.realtimeSinceStartup; } } catch (Exception ex) { if (!_loggedUnavailable) { _loggedUnavailable = true; Plugin.Log.LogWarning((object)("[STEAM-AUTH] ticket request unavailable: " + ex.Message + " — running without session auth")); } } } private static void OnWebTicket(GetTicketForWebApiResponse_t cb) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) _requestInFlight = false; try { if ((int)cb.m_eResult != 1 || cb.m_cubTicket <= 0 || cb.m_rgubTicket == null) { Plugin.Log.LogWarning((object)$"[STEAM-AUTH] ticket callback failed: {cb.m_eResult}"); return; } string ticketHex = BitConverter.ToString(cb.m_rgubTicket, 0, cb.m_cubTicket).Replace("-", ""); Plugin.Log.LogInfo((object)$"[STEAM-AUTH] web ticket minted ({cb.m_cubTicket} bytes) — exchanging for session"); ApiClient.PostSteamAuth(ticketHex); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[STEAM-AUTH] ticket handling error: " + ex.Message)); } } public static void SetSession(string token, int expiresInSeconds) { if (!string.IsNullOrEmpty(token)) { SessionToken = token; _sessionExpiresAt = Time.realtimeSinceStartup + (float)Mathf.Max(600, expiresInSeconds); Plugin.Log.LogInfo((object)$"[STEAM-AUTH] session established (expires in {expiresInSeconds}s)"); } } public static void InvalidateSession() { SessionToken = null; _sessionExpiresAt = -1f; _lastAttemptAt = -999f; } public static void InvalidateSessionIf(string token) { if (!string.IsNullOrEmpty(token) && token == SessionToken) { InvalidateSession(); } } } internal static class TabStatsOverlay { private sealed class CardDisplay { public string canonicalName; public readonly GUIContent content = new GUIContent(); } private sealed class CardRow { public readonly CardDisplay[] cards = new CardDisplay[8]; public readonly GUIContent message = new GUIContent(); public readonly GUIContent tail = new GUIContent(); public readonly float[] nameWidths = new float[9]; public readonly float[] tokenWidths = new float[9]; public readonly float[] lineWidths = new float[9]; public readonly float[] lineX = new float[9]; public readonly float[] tokenX = new float[9]; public readonly int[] tokenLines = new int[9]; public int count; public int totalCount; public int visibleCount; public int lineCount; public bool hasTail; public CardRow() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown for (int i = 0; i < cards.Length; i++) { cards[i] = new CardDisplay(); } } } private struct StatRow { public string label; public Func value; public StatRow(string l, Func v) { label = l; value = v; } } private static GUIStyle stTitle; private static GUIStyle stName; private static GUIStyle stLabel; private static GUIStyle stCell; private static GUIStyle stCards; private static readonly List cachedPlayers = new List(4); private static readonly List cachedNames = new List(4); private static readonly List cachedCards = new List(4); private static readonly List cachedColors = new List(4); private static readonly List cachedValues = new List(4); private static readonly Dictionary cardTextures = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary cardTexRetryAt = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int cachedPlayerCount; private static float nextSnapshotAt; private static bool cardLayoutDirty = true; private static float cachedCardLayoutWidth = -1f; private static float cachedCardsHeight = 24f; private static float cardSeparatorWidth; private const int MAX_SHOWN_CARDS = 8; private const int MAX_CARD_TOKENS = 9; private static readonly GUIContent CARD_SEPARATOR = new GUIContent(", "); private static readonly StatRow[] ROWS = new StatRow[21] { new StatRow("HP", (Player p) => $"{Mathf.Max(0f, p.data.health):F0}/{p.data.MaxHealth:F0}"), new StatRow("Lives", (Player p) => $"{p.data.stats.remainingRespawns + 1:F0}"), new StatRow("Damage", (Player p) => $"{Gun(p).damage * Gun(p).bulletDamageMultiplier * 55f:F0}"), new StatRow("Attack spd", (Player p) => $"{Gun(p).attackSpeed * Gun(p).attackSpeedMultiplier:F2}s"), new StatRow("Reload", delegate(Player p) { GunAmmo val = Ammo(p); return $"{(val.reloadTime + val.reloadTimeAdd) * val.reloadTimeMultiplier:F2}s"; }), new StatRow("Ammo", (Player p) => $"{Ammo(p).maxAmmo:F0}"), new StatRow("Bullets", (Player p) => $"{Gun(p).numberOfProjectiles:F0}"), new StatRow("Bursts", (Player p) => $"{Gun(p).bursts:F0}"), new StatRow("Bounces", (Player p) => $"{Gun(p).reflects:F0}"), new StatRow("Bullet spd", (Player p) => $"{Gun(p).projectileSpeed:F2}"), new StatRow("Bullet slow", (Player p) => $"{Gun(p).slow:F2}"), new StatRow("Knockback", (Player p) => $"{Gun(p).knockback:F2}"), new StatRow("Spread", (Player p) => $"{Gun(p).spread:F2}"), new StatRow("Life steal", (Player p) => $"{p.data.stats.lifeSteal:F2}"), new StatRow("Block CD", (Player p) => $"{p.data.block.Cooldown():F2}s"), new StatRow("Blocks", (Player p) => $"{p.data.block.additionalBlocks + 1:F0}"), new StatRow("Regen", (Player p) => $"{p.data.healthHandler.regeneration:F1}/s"), new StatRow("Move spd", (Player p) => $"{p.data.stats.movementSpeed:F2}"), new StatRow("Jump", (Player p) => $"{p.data.stats.jump:F2}"), new StatRow("Jumps", (Player p) => $"{p.data.stats.numberOfJumps:F0}"), new StatRow("Size", (Player p) => $"{p.data.stats.sizeMultiplier:F2}") }; private static readonly Color[] FALLBACK = (Color[])(object)new Color[4] { new Color(0.96f, 0.55f, 0.23f), new Color(0.35f, 0.6f, 0.95f), new Color(0.9f, 0.3f, 0.3f), new Color(0.4f, 0.85f, 0.45f) }; private static readonly Dictionary cardBaseline = new Dictionary(); private static Gun Gun(Player p) { return p.data.weaponHandler.gun; } private static GunAmmo Ammo(Player p) { return ((Component)p.data.weaponHandler.gun).GetComponentInChildren(true); } private static void RefreshSnapshot(PlayerManager pm) { //IL_01a6: 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) nextSnapshotAt = Time.unscaledTime + 0.125f; cachedPlayers.Clear(); foreach (Player player in pm.players) { if ((Object)(object)player != (Object)null && (Object)(object)player.data != (Object)null) { cachedPlayers.Add(player); } } cachedPlayers.Sort((Player a, Player b) => (a.TeamID != b.TeamID) ? a.TeamID.CompareTo(b.TeamID) : a.PlayerID.CompareTo(b.PlayerID)); cachedPlayerCount = cachedPlayers.Count; while (cachedNames.Count < cachedPlayerCount) { cachedNames.Add(""); } while (cachedCards.Count < cachedPlayerCount) { cachedCards.Add(new CardRow()); } while (cachedColors.Count < cachedPlayerCount) { cachedColors.Add(Color.white); } while (cachedValues.Count < cachedPlayerCount) { cachedValues.Add(new string[ROWS.Length]); } for (int num = 0; num < cachedPlayerCount; num++) { Player val = cachedPlayers[num]; cachedNames[num] = Trunc(PlayerName(val), 16); RefreshCardRow(cachedCards[num], val); cachedColors[num] = TeamColor(val); string[] array = cachedValues[num]; for (int num2 = 0; num2 < ROWS.Length; num2++) { try { array[num2] = ROWS[num2].value(val); } catch { array[num2] = "-"; } } } cardLayoutDirty = true; } public static void Draw() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_04aa: Unknown result type (might be due to invalid IL or missing references) try { if (Event.current == null || (int)Event.current.type != 7 || !Input.GetKey((KeyCode)9) || NativeUI.IsOpen || CompetitiveUI.IsChatInputOpen) { return; } PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null || instance.players.Count == 0) { return; } if (Time.unscaledTime >= nextSnapshotAt) { RefreshSnapshot(instance); } if (cachedPlayerCount == 0) { return; } EnsureStyles(); float num = 118f; float num2 = Mathf.Clamp(((float)Screen.width * 0.62f - num) / (float)cachedPlayerCount, 130f, 210f); float num3 = num + num2 * (float)cachedPlayerCount + 24f; float num4 = 21f; float num5 = num2 - 8f; if (cardLayoutDirty || Mathf.Abs(cachedCardLayoutWidth - num5) > 0.5f) { float num6 = Mathf.Max(15f, stCards.lineHeight + 3f); int num7 = 1; for (int i = 0; i < cachedPlayerCount; i++) { num7 = Mathf.Max(num7, PrepareCardRowLayout(cachedCards[i], num5, 4)); } cachedCardsHeight = (float)num7 * num6 + 8f; cachedCardLayoutWidth = num5; cardLayoutDirty = false; } float num8 = cachedCardsHeight; float num9 = 60f + (float)ROWS.Length * num4 + num8 + 16f; float num10 = ((float)Screen.width - num3) / 2f; float num11 = Mathf.Max(24f, ((float)Screen.height - num9) * 0.5f); GUI.DrawTexture(new Rect(num10, num11, num3, num9), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0f, 0f, 0f, 0.88f), 0f, 0f); GUI.Label(new Rect(num10 + 12f, num11 + 6f, num3 - 24f, 24f), "MATCH STATS (hold Tab)", stTitle); float num12 = num10 + 12f + num; for (int j = 0; j < cachedPlayerCount; j++) { Color contentColor = GUI.contentColor; GUI.contentColor = cachedColors[j]; GUI.Label(new Rect(num12, num11 + 34f, num2 - 6f, 22f), cachedNames[j], stName); GUI.contentColor = contentColor; num12 += num2; } float num13 = num11 + 34f + 26f; for (int k = 0; k < ROWS.Length; k++) { if ((k & 1) == 0) { GUI.DrawTexture(new Rect(num10 + 6f, num13, num3 - 12f, num4), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(1f, 1f, 1f, 0.03f), 0f, 0f); } GUI.Label(new Rect(num10 + 12f, num13, num, num4), ROWS[k].label, stLabel); num12 = num10 + 12f + num; for (int l = 0; l < cachedPlayerCount; l++) { GUI.Label(new Rect(num12, num13, num2 - 6f, num4), cachedValues[l][k], stCell); num12 += num2; } num13 += num4; } num13 += 4f; GUI.Label(new Rect(num10 + 12f, num13, num, num8), "Cards", stLabel); num12 = num10 + 12f + num; Vector2 mousePosition = Event.current.mousePosition; Texture2D val = null; for (int m = 0; m < cachedPlayerCount; m++) { val = DrawCardRow(cachedCards[m], new Rect(num12, num13, num2 - 8f, num8), mousePosition, val); num12 += num2; } if ((Object)(object)val != (Object)null) { DrawHoveredCardArt(val, mousePosition); } } catch { } } private static void EnsureStyles() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0049: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0076: 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_0084: 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_0099: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) if (stTitle == null) { stTitle = new GUIStyle(GUI.skin.label) { fontSize = 16, fontStyle = (FontStyle)1, richText = true }; stName = new GUIStyle(GUI.skin.label) { fontSize = 14, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; stLabel = new GUIStyle(GUI.skin.label) { fontSize = 13, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; stLabel.normal.textColor = new Color(0.75f, 0.78f, 0.85f); stCell = new GUIStyle(GUI.skin.label) { fontSize = 13, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; stCards = new GUIStyle(GUI.skin.label) { fontSize = 11, fontStyle = (FontStyle)1, alignment = (TextAnchor)1, wordWrap = true, richText = true }; stCards.clipping = (TextClipping)0; stCards.normal.textColor = new Color(0.7f, 0.78f, 0.9f); cardSeparatorWidth = stCards.CalcSize(CARD_SEPARATOR).x; } } private static string PlayerName(Player p) { try { PhotonView view = p.data.view; object obj; if (view == null) { obj = null; } else { Player owner = view.Owner; obj = ((owner != null) ? owner.NickName : null); } string text = (string)obj; if (!string.IsNullOrEmpty(text)) { return NametagStyler.Clean(text); } } catch { } return $"Player {p.PlayerID + 1}"; } private static Color TeamColor(Player p) { //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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) try { PlayerSkin playerSkinColors = PlayerSkinBank.GetPlayerSkinColors(p.PlayerID); if ((Object)(object)playerSkinColors != (Object)null) { return playerSkinColors.color; } } catch { } return FALLBACK[Mathf.Abs(p.TeamID) % FALLBACK.Length]; } public static void RecordCardBaseline(Player p) { try { if ((Object)(object)p != (Object)null && (Object)(object)p.data != (Object)null && p.data.currentCards != null) { cardBaseline[p] = p.data.currentCards.Count; } } catch { } } public static void ClearCardBaselines() { cardBaseline.Clear(); } private static void RefreshCardRow(CardRow row, Player p) { try { List currentCards = p.data.currentCards; int num = 0; if (currentCards != null && cardBaseline.TryGetValue(p, out var value) && value > 0 && value <= currentCards.Count) { num = value; } row.count = 0; row.totalCount = 0; row.visibleCount = 0; row.lineCount = 1; row.hasTail = false; if (currentCards == null || currentCards.Count - num <= 0) { row.message.text = "no cards"; return; } row.message.text = ""; for (int i = num; i < currentCards.Count; i++) { if (!((Object)(object)currentCards[i] == (Object)null)) { row.totalCount++; if (row.count < 8) { string text = currentCards[i].cardName ?? "?"; string canonicalName = CardRarityLookup.GetCanonicalName(text) ?? text; CardDisplay cardDisplay = row.cards[row.count++]; cardDisplay.canonicalName = canonicalName; cardDisplay.content.text = Trunc(text, 12).ToUpperInvariant().Replace("<", "(").Replace(">", ")"); } } } } catch { row.count = 0; row.totalCount = 0; row.visibleCount = 0; row.lineCount = 1; row.hasTail = false; row.message.text = "-"; } } private static Texture2D GetCardTexture(string canonicalName) { if (string.IsNullOrEmpty(canonicalName)) { return null; } if (cardTextures.TryGetValue(canonicalName, out var value)) { if ((Object)(object)value != (Object)null) { return value; } if (cardTexRetryAt.TryGetValue(canonicalName, out var value2) && Time.realtimeSinceStartup < value2) { return null; } } Sprite sprite = CardImageLoader.GetSprite(canonicalName); value = (((Object)(object)sprite != (Object)null) ? sprite.texture : null); cardTextures[canonicalName] = value; if ((Object)(object)value == (Object)null) { cardTexRetryAt[canonicalName] = Time.realtimeSinceStartup + 5f; } return value; } private static int PrepareCardRowLayout(CardRow row, float width, int maxLines) { //IL_00f5: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(row.message.text)) { row.visibleCount = 0; row.hasTail = false; row.lineCount = 1; return 1; } float num = cardSeparatorWidth; int num2 = 1; for (int num3 = row.count; num3 >= 0; num3--) { int num4 = Mathf.Max(0, row.totalCount - num3); bool flag = num4 > 0; if (flag) { row.tail.text = $" +{num4}"; } int num5 = num3 + (flag ? 1 : 0); if (num5 == 0) { row.visibleCount = 0; row.hasTail = false; row.lineCount = 1; return 1; } int num6 = 0; float num7 = 0f; for (int i = 0; i < num5; i++) { GUIContent val = ((i < num3) ? row.cards[i].content : row.tail); float x = stCards.CalcSize(val).x; float num8 = x + ((i < num3 - 1) ? num : 0f); if (num7 > 0f && num7 + num8 > width) { row.lineWidths[num6] = num7; num6++; num7 = 0f; } row.nameWidths[i] = x; row.tokenWidths[i] = num8; row.tokenLines[i] = num6; num7 += num8; } row.lineWidths[num6] = num7; num2 = num6 + 1; if (num2 <= maxLines || num3 == 0) { row.visibleCount = num3; row.hasTail = flag; row.lineCount = Mathf.Min(num2, maxLines); int num9 = num3 + (flag ? 1 : 0); for (int j = 0; j < row.lineCount; j++) { row.lineX[j] = Mathf.Max(0f, (width - row.lineWidths[j]) * 0.5f); } for (int k = 0; k < num9; k++) { int num10 = row.tokenLines[k]; row.tokenX[k] = row.lineX[num10]; row.lineX[num10] += row.tokenWidths[k]; } return row.lineCount; } } return Mathf.Min(num2, maxLines); } private static Texture2D DrawCardRow(CardRow row, Rect rect, Vector2 mousePosition, Texture2D hoveredTexture) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(row.message.text)) { GUI.Label(rect, row.message, stCards); return hoveredTexture; } int num = row.visibleCount + (row.hasTail ? 1 : 0); if (num == 0) { return hoveredTexture; } float num2 = cardSeparatorWidth; float num3 = Mathf.Max(12f, stCards.lineHeight); Rect val = default(Rect); for (int i = 0; i < num; i++) { int num4 = row.tokenLines[i]; float num5 = ((Rect)(ref rect)).y + (float)num4 * num3; if (num5 >= ((Rect)(ref rect)).yMax) { continue; } float num6 = ((Rect)(ref rect)).x + row.tokenX[i]; float num7 = row.nameWidths[i]; if (i < row.visibleCount) { ((Rect)(ref val))..ctor(num6, num5, num7, num3); GUI.Label(val, row.cards[i].content, stCards); if (((Rect)(ref val)).Contains(mousePosition)) { hoveredTexture = GetCardTexture(row.cards[i].canonicalName); } num6 += num7; if (i < row.visibleCount - 1) { GUI.Label(new Rect(num6, num5, num2, num3), CARD_SEPARATOR, stCards); } } else { GUI.Label(new Rect(num6, num5, num7, num3), row.tail, stCards); } } return hoveredTexture; } private static void DrawHoveredCardArt(Texture2D texture, Vector2 mousePosition) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Min(1f, Mathf.Min(Mathf.Max(1f, (float)Screen.width - 8f) / 180f, Mathf.Max(1f, (float)Screen.height - 8f) / 270f)); float num2 = 180f * num; float num3 = 270f * num; float num4 = mousePosition.x + 16f; float num5 = mousePosition.y + 16f; if (num4 + num2 > (float)Screen.width - 4f) { num4 = mousePosition.x - num2 - 16f; } if (num5 + num3 > (float)Screen.height - 4f) { num5 = mousePosition.y - num3 - 16f; } num4 = Mathf.Clamp(num4, 4f, Mathf.Max(4f, (float)Screen.width - num2 - 4f)); num5 = Mathf.Clamp(num5, 4f, Mathf.Max(4f, (float)Screen.height - num3 - 4f)); GUI.DrawTexture(new Rect(num4, num5, num2, num3), (Texture)(object)texture, (ScaleMode)2, true); } private static string Trunc(string s, int n) { return string.IsNullOrEmpty(s) ? "" : ((s.Length <= n) ? s : (s.Substring(0, n - 1) + "~")); } } internal static class TrailCosmetic { private const string PROP_SKU = "cr_trail_sku"; private const string PROP_COLOR = "cr_trail_color"; private const string PROP_PRICE = "cr_trail_price"; private static readonly Dictionary attached = new Dictionary(); public static void PublishLocalProps() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown try { if (PhotonNetwork.IsConnected && PhotonNetwork.LocalPlayer != null) { ApiClient.PlayerStatsData cachedPlayerStats = ApiClient.CachedPlayerStats; Hashtable val = new Hashtable(); val[(object)"cr_trail_sku"] = cachedPlayerStats?.active_trail_sku ?? ""; val[(object)"cr_trail_color"] = cachedPlayerStats?.active_trail_color ?? ""; val[(object)"cr_trail_price"] = cachedPlayerStats?.active_trail_price ?? 0; PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)string.Format("[TRAIL] Published local props sku={0} color={1} price={2}", val[(object)"cr_trail_sku"], val[(object)"cr_trail_color"], val[(object)"cr_trail_price"])); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TRAIL] PublishLocalProps failed: " + ex.Message)); } } public static void OnMatchStart() { try { if (Plugin.ShowTrails != null && !Plugin.ShowTrails.Value) { Plugin.Log.LogInfo((object)"[TRAIL] Skipped — ShowTrails is off"); } else { ((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedAttachAll()); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TRAIL] OnMatchStart error: " + ex.Message)); } } public static void OnPlayerPropertiesChanged(Player target, Hashtable changed) { if (target != null && changed != null && (((Dictionary)(object)changed).ContainsKey((object)"cr_trail_sku") || ((Dictionary)(object)changed).ContainsKey((object)"cr_trail_color") || ((Dictionary)(object)changed).ContainsKey((object)"cr_trail_price")) && (PhotonNetwork.LocalPlayer == null || target.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)) { ReattachForActor(target.ActorNumber); } } public static void ReattachForActor(int actor) { try { if (Plugin.ShowTrails != null && !Plugin.ShowTrails.Value) { return; } PlayerManager instance = PlayerManager.instance; if ((Object)(object)instance == (Object)null || instance.players == null || instance.players.Count == 0) { return; } Player val = null; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val2 in playerList) { if (val2 != null && val2.ActorNumber == actor) { val = val2; break; } } if (val == null || val.CustomProperties == null) { return; } Hashtable customProperties = val.CustomProperties; string text = ((!((Dictionary)(object)customProperties).ContainsKey((object)"cr_trail_sku")) ? "" : (customProperties[(object)"cr_trail_sku"]?.ToString() ?? "")); string hexColor = ((!((Dictionary)(object)customProperties).ContainsKey((object)"cr_trail_color")) ? "" : (customProperties[(object)"cr_trail_color"]?.ToString() ?? "")); int price = 0; if (((Dictionary)(object)customProperties).ContainsKey((object)"cr_trail_price")) { try { price = Convert.ToInt32(customProperties[(object)"cr_trail_price"]); } catch { } } if (string.IsNullOrEmpty(text)) { return; } foreach (Player player in instance.players) { if (!((Object)(object)player == (Object)null)) { PhotonView component = ((Component)player).GetComponent(); if (!((Object)(object)component == (Object)null) && component.OwnerActorNr == actor) { AttachTrail(((Component)player).transform, actor, text, hexColor, price); Plugin.Log.LogInfo((object)$"[TRAIL] Re-attached for actor={actor} (late props) sku={text}"); break; } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TRAIL] ReattachForActor failed: " + ex.Message)); } } public static void OnMatchEnd() { try { foreach (KeyValuePair item in attached) { if ((Object)(object)item.Value != (Object)null) { Object.Destroy((Object)(object)item.Value); } } attached.Clear(); Plugin.Log.LogInfo((object)"[TRAIL] All detached"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TRAIL] OnMatchEnd error: " + ex.Message)); } } private static IEnumerator DelayedAttachAll() { for (int i = 0; i < 30; i++) { yield return null; } PlayerManager pm = PlayerManager.instance; if ((Object)(object)pm == (Object)null || pm.players == null) { yield break; } foreach (Player p in pm.players) { if ((Object)(object)p == (Object)null) { continue; } PhotonView pv = ((Component)p).GetComponent(); if ((Object)(object)pv == (Object)null) { continue; } int actor = pv.OwnerActorNr; Player photonPlayer = null; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player pp in playerList) { if (pp != null && pp.ActorNumber == actor) { photonPlayer = pp; break; } } string sku = ""; string color = ""; int price = 0; if (pv.IsMine) { ApiClient.PlayerStatsData s = ApiClient.CachedPlayerStats; sku = s?.active_trail_sku ?? ""; color = s?.active_trail_color ?? ""; price = s?.active_trail_price ?? 0; } else if (photonPlayer != null && photonPlayer.CustomProperties != null) { Hashtable cp = photonPlayer.CustomProperties; if (((Dictionary)(object)cp).ContainsKey((object)"cr_trail_sku")) { sku = cp[(object)"cr_trail_sku"]?.ToString() ?? ""; } if (((Dictionary)(object)cp).ContainsKey((object)"cr_trail_color")) { color = cp[(object)"cr_trail_color"]?.ToString() ?? ""; } if (((Dictionary)(object)cp).ContainsKey((object)"cr_trail_price")) { try { price = Convert.ToInt32(cp[(object)"cr_trail_price"]); } catch { price = 0; } } } if (!string.IsNullOrEmpty(sku)) { AttachTrail(((Component)p).transform, actor, sku, color, price); } } } private static void AttachTrail(Transform playerT, int actor, string sku, string hexColor, int price) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)playerT == (Object)null) { return; } if (attached.TryGetValue(actor, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } GameObject val = new GameObject($"CR_Trail_{actor}_{sku}"); val.transform.SetParent(playerT, false); val.transform.localPosition = Vector3.zero; TrailRenderer val2 = val.AddComponent(); float num = 0.35f; if (price >= 10000) { num = 0.9f; } else if (price >= 5000) { num = 0.6f; } else if (price >= 3000) { num = 0.35f; } val2.time = num; val2.startWidth = 0.5f; val2.endWidth = 0f; val2.minVertexDistance = 0.05f; val2.autodestruct = false; val2.emitting = true; Material val3 = new Material(Shader.Find("Sprites/Default")); Color white = Color.white; if (!string.IsNullOrEmpty(hexColor)) { ColorUtility.TryParseHtmlString(hexColor, ref white); } Gradient val4 = BuildGradientForSku(sku, white); val3.color = ((val4 != null) ? Color.white : white); ((Renderer)val2).material = val3; if (val4 != null) { val2.colorGradient = val4; } else { val2.startColor = white; val2.endColor = new Color(white.r, white.g, white.b, 0f); } attached[actor] = val; if (sku == "trail_prism") { val.AddComponent().Target = val2; } switch (sku) { default: if (!(sku == "trail_tride")) { break; } goto case "trail_phoenix"; case "trail_phoenix": case "trail_void": case "trail_prism": AttachParticles(val.transform, sku); break; } Plugin.Log.LogInfo((object)string.Format("[TRAIL] Attached actor={0} sku={1} color={2} len={3:F2}s gradient={4}", actor, sku, hexColor, num, (val4 != null) ? "yes" : "no")); } private static void AttachParticles(Transform parent, string sku) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Expected O, but got Unknown //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_046c: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Expected O, but got Unknown //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Expected O, but got Unknown //IL_04b6: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = new GameObject("CR_TrailFX_" + sku); val.transform.SetParent(parent, false); val.transform.localPosition = Vector3.zero; ParticleSystem val2 = val.AddComponent(); val2.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = val2.main; ((MainModule)(ref main)).duration = 1f; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit((sku == "trail_void") ? 0.7f : 0.5f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit((sku == "trail_void") ? 0.6f : 1.4f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit((sku == "trail_void") ? 0.18f : 0.12f); ((MainModule)(ref main)).maxParticles = 80; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)1; Color val3 = default(Color); switch (sku) { case "trail_phoenix": ((Color)(ref val3))..ctor(1f, 0.65f, 0.15f, 1f); break; case "trail_void": ((Color)(ref val3))..ctor(0.6f, 0.25f, 0.95f, 1f); break; case "trail_tride": ((Color)(ref val3))..ctor(0.95f, 0.78f, 0.87f, 1f); break; default: ((Color)(ref val3))..ctor(1f, 1f, 1f, 1f); break; } ((MainModule)(ref main)).startColor = new MinMaxGradient(val3); EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit((sku == "trail_void") ? 14f : 22f); ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.25f; ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val4 = new Gradient(); if (sku == "trail_prism") { val4.SetKeys((GradientColorKey[])(object)new GradientColorKey[6] { new GradientColorKey(Color.red, 0f), new GradientColorKey(Color.yellow, 0.2f), new GradientColorKey(Color.green, 0.4f), new GradientColorKey(Color.cyan, 0.6f), new GradientColorKey(new Color(0.55f, 0.4f, 1f), 0.8f), new GradientColorKey(new Color(1f, 0.4f, 0.85f), 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[2] { new GradientAlphaKey(0.95f, 0f), new GradientAlphaKey(0f, 1f) }); } else if (sku == "trail_tride") { val4.SetKeys((GradientColorKey[])(object)new GradientColorKey[3] { new GradientColorKey(ParseHex("#55CDFC"), 0f), new GradientColorKey(ParseHex("#F7A8B8"), 0.5f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[2] { new GradientAlphaKey(0.95f, 0f), new GradientAlphaKey(0f, 1f) }); } else { val4.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(val3, 0f), new GradientColorKey(val3, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[2] { new GradientAlphaKey(0.95f, 0f), new GradientAlphaKey(0f, 1f) }); } ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val4); SizeOverLifetimeModule sizeOverLifetime = val2.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true; AnimationCurve val5 = new AnimationCurve((Keyframe[])(object)new Keyframe[2] { new Keyframe(0f, 1f), new Keyframe(1f, 0f) }); ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, val5); ParticleSystemRenderer component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Material val6 = new Material(Shader.Find("Sprites/Default")); val6.color = Color.white; ((Renderer)component).material = val6; ((Renderer)component).sortingOrder = 1; } val2.Play(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TRAIL] AttachParticles failed for " + sku + ": " + ex.Message)); } } private static Gradient BuildGradientForSku(string sku, Color baseColor) { //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_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_0181: 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_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) return (Gradient)(sku switch { "trail_phoenix" => MakeGradient((Color[])(object)new Color[3] { new Color(1f, 0.95f, 0.2f), new Color(1f, 0.55f, 0.1f), new Color(0.9f, 0.15f, 0.05f) }, new float[3] { 0f, 0.5f, 1f }), "trail_void" => MakeGradient((Color[])(object)new Color[3] { new Color(0.75f, 0.35f, 1f), new Color(0.35f, 0.05f, 0.6f), new Color(0f, 0f, 0f) }, new float[3] { 0f, 0.55f, 1f }), "trail_colossus" => MakeGradient((Color[])(object)new Color[2] { ParseHex("#4CADD0"), ParseHex("#E3ECEC") }, new float[2] { 0f, 1f }), "trail_ascendant" => MakeGradient((Color[])(object)new Color[2] { ParseHex("#71FF9E"), ParseHex("#376655") }, new float[2] { 0f, 1f }), "trail_sovereign" => MakeGradient((Color[])(object)new Color[2] { ParseHex("#8E4CD0"), ParseHex("#B2F9FF") }, new float[2] { 0f, 1f }), "trail_titan" => MakeGradient((Color[])(object)new Color[2] { ParseHex("#FF4848"), ParseHex("#CC9AAB") }, new float[2] { 0f, 1f }), "trail_tride" => MakeGradient((Color[])(object)new Color[5] { ParseHex("#5BCEFA"), ParseHex("#F5A9B8"), ParseHex("#5BCEFA"), ParseHex("#F5A9B8"), ParseHex("#5BCEFA") }, new float[5] { 0f, 0.25f, 0.5f, 0.75f, 1f }), "trail_prism" => null, _ => null, }); } private static Color ParseHex(string hex) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Color white = Color.white; ColorUtility.TryParseHtmlString(hex, ref white); return white; } private static Gradient MakeGradient(Color[] colors, float[] times) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) Gradient val = new Gradient(); GradientColorKey[] array = (GradientColorKey[])(object)new GradientColorKey[colors.Length]; GradientAlphaKey[] array2 = (GradientAlphaKey[])(object)new GradientAlphaKey[colors.Length]; for (int i = 0; i < colors.Length; i++) { array[i] = new GradientColorKey(colors[i], times[i]); float num = Mathf.Lerp(1f, 0f, times[i]); array2[i] = new GradientAlphaKey(num, times[i]); } val.SetKeys(array, array2); return val; } } internal class TrailPhotonCallbacks : MonoBehaviour, IInRoomCallbacks { private void OnEnable() { try { PhotonNetwork.AddCallbackTarget((object)this); } catch { } } private void OnDisable() { try { PhotonNetwork.RemoveCallbackTarget((object)this); } catch { } } public void OnPlayerPropertiesUpdate(Player target, Hashtable changedProps) { try { TrailCosmetic.OnPlayerPropertiesChanged(target, changedProps); } catch { } try { PlayerColorCosmetic.OnPlayerPropertiesChanged(target, changedProps); } catch { } try { PlayerEffectCosmetic.OnPlayerPropertiesChanged(target, changedProps); } catch { } } public void OnPlayerEnteredRoom(Player newPlayer) { } public void OnPlayerLeftRoom(Player otherPlayer) { } public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { } public void OnMasterClientSwitched(Player newMasterClient) { } } internal class PrismaticHueCycle : MonoBehaviour { public TrailRenderer Target; private float t; private bool colorApplied; private void Update() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Target == (Object)null) { return; } bool flag = Plugin.AnimatedCosmetics == null || Plugin.AnimatedCosmetics.Value; if (flag || !colorApplied) { if (flag) { t = (t + Time.deltaTime * 0.6f) % 1f; } Color val = Color.HSVToRGB(t, 0.85f, 1f); Target.startColor = val; Target.endColor = new Color(val.r, val.g, val.b, 0f); colorApplied = true; } } } internal static class TrailPreview { private static GameObject canvasGO; private static GameObject previewGO; private static string activeSku = ""; public static string ActiveSku => activeSku; public static bool IsActive => (Object)(object)previewGO != (Object)null; public static void Toggle(string sku, string hexColor, int price) { if (string.IsNullOrEmpty(sku)) { Stop(); return; } if (activeSku == sku && (Object)(object)previewGO != (Object)null) { Stop(); return; } Stop(); Start(sku, hexColor, price); } public static void Start(string sku, string hexColor, int price) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) try { Stop(); EnsureCanvas(); if (!((Object)(object)canvasGO == (Object)null)) { previewGO = new GameObject("CR_TrailPreviewUI_" + sku); previewGO.transform.SetParent(canvasGO.transform, false); previewGO.AddComponent(); Color white = Color.white; if (!string.IsNullOrEmpty(hexColor)) { ColorUtility.TryParseHtmlString(hexColor, ref white); } float num = 0.45f; if (price >= 10000) { num = 0.9f; } else if (price >= 5000) { num = 0.6f; } CursorTrailUI cursorTrailUI = previewGO.AddComponent(); cursorTrailUI.lifetime = num; cursorTrailUI.dotSizeStart = 26f; cursorTrailUI.dotSizeEnd = 4f; cursorTrailUI.maxDots = 36; ConfigureColorsForSku(cursorTrailUI, sku, white); activeSku = sku; Plugin.Log.LogInfo((object)$"[TRAIL-PREVIEW] Started sku={sku} lifetime={num:F2}s (uGUI)"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TRAIL-PREVIEW] Start failed: " + ex.Message)); Stop(); } } public static void Stop() { if ((Object)(object)previewGO != (Object)null) { try { Object.Destroy((Object)(object)previewGO); } catch { } previewGO = null; } activeSku = ""; } private static void EnsureCanvas() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if ((Object)(object)canvasGO != (Object)null) { return; } try { canvasGO = new GameObject("CR_TrailPreviewCanvas"); ((Object)canvasGO).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)canvasGO); if (UIFactory.tCanvas != null) { Component obj = canvasGO.AddComponent(UIFactory.tCanvas); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; PropertyInfo property = UIFactory.tCanvas.GetProperty("renderMode", bindingAttr); property?.SetValue(obj, Enum.ToObject(property.PropertyType, 0)); UIFactory.tCanvas.GetProperty("sortingOrder", bindingAttr)?.SetValue(obj, 30001); } if (UIFactory.tCanvasScaler != null) { Component obj2 = canvasGO.AddComponent(UIFactory.tCanvasScaler); BindingFlags bindingAttr2 = BindingFlags.Instance | BindingFlags.Public; PropertyInfo property2 = UIFactory.tCanvasScaler.GetProperty("uiScaleMode", bindingAttr2); if (property2 != null) { property2.SetValue(obj2, Enum.ToObject(property2.PropertyType, 0)); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[TRAIL-PREVIEW] Canvas create failed: " + ex.Message)); } } private static void ConfigureColorsForSku(CursorTrailUI fx, string sku, Color baseColor) { //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: 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_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_056f: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Unknown result type (might be due to invalid IL or missing references) //IL_057b: Unknown result type (might be due to invalid IL or missing references) //IL_0581: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0420: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_04d6: Unknown result type (might be due to invalid IL or missing references) //IL_04ed: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_0540: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Unknown result type (might be due to invalid IL or missing references) //IL_055f: Unknown result type (might be due to invalid IL or missing references) switch (sku) { case "trail_phoenix": fx.startColor = new Color(1f, 0.95f, 0.2f); fx.midColor = new Color(1f, 0.55f, 0.1f); fx.endColor = new Color(0.9f, 0.15f, 0.05f, 0f); break; case "trail_void": fx.startColor = new Color(0.75f, 0.35f, 1f); fx.midColor = new Color(0.35f, 0.05f, 0.6f); fx.endColor = new Color(0f, 0f, 0f, 0f); break; case "trail_colossus": fx.startColor = Hex("#4CADD0"); fx.midColor = Color.Lerp(Hex("#4CADD0"), Hex("#E3ECEC"), 0.5f); fx.endColor = new Color(Hex("#E3ECEC").r, Hex("#E3ECEC").g, Hex("#E3ECEC").b, 0f); break; case "trail_ascendant": fx.startColor = Hex("#71FF9E"); fx.midColor = Color.Lerp(Hex("#71FF9E"), Hex("#376655"), 0.5f); fx.endColor = new Color(Hex("#376655").r, Hex("#376655").g, Hex("#376655").b, 0f); break; case "trail_sovereign": fx.startColor = Hex("#8E4CD0"); fx.midColor = Color.Lerp(Hex("#8E4CD0"), Hex("#B2F9FF"), 0.5f); fx.endColor = new Color(Hex("#B2F9FF").r, Hex("#B2F9FF").g, Hex("#B2F9FF").b, 0f); break; case "trail_titan": fx.startColor = Hex("#FF4848"); fx.midColor = Color.Lerp(Hex("#FF4848"), Hex("#CC9AAB"), 0.5f); fx.endColor = new Color(Hex("#CC9AAB").r, Hex("#CC9AAB").g, Hex("#CC9AAB").b, 0f); break; case "trail_tride": fx.cycleColors = (Color[])(object)new Color[16] { Hex("#5BCEFA"), Hex("#5BCEFA"), Hex("#5BCEFA"), Hex("#5BCEFA"), Hex("#5BCEFA"), Hex("#5BCEFA"), Hex("#5BCEFA"), Hex("#5BCEFA"), Hex("#F5A9B8"), Hex("#F5A9B8"), Hex("#F5A9B8"), Hex("#F5A9B8"), Hex("#F5A9B8"), Hex("#F5A9B8"), Hex("#F5A9B8"), Hex("#F5A9B8") }; fx.preserveSpawnColor = true; fx.startColor = Hex("#5BCEFA"); fx.midColor = Hex("#F5A9B8"); fx.endColor = new Color(0f, 0f, 0f, 0f); break; case "trail_prism": fx.cyclePrismatic = true; fx.startColor = Color.red; fx.midColor = Color.white; fx.endColor = new Color(1f, 0f, 1f, 0f); break; default: fx.startColor = baseColor; fx.midColor = baseColor; fx.endColor = new Color(baseColor.r, baseColor.g, baseColor.b, 0f); break; } } private static Color Hex(string h) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Color white = Color.white; ColorUtility.TryParseHtmlString(h, ref white); return white; } } internal class CursorTrailUI : MonoBehaviour { private struct DotEntry { public GameObject go; public RectTransform rt; public Component img; public float spawnedAt; public Color spawnColor; public bool active; } public Color startColor = Color.white; public Color midColor = Color.white; public Color endColor = new Color(1f, 1f, 1f, 0f); public float lifetime = 0.5f; public float dotSizeStart = 28f; public float dotSizeEnd = 4f; public int maxDots = 120; public bool cyclePrismatic = false; public Color[] cycleColors; public bool preserveSpawnColor = false; private const float SAMPLE_STEP = 3f; private const float MAX_FILL_DOTS = 30f; private DotEntry[] dots; private int nextSlot = 0; private int spawnIndex = 0; private Vector2 lastSpawnPos = new Vector2(float.NegativeInfinity, float.NegativeInfinity); private float prismT; private static PropertyInfo s_imgColorProp; private static PropertyInfo s_imgSpriteProp; private static PropertyInfo s_imgRayProp; private static Sprite s_dotSprite; private void Awake() { EnsureSprite(); dots = new DotEntry[maxDots]; for (int i = 0; i < maxDots; i++) { dots[i] = MakeDot(i); } } private static void EnsureSprite() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_dotSprite != (Object)null) { return; } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); ((Object)val).hideFlags = (HideFlags)61; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; Color32[] array = (Color32[])(object)new Color32[4096]; float num = 31.5f; float num2 = 31.5f; float num3 = 32f; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num4 = (float)j - num; float num5 = (float)i - num2; float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5) / num3; float num7 = Mathf.Clamp01(1f - num6); num7 *= num7; array[i * 64 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num7 * 255f)); } } val.SetPixels32(array); val.Apply(false, true); s_dotSprite = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); ((Object)s_dotSprite).hideFlags = (HideFlags)61; } private DotEntry MakeDot(int i) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"d{i}"); val.transform.SetParent(((Component)this).transform, false); RectTransform val2 = val.AddComponent(); val2.sizeDelta = new Vector2(dotSizeStart, dotSizeStart); DotEntry result = new DotEntry { go = val, rt = val2, active = false }; if (UIFactory.tImage != null) { Component obj = (result.img = val.AddComponent(UIFactory.tImage)); if (s_imgColorProp == null) { s_imgColorProp = UIFactory.tImage.GetProperty("color", BindingFlags.Instance | BindingFlags.Public); } if (s_imgSpriteProp == null) { s_imgSpriteProp = UIFactory.tImage.GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public); } if (s_imgRayProp == null) { s_imgRayProp = UIFactory.tImage.GetProperty("raycastTarget", BindingFlags.Instance | BindingFlags.Public); } s_imgRayProp?.SetValue(obj, false); s_imgSpriteProp?.SetValue(obj, s_dotSprite); s_imgColorProp?.SetValue(obj, (object)new Color(1f, 1f, 1f, 0f)); } val.SetActive(false); return result; } private void Update() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: 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) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) Vector2 val = Vector2.op_Implicit(Input.mousePosition); if (cyclePrismatic && (Plugin.AnimatedCosmetics == null || Plugin.AnimatedCosmetics.Value)) { prismT += Time.unscaledDeltaTime * 0.6f; if (prismT > 1f) { prismT -= 1f; } } if (float.IsNegativeInfinity(lastSpawnPos.x)) { lastSpawnPos = val; } float num = Vector2.Distance(lastSpawnPos, val); int num2 = Mathf.Min(Mathf.FloorToInt(num / 3f), 30); for (int i = 1; i <= num2; i++) { float num3 = (float)i / (float)num2; Vector2 pos = Vector2.Lerp(lastSpawnPos, val, num3); SpawnDot(pos); } if (num2 > 0) { lastSpawnPos = val; } for (int j = 0; j < dots.Length; j++) { if (!dots[j].active) { continue; } float num4 = Time.unscaledTime - dots[j].spawnedAt; float num5 = num4 / lifetime; if (num5 >= 1f) { dots[j].active = false; dots[j].go.SetActive(false); continue; } Color val2; if (preserveSpawnColor) { val2 = dots[j].spawnColor; val2.a = Mathf.Lerp(dots[j].spawnColor.a, 0f, num5); } else { val2 = ((num5 < 0.5f) ? Color.Lerp(dots[j].spawnColor, midColor, num5 * 2f) : Color.Lerp(midColor, endColor, (num5 - 0.5f) * 2f)); } s_imgColorProp?.SetValue(dots[j].img, val2); float num6 = Mathf.Lerp(dotSizeStart, dotSizeEnd, num5); dots[j].rt.sizeDelta = new Vector2(num6, num6); } } private void SpawnDot(Vector2 pos) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0078: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_00eb: Unknown result type (might be due to invalid IL or missing references) Color val = ((cycleColors != null && cycleColors.Length != 0) ? cycleColors[spawnIndex % cycleColors.Length] : ((!cyclePrismatic) ? startColor : Color.HSVToRGB(prismT, 0.85f, 1f))); DotEntry dotEntry = dots[nextSlot]; ((Transform)dotEntry.rt).position = new Vector3(pos.x, pos.y, 0f); dotEntry.rt.sizeDelta = new Vector2(dotSizeStart, dotSizeStart); dotEntry.spawnedAt = Time.unscaledTime; dotEntry.spawnColor = val; dotEntry.active = true; dotEntry.go.SetActive(true); s_imgColorProp?.SetValue(dotEntry.img, val); dots[nextSlot] = dotEntry; nextSlot = (nextSlot + 1) % dots.Length; spawnIndex++; } } internal static class UnicodeFallback { private sealed class FontState { public string Path; public string Name; public object Asset; public Texture2D Texture; public Material Material; public IList GlyphTable; public IList CharacterTable; public IList FreeGlyphRects; public IList UsedGlyphRects; public int AddedCount; public readonly Dictionary GlyphsByIndex = new Dictionary(); } private sealed class ListRegistration { public object Owner; public PropertyInfo Property; public FieldInfo Field; public object OriginalValue; public IList List; public bool AssignedNewList; public readonly List Added = new List(); } private struct CodepointRange { public readonly uint First; public readonly uint Last; public CodepointRange(uint first, uint last) { First = first; Last = last; } } private const int SamplingPointSize = 48; private const int AtlasSize = 2048; private const int AtlasPadding = 5; private const int MaxAddedGlyphs = 1200; private const int GlyphRenderModeSdffaa = 4165; private const int GlyphLoadFlagsForSdffaa = 10; private static readonly List _fonts = new List(); private static readonly HashSet _knownCodepoints = new HashSet(); private static readonly HashSet _missingCodepoints = new HashSet(); private static Type _fontAssetType; private static Type _tmpCharacterType; private static Type _fontEngineType; private static Type _glyphRectType; private static Type _glyphRenderModeType; private static Type _glyphPackingModeType; private static Type _glyphLoadFlagsType; private static Type _atlasPopulationModeType; private static Type _shaderUtilitiesType; private static MethodInfo _initializeFontEngine; private static MethodInfo _loadFontFace; private static MethodInfo _getFaceInfo; private static MethodInfo _tryGetGlyph; private static MethodInfo _tryAddGlyphToTexture; private static MethodInfo _readFontAssetDefinition; private static ConstructorInfo _tmpCharacterConstructor; private static bool _installed; private static bool _failureLogged; private static bool _capLogged; private static int _totalAdded; public static bool Ready => _installed && _fonts.Count > 0; public static void Install() { if (_installed) { return; } List list = new List(); List registrations = new List(); try { ResolveReflection(); string text = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); if (string.IsNullOrEmpty(text) || !Directory.Exists(text)) { text = "C:\\Windows\\Fonts"; } string text2 = FindFirstExisting(text, new string[3] { "seguiui.ttf", "arial.ttf", "tahoma.ttf" }); if (text2 == null) { throw new InvalidOperationException("font selection failed: no Latin fallback file found"); } list.Add(BuildFontAsset(text2, GetAssetName(text2))); try { string text3 = FindFirstExisting(text, new string[2] { "seguisym.ttf", "cambria.ttc" }); if (text3 != null && !string.Equals(text3, text2, StringComparison.OrdinalIgnoreCase)) { list.Add(BuildFontAsset(text3, GetAssetName(text3))); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FONT] symbol fallback skipped: " + UnwrapMessage(ex))); } string[][] array = new string[3][] { new string[3] { "msyh.ttc", "msyh.ttf", "simsun.ttc" }, new string[3] { "YuGothM.ttc", "meiryo.ttc", "msgothic.ttc" }, new string[3] { "malgun.ttf", "gulim.ttc", "batang.ttc" } }; List list2 = new List(); for (int i = 0; i < array.Length; i++) { string text4 = FindFirstExisting(text, array[i]); if (text4 == null) { continue; } bool flag = false; for (int j = 0; j < list2.Count; j++) { if (string.Equals(list2[j], text4, StringComparison.OrdinalIgnoreCase)) { flag = true; break; } } if (!flag) { list2.Add(text4); list.Add(BuildFontAsset(text4, GetAssetName(text4))); } } _fonts.AddRange(list); int totalAdded = _totalAdded; AddRanges(new CodepointRange[3] { new CodepointRange(160u, 383u), new CodepointRange(880u, 1023u), new CodepointRange(1024u, 1279u) }); int num = _totalAdded - totalAdded; object obj = FindGameFont(); if (obj == null) { throw new InvalidOperationException("registration failed: game font was not available"); } List list3 = new List(); for (int k = 0; k < _fonts.Count; k++) { list3.Add(_fonts[k].Asset); } RegisterFallbacks(obj, list3, registrations); _installed = true; _failureLogged = false; string[] array2 = new string[_fonts.Count]; string[] array3 = new string[_fonts.Count]; for (int l = 0; l < _fonts.Count; l++) { array2[l] = _fonts[l].Name; array3[l] = Path.GetFileName(_fonts[l].Path); } Plugin.Log.LogInfo((object)("[FONT] fallback ready: " + string.Join(", ", array2) + " (" + num + " glyphs preloaded, source=" + string.Join(",", array3) + ")")); } catch (Exception ex2) { RollBackRegistrations(registrations); _fonts.Clear(); _knownCodepoints.Clear(); _missingCodepoints.Clear(); _totalAdded = 0; DestroyBuiltFonts(list); if (!_failureLogged) { Plugin.Log.LogWarning((object)("[FONT] fallback install failed: " + UnwrapMessage(ex2))); _failureLogged = true; } } } public static void EnsureCharacters(string s) { if (!_installed || string.IsNullOrEmpty(s)) { return; } bool flag = true; for (int i = 0; i < s.Length; i++) { if (s[i] >= '\u0080') { flag = false; break; } } if (flag) { return; } List list = null; try { HashSet hashSet = null; for (int j = 0; j < s.Length; j++) { char c = s[j]; uint num; if (char.IsHighSurrogate(c) && j + 1 < s.Length && char.IsLowSurrogate(s[j + 1])) { num = (uint)char.ConvertToUtf32(c, s[j + 1]); j++; } else { num = c; } if (num >= 128 && !_knownCodepoints.Contains(num) && !_missingCodepoints.Contains(num)) { if (list == null) { list = new List(); hashSet = new HashSet(); } if (hashSet.Add(num)) { list.Add(num); } } } if (list != null) { AddCodepoints(list); } } catch (Exception ex) { if (list != null) { for (int k = 0; k < list.Count; k++) { _missingCodepoints.Add(list[k]); } } Plugin.Log.LogWarning((object)("[FONT] glyph batch failed: " + UnwrapMessage(ex))); } } private static void ResolveReflection() { _fontAssetType = RequireType("TMPro.TMP_FontAsset, Unity.TextMeshPro"); _tmpCharacterType = RequireType("TMPro.TMP_Character, Unity.TextMeshPro"); _atlasPopulationModeType = RequireType("TMPro.AtlasPopulationMode, Unity.TextMeshPro"); _shaderUtilitiesType = RequireType("TMPro.ShaderUtilities, Unity.TextMeshPro"); _fontEngineType = RequireType("UnityEngine.TextCore.LowLevel.FontEngine, UnityEngine.TextCoreFontEngineModule"); _glyphRectType = RequireType("UnityEngine.TextCore.GlyphRect, UnityEngine.TextCoreFontEngineModule"); _glyphRenderModeType = RequireType("UnityEngine.TextCore.LowLevel.GlyphRenderMode, UnityEngine.TextCoreFontEngineModule"); _glyphPackingModeType = RequireType("UnityEngine.TextCore.LowLevel.GlyphPackingMode, UnityEngine.TextCoreFontEngineModule"); _glyphLoadFlagsType = RequireType("UnityEngine.TextCore.LowLevel.GlyphLoadFlags, UnityEngine.TextCoreFontEngineModule"); _initializeFontEngine = RequireMethod(_fontEngineType, "InitializeFontEngine", BindingFlags.Static | BindingFlags.Public, 0); _loadFontFace = FindMethod(_fontEngineType, "LoadFontFace", BindingFlags.Static | BindingFlags.Public, new Type[2] { typeof(string), typeof(int) }); _getFaceInfo = RequireMethod(_fontEngineType, "GetFaceInfo", BindingFlags.Static | BindingFlags.Public, 0); _tryGetGlyph = FindOutMethod(_fontEngineType, "TryGetGlyphWithUnicodeValue", BindingFlags.Static | BindingFlags.Public, 3); _tryAddGlyphToTexture = FindOutMethod(_fontEngineType, "TryAddGlyphToTexture", BindingFlags.Static | BindingFlags.NonPublic, 8); _readFontAssetDefinition = RequireMethod(_fontAssetType, "ReadFontAssetDefinition", BindingFlags.Instance | BindingFlags.Public, 0); Type type = RequireType("UnityEngine.TextCore.Glyph, UnityEngine.TextCoreFontEngineModule"); _tmpCharacterConstructor = _tmpCharacterType.GetConstructor(new Type[3] { typeof(uint), _fontAssetType, type }); if (_loadFontFace == null) { throw new MissingMethodException("FontEngine.LoadFontFace(path,size)"); } if (_tryGetGlyph == null) { throw new MissingMethodException("FontEngine.TryGetGlyphWithUnicodeValue"); } if (_tryAddGlyphToTexture == null) { throw new MissingMethodException("FontEngine.TryAddGlyphToTexture"); } if (_tmpCharacterConstructor == null) { throw new MissingMethodException("TMP_Character(unicode,font,glyph)"); } object obj = _initializeFontEngine.Invoke(null, null); if (Convert.ToInt32(obj) != 0) { throw new InvalidOperationException("font engine initialization returned " + obj); } } private static FontState BuildFontAsset(string path, string assetName) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown EnsureFaceLoaded(path); object obj = ScriptableObject.CreateInstance(_fontAssetType); if (obj == null) { throw new InvalidOperationException("asset creation failed for " + Path.GetFileName(path)); } FontState fontState = new FontState { Path = path, Name = assetName, Asset = obj }; try { ((Object)obj).name = assetName; SetMember(obj, "m_Version", "1.1.0"); SetMember(obj, "faceInfo", _getFaceInfo.Invoke(null, null)); SetMember(obj, "atlasPopulationMode", Enum.ToObject(_atlasPopulationModeType, 0)); SetMember(obj, "atlasWidth", 2048); SetMember(obj, "atlasHeight", 2048); SetMember(obj, "atlasPadding", 5); SetMember(obj, "atlasRenderMode", Enum.ToObject(_glyphRenderModeType, 4165)); SetMember(obj, "isMultiAtlasTexturesEnabled", false); fontState.Texture = new Texture2D(2048, 2048, (TextureFormat)1, false); ((Object)fontState.Texture).name = assetName + " Atlas"; SetMember(obj, "atlasTextures", new Texture2D[1] { fontState.Texture }); object staticMember = GetStaticMember(_shaderUtilitiesType, "ShaderRef_MobileSDF"); Shader val = (Shader)((staticMember is Shader) ? staticMember : null); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("Mobile SDF shader lookup failed"); } fontState.Material = new Material(val); ((Object)fontState.Material).name = assetName + " Material"; fontState.Material.SetTexture(GetShaderId("ID_MainTex"), (Texture)(object)fontState.Texture); fontState.Material.SetFloat(GetShaderId("ID_TextureWidth"), 2048f); fontState.Material.SetFloat(GetShaderId("ID_TextureHeight"), 2048f); fontState.Material.SetFloat(GetShaderId("ID_GradientScale"), 6f); fontState.Material.SetFloat(GetShaderId("ID_WeightNormal"), Convert.ToSingle(GetMember(obj, "normalStyle"))); fontState.Material.SetFloat(GetShaderId("ID_WeightBold"), Convert.ToSingle(GetMember(obj, "boldStyle"))); SetMember(obj, "material", fontState.Material); Type type = typeof(List<>).MakeGenericType(_glyphRectType); fontState.FreeGlyphRects = (IList)Activator.CreateInstance(type); fontState.UsedGlyphRects = (IList)Activator.CreateInstance(type); fontState.FreeGlyphRects.Add(Activator.CreateInstance(_glyphRectType, 0, 0, 2047, 2047)); SetMember(obj, "freeGlyphRects", fontState.FreeGlyphRects); SetMember(obj, "usedGlyphRects", fontState.UsedGlyphRects); _readFontAssetDefinition.Invoke(obj, null); fontState.GlyphTable = GetMember(obj, "glyphTable") as IList; fontState.CharacterTable = GetMember(obj, "characterTable") as IList; if (fontState.GlyphTable == null || fontState.CharacterTable == null) { throw new InvalidOperationException("font tables were not initialized"); } return fontState; } catch { DestroyFont(fontState); throw; } } private static void AddRanges(CodepointRange[] ranges) { List list = new List(); for (int i = 0; i < ranges.Length; i++) { for (uint num = ranges[i].First; num <= ranges[i].Last; num++) { list.Add(num); } } AddCodepoints(list); } private static void AddCodepoints(List requested) { if (requested == null || requested.Count == 0) { return; } List list = new List(); for (int i = 0; i < requested.Count; i++) { uint item = requested[i]; if (!_knownCodepoints.Contains(item) && !_missingCodepoints.Contains(item)) { list.Add(item); } } for (int j = 0; j < _fonts.Count; j++) { if (list.Count <= 0) { break; } FontState fontState = _fonts[j]; EnsureFaceLoaded(fontState.Path); List list2 = new List(); List list3 = new List(); bool flag = false; for (int k = 0; k < list.Count; k++) { uint num = list[k]; if (fontState.AddedCount >= 1200) { list2.Add(num); LogCapOnce(); continue; } try { if (!TryGetGlyph(num, out var _, out var glyphIndex)) { list2.Add(num); continue; } if (fontState.GlyphsByIndex.TryGetValue(glyphIndex, out var value)) { goto IL_0166; } if (!TryPackGlyph(fontState, glyphIndex, out value)) { list2.Add(num); continue; } fontState.GlyphTable.Add(value); fontState.GlyphsByIndex[glyphIndex] = value; goto IL_0166; IL_0166: object value2 = _tmpCharacterConstructor.Invoke(new object[3] { num, fontState.Asset, value }); fontState.CharacterTable.Add(value2); list3.Add(num); fontState.AddedCount++; _totalAdded++; flag = true; } catch { list2.Add(num); } } if (flag) { try { _readFontAssetDefinition.Invoke(fontState.Asset, null); fontState.Texture.Apply(false, false); for (int l = 0; l < list3.Count; l++) { _knownCodepoints.Add(list3[l]); } } catch { for (int m = 0; m < list3.Count; m++) { _missingCodepoints.Add(list3[m]); } } } list = list2; } for (int n = 0; n < list.Count; n++) { _missingCodepoints.Add(list[n]); } } private static bool TryGetGlyph(uint unicode, out object glyph, out uint glyphIndex) { object[] array = new object[3] { unicode, Enum.ToObject(_glyphLoadFlagsType, 10), null }; bool flag = (bool)_tryGetGlyph.Invoke(null, array); glyph = array[2]; glyphIndex = 0u; if (!flag || glyph == null) { return false; } glyphIndex = Convert.ToUInt32(GetMember(glyph, "index")); return glyphIndex != 0; } private static bool TryPackGlyph(FontState state, uint glyphIndex, out object packedGlyph) { if (_tryAddGlyphToTexture.GetParameters().Length != 8) { throw new InvalidOperationException("glyph packer signature changed"); } object[] array = new object[8] { glyphIndex, 5, Enum.ToObject(_glyphPackingModeType, 0), state.FreeGlyphRects, state.UsedGlyphRects, Enum.ToObject(_glyphRenderModeType, 4165), state.Texture, null }; bool flag = (bool)_tryAddGlyphToTexture.Invoke(null, array); packedGlyph = array[7]; return flag && packedGlyph != null; } private static void RegisterFallbacks(object gameFont, List assets, List registrations) { IList orCreateInstanceList = GetOrCreateInstanceList(gameFont, "fallbackFontAssetTable", registrations, required: true); AddAssets(orCreateInstanceList, assets, registrations[registrations.Count - 1]); IList orCreateInstanceList2 = GetOrCreateInstanceList(gameFont, "fallbackFontAssets", registrations, required: false); if (orCreateInstanceList2 != null) { AddAssets(orCreateInstanceList2, assets, registrations[registrations.Count - 1]); } Type type = RequireType("TMPro.TMP_Settings, Unity.TextMeshPro"); PropertyInfo property = type.GetProperty("fallbackFontAssets", BindingFlags.Static | BindingFlags.Public); IList list = ((property == null) ? null : (property.GetValue(null, null) as IList)); ListRegistration listRegistration = null; if (list == null) { PropertyInfo property2 = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((property2 == null) ? null : property2.GetValue(null, null)); if (obj != null) { list = GetOrCreateInstanceList(obj, "m_fallbackFontAssets", registrations, required: true); listRegistration = registrations[registrations.Count - 1]; } } else { listRegistration = new ListRegistration { List = list }; registrations.Add(listRegistration); } if (list == null) { throw new InvalidOperationException("registration failed: TMP settings fallback list unavailable"); } AddAssets(list, assets, listRegistration); } private static IList GetOrCreateInstanceList(object owner, string memberName, List registrations, bool required) { PropertyInfo property = owner.GetType().GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field = owner.GetType().GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((property != null) ? property.GetValue(owner, null) : ((field != null) ? field.GetValue(owner) : null)); IList list = obj as IList; ListRegistration listRegistration = new ListRegistration { Owner = owner, Property = property, Field = field, OriginalValue = obj, List = list }; if (list == null && (property != null || field != null)) { Type type = ((property != null) ? property.PropertyType : field.FieldType); list = Activator.CreateInstance(type) as IList; if (list != null) { if (property != null && property.GetSetMethod(nonPublic: true) != null) { property.SetValue(owner, list, null); } else if (field != null) { field.SetValue(owner, list); } else { list = null; } } listRegistration.List = list; listRegistration.AssignedNewList = list != null; } if (list == null) { if (required) { throw new InvalidOperationException("registration failed: " + memberName + " unavailable"); } return null; } registrations.Add(listRegistration); return list; } private static void AddAssets(IList list, List assets, ListRegistration registration) { for (int i = 0; i < assets.Count; i++) { if (!list.Contains(assets[i])) { list.Add(assets[i]); registration.Added.Add(assets[i]); } } } private static object FindGameFont() { try { FieldInfo field = typeof(UIFactory).GetField("tmpFont", BindingFlags.Static | BindingFlags.NonPublic); object obj = ((field == null) ? null : field.GetValue(null)); if (obj != null && _fontAssetType.IsInstanceOfType(obj)) { return obj; } } catch { } Object[] array = Resources.FindObjectsOfTypeAll(_fontAssetType); object obj3 = null; for (int i = 0; i < array.Length; i++) { if (!(array[i] == (Object)null) && !array[i].name.StartsWith("CR_Fallback_", StringComparison.Ordinal)) { if (obj3 == null) { obj3 = array[i]; } if (array[i].name.StartsWith("Gravity-", StringComparison.OrdinalIgnoreCase)) { return array[i]; } } } return obj3; } private static void EnsureFaceLoaded(string path) { object obj = _loadFontFace.Invoke(null, new object[2] { path, 48 }); if (Convert.ToInt32(obj) != 0) { throw new InvalidOperationException("font face load failed for " + Path.GetFileName(path) + " (error " + obj?.ToString() + ")"); } } private static string FindFirstExisting(string directory, string[] candidates) { for (int i = 0; i < candidates.Length; i++) { string text = Path.Combine(directory, candidates[i]); if (File.Exists(text)) { return text; } } return null; } private static string GetAssetName(string path) { string fileName = Path.GetFileName(path); if (fileName.Equals("seguiui.ttf", StringComparison.OrdinalIgnoreCase)) { return "CR_Fallback_SegoeUI"; } if (fileName.Equals("arial.ttf", StringComparison.OrdinalIgnoreCase)) { return "CR_Fallback_Arial"; } if (fileName.Equals("tahoma.ttf", StringComparison.OrdinalIgnoreCase)) { return "CR_Fallback_Tahoma"; } if (fileName.Equals("msyh.ttc", StringComparison.OrdinalIgnoreCase)) { return "CR_Fallback_MicrosoftYaHei"; } if (fileName.Equals("malgun.ttf", StringComparison.OrdinalIgnoreCase)) { return "CR_Fallback_Malgun"; } if (fileName.Equals("YuGothM.ttc", StringComparison.OrdinalIgnoreCase)) { return "CR_Fallback_YuGothic"; } if (fileName.Equals("meiryo.ttc", StringComparison.OrdinalIgnoreCase)) { return "CR_Fallback_Meiryo"; } if (fileName.Equals("simsun.ttc", StringComparison.OrdinalIgnoreCase)) { return "CR_Fallback_SimSun"; } return "CR_Fallback_" + Path.GetFileNameWithoutExtension(path); } private static int GetShaderId(string fieldName) { FieldInfo field = _shaderUtilitiesType.GetField(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { throw new MissingFieldException("ShaderUtilities." + fieldName); } return Convert.ToInt32(field.GetValue(null)); } private static object GetStaticMember(Type type, string name) { PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(null, null); } FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(null); } throw new MissingMemberException(type.FullName, name); } private static object GetMember(object target, string name) { PropertyInfo property = target.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(target, null); } FieldInfo field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(target); } throw new MissingMemberException(target.GetType().FullName, name); } private static void SetMember(object target, string name, object value) { PropertyInfo property = target.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.GetSetMethod(nonPublic: true) != null) { property.SetValue(target, value, null); return; } FieldInfo field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(target, value); return; } throw new MissingMemberException(target.GetType().FullName, name); } private static Type RequireType(string assemblyQualifiedName) { Type type = Type.GetType(assemblyQualifiedName, throwOnError: false); if (type == null) { throw new TypeLoadException(assemblyQualifiedName); } return type; } private static MethodInfo RequireMethod(Type type, string name, BindingFlags flags, int parameterCount) { MethodInfo methodInfo = FindMethod(type, name, flags, parameterCount); if (methodInfo == null) { throw new MissingMethodException(type.FullName, name); } return methodInfo; } private static MethodInfo FindMethod(Type type, string name, BindingFlags flags, int parameterCount) { MethodInfo[] methods = type.GetMethods(flags); for (int i = 0; i < methods.Length; i++) { if (methods[i].Name == name && methods[i].GetParameters().Length == parameterCount) { return methods[i]; } } return null; } private static MethodInfo FindMethod(Type type, string name, BindingFlags flags, Type[] parameterTypes) { return type.GetMethod(name, flags, null, parameterTypes, null); } private static MethodInfo FindOutMethod(Type type, string name, BindingFlags flags, int parameterCount) { MethodInfo[] methods = type.GetMethods(flags); for (int i = 0; i < methods.Length; i++) { ParameterInfo[] parameters = methods[i].GetParameters(); if (methods[i].Name == name && parameters.Length == parameterCount && parameters[^1].IsOut) { return methods[i]; } } return null; } private static void LogCapOnce() { if (!_capLogged) { _capLogged = true; Plugin.Log.LogWarning((object)("[FONT] a fallback atlas hit its glyph cap (" + 1200 + "); further characters fall through to the next fallback font, and only render as the missing-glyph marker if every atlas is full")); } } private static void RollBackRegistrations(List registrations) { for (int num = registrations.Count - 1; num >= 0; num--) { ListRegistration listRegistration = registrations[num]; try { for (int num2 = listRegistration.Added.Count - 1; num2 >= 0; num2--) { listRegistration.List.Remove(listRegistration.Added[num2]); } if (listRegistration.AssignedNewList) { if (listRegistration.Property != null && listRegistration.Property.GetSetMethod(nonPublic: true) != null) { listRegistration.Property.SetValue(listRegistration.Owner, listRegistration.OriginalValue, null); } else if (listRegistration.Field != null) { listRegistration.Field.SetValue(listRegistration.Owner, listRegistration.OriginalValue); } } } catch { } } } private static void DestroyBuiltFonts(List built) { for (int i = 0; i < built.Count; i++) { DestroyFont(built[i]); } } private static void DestroyFont(FontState state) { if (state == null) { return; } try { if ((Object)(object)state.Material != (Object)null) { Object.Destroy((Object)(object)state.Material); } } catch { } try { if ((Object)(object)state.Texture != (Object)null) { Object.Destroy((Object)(object)state.Texture); } } catch { } try { object asset = state.Asset; Object val = (Object)((asset is Object) ? asset : null); if (val != (Object)null) { Object.Destroy(val); } } catch { } } private static string UnwrapMessage(Exception ex) { while (ex is TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } return ex.Message; } } internal static class VanillaFixSupport { private static readonly object Sync = new object(); private static readonly HashSet AttachedPatches = new HashSet(); private static readonly Dictionary LastErrors = new Dictionary(); private static readonly Dictionary DiagnosticCounts = new Dictionary(); internal static bool GameplayScope() { try { return PhotonNetwork.OfflineMode || CompetitiveRoomDetect.IsCompetitiveRoom(); } catch (Exception exception) { LogError("GameplayScope", exception); return false; } } internal static Exception Cleanup(string name, Exception exception) { try { if (exception != null) { return exception; } bool flag; lock (Sync) { flag = AttachedPatches.Add(name); } if (flag) { Plugin.Log.LogInfo((object)("[VANILLA-FIX] " + name + " attached")); } } catch { } return exception; } internal static void LogError(string name, Exception exception) { try { float realtimeSinceStartup = Time.realtimeSinceStartup; lock (Sync) { if (LastErrors.TryGetValue(name, out var value) && realtimeSinceStartup - value < 5f) { return; } LastErrors[name] = realtimeSinceStartup; } Plugin.Log.LogWarning((object)("[VANILLA-FIX] " + name + " error: " + exception.GetType().Name + ": " + exception.Message)); } catch { } } internal static void DiagLimited(string key, string message, int maximum) { try { bool flag; lock (Sync) { DiagnosticCounts.TryGetValue(key, out var value); flag = value < maximum; if (flag) { DiagnosticCounts[key] = value + 1; } } if (flag) { Plugin.Log.LogInfo((object)("[VANILLA-DIAG] " + message)); } } catch { } } internal static string Float(float value) { return value.ToString("0.000", CultureInfo.InvariantCulture); } internal static string PlayerId(Component component) { try { Player component2 = component.GetComponent(); return ((Object)(object)component2 == (Object)null) ? "unknown" : component2.PlayerID.ToString(CultureInfo.InvariantCulture); } catch { return "unknown"; } } } [HarmonyPatch(typeof(SpawnObjects), "Spawn")] internal static class RadarVisualLifetimePatch { [HarmonyPostfix] private static void AfterSpawn(SpawnObjects __instance) { try { if (VanillaFixSupport.GameplayScope()) { GameObject mostRecentlySpawnedObject = __instance.mostRecentlySpawnedObject; if (!((Object)(object)mostRecentlySpawnedObject == (Object)null) && ((Object)mostRecentlySpawnedObject).name.StartsWith("VE_Radar") && !((Object)(object)mostRecentlySpawnedObject.GetComponent() != (Object)null)) { RemoveAfterSeconds val = mostRecentlySpawnedObject.AddComponent(); val.seconds = 2f; } } } catch { } } } [HarmonyPatch(typeof(Gun), "ResetStats")] internal static class DemonicPactSprayPatch { [HarmonyPostfix] private static void AfterResetStats(Gun __instance) { try { if (VanillaFixSupport.GameplayScope() && __instance.dontAllowAutoFire) { __instance.dontAllowAutoFire = false; VanillaFixSupport.DiagLimited("DemonicPactSpray-cleared", "DemonicPactSpray cleared stale dontAllowAutoFire in Gun.ResetStats", 8); } } catch (Exception exception) { VanillaFixSupport.LogError("DemonicPactSpray", exception); } } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("DemonicPactSpray", exception); } } [HarmonyPatch(typeof(HealthHandler), "DoDamage", new Type[] { typeof(Vector2), typeof(Vector2), typeof(Color), typeof(GameObject), typeof(Player), typeof(bool), typeof(bool), typeof(bool), typeof(DamageSource) })] internal static class PoisonGhostPatch { [HarmonyPrefix] private static void BeforeDoDamage(HealthHandler __instance, Vector2 damage, bool healthRemoval, ref bool ignoreBlock) { try { if (!healthRemoval || !VanillaFixSupport.GameplayScope() || PoisonSync.Authoritative) { return; } try { if (!PhotonNetwork.InRoom || PhotonNetwork.OfflineMode) { return; } } catch { } Block component = ((Component)__instance).GetComponent(); if (!ignoreBlock && (Object)(object)component != (Object)null && component.IsBlocking()) { PhotonView component2 = ((Component)__instance).GetComponent(); VanillaFixSupport.DiagLimited("PoisonGhost-block-window", "PoisonGhost bypassed a later block window player=" + VanillaFixSupport.PlayerId((Component)(object)__instance) + " mine=" + ((Object)(object)component2 != (Object)null && component2.IsMine) + " sinceBlock=" + VanillaFixSupport.Float(component.sinceBlock) + " damage=" + VanillaFixSupport.Float(((Vector2)(ref damage)).magnitude) + " frame=" + Time.frameCount.ToString(CultureInfo.InvariantCulture), 20); } ignoreBlock = true; } catch (Exception exception) { VanillaFixSupport.LogError("PoisonGhost", exception); } } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("PoisonGhost", exception); } } [HarmonyPatch] internal static class DrillVisibilityPatch { [HarmonyPrefix] [HarmonyPatch(typeof(RayHitDrill), "RPCA_Deactivate", new Type[] { typeof(Vector2) })] private static void BeforeDrillDeactivate(RayHitDrill __instance, Vector2 tpPos) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) try { if (!VanillaFixSupport.GameplayScope()) { return; } Transform root = ((Component)__instance).transform.root; if ((Object)(object)root == (Object)null) { return; } PhotonView component = ((Component)root).GetComponent(); if ((Object)(object)component == (Object)null || component.IsMine) { return; } Vector3 position = root.position; float num = Vector2.Distance(new Vector2(position.x, position.y), tpPos); root.position = new Vector3(tpPos.x, tpPos.y, position.z); RayCastTrail component2 = ((Component)root).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.MoveRay(); } TrailRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { componentsInChildren[i].Clear(); } } bool flag = num > 0.001f; VanillaFixSupport.DiagLimited(flag ? "DrillVisibility-root-correction" : "DrillVisibility-root-zero", "DrillVisibility corrected remote root error=" + VanillaFixSupport.Float(num) + " view=" + component.ViewID.ToString(CultureInfo.InvariantCulture) + " frame=" + Time.frameCount.ToString(CultureInfo.InvariantCulture), (!flag) ? 1 : 20); } catch (Exception exception) { VanillaFixSupport.LogError("DrillVisibility.Deactivate", exception); } } [HarmonyPrefix] [HarmonyPatch(typeof(ProjectileHit), "RPCA_DoHit", new Type[] { typeof(Vector2), typeof(Vector2), typeof(Vector2), typeof(int), typeof(int), typeof(bool) })] private static void DiagnoseMissingDrillEffect(ProjectileHit __instance, int viewID, int colliderID) { try { if (viewID != -1 || colliderID < 0 || !VanillaFixSupport.GameplayScope()) { return; } PhotonView component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || component.IsMine) { return; } RayHitDrill[] componentsInChildren = ((Component)__instance).GetComponentsInChildren(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return; } bool flag = __instance.effects == null; if (!flag) { for (int i = 0; i < componentsInChildren.Length; i++) { if (!__instance.effects.Contains((RayHitEffect)(object)componentsInChildren[i])) { flag = true; break; } } } if (flag) { VanillaFixSupport.DiagLimited("DrillVisibility-missing-effect", "DrillVisibility found a Drill child missing from ProjectileHit.effects view=" + component.ViewID.ToString(CultureInfo.InvariantCulture) + " frame=" + Time.frameCount.ToString(CultureInfo.InvariantCulture), 20); } } catch (Exception exception) { VanillaFixSupport.LogError("DrillVisibility.Diagnostic", exception); } } [HarmonyPrefix] [HarmonyPatch(typeof(ChildRPC), "RPCA_RecieveFunction", new Type[] { typeof(string), typeof(Vector2) })] private static void DiagnoseDroppedDrillStop(ChildRPC __instance, string key) { try { if (string.Equals(key, "DrillStop", StringComparison.Ordinal) && VanillaFixSupport.GameplayScope()) { PhotonView component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null) && !component.IsMine && (__instance.childRPCsVector2 == null || !__instance.childRPCsVector2.ContainsKey(key))) { VanillaFixSupport.DiagLimited("DrillVisibility-dropped-stop", "DrillVisibility observed DrillStop before remote handler registration view=" + component.ViewID.ToString(CultureInfo.InvariantCulture) + " frame=" + Time.frameCount.ToString(CultureInfo.InvariantCulture), 20); } } } catch (Exception exception) { VanillaFixSupport.LogError("DrillVisibility.ChildRPCDiagnostic", exception); } } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("DrillVisibility", exception); } } [HarmonyPatch] internal static class ChaseCardTextPatch { [HarmonyPostfix] [HarmonyPatch(typeof(CardChoice), "Awake")] private static void AfterCardChoiceAwake(CardChoice __instance) { try { if (__instance.cards != null) { for (int i = 0; i < __instance.cards.Length; i++) { RemoveHealthRow(__instance.cards[i]); } } } catch (Exception exception) { VanillaFixSupport.LogError("ChaseCardText.CardChoice", exception); } } [HarmonyPrefix] [HarmonyPatch(typeof(CardInfo), "Awake")] private static void BeforeCardInfoAwake(CardInfo __instance) { try { RemoveHealthRow(__instance); } catch (Exception exception) { VanillaFixSupport.LogError("ChaseCardText.CardInfo", exception); } } private static void RemoveHealthRow(CardInfo card) { if ((Object)(object)card == (Object)null || (Object)(object)((Component)card).gameObject == (Object)null) { return; } string a = ((Object)((Component)card).gameObject).name.Replace("(Clone)", "").Trim(); if (!string.Equals(a, "Chase", StringComparison.OrdinalIgnoreCase) || card.cardStats == null || card.cardStats.Length == 0) { return; } List list = new List(card.cardStats.Length); int num = 0; for (int i = 0; i < card.cardStats.Length; i++) { CardInfoStat val = card.cardStats[i]; string a2 = ((val == null || val.stat == null) ? "" : val.stat.Trim()); if (string.Equals(a2, "Health", StringComparison.OrdinalIgnoreCase) || string.Equals(a2, "HP", StringComparison.OrdinalIgnoreCase)) { num++; } else { list.Add(val); } } if (num != 0) { card.cardStats = list.ToArray(); VanillaFixSupport.DiagLimited("ChaseCardText-removed", "ChaseCardText removed_health=" + num.ToString(CultureInfo.InvariantCulture) + " remaining=" + list.Count.ToString(CultureInfo.InvariantCulture), 1); } } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("ChaseCardText", exception); } } [HarmonyPatch] internal static class EndScreenKillPatch { [HarmonyPrefix] [HarmonyPatch(typeof(HealthHandler), "DoDamage", new Type[] { typeof(Vector2), typeof(Vector2), typeof(Color), typeof(GameObject), typeof(Player), typeof(bool), typeof(bool), typeof(bool), typeof(DamageSource) })] private static bool BeforeTransitionDamage(HealthHandler __instance, Vector2 damage, bool healthRemoval) { try { if (!healthRemoval) { return true; } if (!VanillaFixSupport.GameplayScope()) { return true; } if ((Object)(object)GameManager.instance == (Object)null || GameManager.instance.battleOngoing) { return true; } VanillaFixSupport.DiagLimited("EndScreenKill-damage", "EndScreenKill blocked transition DoT player=" + VanillaFixSupport.PlayerId((Component)(object)__instance) + " damage=" + VanillaFixSupport.Float(((Vector2)(ref damage)).magnitude) + " frame=" + Time.frameCount.ToString(CultureInfo.InvariantCulture), 20); return false; } catch (Exception exception) { VanillaFixSupport.LogError("EndScreenKill.DoDamage", exception); return true; } } [HarmonyPrefix] [HarmonyPatch(typeof(GM_ArmsRace), "PlayerDied", new Type[] { typeof(Player), typeof(int) })] private static bool BeforeTransitionPlayerDied(Player killedPlayer) { try { if (!VanillaFixSupport.GameplayScope()) { return true; } if ((Object)(object)GameManager.instance == (Object)null || GameManager.instance.battleOngoing) { return true; } VanillaFixSupport.DiagLimited("EndScreenKill-player-died", "EndScreenKill ignored PlayerDied while battleOngoing=false player=" + VanillaFixSupport.PlayerId((Component)(object)killedPlayer) + " frame=" + Time.frameCount.ToString(CultureInfo.InvariantCulture), 20); return false; } catch (Exception exception) { VanillaFixSupport.LogError("EndScreenKill.PlayerDied", exception); return true; } } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("EndScreenKill", exception); } } [HarmonyPatch(typeof(HealthHandler), "RPCA_SendForceOverTime")] internal static class DeadPlayerForcePatch { [HarmonyPrefix] private static bool BeforeForceOverTime(HealthHandler __instance) { try { if (!VanillaFixSupport.GameplayScope()) { return true; } if ((Object)(object)__instance != (Object)null && !((Component)__instance).gameObject.activeInHierarchy) { VanillaFixSupport.DiagLimited("DeadPlayerForce-skip", "Skipped RPCA_SendForceOverTime on inactive player (post-death knockback)", 4); return false; } } catch (Exception exception) { VanillaFixSupport.LogError("DeadPlayerForce", exception); } return true; } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("DeadPlayerForce", exception); } } [HarmonyPatch(typeof(HealthHandler), "RPCA_SendForceTowardsPointOverTime")] internal static class DeadPlayerForcePointPatch { [HarmonyPrefix] private static bool BeforeForceTowardsPoint(HealthHandler __instance) { try { if (!VanillaFixSupport.GameplayScope()) { return true; } if ((Object)(object)__instance != (Object)null && !((Component)__instance).gameObject.activeInHierarchy) { return false; } } catch (Exception exception) { VanillaFixSupport.LogError("DeadPlayerForcePoint", exception); } return true; } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("DeadPlayerForcePoint", exception); } } [HarmonyPatch(typeof(DamageOverTime), "TakeDamageOverTime")] internal static class DeadPlayerDotPatch { [HarmonyPrefix] private static bool BeforeDotTick(DamageOverTime __instance) { try { if (!VanillaFixSupport.GameplayScope()) { return true; } if ((Object)(object)__instance != (Object)null && !((Component)__instance).gameObject.activeInHierarchy) { return false; } } catch (Exception exception) { VanillaFixSupport.LogError("DeadPlayerDot", exception); } return true; } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("DeadPlayerDot", exception); } } [HarmonyPatch(typeof(CardChoiceVisuals), "Hide")] internal static class InactiveVisualsHidePatch { [HarmonyPrefix] private static bool BeforeHide(CardChoiceVisuals __instance) { try { if (!VanillaFixSupport.GameplayScope()) { return true; } if ((Object)(object)__instance != (Object)null && !((Component)__instance).gameObject.activeInHierarchy) { return false; } } catch (Exception exception) { VanillaFixSupport.LogError("InactiveVisualsHide", exception); } return true; } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("InactiveVisualsHide", exception); } } [HarmonyPatch] internal static class DevConsoleToggleGuardPatch { private static IEnumerable TargetMethods() { List list = new List(); try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { type = assembly.GetType("DevConsole"); } catch { } if (type != null) { break; } } MethodInfo methodInfo = type?.GetMethod("ToggleConsole", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo != null) { list.Add(methodInfo); } else { Plugin.Log.LogWarning((object)"[VANILLA-FIX] DevConsole.ToggleConsole NOT found — our chat's Enter will also toggle the vanilla chat"); } } catch (Exception exception) { VanillaFixSupport.LogError("DevConsoleToggleGuard", exception); } return list; } [HarmonyPrefix] private static bool BeforeToggle() { try { if (CompetitiveUI.IsChatInputOpen && !CompetitiveUI.VanillaChatBoxOnScreen) { return false; } } catch (Exception exception) { VanillaFixSupport.LogError("DevConsoleToggleGuard", exception); } return true; } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("DevConsoleToggleGuard", exception); } } [HarmonyPatch(typeof(CharacterStatModifiers), "DealtDamage")] internal static class FfaDamageDealtTrackerPatch { [HarmonyPostfix] private static void AfterDealtDamage(CharacterStatModifiers __instance, Vector2 damage, bool selfDamage, Player damagedPlayer) { try { if (!selfDamage && !((Object)(object)damagedPlayer == (Object)null) && FfaMode.EngineActive()) { Player val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent() : null); if (!((Object)(object)val == (Object)null)) { FfaMode.RecordDamageDealt(val, damagedPlayer, ((Vector2)(ref damage)).magnitude); } } } catch (Exception exception) { VanillaFixSupport.LogError("FfaDamageDealtTracker", exception); } } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("FfaDamageDealtTracker", exception); } } [HarmonyPatch(typeof(CardChoice), "DoPlayerSelect")] internal static class CardPickChatInputGuardPatch { [HarmonyPrefix] private static bool BeforeDoPlayerSelect() { try { if (CompetitiveUI.AnyChatTyping) { return false; } } catch (Exception exception) { VanillaFixSupport.LogError("CardPickChatInputGuard", exception); } return true; } [HarmonyCleanup] private static Exception Cleanup(MethodBase original, Exception exception) { if (original != null) { return exception; } return VanillaFixSupport.Cleanup("CardPickChatInputGuard", exception); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }