2025-01-25 04:38:09 +08:00

328 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if UNITY_STANDALONE_WIN
using AOT;
using BestHTTP.WebSocket;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Gonbest.MagicCube;
//QQ大厅运行时
public class QQGameRunTime : MonoBehaviour
{
//启动脚本
public static void RunScript()
{
if (IsStarted)
{
return;
}
var go = GameObject.Find("[QQGameRunTime]");
if (go == null)
{
go = new GameObject("[QQGameRunTime]");
GameObject.DontDestroyOnLoad(go);
}
var script = go.GetComponent<QQGameRunTime>();
if (script == null)
{
script = go.AddComponent<QQGameRunTime>();
}
go.SetActive(true);
script.enabled = true;
WebSocketIsOpen = false;
IsStarted = true;
}
//是否已经启动
public static bool IsStarted = false;
//是否连接成功
public static bool WebSocketIsOpen = false;
#region//私有变量
//启动命令行参数
private Dictionary<string, string> _commandlines = null;
//json版本的命令行
private string _commandlinesJson = null;
//qq大厅连接
private WebSocket _webSocket = null;
//当前窗口句柄
private IntPtr _curHwnd = IntPtr.Zero;
#endregion
#region//属性
#endregion
#region//脚本函数
private void Awake()
{
//获取命令行参数
_commandlines = new Dictionary<string, string>();
UnityEngine.Debug.LogErrorFormat("QQ大厅启动命令行参数 {0}", Environment.CommandLine);
var commandLineArgs = Environment.GetCommandLineArgs();
for (int i = 0; i < commandLineArgs.Length; ++i)
{
var comline = commandLineArgs[i];
var firstIndex = comline.IndexOf('=');
if (firstIndex <= 0)
{
continue;
}
var key = comline.Substring(0, firstIndex).Trim();
var value = comline.Substring(firstIndex + 1).Trim();
_commandlines[key] = value;
}
//判断参数是否足够
string _openId = string.Empty;
string _pfKey = string.Empty;
string _openKey = string.Empty;
string _port = string.Empty;
if (!_commandlines.TryGetValue("id", out _openId) ||
!_commandlines.TryGetValue("pfkey", out _pfKey) ||
!_commandlines.TryGetValue("key", out _openKey) ||
!_commandlines.TryGetValue("port", out _port)
)
{
//大厅参数不正确,直接退出
UnityEngine.Debug.LogError("大厅参数不正确,直接退出");
ReqExitGame();
return;
}
_commandlinesJson = BestHTTP.JSON.Json.Encode(_commandlines);
//启动websocket
string url = string.Format("ws://localhost:{0}/websocket/{1}", _port, _openId);
UnityEngine.Debug.LogErrorFormat("开始连接QQ大厅 url = {0}", url);
_webSocket = new WebSocket(new Uri(url));
_webSocket.OnOpen += OnQQGameOpen;
_webSocket.OnMessage += OnQQGameMsgReceived;
_webSocket.OnError += OnQQGameError;
_webSocket.OnClosed += OnQQGameClosed;
_webSocket.Open();
EventManager.SharedInstance.RegFixEventHandle(CoreEventDefine.EID_CORE_LOGIC_TO_QQGAME, OnLogicMsg);
}
private void OnDestroy()
{
if (_webSocket != null)
{
if (_webSocket.IsOpen)
{
_webSocket.Close();
}
_webSocket.OnOpen = null;
_webSocket.OnMessage = null;
_webSocket.OnError = null;
_webSocket.OnClosed = null;
}
_webSocket = null;
}
#endregion
#region//公有函数
#endregion
#region//私有函数
private void OnLogicMsg(object obj, object sender)
{
var cmdId = (int)obj;
//0获取命令行参数1发送消息给大厅
switch(cmdId)
{
case 0:
{
EventManager.SharedInstance.PushFixEvent(CoreEventDefine.EID_CORE_QQGAME_TO_LOGIC, 0, _commandlinesJson);
}
break;
case 1:
{
var msgText = obj as string;
if (string.IsNullOrEmpty(msgText))
{
return;
}
SendQQGameMsg(msgText);
}
break;
}
}
private void SendQQGameMsg(string cmd)
{
if (_webSocket != null && _webSocket.IsOpen)
{
_webSocket.Send(cmd);
}
else
{
UnityEngine.Debug.LogError("连接已断开,消息发送失败!直接退出游戏");
ReqExitGame();
}
}
private void OnQQGameOpen(WebSocket ws)
{
WebSocketIsOpen = true;
UnityEngine.Debug.LogError("QQ大厅连接成功");
}
private void OnQQGameMsgReceived(WebSocket ws, string message)
{
UnityEngine.Debug.Log("收到大厅消息:" + message);
if (!string.IsNullOrEmpty(message))
{
JSONNode node = JSONClass.Parse(message);
string cmd = node["cmd"];
switch (cmd)
{
//游戏侧跟进参数show显示或隐藏游戏界面
case "boss_key":
{
// show0隐藏非0显示
int show = node["show"].AsInt;
if (_curHwnd != IntPtr.Zero)
{
if (show != 0)
{
//显示窗口
ShowWindow(_curHwnd, 9);
//前置窗口
SetForegroundWindow(_curHwnd);
}
else
{
//隐藏窗口
ShowWindow(_curHwnd, 0);
}
}
}
break;
//游戏收到该消息后,前置显示界面
case "bring_to_top":
{
if (_curHwnd != IntPtr.Zero)
{
SetForegroundWindow(_curHwnd);
}
}
break;
//open_web请求的页面关闭时通知游戏。
case "web_close":
break;
//支付页关闭时,通知游戏
case "pay_close":
break;
//购买蓝钻页面关闭,游戏需刷新蓝钻信息
case "buy_vip_close":
break;
}
//0命令行参数1qq大厅消息
EventManager.SharedInstance.PushFixEvent(CoreEventDefine.EID_CORE_QQGAME_TO_LOGIC, 1, message);
}
}
private void OnQQGameError(WebSocket ws, Exception ex)
{
if (ws.InternalRequest.Response != null)
{
UnityEngine.Debug.LogErrorFormat("QQ大厅连接错误 code = {0} msg = {1}", ws.InternalRequest.Response.StatusCode, ws.InternalRequest.Response.Message);
}
ReqExitGame();
}
private void OnQQGameClosed(WebSocket ws, UInt16 code, string message)
{
UnityEngine.Debug.LogErrorFormat("QQ大厅连接关闭msg = {0}", message);
ReqExitGame();
}
private void ReqExitGame()
{
AppPersistData.WantExitResult = true;
Application.Quit();
}
#endregion
#region
private void Start()
{
//获取当前窗口句柄
_curHwnd = GetProcessWnd();
if (_curHwnd == IntPtr.Zero)
{
UnityEngine.Debug.LogError("获取窗口句柄失败");
}
}
//隐藏或显示窗口
private void OnShowOrHideWindows(object obj, object sender)
{
if (_curHwnd == IntPtr.Zero)
{
return;
}
var isShow = (bool)obj;
if (isShow)
{
//显示窗口
ShowWindow(_curHwnd, 9);
//前置窗口
SetForegroundWindow(_curHwnd);
}
else
{
//隐藏窗口
ShowWindow(_curHwnd, 0);
}
}
//前置窗口
private void OnForegrounWindows(object obj, object sender)
{
if (_curHwnd == IntPtr.Zero)
{
return;
}
SetForegroundWindow(_curHwnd);
}
#endregion
#region//windows函数
public delegate bool WNDENUMPROC(IntPtr hwnd, uint lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, uint lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint lpdwProcessId);
[DllImport("kernel32.dll")]
public static extern void SetLastError(uint dwErrCode);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);//设置此窗体为活动窗体
[DllImport("User32.dll")]
//返回值:如果窗口原来可见,返回值为非零;如果函数原来被隐藏,返回值为零。
private static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
static IntPtr findeHwnd = IntPtr.Zero;
[MonoPInvokeCallback(typeof(WNDENUMPROC))]
static bool OnWindowEnum(IntPtr hwnd, uint lParam)
{
uint id = 0;
if (GetParent(hwnd) == IntPtr.Zero)
{
GetWindowThreadProcessId(hwnd, ref id);
if (id == lParam) // 找到进程对应的主窗口句柄
{
findeHwnd = hwnd; // 把句柄缓存起来
SetLastError(0); // 设置无错误
return false; // 返回 false 以终止枚举窗口
}
}
return true;
}
public static IntPtr GetProcessWnd()
{
IntPtr ptrWnd = IntPtr.Zero;
uint pid = (uint)Process.GetCurrentProcess().Id; // 当前进程 ID
bool bResult = EnumWindows(OnWindowEnum, pid);
ptrWnd = findeHwnd;
return (!bResult && Marshal.GetLastWin32Error() == 0) ? ptrWnd : IntPtr.Zero;
}
#endregion
}
#endif