147 lines
5.2 KiB
C#
147 lines
5.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using UnityEngine;
|
|
|
|
namespace XGame.MiniGame
|
|
{
|
|
// PC 本地端到端烟测入口:连接本地 Gateway,再用 MiniGameHost 下载/加载 rps 小游戏。
|
|
// 挂到任意场景对象后 Play;也可以运行时由 AddComponent 创建。
|
|
public sealed class PcMiniGameSmokeLauncher : MonoBehaviour
|
|
{
|
|
public string GatewayUrl = "ws://127.0.0.1:5005/ws?pid=1";
|
|
public string CdnBase = "";
|
|
public string GameId = "rps";
|
|
public int Version = 1;
|
|
public bool AutoStart;
|
|
|
|
private string _status = "idle";
|
|
private XWebSocket _socket;
|
|
private MiniGameHost _host;
|
|
|
|
private void Start()
|
|
{
|
|
if (AutoStart) StartSmoke();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
_socket?.close();
|
|
_socket = null;
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
GUILayout.BeginArea(new Rect(16, 16, 620, 230), GUI.skin.box);
|
|
GUILayout.Label("PC MiniGame Smoke");
|
|
GUILayout.Label("Status: " + _status);
|
|
GUILayout.Label("Gateway URL");
|
|
GatewayUrl = GUILayout.TextField(GatewayUrl);
|
|
GUILayout.Label("CDN Base");
|
|
CdnBase = GUILayout.TextField(string.IsNullOrEmpty(CdnBase) ? DefaultCdnBase() : CdnBase);
|
|
GUILayout.BeginHorizontal();
|
|
GUILayout.Label("Game", GUILayout.Width(48));
|
|
GameId = GUILayout.TextField(GameId, GUILayout.Width(120));
|
|
GUILayout.Label("Version", GUILayout.Width(56));
|
|
int.TryParse(GUILayout.TextField(Version.ToString(), GUILayout.Width(60)), out Version);
|
|
GUILayout.EndHorizontal();
|
|
if (GUILayout.Button("Start Smoke")) StartSmoke();
|
|
GUILayout.Label("Expected: download rps DLLs -> connect -> MatchFound(+AI) -> snapshots -> RoomEnd.");
|
|
GUILayout.EndArea();
|
|
}
|
|
|
|
public void StartSmoke()
|
|
{
|
|
string gatewayUrl = WithLocalPid(GatewayUrl);
|
|
_status = "connecting " + gatewayUrl;
|
|
_socket?.close();
|
|
_socket = new XWebSocket();
|
|
_socket.Connect(gatewayUrl, (sock, err) =>
|
|
{
|
|
if (!string.IsNullOrEmpty(err) || sock == null)
|
|
{
|
|
_status = "connect failed: " + err;
|
|
Debug.LogError("[PcMiniGameSmoke] " + _status);
|
|
return;
|
|
}
|
|
|
|
_status = "connected, entering " + GameId + " v" + Version;
|
|
Debug.Log("[PcMiniGameSmoke] " + _status);
|
|
_host = gameObject.GetComponent<MiniGameHost>();
|
|
if (_host == null) _host = gameObject.AddComponent<MiniGameHost>();
|
|
_host.EnterGame(ResolvedCdnBase(), GameId, Version, sock);
|
|
});
|
|
}
|
|
|
|
private static string WithLocalPid(string gatewayUrl)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(gatewayUrl))
|
|
{
|
|
return gatewayUrl;
|
|
}
|
|
int pid = GetLocalPlayerId();
|
|
int queryStart = gatewayUrl.IndexOf('?');
|
|
if (queryStart < 0)
|
|
{
|
|
return gatewayUrl + "?pid=" + pid;
|
|
}
|
|
|
|
string head = gatewayUrl.Substring(0, queryStart);
|
|
string query = gatewayUrl.Substring(queryStart + 1);
|
|
string[] parts = query.Split('&');
|
|
bool replaced = false;
|
|
for (int i = 0; i < parts.Length; i++)
|
|
{
|
|
if (parts[i].StartsWith("pid=", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
parts[i] = "pid=" + pid;
|
|
replaced = true;
|
|
break;
|
|
}
|
|
}
|
|
return head + "?" + (replaced ? string.Join("&", parts) : query + "&pid=" + pid);
|
|
}
|
|
|
|
private static int GetLocalPlayerId()
|
|
{
|
|
const string key = "LocalClientId";
|
|
string id = XData.GetString(key, string.Empty);
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
id = SystemInfo.deviceUniqueIdentifier;
|
|
if (string.IsNullOrEmpty(id) || id == "unsupported")
|
|
{
|
|
id = Guid.NewGuid().ToString("N");
|
|
}
|
|
XData.SetString(key, id);
|
|
XData.Save();
|
|
}
|
|
|
|
unchecked
|
|
{
|
|
uint hash = 2166136261u;
|
|
for (int i = 0; i < id.Length; i++)
|
|
{
|
|
hash ^= id[i];
|
|
hash *= 16777619u;
|
|
}
|
|
return (int)(hash % 2000000000u) + 1;
|
|
}
|
|
}
|
|
|
|
private string ResolvedCdnBase()
|
|
{
|
|
return string.IsNullOrEmpty(CdnBase) ? DefaultCdnBase() : CdnBase;
|
|
}
|
|
|
|
private static string DefaultCdnBase()
|
|
{
|
|
// Editor: <repo>/Client/Assets -> <repo>/CDN/minigame/(由 XWorld/生成小游戏更新 菜单产出)
|
|
var assets = new DirectoryInfo(Application.dataPath);
|
|
var client = assets.Parent;
|
|
var repo = client?.Parent;
|
|
string root = repo != null ? repo.FullName : Directory.GetCurrentDirectory();
|
|
return "file:///" + root.Replace('\\', '/') + "/CDN/minigame/";
|
|
}
|
|
}
|
|
}
|