328 lines
10 KiB
C#
328 lines
10 KiB
C#
|
#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":
|
|||
|
{
|
|||
|
// show:0隐藏,非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
|