UI换了很多,spine主视觉停用
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -135,7 +135,7 @@ namespace GameServer.Client
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
||||
private static void TriggerStartupLeaveOnce()
|
||||
{
|
||||
if (Instance == null || _startupLeaveScheduled || _startupLeaveCompleted)
|
||||
if (Instance == null || _startupLeaveScheduled || _startupLeaveCompleted || OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -155,10 +155,14 @@ namespace GameServer.Client
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
SceneManager.sceneLoaded += HandleSceneLoaded;
|
||||
OnlineModeSettings.ModeChanged += HandleOnlineModeChanged;
|
||||
if (!_startupSocialConnectStarted)
|
||||
{
|
||||
_startupSocialConnectStarted = true;
|
||||
StartCoroutine(StartupSocialConnectCoroutine());
|
||||
if (!OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
StartCoroutine(StartupSocialConnectCoroutine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +191,7 @@ namespace GameServer.Client
|
||||
_ = _client?.Close();
|
||||
_ = _socialClient?.Close();
|
||||
SceneManager.sceneLoaded -= HandleSceneLoaded;
|
||||
OnlineModeSettings.ModeChanged -= HandleOnlineModeChanged;
|
||||
if (Instance == this)
|
||||
{
|
||||
Instance = null;
|
||||
@@ -275,6 +280,11 @@ namespace GameServer.Client
|
||||
|
||||
private IEnumerator StartupLeaveRoomCoroutine()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
float timeout = Time.realtimeSinceStartup + 8f;
|
||||
while ((NetworkManager.Instance == null || string.IsNullOrWhiteSpace(NetworkManager.Instance.SteamId))
|
||||
&& Time.realtimeSinceStartup < timeout)
|
||||
@@ -297,6 +307,11 @@ namespace GameServer.Client
|
||||
|
||||
private async Task LeaveAnyRoomAtStartupAsync()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_startupLeaveCompleted)
|
||||
{
|
||||
return;
|
||||
@@ -750,6 +765,11 @@ namespace GameServer.Client
|
||||
|
||||
private async Task EnsureConnected()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
throw new InvalidOperationException("Arena online features are disabled in local-only mode.");
|
||||
}
|
||||
|
||||
if (_client != null && _client.IsConnected)
|
||||
{
|
||||
return;
|
||||
@@ -805,6 +825,11 @@ namespace GameServer.Client
|
||||
|
||||
private async Task EnsureSocialConnected()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
throw new InvalidOperationException("Social online features are disabled in local-only mode.");
|
||||
}
|
||||
|
||||
if (_socialClient != null && _socialClient.IsConnected)
|
||||
{
|
||||
return;
|
||||
@@ -3413,6 +3438,11 @@ namespace GameServer.Client
|
||||
|
||||
private IEnumerator StartupSocialConnectCoroutine()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
float timeout = Time.realtimeSinceStartup + 12f;
|
||||
while ((NetworkManager.Instance == null || string.IsNullOrWhiteSpace(NetworkManager.Instance.SteamId))
|
||||
&& Time.realtimeSinceStartup < timeout)
|
||||
@@ -3437,6 +3467,32 @@ namespace GameServer.Client
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleOnlineModeChanged(bool enabled)
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
_manualClose = true;
|
||||
_manualSocialClose = true;
|
||||
_heartbeatCts?.Cancel();
|
||||
_socialHeartbeatCts?.Cancel();
|
||||
StopArenaReconnectLoop();
|
||||
StopSocialReconnectLoop();
|
||||
_ = _client?.Close();
|
||||
_ = _socialClient?.Close();
|
||||
_client = null;
|
||||
_socialClient = null;
|
||||
_isConnecting = false;
|
||||
_isSocialConnecting = false;
|
||||
_joinedSocialRoomCode = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_startupSocialConnectStarted && _socialReconnectCoroutine == null && _socialClient == null && Application.isPlaying)
|
||||
{
|
||||
StartCoroutine(StartupSocialConnectCoroutine());
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshLocalPresenceSilently()
|
||||
{
|
||||
_ = RefreshLocalPresenceSilentlyAsync();
|
||||
@@ -3528,7 +3584,7 @@ namespace GameServer.Client
|
||||
yield break;
|
||||
}
|
||||
|
||||
SongDetailsUI ui = FindAnyObjectByType<SongDetailsUI>();
|
||||
SongDetailsUI ui = SceneObjectLookupCache.FindAny<SongDetailsUI>();
|
||||
if (ui != null)
|
||||
{
|
||||
ui.OpenRoomDetailsForCurrentRoom();
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace GameServer.Client
|
||||
public enum ConnectionState
|
||||
{
|
||||
Disconnected,
|
||||
LocalOnly,
|
||||
Connecting,
|
||||
Handshaking,
|
||||
LoadingProfile,
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
@@ -22,7 +21,7 @@ namespace GameServer.Client
|
||||
{
|
||||
public class NetworkManager : MonoBehaviour
|
||||
{
|
||||
private const bool VerboseLogs = false;
|
||||
private static readonly bool VerboseLogs = false;
|
||||
public static NetworkManager Instance { get; private set; }
|
||||
private static string _startupSteamId = string.Empty;
|
||||
private static string _startupSteamDisplayName = string.Empty;
|
||||
@@ -57,6 +56,7 @@ public class NetworkManager : MonoBehaviour
|
||||
private bool _startupHandshakeStarted;
|
||||
private bool _startupHandshakeCompleted;
|
||||
private Task<string> _avatarUploadTask;
|
||||
private bool _isRefreshingSteamIdentity;
|
||||
|
||||
private struct CachedRemoteIdentity
|
||||
{
|
||||
@@ -69,6 +69,8 @@ public class NetworkManager : MonoBehaviour
|
||||
public bool IsReady => _state == ConnectionState.Ready;
|
||||
public bool IsConnectedAndHandshaked => _state == ConnectionState.Ready;
|
||||
public string ServerUrl => serverUrl;
|
||||
public bool OnlineFeaturesEnabled => OnlineModeSettings.IsOnlineEnabled;
|
||||
public bool IsLocalOnlyMode => OnlineModeSettings.IsLocalOnlyMode;
|
||||
public string SteamId
|
||||
{
|
||||
get
|
||||
@@ -134,12 +136,20 @@ public class NetworkManager : MonoBehaviour
|
||||
}
|
||||
RefreshSteamIdentity(false);
|
||||
CacheIdentity(steamId, steamDisplayName, steamAvatarUrl);
|
||||
OnlineModeSettings.ModeChanged += HandleOnlineModeChanged;
|
||||
ApplyRuntimeModeState();
|
||||
if (VerboseLogs) Debug.Log("[NetworkManager] HTTP lazy mode singleton initialized");
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
RefreshSteamIdentity(false);
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
return;
|
||||
}
|
||||
|
||||
StartCoroutine(StartupHandshakeRoutine());
|
||||
if (VerboseLogs) Debug.Log($"[NetworkManager] Startup handshake enabled. Settlement submit will use {BuildApiUrl("/api/submit")}");
|
||||
}
|
||||
@@ -152,6 +162,7 @@ public class NetworkManager : MonoBehaviour
|
||||
private void OnDestroy()
|
||||
{
|
||||
_requestCts?.Cancel();
|
||||
OnlineModeSettings.ModeChanged -= HandleOnlineModeChanged;
|
||||
if (!_isApplicationQuitting && Instance == this)
|
||||
{
|
||||
Instance = null;
|
||||
@@ -160,6 +171,12 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
return;
|
||||
}
|
||||
|
||||
_requestCts?.Cancel();
|
||||
_requestCts = new CancellationTokenSource();
|
||||
ConnectWithErrorHandling(_requestCts.Token);
|
||||
@@ -178,6 +195,12 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task SendHandshake()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
return;
|
||||
}
|
||||
|
||||
await PerformHandshakeAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
@@ -206,6 +229,11 @@ public class NetworkManager : MonoBehaviour
|
||||
throw new ArgumentException("targetSteamId is empty", nameof(targetSteamId));
|
||||
}
|
||||
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return BuildLocalOnlyProfile(targetSteamId);
|
||||
}
|
||||
|
||||
ProfileData data = await GetJson<ProfileData>(BuildApiUrl($"/api/profile/{targetSteamId}"), CancellationToken.None);
|
||||
CacheIdentity(targetSteamId, data != null ? data.display_name : null, data != null ? data.avatar_url : null);
|
||||
return data;
|
||||
@@ -218,6 +246,16 @@ public class NetworkManager : MonoBehaviour
|
||||
throw new ArgumentOutOfRangeException(nameof(uid), "uid must be positive");
|
||||
}
|
||||
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return new ProfileData
|
||||
{
|
||||
success = false,
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Online profile lookup is unavailable in local-only mode."
|
||||
};
|
||||
}
|
||||
|
||||
ProfileData data = await GetJson<ProfileData>(BuildApiUrl($"/api/players/uid/{uid}"), CancellationToken.None);
|
||||
string identitySteamId = data != null ? data.steam_id : null;
|
||||
CacheIdentity(identitySteamId, data != null ? data.display_name : null, data != null ? data.avatar_url : null);
|
||||
@@ -226,6 +264,18 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task<SteamFriendsImportResponse> ImportSteamFriends(IEnumerable<string> steamFriends)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return new SteamFriendsImportResponse
|
||||
{
|
||||
success = false,
|
||||
added = 0,
|
||||
skipped = 0,
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Steam friend import is unavailable in local-only mode."
|
||||
};
|
||||
}
|
||||
|
||||
var unique = new HashSet<string>(StringComparer.Ordinal);
|
||||
var normalized = new List<string>();
|
||||
if (steamFriends != null)
|
||||
@@ -253,6 +303,19 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task<SocialFriendsApiResponse> GetFriendsList(IEnumerable<string> steamFriends)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return new SocialFriendsApiResponse
|
||||
{
|
||||
success = true,
|
||||
friends = new List<SocialFriendEntry>(),
|
||||
added = 0,
|
||||
skipped = 0,
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Online friends are disabled in local-only mode."
|
||||
};
|
||||
}
|
||||
|
||||
var unique = new HashSet<string>(StringComparer.Ordinal);
|
||||
var normalized = new List<string>();
|
||||
if (steamFriends != null)
|
||||
@@ -294,12 +357,22 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task<MailApiVersionResponse> GetMailVersion()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return BuildLocalOnlyMailVersionResponse();
|
||||
}
|
||||
|
||||
string steamIdQuery = Uri.EscapeDataString(SteamId ?? string.Empty);
|
||||
return await GetJson<MailApiVersionResponse>(BuildApiUrl($"/api/mail/version?steam_id={steamIdQuery}"), CancellationToken.None);
|
||||
}
|
||||
|
||||
public async Task<MailApiListResponse> GetMailList()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return BuildLocalOnlyMailListResponse();
|
||||
}
|
||||
|
||||
string steamIdQuery = Uri.EscapeDataString(SteamId ?? string.Empty);
|
||||
return await GetJson<MailApiListResponse>(BuildApiUrl($"/api/mail/list?steam_id={steamIdQuery}"), CancellationToken.None);
|
||||
}
|
||||
@@ -311,6 +384,18 @@ public class NetworkManager : MonoBehaviour
|
||||
throw new ArgumentOutOfRangeException(nameof(mailId), "mailId must be positive");
|
||||
}
|
||||
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return new MailClaimResponse
|
||||
{
|
||||
success = false,
|
||||
mail_id = mailId,
|
||||
steam_id = SteamId,
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Online mail sync is unavailable in local-only mode."
|
||||
};
|
||||
}
|
||||
|
||||
var req = new MailClaimRequest
|
||||
{
|
||||
steam_id = SteamId,
|
||||
@@ -322,12 +407,24 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public IEnumerator GetMailVersionRoutine(Action<MailApiVersionResponse, Exception> onCompleted)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
onCompleted?.Invoke(BuildLocalOnlyMailVersionResponse(), null);
|
||||
yield break;
|
||||
}
|
||||
|
||||
string steamIdQuery = Uri.EscapeDataString(SteamId ?? string.Empty);
|
||||
yield return GetJsonRoutine(BuildApiUrl($"/api/mail/version?steam_id={steamIdQuery}"), onCompleted);
|
||||
}
|
||||
|
||||
public IEnumerator GetMailListRoutine(Action<MailApiListResponse, Exception> onCompleted)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
onCompleted?.Invoke(BuildLocalOnlyMailListResponse(), null);
|
||||
yield break;
|
||||
}
|
||||
|
||||
string steamIdQuery = Uri.EscapeDataString(SteamId ?? string.Empty);
|
||||
yield return GetJsonRoutine(BuildApiUrl($"/api/mail/list?steam_id={steamIdQuery}"), onCompleted);
|
||||
}
|
||||
@@ -422,6 +519,12 @@ public class NetworkManager : MonoBehaviour
|
||||
int chartScore, int idolScore, long totalScore, string grade,
|
||||
double runtimeSeconds, string playedAt, string hmac = "")
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
return "LOCAL_ONLY";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await PerformHandshakeAsync(CancellationToken.None);
|
||||
@@ -469,6 +572,16 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task<ArenaCreateResponse> CreateArenaRoom(string songId, string difficulty, string password = null)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return new ArenaCreateResponse
|
||||
{
|
||||
success = false,
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Arena rooms are unavailable in local-only mode."
|
||||
};
|
||||
}
|
||||
|
||||
var req = new ArenaCreateRequest
|
||||
{
|
||||
steam_id = SteamId,
|
||||
@@ -483,6 +596,17 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task<ArenaJoinResponse> JoinArenaRoom(string roomCode, string password = null)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return new ArenaJoinResponse
|
||||
{
|
||||
success = false,
|
||||
room_code = roomCode,
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Arena rooms are unavailable in local-only mode."
|
||||
};
|
||||
}
|
||||
|
||||
var req = new ArenaJoinRequest
|
||||
{
|
||||
steam_id = SteamId,
|
||||
@@ -496,6 +620,11 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task StartArenaGame()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
throw CreateLocalOnlyException("Arena gameplay start is unavailable in local-only mode.");
|
||||
}
|
||||
|
||||
var req = new ArenaStartRequest
|
||||
{
|
||||
steam_id = SteamId
|
||||
@@ -509,6 +638,11 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task SubmitArenaScore(string roomCode, long totalScore, string grade)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
throw CreateLocalOnlyException("Arena score submit is unavailable in local-only mode.");
|
||||
}
|
||||
|
||||
var req = new ArenaSubmitRequest
|
||||
{
|
||||
steam_id = SteamId,
|
||||
@@ -529,6 +663,12 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public async Task SendHeartbeat()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
return;
|
||||
}
|
||||
|
||||
HeartbeatResponse resp = await GetJson<HeartbeatResponse>(BuildApiUrl("/api/ping"), CancellationToken.None);
|
||||
if (VerboseLogs) Debug.Log($"[NetworkManager] Ping: {resp.message}");
|
||||
}
|
||||
@@ -540,6 +680,14 @@ public class NetworkManager : MonoBehaviour
|
||||
throw new ArgumentException("songId is required", nameof(songId));
|
||||
}
|
||||
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
LeaderboardData localData = BuildLocalOnlyLeaderboard(songId);
|
||||
OnLeaderboardLoaded?.Invoke(localData);
|
||||
return localData;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SetState(ConnectionState.LoadingLeaderboard);
|
||||
@@ -562,6 +710,11 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
internal Task<LeaderboardData> FetchLeaderboardFromServer(string songId)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
return Task.FromResult(BuildLocalOnlyLeaderboard(songId));
|
||||
}
|
||||
|
||||
return GetJson<LeaderboardData>(BuildApiUrl($"/api/leaderboard/{songId}"), CancellationToken.None);
|
||||
}
|
||||
|
||||
@@ -585,6 +738,19 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
private async Task PerformHandshakeAsync(CancellationToken token)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
OnHandshakeResult?.Invoke(new HandshakeResponse
|
||||
{
|
||||
success = false,
|
||||
steam_id = SteamId,
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Online handshake is disabled in local-only mode."
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
HandshakeRequest req = await PrepareHandshakeRequestAsync(token, true);
|
||||
SetState(ConnectionState.Handshaking);
|
||||
|
||||
@@ -626,6 +792,13 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
private IEnumerator StartupHandshakeRoutine()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
_startupHandshakeStarted = true;
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (_startupHandshakeStarted || _startupHandshakeCompleted)
|
||||
{
|
||||
yield break;
|
||||
@@ -684,36 +857,49 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
public bool RefreshSteamIdentity(bool logWarnings)
|
||||
{
|
||||
bool refreshed = TryReadSteamIdentity(out string currentSteamId, out string currentDisplayName, logWarnings);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(currentSteamId))
|
||||
if (_isRefreshingSteamIdentity)
|
||||
{
|
||||
steamId = currentSteamId;
|
||||
_startupSteamId = currentSteamId;
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(steamId))
|
||||
{
|
||||
steamId = _startupSteamId;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsUsableDisplayName(currentDisplayName, steamId))
|
||||
_isRefreshingSteamIdentity = true;
|
||||
try
|
||||
{
|
||||
steamDisplayName = currentDisplayName;
|
||||
_startupSteamDisplayName = currentDisplayName;
|
||||
bool refreshed = TryReadSteamIdentity(out string currentSteamId, out string currentDisplayName, logWarnings);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(currentSteamId))
|
||||
{
|
||||
steamId = currentSteamId;
|
||||
_startupSteamId = currentSteamId;
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(steamId))
|
||||
{
|
||||
steamId = _startupSteamId;
|
||||
}
|
||||
|
||||
if (IsUsableDisplayName(currentDisplayName, steamId))
|
||||
{
|
||||
steamDisplayName = currentDisplayName;
|
||||
_startupSteamDisplayName = currentDisplayName;
|
||||
}
|
||||
else if (!IsUsableDisplayName(steamDisplayName, steamId))
|
||||
{
|
||||
steamDisplayName = ResolveDisplayName(_startupSteamDisplayName, steamId, false);
|
||||
}
|
||||
|
||||
if (!IsUsableAvatarUrl(steamAvatarUrl))
|
||||
{
|
||||
steamAvatarUrl = BuildSteamAvatarUrl(steamId);
|
||||
}
|
||||
|
||||
CacheIdentity(steamId, steamDisplayName, steamAvatarUrl);
|
||||
|
||||
return refreshed;
|
||||
}
|
||||
else if (!IsUsableDisplayName(steamDisplayName, steamId))
|
||||
finally
|
||||
{
|
||||
steamDisplayName = ResolveDisplayName(_startupSteamDisplayName, steamId, false);
|
||||
_isRefreshingSteamIdentity = false;
|
||||
}
|
||||
|
||||
if (!IsUsableAvatarUrl(steamAvatarUrl))
|
||||
{
|
||||
steamAvatarUrl = BuildSteamAvatarUrl(steamId);
|
||||
}
|
||||
|
||||
CacheIdentity(steamId, steamDisplayName, steamAvatarUrl);
|
||||
|
||||
return refreshed;
|
||||
}
|
||||
|
||||
private async Task<string> EnsureAvatarUploadedAsync(CancellationToken token)
|
||||
@@ -780,11 +966,12 @@ public class NetworkManager : MonoBehaviour
|
||||
NetworkManager instance = Instance;
|
||||
if (instance != null)
|
||||
{
|
||||
instance.RefreshSteamIdentity(false);
|
||||
if (string.Equals(instance.steamId, normalizedSteamId, StringComparison.Ordinal)
|
||||
&& IsUsableDisplayName(instance.steamDisplayName, normalizedSteamId))
|
||||
string instanceSteamId = instance.steamId;
|
||||
string instanceDisplayName = instance.steamDisplayName;
|
||||
if (string.Equals(instanceSteamId, normalizedSteamId, StringComparison.Ordinal)
|
||||
&& IsUsableDisplayName(instanceDisplayName, normalizedSteamId))
|
||||
{
|
||||
return instance.steamDisplayName.Trim();
|
||||
return instanceDisplayName.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,6 +1425,11 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
private async Task<AvatarUploadResponse> UploadAvatarAsync(string targetSteamId, byte[] avatarBytes, CancellationToken token)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
throw CreateLocalOnlyException("Avatar upload is disabled in local-only mode.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(targetSteamId))
|
||||
{
|
||||
throw new ArgumentException("targetSteamId is empty", nameof(targetSteamId));
|
||||
@@ -1277,6 +1469,11 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
private async Task<T> PostJson<T>(string url, object payload, CancellationToken token)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
throw CreateLocalOnlyException($"HTTP POST is disabled in local-only mode. url={url}");
|
||||
}
|
||||
|
||||
string json = JsonConvert.SerializeObject(payload);
|
||||
using (UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST))
|
||||
{
|
||||
@@ -1308,6 +1505,11 @@ public class NetworkManager : MonoBehaviour
|
||||
|
||||
private async Task<T> GetJson<T>(string url, CancellationToken token)
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
throw CreateLocalOnlyException($"HTTP GET is disabled in local-only mode. url={url}");
|
||||
}
|
||||
|
||||
using (UnityWebRequest request = UnityWebRequest.Get(url))
|
||||
{
|
||||
request.timeout = 15;
|
||||
@@ -1331,6 +1533,89 @@ public class NetworkManager : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleOnlineModeChanged(bool enabled)
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
_requestCts?.Cancel();
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_state == ConnectionState.LocalOnly)
|
||||
{
|
||||
SetState(ConnectionState.Disconnected);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyRuntimeModeState()
|
||||
{
|
||||
if (OnlineModeSettings.IsLocalOnlyMode)
|
||||
{
|
||||
SetState(ConnectionState.LocalOnly);
|
||||
}
|
||||
}
|
||||
|
||||
private static Exception CreateLocalOnlyException(string message)
|
||||
{
|
||||
return new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
private ProfileData BuildLocalOnlyProfile(string targetSteamId)
|
||||
{
|
||||
string normalizedSteamId = string.IsNullOrWhiteSpace(targetSteamId) ? string.Empty : targetSteamId.Trim();
|
||||
bool isSelf = string.Equals(normalizedSteamId, SteamId, StringComparison.Ordinal);
|
||||
string displayName = ResolveDisplayName(string.Empty, normalizedSteamId, false);
|
||||
string avatarUrl = ResolveAvatarUrl(null, normalizedSteamId);
|
||||
|
||||
return new ProfileData
|
||||
{
|
||||
success = isSelf,
|
||||
error_code = isSelf ? null : "LOCAL_ONLY_MODE",
|
||||
message = isSelf ? "Loaded local profile in local-only mode." : "Remote profiles are unavailable in local-only mode.",
|
||||
steam_id = normalizedSteamId,
|
||||
display_name = displayName,
|
||||
avatar_url = avatarUrl
|
||||
};
|
||||
}
|
||||
|
||||
private static MailApiVersionResponse BuildLocalOnlyMailVersionResponse()
|
||||
{
|
||||
return new MailApiVersionResponse
|
||||
{
|
||||
success = true,
|
||||
revision = "local-only",
|
||||
count = 0,
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Server mail is disabled in local-only mode."
|
||||
};
|
||||
}
|
||||
|
||||
private static MailApiListResponse BuildLocalOnlyMailListResponse()
|
||||
{
|
||||
return new MailApiListResponse
|
||||
{
|
||||
success = true,
|
||||
revision = "local-only",
|
||||
count = 0,
|
||||
mails = new List<MailApiEntry>(),
|
||||
deletions = new List<MailApiDeletionEntry>(),
|
||||
error_code = "LOCAL_ONLY_MODE",
|
||||
message = "Server mail is disabled in local-only mode."
|
||||
};
|
||||
}
|
||||
|
||||
private static LeaderboardData BuildLocalOnlyLeaderboard(string songId)
|
||||
{
|
||||
return new LeaderboardData
|
||||
{
|
||||
song_id = songId,
|
||||
cycle_id = 0,
|
||||
is_locked = false,
|
||||
rankings = new List<LeaderboardEntry>()
|
||||
};
|
||||
}
|
||||
|
||||
private IEnumerator GetJsonRoutine<T>(string url, Action<T, Exception> onCompleted)
|
||||
{
|
||||
using (UnityWebRequest request = UnityWebRequest.Get(url))
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameServer.Client
|
||||
{
|
||||
public static class OnlineModeSettings
|
||||
{
|
||||
public const string PlayerPrefsKey = "bansonic_online_enabled";
|
||||
private const int DefaultOnlineEnabled = 1;
|
||||
private static bool _initialized;
|
||||
|
||||
public static event Action<bool> ModeChanged;
|
||||
|
||||
public static bool IsOnlineEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureInitialized();
|
||||
return PlayerPrefs.GetInt(PlayerPrefsKey, DefaultOnlineEnabled) != 0;
|
||||
}
|
||||
set => SetOnlineEnabled(value);
|
||||
}
|
||||
|
||||
public static bool IsLocalOnlyMode => !IsOnlineEnabled;
|
||||
|
||||
public static void SetOnlineEnabled(bool enabled)
|
||||
{
|
||||
EnsureInitialized();
|
||||
bool previous = IsOnlineEnabled;
|
||||
int persistedValue = enabled ? 1 : 0;
|
||||
if (PlayerPrefs.GetInt(PlayerPrefsKey, DefaultOnlineEnabled) == persistedValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerPrefs.SetInt(PlayerPrefsKey, persistedValue);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
if (previous != enabled)
|
||||
{
|
||||
ModeChanged?.Invoke(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureInitialized()
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
if (!PlayerPrefs.HasKey(PlayerPrefsKey))
|
||||
{
|
||||
PlayerPrefs.SetInt(PlayerPrefsKey, DefaultOnlineEnabled);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a38c03061babdb24b9208ec991bde237
|
||||
@@ -42,7 +42,7 @@ namespace GameServer.Client
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
// 跳过系统代理
|
||||
_ws.Options.Proxy = GlobalProxySelection.GetEmptyWebProxy();
|
||||
_ws.Options.Proxy = null;
|
||||
_ws.Options.KeepAliveInterval = TimeSpan.FromSeconds(20);
|
||||
|
||||
try
|
||||
@@ -205,4 +205,4 @@ namespace GameServer.Client
|
||||
_ws?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user