114 lines
3.6 KiB
C#

using Godot;
using Godot.Collections;
public partial class EventDrivenWebSocket : WebSocketPeer {
public delegate void WebSocketEventHandler(string eventName, params object[] args);
public delegate void WSBinMsgEventHandler(byte[] args);
public delegate void WSMsgEventHandler(string args);
public event WebSocketEventHandler OnOpen;
public event WSBinMsgEventHandler OnMessage;
public event WSMsgEventHandler OnText;
public event WSBinMsgEventHandler OnBinary;
public event WebSocketEventHandler OnClose;
public event WebSocketEventHandler OnError;
private bool isConnected = false;
private bool isCloseEventFired = false;
private double connectingTime = double.NegativeInfinity;
public EventDrivenWebSocket() : base() {
isConnected = false;
}
public bool GetIsConnected() {
return isConnected;
}
public void PollEx(double delta) {
base.Poll();
CheckAndDispatchEvents(delta);
}
public void ConnectToUrlEx(string url, double delayTime = 3,
TlsOptions tlsClientOptions = null) {
if (connectingTime >= 0) {
return;
}
Error err = ConnectToUrl(url, tlsClientOptions);
if (err != Error.Ok) {
OnError?.Invoke("error", err);
}
connectingTime = delayTime;
}
protected void CheckAndDispatchEvents(double delta) {
var state = GetReadyState();
switch (state) {
case State.Open when !isConnected:
isConnected = true;
OnOpen?.Invoke("open", null);
break;
case State.Open:
while (GetAvailablePacketCount() > 0) {
byte[] packet = GetPacket();
OnMessage?.Invoke(packet);
if (WasStringPacket()) {
OnText?.Invoke(packet.GetStringFromUtf8());
} else {
OnBinary?.Invoke(packet);
}
}
break;
case State.Closed:
connectingTime = double.NegativeInfinity;
OnClose?.Invoke("closed", GetCloseCode(), GetCloseReason());
isConnected = false;
break;
case State.Closing:
// OnClose?.Invoke("closing");
break;
case State.Connecting:
if (connectingTime >= 0) {
connectingTime -= delta;
} else if (connectingTime != double.NegativeInfinity){
connectingTime = double.NegativeInfinity;
Close();
OnError?.Invoke("connectTimeOut", Error.Timeout);
}
break;
default:
// 可以在这里处理其他状态或错误
OnError?.Invoke("error", "Unknown WebSocket state.");
break;
}
}
public void SendBinaryEx(byte[] data) {
SendEx(data);
}
public void SendJsonEx(Dictionary msg) {
SendTextEx(Json.Stringify(msg));
}
public Error SendTextEx(string message) {
if (isConnected) {
return SendText(message);
} else {
OnError?.Invoke("error", "Attempt to send on a closed connection.");
return Error.ConnectionError;
}
}
public Error SendEx(byte[] message, WriteMode writeMode = WriteMode.Binary) {
if (isConnected) {
return Send(message, writeMode);
} else {
OnError?.Invoke("error", "Attempt to send on a closed connection.");
return Error.ConnectionError;
}
}
}