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 |