Files
BH3/Assets/Scripts/Assembly-CSharp/MoleMole/UNetMPPeer.cs
2025-08-13 09:26:42 +08:00

517 lines
12 KiB
C#

using UnityEngine;
using UnityEngine.Networking;
namespace MoleMole
{
public class UNetMPPeer : MPPeer
{
private enum ClientConnectState
{
Idle = 0,
JustConnectedWaitingForSetClientID = 1,
ConnectedAndGotClientID = 2
}
private const int MAX_CONNECTION_COUNT = 5;
private const int INVALID_CONNECTION_ID = -1;
private const int SIMULATOR_MAX_TIME_OUT = 1500;
private const int SIMULATOR_MIN_TIME_OUT = 1000;
private const int SIMULATOR_AVG_TIME_OUT = 1250;
private const int PEER_USE_CHANNEL = 0;
private const int PEER_CHANNEL_COUNT = 2;
private PeerState _state;
private int _peerID;
private ClientConnectState _clientConnectState;
private bool _isDelaySimulator;
private ConnectionSimulatorConfig _simulatorConfig;
private ConnectionConfig _connConfig;
private GlobalConfig _globalConfig;
private byte[] _selfBuffer;
private int _hostID;
private int _selfConnID;
private HostTopology _ht;
private int _recvConnID;
private int _recvChannelID;
private int _recvDataSize;
private byte[] _recvBuffer;
private byte _recvErr;
private int[] _peerMap;
private int _serverConnectedPeerCount;
private int _totalPeerCount;
public override PeerState state
{
get
{
return _state;
}
}
public override int peerID
{
get
{
return _peerID;
}
}
public override int totalPeerCount
{
get
{
return _totalPeerCount;
}
}
public override int channelSequenceCapacity
{
get
{
return 32;
}
}
private bool isServer
{
get
{
return _peerID == 1;
}
}
public override int reliableChannel
{
get
{
return 0;
}
}
public override int stateUpdateChannel
{
get
{
return 1;
}
}
public UNetMPPeer(bool delaySimulator = false)
{
_state = PeerState.Unitialized;
_globalConfig = new GlobalConfig();
_globalConfig.ReactorModel = ReactorModel.FixRateReactor;
_globalConfig.ThreadAwakeTimeout = 22u;
_globalConfig.MaxPacketSize = 1000;
ConnectionConfig connectionConfig = new ConnectionConfig
{
IsAcksLong = true,
PacketSize = 800,
MaxCombinedReliableMessageCount = 8,
MaxCombinedReliableMessageSize = 64,
DisconnectTimeout = 10000u,
PingTimeout = 10000u
};
for (int i = 0; i < channelSequenceCapacity; i++)
{
connectionConfig.AddChannel(QosType.ReliableSequenced);
connectionConfig.AddChannel(QosType.StateUpdate);
}
_connConfig = connectionConfig;
_ht = new HostTopology(connectionConfig, 5);
_ht.ReceivedMessagePoolSize = 1024;
_ht.SentMessagePoolSize = 1024;
_recvBuffer = new byte[connectionConfig.PacketSize + 128];
_isDelaySimulator = delaySimulator;
_simulatorConfig = new ConnectionSimulatorConfig(1000, 1250, 1000, 1250, 0f);
}
public override void Init()
{
NetworkTransport.Init(_globalConfig);
_state = PeerState.Inited;
_selfConnID = -1;
_hostID = -1;
_selfBuffer = new byte[16];
_serverConnectedPeerCount = 0;
_peerMap = new int[7];
_totalPeerCount = 0;
ResetServerData();
}
public override void Shutdown()
{
if (_state > PeerState.Inited)
{
NetworkTransport.RemoveHost(_hostID);
}
NetworkTransport.Shutdown();
ResetServerData();
_clientConnectState = ClientConnectState.Idle;
_state = PeerState.Unitialized;
}
private void ResetServerData()
{
_serverConnectedPeerCount = 0;
for (int i = 0; i < _peerMap.Length; i++)
{
_peerMap[i] = -1;
}
}
public override void Core()
{
if (_state <= PeerState.Inited)
{
return;
}
NetworkEventType networkEventType = NetworkEventType.DataEvent;
while (networkEventType != NetworkEventType.Nothing && _state > PeerState.Inited)
{
networkEventType = NetworkTransport.ReceiveFromHost(_hostID, out _recvConnID, out _recvChannelID, _recvBuffer, _recvBuffer.Length, out _recvDataSize, out _recvErr);
if (_state == PeerState.ServerListening)
{
switch (networkEventType)
{
case NetworkEventType.ConnectEvent:
{
CheckNetError(_recvErr, networkEventType);
_serverConnectedPeerCount++;
byte b = (byte)(_peerID + _serverConnectedPeerCount);
_peerMap[b] = _recvConnID;
_selfBuffer[0] = PackHeader(b, 1);
_selfBuffer[1] = b;
SendTo(_recvConnID, 0, _selfBuffer, 2);
if (onConnected != null)
{
onConnected(b);
}
break;
}
case NetworkEventType.DisconnectEvent:
{
bool flag = false;
for (int i = 2; i <= 1 + _serverConnectedPeerCount; i++)
{
if (_peerMap[i] != -1 && _peerMap[i] == _recvConnID)
{
_peerMap[i] = -1;
if (onDisconnected != null)
{
onDisconnected(i);
}
flag = true;
break;
}
}
break;
}
case NetworkEventType.DataEvent:
ServerDispatchDataEvent(networkEventType);
break;
}
}
else if (_state == PeerState.ClientConnecting)
{
if (_clientConnectState == ClientConnectState.Idle)
{
switch (networkEventType)
{
case NetworkEventType.ConnectEvent:
CheckNetError(_recvErr, networkEventType);
_clientConnectState = ClientConnectState.JustConnectedWaitingForSetClientID;
break;
case NetworkEventType.DataEvent:
Debug.LogError("not expecting data event before peer ID is set");
break;
}
}
else if (_clientConnectState == ClientConnectState.JustConnectedWaitingForSetClientID && networkEventType == NetworkEventType.DataEvent)
{
CheckNetError(_recvErr, networkEventType);
int num = ParseMessageType(_recvBuffer);
int num2 = ParsePeerID(_recvBuffer);
_peerID = num2;
_state = PeerState.ClientConnected;
_clientConnectState = ClientConnectState.ConnectedAndGotClientID;
if (onConnected != null)
{
onConnected(_selfConnID);
}
}
}
else if (_state == PeerState.ClientConnected)
{
switch (networkEventType)
{
case NetworkEventType.DisconnectEvent:
if (onDisconnected != null)
{
onDisconnected(_selfConnID);
}
_state = PeerState.ClientDropped;
break;
case NetworkEventType.DataEvent:
{
int num3 = ParseMessageType(_recvBuffer);
CheckNetError(_recvErr, networkEventType);
if (num3 == 2)
{
_totalPeerCount = _recvBuffer[1];
_state = PeerState.Established;
if (onEstablished != null)
{
onEstablished();
}
}
else if (onPacket != null)
{
onPacket(_recvBuffer, _recvDataSize - 1, 1, _recvChannelID % 2);
}
break;
}
}
}
else
{
if (_state != PeerState.Established)
{
continue;
}
if (isServer)
{
switch (networkEventType)
{
case NetworkEventType.DataEvent:
ServerDispatchDataEvent(networkEventType);
break;
}
continue;
}
switch (networkEventType)
{
case NetworkEventType.DataEvent:
CheckNetError(_recvErr, networkEventType);
if (onPacket != null)
{
onPacket(_recvBuffer, _recvDataSize - 1, 1, _recvChannelID % 2);
}
break;
}
}
}
}
public override void Listen(int serverPort = 0, string ipAddress = null)
{
if (ipAddress != null && serverPort != 0)
{
_hostID = NetworkTransport.AddHost(_ht, serverPort, ipAddress);
}
else if (ipAddress == null && serverPort != 0)
{
_hostID = NetworkTransport.AddHost(_ht, serverPort);
}
else
{
_hostID = NetworkTransport.AddHost(_ht);
}
_peerID = 1;
_state = PeerState.ServerListening;
}
public override void StopListen()
{
NetworkTransport.RemoveHost(_hostID);
_peerID = 0;
_state = PeerState.Inited;
ResetServerData();
}
public override void ServerReady()
{
_totalPeerCount = 1 + _serverConnectedPeerCount;
for (int i = 2; i <= 1 + _serverConnectedPeerCount; i++)
{
_selfBuffer[0] = PackHeader((byte)i, 2);
_selfBuffer[1] = (byte)_totalPeerCount;
SendTo(_peerMap[i], 0, _selfBuffer, 2);
}
_state = PeerState.Established;
if (onEstablished != null)
{
onEstablished();
}
}
public override void Connect(string ipAddress, int serverPort)
{
byte error;
if (_isDelaySimulator)
{
_hostID = NetworkTransport.AddHostWithSimulator(_ht, 1000, 1500);
_selfConnID = NetworkTransport.ConnectWithSimulator(_hostID, ipAddress, serverPort, 0, out error, _simulatorConfig);
}
else
{
_hostID = NetworkTransport.AddHost(_ht);
_selfConnID = NetworkTransport.Connect(_hostID, ipAddress, serverPort, 0, out error);
}
if (error != 0)
{
throw new UnityException("bad connection : " + (NetworkError)error);
}
_state = PeerState.ClientConnecting;
_clientConnectState = ClientConnectState.Idle;
}
private void ServerDispatchDataEvent(NetworkEventType netEvent)
{
CheckNetError(_recvErr, netEvent);
int num = ParsePeerID(_recvBuffer);
if (num == 7)
{
if (onPacket != null)
{
onPacket(_recvBuffer, _recvDataSize - 1, 1, _recvChannelID % 2);
}
for (int i = 2; i <= 1 + _serverConnectedPeerCount; i++)
{
int num2 = _peerMap[i];
if (num2 != -1 && num2 != _recvConnID)
{
SendTo(num2, _recvChannelID, _recvBuffer, _recvDataSize);
}
}
}
else if (num == _peerID)
{
if (onPacket != null)
{
onPacket(_recvBuffer, _recvDataSize - 1, 1, _recvChannelID % 2);
}
}
else
{
int num3 = _peerMap[num];
if (num3 != -1)
{
SendTo(num3, _recvChannelID, _recvBuffer, _recvDataSize);
}
}
}
private void SendTo(int connID, int channel, byte[] data, int len)
{
byte error;
NetworkTransport.Send(_hostID, connID, channel, data, len, out error);
CheckNetError(error);
}
public override void SendByChannel(byte[] data, int len, int channel, int channelSequence)
{
int num = ParsePeerID(data);
if (num == _peerID)
{
if (onPacket != null)
{
onPacket(data, len - 1, 1, channel);
}
return;
}
int channel2 = channelSequence * 2 + channel;
if (isServer)
{
if (num == 7)
{
for (int i = 2; i <= 1 + _serverConnectedPeerCount; i++)
{
int num2 = _peerMap[i];
if (num2 != -1)
{
SendTo(num2, channel2, data, len);
}
}
}
else
{
int num3 = _peerMap[num];
if (num3 != -1)
{
SendTo(num3, channel2, data, len);
}
}
}
else
{
SendTo(_selfConnID, channel2, data, len);
}
}
private void CheckNetError(byte err, NetworkEventType evt = NetworkEventType.Nothing)
{
if (err != 0)
{
string text = string.Format("net error: {0} ", (NetworkError)err);
if (evt != NetworkEventType.Nothing)
{
text = text + " evt: " + evt;
}
throw new UnityException(text);
}
}
public override void OnGUI()
{
byte error;
GUILayout.Label(string.Format("state: {0}, isServer: {1}, peerID: {2}, peerCnt: {3}, trans recv: {4,5}, trans send {5,5}", _state, isServer, _peerID, _totalPeerCount, (state != PeerState.Established) ? "<>" : NetworkTransport.GetPacketReceivedRate(_hostID, _selfConnID, out error).ToString(), (state != PeerState.Established) ? "<>" : NetworkTransport.GetPacketSentRate(_hostID, _selfConnID, out error).ToString()));
}
public override void GetPeerStats(out ulong sendTotal, out ulong recvTotal, out ulong sendCount, out ulong recvCount)
{
sendTotal = 0uL;
recvTotal = 0uL;
sendCount = 0uL;
recvCount = 0uL;
}
public override void GetPeerStats2(out string stat2)
{
if (isServer)
{
stat2 = "<server>";
}
else
{
byte error;
stat2 = string.Format("rtt: {0,5:0000.00}", NetworkTransport.GetCurrentRtt(_hostID, _selfConnID, out error));
}
}
}
}