Ignore AIClient/Library and AIClient/HybridCLRData permanently; include HybridCLR/YooAsset project setup and UI tooling. Co-authored-by: Cursor <cursoragent@cursor.com>
125 lines
4.6 KiB
C#
125 lines
4.6 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
using UnityEngine.Networking;
|
|
|
|
namespace HotUpdate.Net
|
|
{
|
|
/// <summary>
|
|
/// 游戏服 HTTP 鉴权:POST /register、POST /login → {token,pid}
|
|
/// </summary>
|
|
public static class AuthApi
|
|
{
|
|
public const string DefaultHttpBase = "https://game.xworld.ren";
|
|
|
|
[Serializable]
|
|
class AuthBody
|
|
{
|
|
public string username;
|
|
public string password;
|
|
}
|
|
|
|
public static IEnumerator Register(string httpBase, string username, string password, Action<AuthResponse, string> onDone)
|
|
{
|
|
yield return PostJson(httpBase, "/register", username, password, onDone);
|
|
}
|
|
|
|
public static IEnumerator Login(string httpBase, string username, string password, Action<AuthResponse, string> onDone)
|
|
{
|
|
yield return PostJson(httpBase, "/login", username, password, onDone);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 优先登录;失败则注册再登录(编辑器/游客自动账号)。
|
|
/// </summary>
|
|
public static IEnumerator EnsureAccount(string httpBase, string username, string password, Action<AuthResponse, string> onDone)
|
|
{
|
|
AuthResponse loginOk = null;
|
|
string loginErr = null;
|
|
yield return Login(httpBase, username, password, (r, e) => { loginOk = r; loginErr = e; });
|
|
if (loginOk != null && !string.IsNullOrEmpty(loginOk.token))
|
|
{
|
|
onDone?.Invoke(loginOk, null);
|
|
yield break;
|
|
}
|
|
|
|
AuthResponse regOk = null;
|
|
string regErr = null;
|
|
yield return Register(httpBase, username, password, (r, e) => { regOk = r; regErr = e; });
|
|
if (regOk != null && !string.IsNullOrEmpty(regOk.token))
|
|
{
|
|
onDone?.Invoke(regOk, null);
|
|
yield break;
|
|
}
|
|
|
|
// 注册失败(例如已存在)再登录一次
|
|
AuthResponse login2 = null;
|
|
string login2Err = null;
|
|
yield return Login(httpBase, username, password, (r, e) => { login2 = r; login2Err = e; });
|
|
if (login2 != null && !string.IsNullOrEmpty(login2.token))
|
|
{
|
|
onDone?.Invoke(login2, null);
|
|
yield break;
|
|
}
|
|
|
|
onDone?.Invoke(null, $"auth failed login={loginErr}|{login2Err} register={regErr}");
|
|
}
|
|
|
|
static IEnumerator PostJson(string httpBase, string path, string username, string password, Action<AuthResponse, string> onDone)
|
|
{
|
|
var url = (httpBase ?? DefaultHttpBase).TrimEnd('/') + path;
|
|
var body = JsonUtility.ToJson(new AuthBody { username = username, password = password });
|
|
var bytes = Encoding.UTF8.GetBytes(body);
|
|
|
|
using (var req = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST))
|
|
{
|
|
req.uploadHandler = new UploadHandlerRaw(bytes);
|
|
req.downloadHandler = new DownloadHandlerBuffer();
|
|
req.SetRequestHeader("Content-Type", "application/json");
|
|
req.timeout = 15;
|
|
yield return req.SendWebRequest();
|
|
|
|
#if UNITY_2020_2_OR_NEWER
|
|
bool failed = req.result != UnityWebRequest.Result.Success;
|
|
#else
|
|
bool failed = req.isNetworkError || req.isHttpError;
|
|
#endif
|
|
var text = req.downloadHandler?.text;
|
|
if (failed)
|
|
{
|
|
string err = req.error;
|
|
if (!string.IsNullOrEmpty(text))
|
|
{
|
|
try
|
|
{
|
|
var ae = JsonUtility.FromJson<AuthError>(text);
|
|
if (!string.IsNullOrEmpty(ae?.error))
|
|
err = ae.error;
|
|
}
|
|
catch { /* ignore */ }
|
|
}
|
|
onDone?.Invoke(null, $"{(int)req.responseCode} {err}");
|
|
yield break;
|
|
}
|
|
|
|
AuthResponse resp = null;
|
|
try { resp = JsonUtility.FromJson<AuthResponse>(text); }
|
|
catch (Exception e)
|
|
{
|
|
onDone?.Invoke(null, $"parse auth: {e.Message}");
|
|
yield break;
|
|
}
|
|
|
|
if (resp == null || string.IsNullOrEmpty(resp.token))
|
|
{
|
|
onDone?.Invoke(null, "auth response missing token");
|
|
yield break;
|
|
}
|
|
|
|
onDone?.Invoke(resp, null);
|
|
}
|
|
}
|
|
}
|
|
}
|