### Coroutine Helpers for Game State Conditions in C# Source: https://context7.com/k073l/locallobby/llms.txt Utility coroutines for waiting on specific game state conditions before executing code, such as waiting for the local player to be ready, network initialization, a specific network singleton to exist, or for an object to become non-null with an optional timeout. These helpers are started using `MelonCoroutines.Start`. ```csharp using LocalLobby.Helpers; using MelonLoader; using System.Collections; // Wait for the local player to be ready before running code IEnumerator MyPlayerRoutine() { // Your code that needs the player to exist Debug.Log($"Player ready: {Player.Local.name}"); yield break; } MelonCoroutines.Start(Utils.WaitForPlayer(MyPlayerRoutine())); // Wait for network (FishNet) to be ready IEnumerator MyNetworkRoutine() { // Your networked code here Debug.Log("Network is ready!"); yield break; } MelonCoroutines.Start(Utils.WaitForNetwork(MyNetworkRoutine())); // Wait for a specific NetworkSingleton to exist MelonCoroutines.Start(Utils.WaitForNetworkSingleton(MyRoutine())); // Wait for an object to become non-null with optional timeout MelonCoroutines.Start(Utils.WaitForNotNull( someObject, timeout: 5.0f, onTimeout: () => Debug.Log("Timed out waiting for object"), onFinish: () => Debug.Log("Object is now available") )); ``` -------------------------------- ### Find Unity Objects and Check Types with Utils Class in C# Source: https://context7.com/k073l/locallobby/llms.txt Utility functions for finding Unity objects by name and type, retrieving all components of a specific type recursively within a GameObject hierarchy, and performing cross-platform type checking between Mono and IL2CPP builds. It also includes a function to get all storable item definitions from the game registry. ```csharp using LocalLobby.Helpers; using UnityEngine; // Find a loaded object by name Sprite mugshot = Utils.FindObjectByName("Dan_Mugshot"); AudioClip clip = Utils.FindObjectByName("explosion_sound"); // Get all components recursively in a GameObject hierarchy List colliders = Utils.GetAllComponentsInChildrenRecursive(someGameObject); List renderers = Utils.GetAllComponentsInChildrenRecursive(rootObject); // Cross-platform type checking (works on both Mono and IL2CPP) if (Utils.Is(someObject, out var definition)) { // definition is now safely cast to StorableItemDefinition Debug.Log($"Found item: {definition.name}"); } // Get all storable item definitions from the game registry List allItems = Utils.GetAllStorableItemDefinitions(); foreach (var item in allItems) { Debug.Log($"Item: {item.name}"); } ``` -------------------------------- ### Launch Game Instances with Command Line Arguments Source: https://context7.com/k073l/locallobby/llms.txt Demonstrates launching 'Schedule I.exe' with various command-line arguments to configure host/client behavior, window adjustments, and save game loading for local lobby testing. ```bash "Schedule I.exe" --host "Schedule I.exe" --client "Schedule I.exe" --join "Schedule I.exe" --host --autoload "Schedule I.exe" --host --saveslot 2 "Schedule I.exe" --host --adjust-window "Schedule I.exe" --host --adjust-window --left-offset 50 ``` -------------------------------- ### Automate Host and Client Launch with Batch Script Source: https://context7.com/k073l/locallobby/llms.txt A batch script to automate the process of launching both host and client instances of 'Schedule I'. It includes steps for creating Goldberg configurations for each instance and setting appropriate window offsets. ```batch @echo off REM Create Goldberg config for host powershell -ExecutionPolicy Bypass -File "createGoldbergConfig.ps1" -Mode host REM Start host instance start "" "Schedule I.exe" --host --adjust-window --left-offset 0 REM Wait for SteamAPI to load (adjust timeout as needed for large modpacks) timeout /t 10 REM Create Goldberg config for client (different SteamID) powershell -ExecutionPolicy Bypass -File "createGoldbergConfig.ps1" -Mode client REM Start client instance start "" "Schedule I.exe" --join --adjust-window --left-offset 20 ``` -------------------------------- ### Parse Command Line Arguments with ArgParser in C# Source: https://context7.com/k073l/locallobby/llms.txt Parses command line arguments for host/client instances and handles window positioning for side-by-side testing. It provides boolean flags for instance type and window adjustment, along with an offset value. Window positioning is handled automatically but can be invoked manually. ```csharp using LocalLobby; using UnityEngine; // Static properties available after ParseArguments() is called bool isHostInstance = ArgParser.IsHost; // true if --host was passed bool isClientInstance = ArgParser.IsClient; // true if --client or --join was passed bool adjustWindow = ArgParser.ShouldSetWindowPositionSize; // true if --adjust-window was passed int leftOffset = ArgParser.LeftOffset; // value from --left-offset (default 0) // Window positioning is handled automatically, but can be called manually ArgParser.SetWindowPositionSize(); // Sets window to half-screen width // Host: positioned at left edge + offset // Client: positioned at center + offset // Both windows use windowed mode at half the work area width ``` -------------------------------- ### Generate Goldberg Steam Emulator Configurations Source: https://context7.com/k073l/locallobby/llms.txt A PowerShell script to create Steam emulator configuration files (`configs.user.ini`) for both host and client instances. It allows for custom SteamIDs and names, ensuring unique identifiers for each emulated game instance. ```powershell # Create host configuration with default values .\createGoldbergConfig.ps1 -Mode host # Output: configs.user.ini with SteamID 76561199320154780 and name "Host" # Create client configuration with default values .\createGoldbergConfig.ps1 -Mode client # Output: configs.user.ini with SteamID 76561199485712034 and name "Client" # Create configuration with custom SteamID and name .\createGoldbergConfig.ps1 -Mode host -SteamId "76561198000000001" -Name "Player1" # Generated config file (Schedule I_Data\Plugins\x86_64\steam_settings\configs.user.ini): # [user::general] # account_name=Player1 # account_steamid=76561198000000001 # language=english ``` -------------------------------- ### Patch Game Settings for Window Positioning (HarmonyLib) Source: https://context7.com/k073l/locallobby/llms.txt A HarmonyLib patch for the `Settings.ApplyDisplaySettings` method. It intercepts display setting application to allow custom window positioning and sizing when running in network testing mode. ```csharp using HarmonyLib; using ScheduleOne.DevUtilities; // Patch prevents game from overriding window position/size when in network testing mode [HarmonyPatch(typeof(Settings), nameof(Settings.ApplyDisplaySettings))] public static class SettingsApplyDisplaySettingsPatch { public static bool Prefix(Settings __instance) { var isNetworkMode = ArgParser.IsHost || ArgParser.IsClient; // Skip original method if we're in network mode with window adjustment enabled if (!isNetworkMode || !ArgParser.ShouldSetWindowPositionSize) return true; // Run original method ArgParser.SetWindowPositionSize(); // Apply our custom window settings return false; // Skip original method } } ``` -------------------------------- ### Convert C# and IL2CPP Collections Source: https://context7.com/k073l/locallobby/llms.txt Provides extension methods for seamless conversion between C# List/IEnumerable and IL2CPP collection types. This is crucial for interoperability when working with IL2CPP builds. ```csharp using LocalLobby.Helpers; using System.Collections.Generic; // Convert C# List to IEnumerable (works on both Mono and IL2CPP) List myList = new List { "a", "b", "c" }; IEnumerable enumerable = myList.AsEnumerable(); #if !MONO // IL2CPP-specific conversions // Convert IEnumerable to IL2CPP List var csharpList = new List { 1, 2, 3 }; Il2CppSystem.Collections.Generic.List il2cppList = csharpList.ToIl2CppList(); // Convert IL2CPP List to C# List List backToCSharp = Il2CppListExtensions.ConvertToList(il2cppList); // Convert IL2CPP List to IEnumerable for LINQ operations Il2CppSystem.Collections.Generic.List il2cppStrings = GetSomeIl2CppList(); foreach (var str in il2cppStrings.AsEnumerable()) { Debug.Log(str); } #endif ``` -------------------------------- ### Debug Logging Extensions for MelonLoader in C# Source: https://context7.com/k073l/locallobby/llms.txt Provides extension methods for MelonLoader's logging system, including support for debug-only logging that is active only in Debug builds. It allows logging messages with or without stack trace information. ```csharp using LocalLobby.Helpers; using MelonLoader; var logger = new MelonLogger.Instance("MyMod"); // Debug logging (only active in Debug builds, no-op in Release) logger.Debug("Variable value: " + someValue); // Output in Debug build: [MyMod] [DEBUG] MyNamespace.MyClass.MyMethod - Variable value: 42 // Debug without stack trace logger.Debug("Simple message", stacktrace: false); // Output: [MyMod] [DEBUG] Simple message ``` -------------------------------- ### LocalLobby C# Mod - Lobby Creation and Joining Source: https://context7.com/k073l/locallobby/llms.txt The main C# class for the LocalLobby mod, handling Steam API initialization, lobby creation for hosts, and lobby joining for clients. It uses file-based communication (`lobby.txt`) to share lobby information between instances. ```csharp using MelonLoader; using Steamworks; // The mod automatically initializes when the game loads // On host: Creates a lobby and writes the lobby ID to UserData/LocalLobby/lobby.txt // On client: Waits for lobby.txt and joins the specified lobby // Lobby creation (called automatically for host instances) public void CreateLobby() { SteamMatchmaking.CreateLobby(ELobbyType.k_ELobbyTypePublic, 2); Callback.Create((Callback.DispatchDelegate)OnLobbyCreated); MelonLogger.Msg("Creating lobby..."); } // Lobby joining coroutine (called automatically for client instances) public IEnumerator WaitForLobbyAndJoin() { // Wait for host to create lobby and write lobby.txt while (!File.Exists(SharedLobbyFile)) { yield return new WaitForSeconds(1f); } var lobbyStr = File.ReadAllText(SharedLobbyFile); if (ulong.TryParse(lobbyStr, out ulong lid)) { _lobbyId = new CSteamID(lid); SteamMatchmaking.JoinLobby(_lobbyId); MelonLogger.Msg("Joining lobby: " + _lobbyId); } } ``` -------------------------------- ### Mute Audio When Window Loses Focus with AudioComponent in C# Source: https://context7.com/k073l/locallobby/llms.txt A Unity component that automatically mutes the game's audio when the application window loses focus, facilitating comfortable side-by-side testing. It's added to a persistent GameObject and monitors `Application.isFocused` to control `AudioListener.volume`. ```csharp using LocalLobby; using UnityEngine; // AudioComponent is automatically added to a persistent GameObject on scene load // It monitors window focus and adjusts audio volume accordingly [RegisterTypeInIl2Cpp] public class AudioComponent : MonoBehaviour { private void Update() { // Mute when window is not focused, unmute when focused var windowFocused = Application.isFocused; AudioListener.volume = windowFocused ? 1 : 0; } } // The component is created automatically in OnSceneWasLoaded: var go = new GameObject("LocalLobbyAudioController"); go.AddComponent(); Object.DontDestroyOnLoad(go); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.