mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-24 05:03:34 -04:00
Get rid of unnecessary allocations in receiving packets.
This reduces pressure on the GC for when many players are connected.
This commit is contained in:
parent
2e1ce9f8f5
commit
e0875e0924
@ -33,7 +33,6 @@ namespace MCGalaxy.Commands.Eco {
|
||||
Item item = Economy.GetItem(parts[0]);
|
||||
if (item == null) { Help(p); return; }
|
||||
|
||||
|
||||
if (!item.Enabled) {
|
||||
Player.Message(p, "%cThe {0} item is not currently buyable.", item.Name); return;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace MCGalaxy.Events.PlayerEvents {
|
||||
|
||||
public delegate void OnPlayerChat(Player p, string message);
|
||||
/// <summary> Called whenever a player chats on the server. </summary>
|
||||
/// <remarks> You must cancel this event to prevent the message being sent to the user. </remarks>
|
||||
/// <remarks> You must cancel this event to prevent the message being sent to the user (and others). </remarks>
|
||||
public sealed class OnPlayerChatEvent : IEvent<OnPlayerChat> {
|
||||
|
||||
public static void Call(Player p, string message) {
|
||||
|
@ -22,8 +22,10 @@ namespace MCGalaxy.Network {
|
||||
public sealed class TcpSocket : INetworkSocket {
|
||||
readonly Player player;
|
||||
readonly Socket socket;
|
||||
byte[] unprocessed = new byte[0];
|
||||
|
||||
byte[] unprocessed = new byte[352];
|
||||
byte[] recvBuffer = new byte[256];
|
||||
int unprocessedLen;
|
||||
|
||||
public TcpSocket(Player p, Socket s) {
|
||||
player = p; socket = s;
|
||||
@ -48,19 +50,25 @@ namespace MCGalaxy.Network {
|
||||
if (p.disconnected) return;
|
||||
|
||||
try {
|
||||
int length = s.socket.EndReceive(result);
|
||||
if (length == 0) { p.Disconnect(); return; }
|
||||
int recvLen = s.socket.EndReceive(result);
|
||||
if (recvLen == 0) { p.Disconnect(); return; }
|
||||
|
||||
byte[] allData = new byte[s.unprocessed.Length + length];
|
||||
Buffer.BlockCopy(s.unprocessed, 0, allData, 0, s.unprocessed.Length);
|
||||
Buffer.BlockCopy(s.recvBuffer, 0, allData, s.unprocessed.Length, length);
|
||||
s.unprocessed = p.ProcessReceived(allData);
|
||||
// Packets may not always be fully received in a Receive call
|
||||
// As such, we may need to retain a little bit of partial packet data
|
||||
Buffer.BlockCopy(s.recvBuffer, 0, s.unprocessed, s.unprocessedLen, recvLen);
|
||||
s.unprocessedLen += recvLen;
|
||||
int processedLen = p.ProcessReceived(s.unprocessed, s.unprocessedLen);
|
||||
|
||||
if (p.nonPlayerClient && s.unprocessed.Length == 0) {
|
||||
s.Close();
|
||||
p.disconnected = true;
|
||||
return;
|
||||
// Disconnect invalid clients
|
||||
if (p.nonPlayerClient && processedLen == -1) { s.Close(); p.disconnected = true; }
|
||||
if (processedLen == -1) return;
|
||||
|
||||
// move remaining partial packet data back to start of unprocessed buffer
|
||||
for (int i = processedLen; i < s.unprocessedLen; i++) {
|
||||
s.unprocessed[i - processedLen] = s.unprocessed[i];
|
||||
}
|
||||
s.unprocessedLen -= processedLen;
|
||||
|
||||
if (!p.disconnected) s.ReceiveNextAsync();
|
||||
} catch (SocketException) {
|
||||
p.Disconnect();
|
||||
|
@ -185,28 +185,27 @@ namespace MCGalaxy {
|
||||
return block == Block.Air || (block >= Block.Water && block <= Block.StillLava);
|
||||
}
|
||||
|
||||
internal byte[] ProcessReceived(byte[] buffer) {
|
||||
internal int ProcessReceived(byte[] buffer, int bufferLen) {
|
||||
int processedLen = 0;
|
||||
try {
|
||||
int size = PacketSize(buffer);
|
||||
if (size == -2) return new byte[1]; // WoM get request
|
||||
if (size == -1) return new byte[0]; // invalid packet
|
||||
|
||||
if (buffer.Length < size) return buffer;
|
||||
HandlePacket(buffer, 0);
|
||||
if (buffer.Length == size) return new byte[0];
|
||||
|
||||
byte[] remaining = new byte[buffer.Length - size];
|
||||
Buffer.BlockCopy(buffer, size, remaining, 0, remaining.Length);
|
||||
return ProcessReceived(remaining);
|
||||
while (processedLen < bufferLen) {
|
||||
int packetLen = PacketSize(buffer[processedLen]);
|
||||
if (packetLen == -1) return -1;
|
||||
|
||||
// Partial packet data received
|
||||
if (processedLen + packetLen > bufferLen) return processedLen;
|
||||
HandlePacket(buffer, processedLen);
|
||||
processedLen += packetLen;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
return buffer;
|
||||
return processedLen;
|
||||
}
|
||||
|
||||
int PacketSize(byte[] buffer) {
|
||||
switch (buffer[0]) {
|
||||
case (byte)'G': return -2; //For wom
|
||||
int PacketSize(byte opcode) {
|
||||
switch (opcode) {
|
||||
case (byte)'G': return -1; // HTTP GET, ignore it
|
||||
case Opcode.Handshake: return 131;
|
||||
case Opcode.SetBlockClient:
|
||||
if (!loggedIn) goto default;
|
||||
@ -226,7 +225,7 @@ namespace MCGalaxy {
|
||||
|
||||
default:
|
||||
if (!nonPlayerClient) {
|
||||
string msg = "Unhandled message id \"" + buffer[0] + "\"!";
|
||||
string msg = "Unhandled message id \"" + opcode + "\"!";
|
||||
Leave(msg, msg, true);
|
||||
}
|
||||
return -1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user