Core/NetworkStorageAutoConfig.cs
using System;
using System.Text.Json;
namespace Sandbox;
public static partial class NetworkStorage
{
private static bool _autoConfigAttempted;
/// <summary>
/// Auto-configure from network-storage.credentials.json.
/// Called automatically on first API use.
/// </summary>
public static void AutoConfigure()
{
if ( _autoConfigAttempted ) return;
_autoConfigAttempted = true;
NetworkStorageBootstrap.CheckEditorOnce();
const string fileName = "network-storage.credentials.json";
string contents = null;
string[] candidates = {
fileName,
$"/{fileName}",
$"Assets/{fileName}",
$"/Assets/{fileName}",
};
foreach ( var path in candidates )
{
if ( FileSystem.Mounted.FileExists( path ) )
{
contents = FileSystem.Mounted.ReadAllText( path );
break;
}
}
if ( string.IsNullOrEmpty( contents ) )
{
// Credentials file not found — try NSConfig constants as fallback.
// The Sync Tool generates a class with hardcoded ProjectId/PublicKey,
// which works on all clients (no filesystem dependency).
if ( TryConfigureFromNSConfig() )
return;
if ( NetworkStorageLogConfig.LogConfig )
Log.Warning( "[NetworkStorage] No network-storage.credentials.json found — run Editor → Network Storage → Setup" );
return;
}
try
{
var json = JsonSerializer.Deserialize<JsonElement>( contents );
var projectId = json.TryGetProperty( "projectId", out var pid ) ? pid.GetString() : null;
var publicKey = json.TryGetProperty( "publicKey", out var pk ) ? pk.GetString() : null;
var baseUrl = json.TryGetProperty( "baseUrl", out var bu ) ? bu.GetString() : null;
var apiVersion = json.TryGetProperty( "apiVersion", out var av ) ? av.GetString() : null;
var cdnUrl = json.TryGetProperty( "cdnUrl", out var cu ) ? cu.GetString() : null;
var publishTarget = json.TryGetProperty( "publishTarget", out var pt ) ? pt.GetString() : null;
// Read proxy setting from credentials — only override when explicitly present.
// ProxyEnabled defaults to false; credentials can explicitly enable it for local multiplayer testing.
if ( json.TryGetProperty( "proxyEnabled", out var pe ) )
ProxyEnabled = pe.GetBoolean();
if ( json.TryGetProperty( "enableAuthSessions", out var eas ) )
EnableAuthSessions = eas.ValueKind == JsonValueKind.True;
if ( json.TryGetProperty( "enableEncryptedRequests", out var eer ) )
EnableEncryptedRequests = eer.ValueKind == JsonValueKind.True;
if ( !string.IsNullOrEmpty( projectId ) && !string.IsNullOrEmpty( publicKey ) )
{
Configure( projectId, publicKey, baseUrl, apiVersion, cdnUrl, publishTarget );
}
else if ( NetworkStorageLogConfig.LogConfig )
{
Log.Warning( "[NetworkStorage] credentials.json missing projectId or publicKey" );
}
}
catch ( Exception ex )
{
if ( NetworkStorageLogConfig.LogConfig )
Log.Warning( $"[NetworkStorage] Failed to parse credentials.json: {ex.Message}" );
}
}
/// <summary>
/// Try to configure from the auto-generated NSConfig class.
/// This provides a fallback when the credentials file isn't available
/// (e.g. non-host multiplayer clients, published games).
/// NSConfig is generated by the Sync Tool with the project's public credentials.
/// </summary>
private static bool TryConfigureFromNSConfig()
{
try
{
var nsConfigType = TypeLibrary.GetType( "NSConfig" );
if ( nsConfigType is null ) return false;
var projectId = nsConfigType.GetStaticValue( "ProjectId" ) as string;
var publicKey = nsConfigType.GetStaticValue( "PublicKey" ) as string;
var baseUrl = nsConfigType.GetStaticValue( "BaseUrl" ) as string;
var apiVersion = nsConfigType.GetStaticValue( "ApiVersion" ) as string;
var publishTarget = nsConfigType.GetStaticValue( "PublishTarget" ) as string;
if ( !string.IsNullOrEmpty( projectId ) && !string.IsNullOrEmpty( publicKey ) )
{
// Read ProxyEnabled from the generated class — this is the authoritative
// runtime source since editor config files are not mounted in game.
var proxyVal = nsConfigType.GetStaticValue( "ProxyEnabled" );
if ( proxyVal is bool proxyBool )
ProxyEnabled = proxyBool;
var authSessionsVal = nsConfigType.GetStaticValue( "EnableAuthSessions" );
if ( authSessionsVal is bool authSessionsBool )
EnableAuthSessions = authSessionsBool;
var encryptedRequestsVal = nsConfigType.GetStaticValue( "EnableEncryptedRequests" );
if ( encryptedRequestsVal is bool encryptedRequestsBool )
EnableEncryptedRequests = encryptedRequestsBool;
Configure( projectId, publicKey, baseUrl, apiVersion, publishTarget: publishTarget );
if ( NetworkStorageLogConfig.LogConfig )
NetLog.Info( "config", $"Configured from NSConfig constants (ProxyEnabled={ProxyEnabled}, PublishTarget={PublishTarget})" );
return true;
}
}
catch
{
// NSConfig may not exist — that's fine, it's optional
}
return false;
}
}