Core/NetworkStorageRevisionHandler.cs
using System;

namespace Sandbox;

/// <summary>
/// Wires <see cref="NetworkStoragePackageInfo.OnRevisionStatusChanged"/> to concrete actions
/// based on <see cref="NetworkStorage.RevisionSettings"/> configuration.
/// Call <see cref="Initialize"/> once during game startup.
/// </summary>
public static class NetworkStorageRevisionHandler
{
	/// <summary>
	/// Set when <see cref="NetworkStorage.RevisionSettings"/> has block-saves
	/// enabled and the client is running an outdated revision.
	/// Endpoint code MUST check this flag before performing write operations.
	/// </summary>
	public static bool BlockWrites { get; private set; }

	/// <summary>
	/// Game code can assign a handler to receive revision warnings.
	/// Useful for showing custom in-game UI when the built-in console logging is not enough.
	/// </summary>
	public static Action<RevisionStatusInfo> OnShowRevisionWarning;

	private static bool _initialized;

	/// <summary>
	/// Subscribe to revision status change events. Safe to call multiple times —
	/// subsequent calls are no-ops.
	/// </summary>
	public static void Initialize()
	{
		if ( _initialized )
			return;

		_initialized = true;
		NetworkStoragePackageInfo.OnRevisionStatusChanged += HandleRevisionStatusChanged;
	}

	private static void HandleRevisionStatusChanged( RevisionStatusInfo info )
	{
		if ( !info.IsOutdated )
		{
			// Revision is current — clear any stale test/outdated state.
			BlockWrites = false;
			NetworkStorageOutdatedUI.Close();
			return;
		}

		var settings = NetworkStorage.RevisionSettings;
		var showDefaultMessage = settings.ShowDefaultMessage && NetworkStoragePackageInfo.PolicyShowDefaultMessage;

		if ( !showDefaultMessage )
		{
			NetworkStorageOutdatedUI.Close();
		}

		if ( settings.Enabled && showDefaultMessage )
		{
			ShowWarningUI( info );
			OnShowRevisionWarning?.Invoke( info );
		}

		// Show the built-in default UI panel when configured
		if ( settings.Enabled && settings.AutoOpenOnOutdated && showDefaultMessage )
		{
			NetworkStorageOutdatedUI.Open();
		}

		if ( settings.Enabled && settings.AutoRefreshLobbies )
		{
			_ = NetworkStorage.RefreshRevisionLobbyListAsync();
		}

		if ( NetworkStorageRevisionConfig.EnableAutoDisconnectHost && info.GraceExpired )
		{
			Log.Warning( $"[NetworkStorage] Auto-disconnecting: revision grace period expired. {info.Message}" );
			Game.Disconnect();
			return;
		}

		if ( NetworkStorageRevisionConfig.EnableBlockSavesOnOutdated )
		{
			BlockWrites = true;
			Log.Warning( $"[NetworkStorage] Revision is outdated — writes are now blocked. {info.Message}" );
		}
	}

	private static void ShowWarningUI( RevisionStatusInfo info )
	{
		Log.Warning( "╔══════════════════════════════════════════════════════╗" );
		Log.Warning( "║ OUTDATED REVISION                                   ║" );
		Log.Warning( $"║ {(info.Message ?? "").PadRight( 50 )}║" );
		Log.Warning( "╚══════════════════════════════════════════════════════╝" );
	}
}