Static bridge for the lobby UI. Exposes delegates and state that the Razor lobby panel sets and game code (console commands, network events) can call without referencing the generated component type.
using System;
namespace NZombies;
/// <summary>
/// A seam between the lobby panel and anything that wants to drive it.
///
/// ⚠️ Razor components are generated types and are NOT visible from a plain
/// .cs file — referencing LobbyMenu directly fails to compile. Forcing a
/// @namespace onto the razor would fix that, but the scene stores its component
/// by type name, so renaming risks the saved reference no longer resolving.
///
/// Instead the panel publishes a few delegates here on start, and commands call
/// those. No type reference either way, and the panel stays free to change
/// without touching the console commands.
/// </summary>
public static class LobbyState
{
/// <summary>Show or hide the lobby. Set by the panel.</summary>
public static Action<bool> SetOpen;
/// <summary>Set the local player's ready state. Set by the panel.</summary>
public static Action<bool> SetReady;
/// <summary>Leave the lobby and begin — invoked by the host's `NZNet.GameStarting`
/// broadcast on every machine, so nobody decides this locally.</summary>
public static Action StartNow;
/// <summary>Is the lobby currently showing?</summary>
public static Func<bool> IsOpen;
/// <summary>
/// Expand or collapse the Character list inside the lobby. Set by the panel.
///
/// ⚠️ IT IS A SWITCH, SO IT GETS A COMMAND — the project rule, and here it earns it twice
/// over: the list is the only place the twelve characters are visible, and a panel's
/// expand/collapse state is the one thing a screenshot cannot reach from outside the game.
/// </summary>
public static Action<bool> SetCharacterListOpen;
public static bool Available => SetOpen is not null;
/// <summary>
/// Draw the lobby's character stage at all. `nz_lobby_preview`.
/// </summary>
///
/// ⛔ IT EXISTS TO BE MEASURED, NOT TO BE TURNED OFF. Reported as *"the lobby is really laggy
/// for some reason even though the rest of the game is not"* — and the stage is the one thing
/// the lobby does that a round does not: `ScenePanel` renders `Scene.SceneWorld` a SECOND time
/// every frame, from its own camera, with its own two lights and a dressed
/// `SkinnedModelRenderer` per connected player. During a round the panel is `display: none`
/// and costs nothing, which is exactly the shape of the complaint.
///
/// ⚠️ ONE SECOND OF A/B IS WORTH AN HOUR OF READING. `nz_lobby_preview 0`, look at the frame
/// rate, `nz_lobby_preview 1`. If nothing moves, the stage is not the cost and the next
/// suspect is the map still being drawn behind a menu that covers it.
public static bool PreviewStage { get; set; } = true;
/// <summary>
/// Ticks every time the panel's OnUpdate runs.
///
/// ⚠️ EXISTS TO ANSWER ONE QUESTION: does the panel's update loop run at all?
/// If it does not, `Mouse.Visibility` is never set to Visible and the cursor
/// stays locked to the game — and the panel still RENDERS perfectly, because
/// drawing is driven by the panel tree rather than by OnUpdate. A lobby that
/// looks right and ignores every click is exactly what that failure looks
/// like, so "is it 0?" is the first thing to check.
/// </summary>
public static int UpdateTicks;
}