Initial commit: Client Doc docs Server Tools
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,602 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user