603 lines
19 KiB
C#
603 lines
19 KiB
C#
using UnityEngine;
|
||
using System.Runtime.InteropServices;
|
||
|
||
#if !UNITY_WEBGL
|
||
using System.Net;
|
||
using System.Net.Sockets;
|
||
#endif
|
||
//using GYGame;
|
||
using System;
|
||
using System.Text;
|
||
using System.Collections.Generic;
|
||
using System.Threading;
|
||
using XLua;
|
||
|
||
namespace XGame
|
||
{
|
||
public class ConsoleWindow : MonoBehaviour
|
||
{
|
||
#if UNITY_STANDALONE_OSX //|| UNITY_EDITOR_OSX
|
||
const string ConsoleWindowsDLL = "ConsoleWindow";
|
||
[DllImport(ConsoleWindowsDLL, CallingConvention = CallingConvention.Cdecl)]
|
||
public static extern int ShowConsoleWin();
|
||
|
||
[DllImport(ConsoleWindowsDLL, CallingConvention = CallingConvention.Cdecl)]
|
||
public static extern void ShowErrorMsg(string msg);
|
||
|
||
[DllImport(ConsoleWindowsDLL, CallingConvention = CallingConvention.Cdecl)]
|
||
public static extern void ShowWarningMsg(string msg);
|
||
|
||
[DllImport(ConsoleWindowsDLL, CallingConvention = CallingConvention.Cdecl)]
|
||
public static extern void ShowLogMsg(string msg);
|
||
|
||
void ShowConsole()
|
||
{
|
||
ShowConsoleWin();
|
||
}
|
||
|
||
void HandleLog(string message, string stackTrace, LogType type)
|
||
{
|
||
message = message + "\n";
|
||
if (type == LogType.Log)
|
||
{
|
||
ShowLogMsg(message);
|
||
}
|
||
else if (type == LogType.Warning)
|
||
{
|
||
ShowWarningMsg(message);
|
||
}
|
||
else
|
||
{
|
||
ShowErrorMsg(message + stackTrace);
|
||
}
|
||
}
|
||
#elif UNITY_STANDALONE_WIN
|
||
void ShowConsole()
|
||
{
|
||
//XConsoleHelper.ClearConsole();
|
||
}
|
||
|
||
void HandleLog(string message, string stackTrace, LogType type)
|
||
{
|
||
message = message + "\n";
|
||
//XConsoleHelper.Write(type, message);
|
||
|
||
//可以根据Type加前缀
|
||
message = message + "\n";
|
||
//发送到服务器转外置console
|
||
//可以根据Type加前缀
|
||
switch (type)
|
||
{
|
||
case LogType.Error:
|
||
message = "Error: " + AppendLuaStackTrace(message);
|
||
break;
|
||
case LogType.Exception:
|
||
message = "Exception: " + AppendLuaStackTrace(message);
|
||
break;
|
||
case LogType.Warning:
|
||
message = "Warning: " + message;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
Send(message);//*/
|
||
}
|
||
#else
|
||
|
||
|
||
|
||
void ShowConsole()
|
||
{
|
||
|
||
}
|
||
|
||
void HandleLog(string message, string stackTrace, LogType type)
|
||
{
|
||
//可以根据Type加前缀
|
||
message = message + "\n";
|
||
//发送到服务器转外置console
|
||
//可以根据Type加前缀
|
||
switch (type)
|
||
{
|
||
case LogType.Error:
|
||
message = "Error: " + AppendLuaStackTrace(message);
|
||
break;
|
||
case LogType.Exception:
|
||
message = "Exception: " + AppendLuaStackTrace(message);
|
||
break;
|
||
case LogType.Warning:
|
||
message = "Warning: " + message;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
Send(message);
|
||
}
|
||
#endif
|
||
//ud 20220106 增加远程信息调试功能
|
||
#if !UNITY_WEBGL
|
||
static private Socket LogSocket;
|
||
static private bool LogSocketConnecting;
|
||
static private readonly object LogSocketLock = new object();
|
||
const string RemoteConsoleHost = "119.91.115.142";
|
||
const int RemoteConsolePort = 15098;
|
||
const int RemoteConsoleConnectTimeoutMs = 1500;
|
||
#else
|
||
static XWebSocket WebSocket;// = new GYWebSocket();
|
||
#endif
|
||
private const int BuffSize = 10240;
|
||
static private string LuaScript = null;
|
||
static byte[] MsgBuffer = new byte[64000];
|
||
static int BufferPos = 0;
|
||
public void Init()
|
||
{
|
||
bool bConsole = true;//起始不加载false
|
||
#if UNITY_EDITOR
|
||
bConsole = false;
|
||
#endif
|
||
//外网包就跳过
|
||
//。。。
|
||
//#if !UNITY_STANDALONE
|
||
if(bConsole)
|
||
{
|
||
ConnectConsoleServer(SystemInfo.graphicsDeviceName);
|
||
}
|
||
//#endif
|
||
}
|
||
|
||
[CSharpCallLua]
|
||
static public void ConnectConsoleServer(string name)
|
||
{
|
||
#if UNITY_EDITOR || UNITY_WEBGL //编辑器和WebGL不开
|
||
#if UNITY_WEBGL
|
||
if (WebSocket == null)
|
||
{
|
||
string url = $"192.168.51.100:15098";//$"ws://182.61.4.164:15098";//$"ws://119.91.115.142:15098";//
|
||
lsocket.connect(url, 0, (ws, err) =>
|
||
{
|
||
WebSocket = ws;
|
||
if (ws != null)
|
||
{
|
||
//Debug.LogError($"Console Connect OK!");
|
||
string msg = "$set~^client$" + name + ",x\r\n";
|
||
Send(msg);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"Console Connect Err: {err}");
|
||
}
|
||
});
|
||
}
|
||
else
|
||
{//重设名字
|
||
//发送客户端登录(改换idname),"$set~^client$"+初始登录name(SystemInfo.deviceUniqueIdentifier)+"|"+账号id
|
||
string msg = "$set~^client$" + name + ",x\r\n";
|
||
Send(msg);
|
||
}
|
||
#endif
|
||
return;
|
||
#else
|
||
ConnectConsoleServerAsync(name);
|
||
return;
|
||
#if false
|
||
if (LogSocket == null || !LogSocket.Connected)
|
||
{
|
||
try
|
||
{
|
||
//初始化网络,连接服务器,接收或发送给服务器
|
||
if (LogSocket == null)
|
||
LogSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||
//LogSocket.Connect("192.168.8.60", 13782);//服务器所在
|
||
LogSocket.Connect("119.91.115.142", 15098);//外网调试服
|
||
//LogSocket.Connect("192.168.10.166", 8861);
|
||
//发送客户端登录(改换idname),"$set~^client$"+初始登录name(SystemInfo.deviceUniqueIdentifier)+"|"+账号id
|
||
string msg = "$set~^client$" + name + ",x\r\n";
|
||
Send(msg);
|
||
ReceiveAsync();
|
||
if (LogSocket != null && !LogSocket.Connected)
|
||
{
|
||
LogSocket.Close();
|
||
LogSocket = null;
|
||
Debug.LogWarning("ConnectConsoleServer Failed!");
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("ConnectConsoleServer OK!");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogWarning("ConnectConsoleServer Failed : " + e.Message);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//发送客户端登录(改换idname),"$set~^client$"+初始登录name(SystemInfo.deviceUniqueIdentifier)+"|"+账号id
|
||
string msg = "$set~^client$" + name + ",x\r\n";
|
||
Send(msg);
|
||
}
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
#if !UNITY_WEBGL && !UNITY_EDITOR
|
||
class ConsoleConnectState
|
||
{
|
||
public Socket Socket;
|
||
public string Name;
|
||
public volatile bool TimedOut;
|
||
|
||
public ConsoleConnectState(Socket socket, string name)
|
||
{
|
||
Socket = socket;
|
||
Name = name;
|
||
}
|
||
}
|
||
|
||
static private void ConnectConsoleServerAsync(string name)
|
||
{
|
||
if (LogSocket != null && LogSocket.Connected)
|
||
{
|
||
string msg = "$set~^client$" + name + ",x\r\n";
|
||
Send(msg);
|
||
return;
|
||
}
|
||
|
||
lock (LogSocketLock)
|
||
{
|
||
if (LogSocketConnecting)
|
||
return;
|
||
LogSocketConnecting = true;
|
||
}
|
||
|
||
Socket socket = null;
|
||
IAsyncResult connectResult = null;
|
||
ConsoleConnectState state = null;
|
||
try
|
||
{
|
||
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||
socket.NoDelay = true;
|
||
state = new ConsoleConnectState(socket, name);
|
||
LogSocket = socket;
|
||
connectResult = socket.BeginConnect(RemoteConsoleHost, RemoteConsolePort, OnConsoleConnected, state);
|
||
|
||
ThreadPool.QueueUserWorkItem(_ =>
|
||
{
|
||
try
|
||
{
|
||
if (connectResult != null && !connectResult.AsyncWaitHandle.WaitOne(RemoteConsoleConnectTimeoutMs))
|
||
{
|
||
state.TimedOut = true;
|
||
SafeClose(socket);
|
||
lock (LogSocketLock)
|
||
{
|
||
if (LogSocket == socket)
|
||
LogSocket = null;
|
||
LogSocketConnecting = false;
|
||
}
|
||
Debug.LogWarning("ConnectConsoleServer timeout.");
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
try
|
||
{
|
||
if (connectResult != null)
|
||
connectResult.AsyncWaitHandle.Close();
|
||
}
|
||
catch { }
|
||
}
|
||
});
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
SafeClose(socket);
|
||
lock (LogSocketLock)
|
||
{
|
||
if (LogSocket == socket)
|
||
LogSocket = null;
|
||
LogSocketConnecting = false;
|
||
}
|
||
Debug.LogWarning("ConnectConsoleServer Failed : " + e.Message);
|
||
}
|
||
}
|
||
|
||
static private void OnConsoleConnected(IAsyncResult result)
|
||
{
|
||
ConsoleConnectState state = result.AsyncState as ConsoleConnectState;
|
||
Socket socket = state != null ? state.Socket : null;
|
||
try
|
||
{
|
||
if (socket == null)
|
||
return;
|
||
|
||
socket.EndConnect(result);
|
||
if (socket.Connected)
|
||
{
|
||
LogSocket = socket;
|
||
string msg = "$set~^client$" + state.Name + ",x\r\n";
|
||
Send(msg);
|
||
ReceiveAsync();
|
||
Debug.Log("ConnectConsoleServer OK!");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
SafeClose(socket);
|
||
lock (LogSocketLock)
|
||
{
|
||
if (LogSocket == socket)
|
||
LogSocket = null;
|
||
}
|
||
if (state == null || !state.TimedOut)
|
||
Debug.LogWarning("ConnectConsoleServer Failed : " + e.Message);
|
||
}
|
||
finally
|
||
{
|
||
lock (LogSocketLock)
|
||
{
|
||
if (LogSocket == socket || LogSocket == null)
|
||
LogSocketConnecting = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
static private void SafeClose(Socket socket)
|
||
{
|
||
try { socket?.Close(); } catch { }
|
||
}
|
||
#endif
|
||
|
||
void Update()
|
||
{
|
||
if (LuaScript != null)
|
||
{//在主线程执行代码
|
||
string sLua = LuaScript;
|
||
LuaScript = null;
|
||
//Debug.Log($"Run Lua : {sLua}");
|
||
try
|
||
{
|
||
LuaManager.m_Instance.DoString(sLua);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogWarning("Do Lua Failed : " + e.Message);
|
||
}
|
||
}
|
||
#if UNITY_WEBGL
|
||
//WebSocket 每帧要获得是否有信息
|
||
if (WebSocket != null)
|
||
{
|
||
int recLength = WebSocket.GetRecvSize();
|
||
if (recLength > 0)
|
||
{
|
||
string strError = "";
|
||
byte[] data = WebSocket.recv(ref strError);
|
||
|
||
//拆粘包处理
|
||
SetData(data, recLength);
|
||
}
|
||
}
|
||
|
||
#endif
|
||
}
|
||
static private void ReceiveAsync()
|
||
{
|
||
#if !UNITY_WEBGL
|
||
if (LogSocket == null || !LogSocket.Connected) return;
|
||
var Buff = new byte[BuffSize];
|
||
LogSocket.BeginReceive(Buff, 0, BuffSize, SocketFlags.None, OnReceived, Buff);
|
||
#endif
|
||
}
|
||
|
||
static public void OnReceived(IAsyncResult result)
|
||
{
|
||
#if !UNITY_WEBGL
|
||
if (LogSocket == null || !LogSocket.Connected)
|
||
{
|
||
Debug.LogError("Remote Console DisConnected: ");
|
||
return;
|
||
}
|
||
byte[] data = (byte[])result.AsyncState;
|
||
int recLength = LogSocket.EndReceive(result, out SocketError error);
|
||
if (recLength <= 0)
|
||
{
|
||
Debug.LogError($"Remote Console Error: {error}");
|
||
return;
|
||
}
|
||
ReceiveAsync();
|
||
|
||
//拆粘包处理
|
||
SetData(data, recLength);
|
||
#endif
|
||
}
|
||
|
||
public static void SetData(byte[] data, int recLength)
|
||
{
|
||
//拆粘包处理
|
||
data.CopyTo(MsgBuffer, BufferPos);
|
||
recLength = recLength + BufferPos;
|
||
int pos = 0;
|
||
for (int j = 0; j < 100; ++j)
|
||
{
|
||
//前两个字节是长度
|
||
short len = BitConverter.ToInt16(MsgBuffer, pos);
|
||
if (recLength - pos - 2 < len)
|
||
{//长度不足
|
||
if (pos == 0)
|
||
{
|
||
BufferPos = recLength;
|
||
}
|
||
else
|
||
{
|
||
data.CopyTo(MsgBuffer, BufferPos);
|
||
Buffer.BlockCopy(MsgBuffer, pos, MsgBuffer, 0, recLength - pos);
|
||
BufferPos = recLength - pos;
|
||
}
|
||
break;
|
||
}
|
||
//处理
|
||
System.Text.Encoding encoding = System.Text.Encoding.Default;
|
||
|
||
//这里是接收线程,不能直接执行代码,可能会出错
|
||
int luasize = len;
|
||
if (MsgBuffer[pos + 2 + len - 1] == '\0')
|
||
luasize = len - 1;
|
||
if (LuaScript == null)
|
||
{//memcpy(msg.sData, p_tsock->buffer + pos + sizeof(unsigned short), len);
|
||
LuaScript = encoding.GetString(MsgBuffer, pos + 2, luasize);
|
||
}
|
||
else
|
||
{
|
||
LuaScript = LuaScript + encoding.GetString(MsgBuffer, pos + 2, luasize);
|
||
}
|
||
pos += len + 2;
|
||
if (pos == recLength + BufferPos)
|
||
{
|
||
BufferPos = 0;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
public static void Log(LogType logType, string log)
|
||
{
|
||
#if !UNITY_WEBGL
|
||
if (LogSocket == null || !LogSocket.Connected) return;
|
||
#else
|
||
if (WebSocket == null) return;
|
||
#endif
|
||
string fLog = "";
|
||
switch (logType)
|
||
{
|
||
case LogType.Error:
|
||
fLog = "Error: " + AppendLuaStackTrace(log);
|
||
break;
|
||
case LogType.Exception:
|
||
fLog = "Exception: " + AppendLuaStackTrace(log);
|
||
break;
|
||
case LogType.Warning:
|
||
fLog = "Warning: " + log;
|
||
break;
|
||
default:
|
||
fLog = log;
|
||
break;
|
||
}
|
||
|
||
Send(fLog);
|
||
}
|
||
|
||
private static string AppendLuaStackTrace(string message)
|
||
{
|
||
string luaStackTrace = GetLuaStackTrace();
|
||
if (string.IsNullOrEmpty(luaStackTrace))
|
||
{
|
||
return message;
|
||
}
|
||
Debug.Log("\nLua Stack:\n" + luaStackTrace);
|
||
return message + "\nLua Stack:\n" + luaStackTrace;
|
||
}
|
||
|
||
private static string GetLuaStackTrace()
|
||
{
|
||
LuaEnv luaEnv = LuaManager.m_LuaEnv;
|
||
if (luaEnv == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
try
|
||
{
|
||
object[] results = luaEnv.DoString("return debug.traceback('', 2)", "ConsoleWindow.GetLuaStackTrace");
|
||
if (results != null && results.Length > 0)
|
||
{
|
||
return results[0] as string;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// Keep logging robust even if the Lua VM is not in a callable state.
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private static void Send(string msg)
|
||
{
|
||
#if !UNITY_WEBGL
|
||
if (LogSocket != null && LogSocket.Connected)
|
||
{
|
||
byte[] content = Encoding.Default.GetBytes(msg);
|
||
ushort size = (ushort)content.Length;
|
||
byte[] bytes = BitConverter.GetBytes(size);
|
||
byte[] buff = new byte[bytes.Length + content.Length];
|
||
bytes.CopyTo(buff, 0);
|
||
content.CopyTo(buff, bytes.Length);
|
||
|
||
int nSend = LogSocket.Send(buff);
|
||
//nSend = size;
|
||
}
|
||
#else
|
||
if (WebSocket != null)
|
||
{
|
||
byte[] content = Encoding.Default.GetBytes(msg);
|
||
ushort size = (ushort)content.Length;
|
||
byte[] bytes = BitConverter.GetBytes(size);
|
||
byte[] buff = new byte[bytes.Length + content.Length];
|
||
bytes.CopyTo(buff, 0);
|
||
content.CopyTo(buff, bytes.Length);
|
||
string errorMsg = null;
|
||
WebSocket.send(buff, null, ref errorMsg);
|
||
}
|
||
#endif
|
||
}
|
||
private static void SendBytes(byte[] buff)
|
||
{
|
||
#if !UNITY_WEBGL
|
||
if (LogSocket != null && LogSocket.Connected)
|
||
{
|
||
ushort size = (ushort)buff.Length;
|
||
byte[] bytes = BitConverter.GetBytes(size);
|
||
byte[] sendbuf = new byte[bytes.Length + buff.Length];
|
||
bytes.CopyTo(sendbuf, 0);
|
||
buff.CopyTo(sendbuf, bytes.Length);
|
||
LogSocket.Send(sendbuf);
|
||
}
|
||
#else
|
||
if (WebSocket != null)
|
||
{
|
||
ushort size = (ushort)buff.Length;
|
||
byte[] bytes = BitConverter.GetBytes(size);
|
||
byte[] sendbuf = new byte[bytes.Length + buff.Length];
|
||
bytes.CopyTo(sendbuf, 0);
|
||
buff.CopyTo(sendbuf, bytes.Length);
|
||
string errorMsg = null;
|
||
WebSocket.send(sendbuf, null, ref errorMsg);
|
||
}
|
||
#endif
|
||
}
|
||
#if !UNITY_EDITOR
|
||
void Awake()
|
||
{
|
||
Init();
|
||
Application.logMessageReceived += HandleLog;
|
||
}
|
||
|
||
void OnDestroy()
|
||
{
|
||
Application.logMessageReceived -= HandleLog;
|
||
//if (LogSocket != null && LogSocket.Connected)
|
||
//{
|
||
// LogSocket.Disconnect(false);
|
||
//}
|
||
}
|
||
#else
|
||
void Awake()
|
||
{
|
||
Init();
|
||
Application.logMessageReceived += HandleLog;
|
||
}
|
||
#endif
|
||
}
|
||
}
|