mirror of
https://gitlab.com/Syroot/Worms.git
synced 2025-05-05 19:29:34 +03:00
Use new BinaryData package to work on spans rather than streams.
This commit is contained in:
parent
fcc2c74399
commit
7852ef9d5a
156
src/Syroot.Worms.Mgame.GameServer/Client.OnlineWorms.cs
Normal file
156
src/Syroot.Worms.Mgame.GameServer/Client.OnlineWorms.cs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Net;
|
||||||
|
using Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms;
|
||||||
|
|
||||||
|
namespace Syroot.Worms.Mgame.GameServer
|
||||||
|
{
|
||||||
|
internal partial class Client
|
||||||
|
{
|
||||||
|
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void HandleOWConnect(ConnectQuery packet)
|
||||||
|
{
|
||||||
|
SendPacket(new ConnectReply
|
||||||
|
{
|
||||||
|
Unknown = _server.Config.Name,
|
||||||
|
Unknown2 = _server.Config.Region,
|
||||||
|
Version = _server.Config.Version
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleOWLogin(LoginQuery packet)
|
||||||
|
{
|
||||||
|
// Send login result.
|
||||||
|
// Create player infos from the given credentials. This would be the place to check for actual accounts.
|
||||||
|
LoginPlayerInfo[] playerInfos = new LoginPlayerInfo[packet.Logins.Length];
|
||||||
|
for (int i = 0; i < packet.Logins.Length; i++)
|
||||||
|
{
|
||||||
|
LoginCredentials credentials = packet.Logins[i];
|
||||||
|
playerInfos[i] = new LoginPlayerInfo { ID = credentials.ID, Rank = 19 };
|
||||||
|
}
|
||||||
|
SendPacket(new LoginReply
|
||||||
|
{
|
||||||
|
Result = LoginResult.Success,
|
||||||
|
PlayerInfos = playerInfos
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send info text.
|
||||||
|
SendPacket(new ServerInfoReply
|
||||||
|
{
|
||||||
|
Text = "Welcome to the Online Worms Server."
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send channels. The port is abused to identify the channel later on.
|
||||||
|
SendPacket(new ChannelInfosReply
|
||||||
|
{
|
||||||
|
Channels = new[]
|
||||||
|
{
|
||||||
|
new ChannelInfo
|
||||||
|
{
|
||||||
|
Name = "Test Channel",
|
||||||
|
EndPoint = new IPEndPoint(_server.Config.IPAddress, 1),
|
||||||
|
Type = ChannelType.Normal,
|
||||||
|
Color = Color.LightGreen,
|
||||||
|
Load = ChannelLoad.Highest
|
||||||
|
},
|
||||||
|
new ChannelInfo
|
||||||
|
{
|
||||||
|
Name = "Real Channel",
|
||||||
|
EndPoint = new IPEndPoint(_server.Config.IPAddress, 2),
|
||||||
|
Type = ChannelType.Normal
|
||||||
|
},
|
||||||
|
new ChannelInfo
|
||||||
|
{
|
||||||
|
Name = "Boredom Time",
|
||||||
|
EndPoint = new IPEndPoint(_server.Config.IPAddress, 3),
|
||||||
|
Type = ChannelType.Normal,
|
||||||
|
Load = ChannelLoad.Medium
|
||||||
|
},
|
||||||
|
new ChannelInfo
|
||||||
|
{
|
||||||
|
Name = "Nothing Goes",
|
||||||
|
EndPoint = new IPEndPoint(_server.Config.IPAddress, 4),
|
||||||
|
Type = ChannelType.Roping,
|
||||||
|
Color = Color.Orange,
|
||||||
|
Coins = 2,
|
||||||
|
Load = ChannelLoad.Closed
|
||||||
|
},
|
||||||
|
new ChannelInfo
|
||||||
|
{
|
||||||
|
Name = "Doper's Heaven",
|
||||||
|
EndPoint = new IPEndPoint(_server.Config.IPAddress, 5),
|
||||||
|
Type = ChannelType.Roping,
|
||||||
|
Color = Color.Orange,
|
||||||
|
Coins = 1,
|
||||||
|
Load = ChannelLoad.Full
|
||||||
|
},
|
||||||
|
new ChannelInfo
|
||||||
|
{
|
||||||
|
Name = "Unhelpful Channel",
|
||||||
|
EndPoint = new IPEndPoint(_server.Config.IPAddress, 6),
|
||||||
|
Type = ChannelType.Special
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleOWChannelEnter(ChannelEnterQuery packet)
|
||||||
|
{
|
||||||
|
// Simply allow joining a channel running on the same server port.
|
||||||
|
SendPacket(new ChannelEnterReply
|
||||||
|
{
|
||||||
|
EndPoint = _server.Config.EndPoint
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleOWChannelConnect(ChannelConnectQuery packet)
|
||||||
|
{
|
||||||
|
SendPacket(new ChannelConnectReply
|
||||||
|
{
|
||||||
|
Result = ChannelConnectResult.Success,
|
||||||
|
Player = new ChannelConnectPlayerInfo
|
||||||
|
{
|
||||||
|
ID = packet.Players[0].ID,
|
||||||
|
Name = "Your Name",
|
||||||
|
Experience = 1337,
|
||||||
|
Gold = 1000000,
|
||||||
|
Rank = 19,
|
||||||
|
GuildMarkIndex = 1,
|
||||||
|
GuildName = "Your Guild"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleOWChannelTop20(ChannelTop20Query packet)
|
||||||
|
{
|
||||||
|
// Send some simulated player rank infos.
|
||||||
|
ChannelTop20Reply reply = new ChannelTop20Reply
|
||||||
|
{
|
||||||
|
UnknownA = "Test",
|
||||||
|
Top20 = new List<ChannelTop20Player>(20)
|
||||||
|
};
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
reply.Top20.Add(new ChannelTop20Player
|
||||||
|
{
|
||||||
|
Name = $"GoodPlayer{(char)('A' + i)}",
|
||||||
|
Rank = (ushort)((i + 6) / 3),
|
||||||
|
Experience = (ulong)(20 - i) * 957
|
||||||
|
});
|
||||||
|
}
|
||||||
|
SendPacket(reply);
|
||||||
|
|
||||||
|
// This is the last channel info packet, tell the client to go to the channel screen.
|
||||||
|
SendPacket(new ChannelEnterFinishReply());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleOWStartSingleGameQuery(StartSingleGameQuery packet)
|
||||||
|
{
|
||||||
|
SendPacket(new StartSingleGameReply
|
||||||
|
{
|
||||||
|
Success = packet.RoundType == GameStartRoundType.First
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
src/Syroot.Worms.Mgame.GameServer/Client.WorldPartyAqua.cs
Normal file
14
src/Syroot.Worms.Mgame.GameServer/Client.WorldPartyAqua.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua;
|
||||||
|
|
||||||
|
namespace Syroot.Worms.Mgame.GameServer
|
||||||
|
{
|
||||||
|
internal partial class Client
|
||||||
|
{
|
||||||
|
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void HandleWWPAConnect(ConnectQuery packet)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,14 @@
|
|||||||
using System.Collections.Generic;
|
using System.Net.Sockets;
|
||||||
using System.Drawing;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Syroot.Worms.Mgame.GameServer.Core;
|
using Syroot.Worms.Mgame.GameServer.Core;
|
||||||
using Syroot.Worms.Mgame.GameServer.Packets;
|
using Syroot.Worms.Mgame.GameServer.Packets;
|
||||||
using Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms;
|
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer
|
namespace Syroot.Worms.Mgame.GameServer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a connection with an Online Worms client which replies to received packets appropriately.
|
/// Represents a connection with an Online Worms client which replies to received packets appropriately.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class Client : AppConnection
|
internal partial class Client : AppConnection
|
||||||
{
|
{
|
||||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -30,174 +26,13 @@ namespace Syroot.Worms.Mgame.GameServer
|
|||||||
: base(tcpClient)
|
: base(tcpClient)
|
||||||
{
|
{
|
||||||
_server = server;
|
_server = server;
|
||||||
}
|
PrePacketHandle += (s, e) => _server.Log.Write(LogCategory.Client, FormatPacket(e, ">>"));
|
||||||
|
PrePacketSend += (s, e) =>
|
||||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
public void HandleConnect(ConnectQuery packet)
|
|
||||||
{
|
|
||||||
SendPacket(new ConnectReply
|
|
||||||
{
|
{
|
||||||
Unknown = _server.Config.Name,
|
_server.Log.Write(LogCategory.Server, FormatPacket(e, "<<"));
|
||||||
Unknown2 = _server.Config.Region,
|
if (_server.Config.SendDelay > 0)
|
||||||
Version = _server.Config.Version
|
Thread.Sleep(_server.Config.SendDelay);
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleLogin(LoginQuery packet)
|
|
||||||
{
|
|
||||||
// Send login result.
|
|
||||||
// Create player infos from the given credentials. This would be the place to check for actual accounts.
|
|
||||||
LoginPlayerInfo[] playerInfos = new LoginPlayerInfo[packet.Logins.Length];
|
|
||||||
for (int i = 0; i < packet.Logins.Length; i++)
|
|
||||||
{
|
|
||||||
LoginCredentials credentials = packet.Logins[i];
|
|
||||||
playerInfos[i] = new LoginPlayerInfo { ID = credentials.ID, Rank = 19 };
|
|
||||||
}
|
|
||||||
SendPacket(new LoginReply
|
|
||||||
{
|
|
||||||
Result = LoginResult.Success,
|
|
||||||
PlayerInfos = playerInfos
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send info text.
|
|
||||||
SendPacket(new ServerInfoReply
|
|
||||||
{
|
|
||||||
Text = "Welcome to the Online Worms Server."
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send channels. The port is abused to identify the channel later on.
|
|
||||||
SendPacket(new ChannelInfosReply
|
|
||||||
{
|
|
||||||
Channels = new[]
|
|
||||||
{
|
|
||||||
new ChannelInfo
|
|
||||||
{
|
|
||||||
Name = "Test Channel",
|
|
||||||
EndPoint = new IPEndPoint(_server.Config.IPAddress, 1),
|
|
||||||
Type = ChannelType.Normal,
|
|
||||||
Color = Color.LightGreen,
|
|
||||||
Load = ChannelLoad.Highest
|
|
||||||
},
|
|
||||||
new ChannelInfo
|
|
||||||
{
|
|
||||||
Name = "Real Channel",
|
|
||||||
EndPoint = new IPEndPoint(_server.Config.IPAddress, 2),
|
|
||||||
Type = ChannelType.Normal
|
|
||||||
},
|
|
||||||
new ChannelInfo
|
|
||||||
{
|
|
||||||
Name = "Boredom Time",
|
|
||||||
EndPoint = new IPEndPoint(_server.Config.IPAddress, 3),
|
|
||||||
Type = ChannelType.Normal,
|
|
||||||
Load = ChannelLoad.Medium
|
|
||||||
},
|
|
||||||
new ChannelInfo
|
|
||||||
{
|
|
||||||
Name = "Nothing Goes",
|
|
||||||
EndPoint = new IPEndPoint(_server.Config.IPAddress, 4),
|
|
||||||
Type = ChannelType.Roping,
|
|
||||||
Color = Color.Orange,
|
|
||||||
Coins = 2,
|
|
||||||
Load = ChannelLoad.Closed
|
|
||||||
},
|
|
||||||
new ChannelInfo
|
|
||||||
{
|
|
||||||
Name = "Doper's Heaven",
|
|
||||||
EndPoint = new IPEndPoint(_server.Config.IPAddress, 5),
|
|
||||||
Type = ChannelType.Roping,
|
|
||||||
Color = Color.Orange,
|
|
||||||
Coins = 1,
|
|
||||||
Load = ChannelLoad.Full
|
|
||||||
},
|
|
||||||
new ChannelInfo
|
|
||||||
{
|
|
||||||
Name = "Unhelpful Channel",
|
|
||||||
EndPoint = new IPEndPoint(_server.Config.IPAddress, 6),
|
|
||||||
Type = ChannelType.Special
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleChannelEnter(ChannelEnterQuery packet)
|
|
||||||
{
|
|
||||||
// Simply allow joining a channel running on the same server port.
|
|
||||||
SendPacket(new ChannelEnterReply
|
|
||||||
{
|
|
||||||
EndPoint = _server.Config.EndPoint
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleChannelConnect(ChannelConnectQuery packet)
|
|
||||||
{
|
|
||||||
SendPacket(new ChannelConnectReply
|
|
||||||
{
|
|
||||||
Result = ChannelConnectResult.Success,
|
|
||||||
Player = new ChannelConnectPlayerInfo
|
|
||||||
{
|
|
||||||
ID = packet.Players[0].ID,
|
|
||||||
Name = "Your Name",
|
|
||||||
Experience = 1337,
|
|
||||||
Gold = 1000000,
|
|
||||||
Rank = 19,
|
|
||||||
GuildMarkIndex = 1,
|
|
||||||
GuildName = "Your Guild"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleChannelTop20(ChannelTop20Query packet)
|
|
||||||
{
|
|
||||||
// Send some simulated player rank infos.
|
|
||||||
ChannelTop20Reply reply = new ChannelTop20Reply
|
|
||||||
{
|
|
||||||
UnknownA = "Test",
|
|
||||||
Top20 = new List<ChannelTop20Player>(20)
|
|
||||||
};
|
};
|
||||||
for (int i = 0; i < 20; i++)
|
|
||||||
{
|
|
||||||
reply.Top20.Add(new ChannelTop20Player
|
|
||||||
{
|
|
||||||
Name = $"GoodPlayer{(char)('A' + i)}",
|
|
||||||
Rank = (ushort)((i + 6) / 3),
|
|
||||||
Experience = (ulong)(20 - i) * 957
|
|
||||||
});
|
|
||||||
}
|
|
||||||
SendPacket(reply);
|
|
||||||
|
|
||||||
// This is the last channel info packet, tell the client to go to the channel screen.
|
|
||||||
SendPacket(new ChannelEnterFinishReply());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleStartSingleGameQuery(StartSingleGameQuery packet)
|
|
||||||
{
|
|
||||||
SendPacket(new StartSingleGameReply
|
|
||||||
{
|
|
||||||
Success = packet.RoundType == GameStartRoundType.First
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
public void HandleRaw(RawPacket packet)
|
|
||||||
{
|
|
||||||
SendPacket(new RawPacket(PacketFormat.Wwpa, 0x0000,
|
|
||||||
new byte[] { 0x01, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00 }));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
protected override void OnPrePacketHandle(Packet packet)
|
|
||||||
{
|
|
||||||
_server.Log.Write(LogCategory.Client, FormatPacket(packet, ">>"));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnPrePacketSend(Packet packet)
|
|
||||||
{
|
|
||||||
_server.Log.Write(LogCategory.Server, FormatPacket(packet, "<<"));
|
|
||||||
if (_server.Config.SendDelay > 0)
|
|
||||||
Thread.Sleep(_server.Config.SendDelay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
|
namespace Syroot.Worms.Mgame.GameServer.Core.IO
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents extension methods for <see cref="SpanWriter"/> instances.
|
||||||
|
/// </summary>
|
||||||
|
internal static class SpanWriterExtensions
|
||||||
|
{
|
||||||
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the given <paramref name="color"/> as an RGB0 integer value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self">The extended instance.</param>
|
||||||
|
/// <param name="color">The <see cref="Color"/> to write.</param>
|
||||||
|
internal static void WriteColor(this SpanWriter self, Color color)
|
||||||
|
{
|
||||||
|
self.WriteByte(color.R);
|
||||||
|
self.WriteByte(color.G);
|
||||||
|
self.WriteByte(color.B);
|
||||||
|
self.WriteByte(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,9 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
using Syroot.Worms.Mgame.GameServer.Core.Net;
|
using Syroot.Worms.Mgame.GameServer.Core.Net;
|
||||||
using Syroot.Worms.Mgame.GameServer.Core.Reflection;
|
using Syroot.Worms.Mgame.GameServer.Core.Reflection;
|
||||||
using Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua;
|
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets
|
namespace Syroot.Worms.Mgame.GameServer.Packets
|
||||||
{
|
{
|
||||||
@ -15,7 +15,7 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
{
|
{
|
||||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
private const int _maxDataSize = 2048;
|
private const int _maxDataSize = 1024;
|
||||||
private const ushort _owTagStartChannel = 0xFFFE;
|
private const ushort _owTagStartChannel = 0xFFFE;
|
||||||
private const ushort _owTagEndChannel = 0xFEFF;
|
private const ushort _owTagEndChannel = 0xFEFF;
|
||||||
private const ushort _wwpaTagStart = 0x2E9E;
|
private const ushort _wwpaTagStart = 0x2E9E;
|
||||||
@ -25,7 +25,6 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
|
|
||||||
private readonly MethodHandler<Packet> _methodHandler;
|
private readonly MethodHandler<Packet> _methodHandler;
|
||||||
private readonly SafeNetworkStream _tcpStream;
|
private readonly SafeNetworkStream _tcpStream;
|
||||||
private readonly PacketDataStream _packetDataStream;
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||||
@ -40,9 +39,13 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
_methodHandler = new MethodHandler<Packet>(this);
|
_methodHandler = new MethodHandler<Packet>(this);
|
||||||
TcpClient = tcpClient;
|
TcpClient = tcpClient;
|
||||||
_tcpStream = TcpClient.GetSafeStream();
|
_tcpStream = TcpClient.GetSafeStream();
|
||||||
_packetDataStream = new PacketDataStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- EVENTS -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected event EventHandler<Packet> PrePacketHandle;
|
||||||
|
protected event EventHandler<Packet> PrePacketSend;
|
||||||
|
|
||||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -68,7 +71,7 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
Packet packet;
|
Packet packet;
|
||||||
while ((packet = ReceivePacket()) != null)
|
while ((packet = ReceivePacket()) != null)
|
||||||
{
|
{
|
||||||
OnPrePacketHandle(packet);
|
PrePacketHandle?.Invoke(this, packet);
|
||||||
_methodHandler.Handle(packet);
|
_methodHandler.Handle(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,41 +83,28 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
if (!_disposed)
|
if (!_disposed)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
|
||||||
TcpClient.Dispose();
|
TcpClient.Dispose();
|
||||||
_packetDataStream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnPrePacketHandle(Packet packet) { }
|
|
||||||
|
|
||||||
protected virtual void OnPrePacketSend(Packet packet) { }
|
|
||||||
|
|
||||||
protected bool SendPacket(Packet packet)
|
protected bool SendPacket(Packet packet)
|
||||||
{
|
{
|
||||||
OnPrePacketSend(packet);
|
PrePacketSend?.Invoke(this, packet);
|
||||||
|
|
||||||
// Serialize the packet data to retrieve its size.
|
|
||||||
_packetDataStream.Position = 0;
|
|
||||||
packet.SaveData(_packetDataStream);
|
|
||||||
|
|
||||||
// Send the total packet data including head and tail.
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Handle specific packet formats.
|
||||||
PacketAttribute attribute = PacketFactory.GetAttribute(packet);
|
PacketAttribute attribute = PacketFactory.GetAttribute(packet);
|
||||||
switch (attribute.Format)
|
switch (attribute.Format)
|
||||||
{
|
{
|
||||||
case PacketFormat.OWChannel:
|
case PacketFormat.OWChannel:
|
||||||
SendOWChannelPacket(attribute.ID);
|
SendOWChannelPacket(attribute.ID, packet);
|
||||||
break;
|
break;
|
||||||
case PacketFormat.OWServer:
|
case PacketFormat.OWServer:
|
||||||
SendOWServerPacket(attribute.ID);
|
SendOWServerPacket(attribute.ID, packet);
|
||||||
break;
|
break;
|
||||||
case PacketFormat.Wwpa:
|
case PacketFormat.Wwpa:
|
||||||
SaveWwpaPacket(packet);
|
SaveWwpaPacket(attribute.ID, packet);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IOException("Cannot send unknown packet format.");
|
throw new IOException("Cannot send unknown packet format.");
|
||||||
@ -155,7 +145,7 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
int dataSize = _tcpStream.ReadUInt16();
|
int dataSize = _tcpStream.ReadUInt16();
|
||||||
int id = _tcpStream.Read1Byte();
|
int id = _tcpStream.Read1Byte();
|
||||||
// Read data.
|
// Read data.
|
||||||
byte[] data = _tcpStream.ReadBytes(dataSize);
|
SpanReader reader = new SpanReader(_tcpStream.ReadBytes(dataSize), encoding: Encodings.Win949);
|
||||||
// Read tail.
|
// Read tail.
|
||||||
ushort endTag = _tcpStream.ReadUInt16();
|
ushort endTag = _tcpStream.ReadUInt16();
|
||||||
if (endTag != _owTagEndChannel)
|
if (endTag != _owTagEndChannel)
|
||||||
@ -163,8 +153,7 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
|
|
||||||
// Instantiate, deserialize, and return packet.
|
// Instantiate, deserialize, and return packet.
|
||||||
Packet packet = PacketFactory.Create(PacketFormat.OWChannel, id);
|
Packet packet = PacketFactory.Create(PacketFormat.OWChannel, id);
|
||||||
using (PacketDataStream stream = new PacketDataStream(data))
|
packet.LoadData(reader);
|
||||||
packet.LoadData(stream);
|
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,12 +162,11 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
// Read head.
|
// Read head.
|
||||||
int dataSize = _tcpStream.ReadUInt16();
|
int dataSize = _tcpStream.ReadUInt16();
|
||||||
// Read data.
|
// Read data.
|
||||||
byte[] data = _tcpStream.ReadBytes(dataSize);
|
SpanReader reader = new SpanReader(_tcpStream.ReadBytes(dataSize), encoding: Encodings.Win949);
|
||||||
|
|
||||||
// Instantiate, deserialize, and return packet.
|
// Instantiate, deserialize, and return packet.
|
||||||
Packet packet = PacketFactory.Create(PacketFormat.OWServer, tag);
|
Packet packet = PacketFactory.Create(PacketFormat.OWServer, tag);
|
||||||
using (PacketDataStream stream = new PacketDataStream(data))
|
packet.LoadData(reader);
|
||||||
packet.LoadData(stream);
|
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,59 +191,60 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
throw new PacketException("Invalid WWPA packet end tag.");
|
throw new PacketException("Invalid WWPA packet end tag.");
|
||||||
|
|
||||||
// Instantiate, deserialize, and return packet.
|
// Instantiate, deserialize, and return packet.
|
||||||
int id = 0;
|
SpanReader reader = new SpanReader(PacketCompression.Decompress(compressedData), encoding: Encodings.Win949);
|
||||||
|
int id = reader.ReadInt32();
|
||||||
Packet packet = PacketFactory.Create(PacketFormat.Wwpa, id);
|
Packet packet = PacketFactory.Create(PacketFormat.Wwpa, id);
|
||||||
ReadOnlySpan<byte> decompressedData = PacketCompression.Decompress(compressedData);
|
packet.LoadData(reader.Slice());
|
||||||
using (PacketDataStream stream = new PacketDataStream(decompressedData.ToArray()))
|
|
||||||
packet.LoadData(stream);
|
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendOWChannelPacket(int id)
|
private void SendOWChannelPacket(int id, Packet packet)
|
||||||
{
|
{
|
||||||
// Retrieve data size. Must have at least 1 byte.
|
// Retrieve data. Must have at least 1 byte.
|
||||||
if (_packetDataStream.Position == 0)
|
SpanWriter writer = new SpanWriter(new byte[_maxDataSize], encoding: Encodings.Win949);
|
||||||
_packetDataStream.WriteByte(0);
|
packet.SaveData(writer);
|
||||||
ushort dataSize = (ushort)_packetDataStream.Position;
|
writer.Position = Math.Max(1, writer.Position);
|
||||||
|
|
||||||
// Send head.
|
// Send head.
|
||||||
_tcpStream.WriteUInt16(_owTagStartChannel);
|
_tcpStream.WriteUInt16(_owTagStartChannel);
|
||||||
_tcpStream.WriteByte(1);
|
_tcpStream.WriteByte(1);
|
||||||
_tcpStream.WriteUInt16(dataSize);
|
_tcpStream.WriteUInt16((ushort)writer.Position);
|
||||||
_tcpStream.WriteByte((byte)id);
|
_tcpStream.WriteByte((byte)id);
|
||||||
|
|
||||||
// Send data.
|
// Send data.
|
||||||
_tcpStream.Write(_packetDataStream.GetSpan());
|
_tcpStream.Write(writer.Span);
|
||||||
|
|
||||||
// Send tail.
|
// Send tail.
|
||||||
_tcpStream.WriteUInt16(_owTagEndChannel);
|
_tcpStream.WriteUInt16(_owTagEndChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendOWServerPacket(int id)
|
private void SendOWServerPacket(int id, Packet packet)
|
||||||
{
|
{
|
||||||
// Retrieve data size.
|
// Retrieve data.
|
||||||
ushort dataSize = (ushort)_packetDataStream.Position;
|
SpanWriter writer = new SpanWriter(new byte[_maxDataSize], encoding: Encodings.Win949);
|
||||||
|
packet.SaveData(writer);
|
||||||
|
|
||||||
// Send head.
|
// Send head.
|
||||||
_tcpStream.WriteUInt16((ushort)id);
|
_tcpStream.WriteUInt16((ushort)id);
|
||||||
_tcpStream.WriteUInt16(dataSize);
|
_tcpStream.WriteUInt16((ushort)writer.Position);
|
||||||
|
|
||||||
// Write data.
|
// Write data.
|
||||||
_tcpStream.Write(_packetDataStream.GetSpan());
|
_tcpStream.Write(writer.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveWwpaPacket(Packet packet)
|
private void SaveWwpaPacket(int id, Packet packet)
|
||||||
{
|
{
|
||||||
// Retrieve (decompressed) data size.
|
// Retrieve (decompressed) data size.
|
||||||
ReadOnlySpan<byte> decompressedData = _packetDataStream.GetSpan();
|
SpanWriter writer = new SpanWriter(new byte[_maxDataSize], encoding: Encodings.Win949);
|
||||||
ReadOnlySpan<byte> compressedData = PacketCompression.Compress(decompressedData);
|
packet.SaveData(writer);
|
||||||
|
ReadOnlySpan<byte> compressedData = PacketCompression.Compress(writer.Span);
|
||||||
|
|
||||||
// Send head.
|
// Send head.
|
||||||
_tcpStream.WriteUInt16(_wwpaTagStart);
|
_tcpStream.WriteUInt16(_wwpaTagStart);
|
||||||
_tcpStream.WriteBoolean(true);
|
_tcpStream.WriteBoolean(true);
|
||||||
_tcpStream.WriteBoolean(false);
|
_tcpStream.WriteBoolean(false);
|
||||||
_tcpStream.WriteBoolean(true); // isCompressed
|
_tcpStream.WriteBoolean(true); // isCompressed
|
||||||
_tcpStream.WriteUInt16((ushort)decompressedData.Length);
|
_tcpStream.WriteUInt16((ushort)writer.Span.Length);
|
||||||
_tcpStream.WriteUInt32((uint)compressedData.Length);
|
_tcpStream.WriteUInt32((uint)compressedData.Length);
|
||||||
_tcpStream.WriteInt32(1); // Apparently only needs to be same as in tail.
|
_tcpStream.WriteInt32(1); // Apparently only needs to be same as in tail.
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -25,33 +25,33 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream)
|
internal override void LoadData(SpanReader reader)
|
||||||
{
|
{
|
||||||
Players = new List<ChannelConnectPlayerCredentials>
|
Players = new List<ChannelConnectPlayerCredentials>
|
||||||
{
|
{
|
||||||
new ChannelConnectPlayerCredentials
|
new ChannelConnectPlayerCredentials
|
||||||
{
|
{
|
||||||
ID = stream.ReadString(12),
|
ID = reader.ReadStringFix(12),
|
||||||
Password = stream.ReadString(12)
|
Password = reader.ReadStringFix(12)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ClientIP = IPAddress.Parse(stream.ReadString(15));
|
ClientIP = IPAddress.Parse(reader.ReadStringFix(15));
|
||||||
ClientVersion = stream.ReadUInt16();
|
ClientVersion = reader.ReadUInt16();
|
||||||
UnknownA = stream.ReadUInt16();
|
UnknownA = reader.ReadUInt16();
|
||||||
|
|
||||||
ushort additionalPlayers = stream.ReadUInt16();
|
ushort additionalPlayers = reader.ReadUInt16();
|
||||||
for (int i = 0; i < additionalPlayers; i++)
|
for (int i = 0; i < additionalPlayers; i++)
|
||||||
{
|
{
|
||||||
Players.Add(new ChannelConnectPlayerCredentials
|
Players.Add(new ChannelConnectPlayerCredentials
|
||||||
{
|
{
|
||||||
ID = stream.ReadString(12),
|
ID = reader.ReadStringFix(12),
|
||||||
Password = stream.ReadString(12)
|
Password = reader.ReadStringFix(12)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
UnknownB = stream.Read1Byte();
|
UnknownB = reader.ReadByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void SaveData(SpanWriter writer) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ChannelConnectPlayerCredentials
|
internal class ChannelConnectPlayerCredentials
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData.Memory;
|
||||||
using Syroot.Worms.Core.IO;
|
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -18,55 +17,55 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
if (Result == ChannelConnectResult.Success)
|
if (Result == ChannelConnectResult.Success)
|
||||||
{
|
{
|
||||||
stream.WriteBoolean(true, BooleanCoding.Word);
|
writer.WriteBoolean2(true);
|
||||||
stream.WriteUInt16(0); // field_1E710
|
writer.WriteUInt16(0); // field_1E710
|
||||||
stream.WriteUInt32(0); // field_1E714
|
writer.WriteUInt32(0); // field_1E714
|
||||||
stream.WriteString(Player.ID, 12);
|
writer.WriteStringFix(Player.ID, 12);
|
||||||
stream.WriteString(Player.Name, 10);
|
writer.WriteStringFix(Player.Name, 10);
|
||||||
stream.WriteUInt16(Player.UnknownB);
|
writer.WriteUInt16(Player.UnknownB);
|
||||||
stream.WriteUInt16(Player.UnknownC);
|
writer.WriteUInt16(Player.UnknownC);
|
||||||
stream.WriteUInt16(Player.UnknownD);
|
writer.WriteUInt16(Player.UnknownD);
|
||||||
stream.WriteUInt16(Player.UnknownE);
|
writer.WriteUInt16(Player.UnknownE);
|
||||||
stream.WriteUInt16(Player.UnknownF);
|
writer.WriteUInt16(Player.UnknownF);
|
||||||
stream.WriteUInt16(Player.UnknownG);
|
writer.WriteUInt16(Player.UnknownG);
|
||||||
stream.WriteUInt16(Player.UnknownH);
|
writer.WriteUInt16(Player.UnknownH);
|
||||||
stream.WriteUInt16(Player.UnknownI);
|
writer.WriteUInt16(Player.UnknownI);
|
||||||
stream.WriteUInt16(Player.UnknownJ);
|
writer.WriteUInt16(Player.UnknownJ);
|
||||||
stream.WriteUInt16(Player.UnknownK);
|
writer.WriteUInt16(Player.UnknownK);
|
||||||
stream.WriteUInt16(Player.UnknownL);
|
writer.WriteUInt16(Player.UnknownL);
|
||||||
stream.WriteUInt16(Player.UnknownM);
|
writer.WriteUInt16(Player.UnknownM);
|
||||||
stream.WriteUInt16(Player.UnknownN);
|
writer.WriteUInt16(Player.UnknownN);
|
||||||
stream.WriteUInt16(Player.UnknownO);
|
writer.WriteUInt16(Player.UnknownO);
|
||||||
stream.WriteUInt64(Player.Experience);
|
writer.WriteUInt64(Player.Experience);
|
||||||
stream.WriteUInt64(Player.Gold);
|
writer.WriteUInt64(Player.Gold);
|
||||||
stream.WriteUInt16(Player.Rank);
|
writer.WriteUInt16(Player.Rank);
|
||||||
stream.WriteUInt16(Player.GuildMarkIndex);
|
writer.WriteUInt16(Player.GuildMarkIndex);
|
||||||
stream.WriteString(Player.GuildName, 12);
|
writer.WriteStringFix(Player.GuildName, 12);
|
||||||
stream.WriteUInt32(Player.UnknownS);
|
writer.WriteUInt32(Player.UnknownS);
|
||||||
stream.WriteUInt32(0); // v29
|
writer.WriteUInt32(0); // v29
|
||||||
stream.WriteUInt16(0); // v30
|
writer.WriteUInt16(0); // v30
|
||||||
stream.WriteUInt16(Player.UnknownT);
|
writer.WriteUInt16(Player.UnknownT);
|
||||||
stream.WriteUInt16(Player.UnknownU);
|
writer.WriteUInt16(Player.UnknownU);
|
||||||
stream.WriteUInt16(Player.UnknownV);
|
writer.WriteUInt16(Player.UnknownV);
|
||||||
stream.WriteUInt16(Player.UnknownW);
|
writer.WriteUInt16(Player.UnknownW);
|
||||||
stream.WriteString(Player.UnknownX, 20);
|
writer.WriteStringFix(Player.UnknownX, 20);
|
||||||
stream.WriteString(Player.UnknownY, 20);
|
writer.WriteStringFix(Player.UnknownY, 20);
|
||||||
stream.WriteString(Player.UnknownZ, 20);
|
writer.WriteStringFix(Player.UnknownZ, 20);
|
||||||
stream.WriteString(Player.UnknownAA, 20);
|
writer.WriteStringFix(Player.UnknownAA, 20);
|
||||||
stream.WriteUInt16(Player.UnknownAB);
|
writer.WriteUInt16(Player.UnknownAB);
|
||||||
stream.WriteUInt16(Player.UnknownAC);
|
writer.WriteUInt16(Player.UnknownAC);
|
||||||
// TODO: Handle UnknownAC counting something.
|
// TODO: Handle UnknownAC counting something.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream.WriteBoolean(false, BooleanCoding.Word);
|
writer.WriteBoolean2(false);
|
||||||
stream.WriteEnum(Result, true);
|
writer.WriteEnumSafe(Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -11,8 +12,8 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
{
|
{
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream) { }
|
internal override void SaveData(SpanWriter writer) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -17,12 +18,12 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream)
|
internal override void LoadData(SpanReader reader)
|
||||||
{
|
{
|
||||||
PlayerID = stream.ReadString();
|
PlayerID = reader.ReadString();
|
||||||
ChannelEndPoint = new IPEndPoint(IPAddress.Parse(stream.ReadString()), stream.ReadUInt16());
|
ChannelEndPoint = new IPEndPoint(IPAddress.Parse(reader.ReadString()), reader.ReadUInt16());
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void SaveData(SpanWriter writer) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -18,12 +19,12 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
stream.WriteString(EndPoint.Address.ToString());
|
writer.WriteString(EndPoint.Address.ToString());
|
||||||
stream.WriteUInt16((ushort)EndPoint.Port);
|
writer.WriteUInt16((ushort)EndPoint.Port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData.Memory;
|
||||||
|
using Syroot.Worms.Mgame.GameServer.Core.IO;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -18,24 +19,24 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
stream.WriteUInt16((ushort)Channels.Count);
|
writer.WriteUInt16((ushort)Channels.Count);
|
||||||
foreach (ChannelInfo channel in Channels)
|
foreach (ChannelInfo channel in Channels)
|
||||||
{
|
{
|
||||||
stream.WriteEnum(channel.Type, true);
|
writer.WriteEnumSafe(channel.Type);
|
||||||
stream.WriteByte(channel.Coins);
|
writer.WriteByte(channel.Coins);
|
||||||
stream.WriteColor(channel.Color);
|
writer.WriteColor(channel.Color);
|
||||||
stream.WriteUInt16(1); // ?
|
writer.WriteUInt16(1); // ?
|
||||||
|
|
||||||
stream.WriteString(channel.Name);
|
writer.WriteString(channel.Name);
|
||||||
stream.WriteByte(0); // ?
|
writer.WriteByte(0); // ?
|
||||||
|
|
||||||
stream.WriteBytes(channel.EndPoint.Address.GetAddressBytes());
|
writer.WriteBytes(channel.EndPoint.Address.GetAddressBytes());
|
||||||
stream.WriteUInt16((ushort)channel.EndPoint.Port);
|
writer.WriteUInt16((ushort)channel.EndPoint.Port);
|
||||||
stream.WriteEnum(channel.Load, true);
|
writer.WriteEnumSafe(channel.Load);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -17,11 +18,11 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream)
|
internal override void LoadData(SpanReader reader)
|
||||||
{
|
{
|
||||||
Count = stream.ReadUInt16();
|
Count = reader.ReadUInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void SaveData(SpanWriter writer) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData.Memory;
|
||||||
using Syroot.Worms.Core.IO;
|
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -19,16 +18,16 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
stream.WriteString(UnknownA, 30);
|
writer.WriteStringFix(UnknownA, 30);
|
||||||
foreach (ChannelTop20Player top20Player in Top20)
|
foreach (ChannelTop20Player top20Player in Top20)
|
||||||
{
|
{
|
||||||
stream.WriteUInt16(top20Player.Rank);
|
writer.WriteUInt16(top20Player.Rank);
|
||||||
stream.WriteString(top20Player.Name, 12);
|
writer.WriteStringFix(top20Player.Name, 12);
|
||||||
stream.WriteUInt64(top20Player.Experience);
|
writer.WriteUInt64(top20Player.Experience);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -10,8 +11,8 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
{
|
{
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) { }
|
internal override void LoadData(SpanReader reader) { }
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void SaveData(SpanWriter writer) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -18,14 +19,14 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
stream.WriteString(Unknown);
|
writer.WriteString(Unknown);
|
||||||
stream.WriteByte(0);
|
writer.WriteByte(0);
|
||||||
stream.WriteString(Unknown2);
|
writer.WriteString(Unknown2);
|
||||||
stream.WriteUInt16(Version);
|
writer.WriteUInt16(Version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -19,22 +20,22 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream)
|
internal override void LoadData(SpanReader reader)
|
||||||
{
|
{
|
||||||
Unknown1 = stream.ReadUInt16();
|
Unknown1 = reader.ReadUInt16();
|
||||||
Logins = new LoginCredentials[stream.ReadUInt16()];
|
Logins = new LoginCredentials[reader.ReadUInt16()];
|
||||||
for (int i = 0; i < Logins.Length; i++)
|
for (int i = 0; i < Logins.Length; i++)
|
||||||
{
|
{
|
||||||
Logins[i] = new LoginCredentials
|
Logins[i] = new LoginCredentials
|
||||||
{
|
{
|
||||||
ID = stream.ReadString(),
|
ID = reader.ReadString(),
|
||||||
Password = stream.ReadString()
|
Password = reader.ReadString()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
ClientIP = IPAddress.Parse(stream.ReadString());
|
ClientIP = IPAddress.Parse(reader.ReadString());
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void SaveData(SpanWriter writer) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class LoginCredentials
|
internal class LoginCredentials
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -23,25 +23,25 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
bool loginSuccessful = Result == LoginResult.Success;
|
bool loginSuccessful = Result == LoginResult.Success;
|
||||||
stream.WriteBoolean(loginSuccessful);
|
writer.WriteBoolean(loginSuccessful);
|
||||||
if (loginSuccessful)
|
if (loginSuccessful)
|
||||||
{
|
{
|
||||||
stream.WriteBoolean(!HasMessageRights, BooleanCoding.Word);
|
writer.WriteBoolean2(!HasMessageRights);
|
||||||
stream.WriteUInt16((ushort)PlayerInfos.Length);
|
writer.WriteUInt16((ushort)PlayerInfos.Length);
|
||||||
foreach (LoginPlayerInfo playerInfo in PlayerInfos)
|
foreach (LoginPlayerInfo playerInfo in PlayerInfos)
|
||||||
{
|
{
|
||||||
stream.WriteString(playerInfo.ID);
|
writer.WriteString(playerInfo.ID);
|
||||||
stream.WriteUInt16(playerInfo.Rank);
|
writer.WriteUInt16(playerInfo.Rank);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream.WriteEnum(Result, true);
|
writer.WriteEnumSafe(Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -18,11 +19,11 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
stream.WriteString(Text.Replace(Environment.NewLine, "\n"));
|
writer.WriteString(Text.Replace(Environment.NewLine, "\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -17,14 +17,14 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream)
|
internal override void LoadData(SpanReader reader)
|
||||||
{
|
{
|
||||||
RoundType = stream.ReadEnum<GameStartRoundType>(true);
|
RoundType = reader.ReadEnumSafe<GameStartRoundType>();
|
||||||
UnknownB = stream.Read1Byte();
|
UnknownB = reader.ReadByte();
|
||||||
UnknownC = stream.Read1Byte();
|
UnknownC = reader.ReadByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void SaveData(SpanWriter writer) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum GameStartRoundType : byte
|
internal enum GameStartRoundType : byte
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
||||||
{
|
{
|
||||||
@ -15,11 +15,11 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.OnlineWorms
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream) => throw new NotImplementedException();
|
internal override void LoadData(SpanReader reader) => throw new NotImplementedException();
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
stream.WriteBoolean(Success, BooleanCoding.Word);
|
writer.WriteBoolean2(Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
namespace Syroot.Worms.Mgame.GameServer.Packets
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
|
namespace Syroot.Worms.Mgame.GameServer.Packets
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a packet with an ID specifying its contents. To allow the server to instantiate child packet classes,
|
/// Represents a packet with an ID specifying its contents. To allow the server to instantiate child packet classes,
|
||||||
@ -8,8 +10,8 @@
|
|||||||
{
|
{
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal abstract void LoadData(PacketDataStream stream);
|
internal abstract void LoadData(SpanReader reader);
|
||||||
|
|
||||||
internal abstract void SaveData(PacketDataStream stream);
|
internal abstract void SaveData(SpanWriter writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData;
|
||||||
@ -22,16 +21,19 @@ namespace Syroot.Worms.Mgame.GameServer
|
|||||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal PacketDataStream() : this(new MemoryStream()) { }
|
internal PacketDataStream(MemoryStream baseStream)
|
||||||
|
|
||||||
internal PacketDataStream(byte[] buffer) : this(new MemoryStream(buffer)) { }
|
|
||||||
|
|
||||||
private PacketDataStream(MemoryStream baseStream)
|
|
||||||
: base(baseStream, encoding: Encoding.GetEncoding(949), stringCoding: StringCoding.Int16CharCount)
|
: base(baseStream, encoding: Encoding.GetEncoding(949), stringCoding: StringCoding.Int16CharCount)
|
||||||
{
|
{
|
||||||
_baseStream = baseStream;
|
_baseStream = baseStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal PacketDataStream(MemoryStream baseStream, int offset)
|
||||||
|
: this(new MemoryStream(baseStream.GetBuffer(), offset, (int)baseStream.Length - offset)) { }
|
||||||
|
|
||||||
|
internal PacketDataStream() : this(new MemoryStream()) { }
|
||||||
|
|
||||||
|
internal PacketDataStream(byte[] buffer) : this(new MemoryStream(buffer)) { }
|
||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -48,17 +50,5 @@ namespace Syroot.Worms.Mgame.GameServer
|
|||||||
{
|
{
|
||||||
return ReadBytes((int)(Length - Position));
|
return ReadBytes((int)(Length - Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes the given <paramref name="color"/> as an RGB0 integer value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="color">The <see cref="Color"/> to write.</param>
|
|
||||||
internal void WriteColor(Color color)
|
|
||||||
{
|
|
||||||
WriteByte(color.R);
|
|
||||||
WriteByte(color.G);
|
|
||||||
WriteByte(color.B);
|
|
||||||
WriteByte(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
using Syroot.BinaryData;
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets
|
namespace Syroot.Worms.Mgame.GameServer.Packets
|
||||||
{
|
{
|
||||||
@ -27,14 +27,14 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
|
|||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal override void LoadData(PacketDataStream stream)
|
internal override void LoadData(SpanReader reader)
|
||||||
{
|
{
|
||||||
Data = stream.ReadBytes((int)stream.Length);
|
Data = reader.ReadBytes(reader.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void SaveData(PacketDataStream stream)
|
internal override void SaveData(SpanWriter writer)
|
||||||
{
|
{
|
||||||
stream.WriteBytes(Data);
|
writer.WriteBytes(Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
using Syroot.BinaryData.Memory;
|
||||||
|
|
||||||
|
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the client request for a <see cref="ConnectReply"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Packet(PacketFormat.Wwpa, 0x8001)]
|
||||||
|
internal class ConnectQuery : Packet
|
||||||
|
{
|
||||||
|
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
internal override void LoadData(SpanReader reader) { }
|
||||||
|
|
||||||
|
internal override void SaveData(SpanWriter writer) { }
|
||||||
|
}
|
||||||
|
}
|
@ -1,329 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents packet data encryption as used in WWPA. Note that most code is a direct translation from the original
|
|
||||||
/// game assembly.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The original implementation has the following bugs caused by specific, but rare patterns (in 1000 random blobs
|
|
||||||
/// of sizes between 1 and 1000 bytes, ~0.5% were decompressed badly):
|
|
||||||
/// - Bad calculation of decompressed bytes. The same wrong bytes are calculated by this implementation. Such data
|
|
||||||
/// may be discarded by the game as soon as it causes the final length to differ.
|
|
||||||
/// - Bad negative source buffer indices cause out-of-bounds memory to be written. Combatted in this implementation
|
|
||||||
/// by ignoring such writes and keeping 0 bytes instead.
|
|
||||||
/// </remarks>
|
|
||||||
public static class PacketCompression
|
|
||||||
{
|
|
||||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
private static int _numBytesTransferred = 0;
|
|
||||||
|
|
||||||
private static int _field_4 = 4;
|
|
||||||
private static int _field_8 = 0;
|
|
||||||
|
|
||||||
private static int _field_C = 0;
|
|
||||||
private static int _field_10 = 0;
|
|
||||||
|
|
||||||
private static int[] _bufferDwords = new int[512];
|
|
||||||
|
|
||||||
private static byte[] _buffer = new byte[256];
|
|
||||||
private static int _bufferCursor = 0;
|
|
||||||
|
|
||||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compresses the given <paramref name="decompressed"/> data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="decompressed">The data to compress.</param>
|
|
||||||
/// <returns>The compressed data.</returns>
|
|
||||||
public static ReadOnlySpan<byte> Compress(ReadOnlySpan<byte> decompressed)
|
|
||||||
{
|
|
||||||
Compressor compressor = new Compressor();
|
|
||||||
int idx;
|
|
||||||
int bytesToRepeat;
|
|
||||||
int idxDword;
|
|
||||||
int i;
|
|
||||||
int offset;
|
|
||||||
int v11;
|
|
||||||
int v12;
|
|
||||||
int field_8;
|
|
||||||
int field_10;
|
|
||||||
byte c;
|
|
||||||
int shiftValue1;
|
|
||||||
|
|
||||||
idx = 0;
|
|
||||||
while (idx < decompressed.Length)
|
|
||||||
{
|
|
||||||
bytesToRepeat = idx - 0xFF;
|
|
||||||
if (idx - 0xFF < 0)
|
|
||||||
bytesToRepeat = 0;
|
|
||||||
idxDword = 0;
|
|
||||||
shiftValue1 = -1;
|
|
||||||
if (bytesToRepeat >= idx)
|
|
||||||
{
|
|
||||||
c = decompressed[idx++];
|
|
||||||
Write(compressor, c);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (i = idx; i < decompressed.Length; ++i)
|
|
||||||
{
|
|
||||||
if (i - idx >= 0x111)
|
|
||||||
break;
|
|
||||||
if (decompressed[bytesToRepeat] != decompressed[i])
|
|
||||||
break;
|
|
||||||
++bytesToRepeat;
|
|
||||||
}
|
|
||||||
offset = idx - i;
|
|
||||||
v11 = i - idx;
|
|
||||||
v12 = offset + bytesToRepeat;
|
|
||||||
if (v11 >= 3 && v11 > idxDword)
|
|
||||||
{
|
|
||||||
idxDword = v11;
|
|
||||||
shiftValue1 = idx - 12;
|
|
||||||
if (v11 == 0x111)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bytesToRepeat = v12 + 1;
|
|
||||||
}
|
|
||||||
while (bytesToRepeat < idx);
|
|
||||||
if (idxDword != 0)
|
|
||||||
{
|
|
||||||
TransferBuffer(compressor);
|
|
||||||
compressor.Compress(true);
|
|
||||||
if (idxDword >= 18)
|
|
||||||
{
|
|
||||||
compressor.Shift(0, 4);
|
|
||||||
compressor.Shift(shiftValue1, 8);
|
|
||||||
compressor.Shift(idxDword - 18, 8);
|
|
||||||
field_10 = _field_10;
|
|
||||||
++_field_C;
|
|
||||||
_field_10 = idxDword - 3 + field_10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
compressor.Shift(idxDword - 2, 4);
|
|
||||||
compressor.Shift(shiftValue1 - 1, 8);
|
|
||||||
field_8 = _field_8;
|
|
||||||
++_field_4;
|
|
||||||
_field_8 = idxDword - 2 + field_8;
|
|
||||||
}
|
|
||||||
idx += idxDword;
|
|
||||||
++_bufferDwords[idxDword];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c = decompressed[idx++];
|
|
||||||
Write(compressor, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TransferBuffer(compressor);
|
|
||||||
compressor.Compress(true);
|
|
||||||
compressor.Shift(0, 4);
|
|
||||||
compressor.Shift(0, 8);
|
|
||||||
|
|
||||||
return compressor.Compressed.AsSpan(0, compressor.Cursor);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ReadOnlySpan<byte> Decompress(ReadOnlySpan<byte> compressed)
|
|
||||||
{
|
|
||||||
Decompressor decompressor = new Decompressor(compressed);
|
|
||||||
byte[] decompressed = new byte[2048];
|
|
||||||
int idx;
|
|
||||||
int bytesToCopyRemain;
|
|
||||||
int idxCopySrc;
|
|
||||||
int v12;
|
|
||||||
int v13;
|
|
||||||
int bytesToCopy;
|
|
||||||
|
|
||||||
idx = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
while (decompressor.sub_4C0BA0() == 0)
|
|
||||||
{
|
|
||||||
bytesToCopy = decompressor.GetBytesToCopy(8);
|
|
||||||
if (bytesToCopy != -1)
|
|
||||||
{
|
|
||||||
++bytesToCopy;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
decompressed[idx++] = decompressor.Read();
|
|
||||||
--bytesToCopy;
|
|
||||||
} while (bytesToCopy != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytesToCopy = decompressor.GetBytesToCopy(4) + 2;
|
|
||||||
if (bytesToCopy <= 2)
|
|
||||||
break;
|
|
||||||
bytesToCopy = decompressor.GetBytesToCopy(8) + 1;
|
|
||||||
bytesToCopyRemain = bytesToCopy - 1;
|
|
||||||
if (bytesToCopy != 0)
|
|
||||||
{
|
|
||||||
++bytesToCopyRemain;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
idxCopySrc = idx++ - bytesToCopy;
|
|
||||||
--bytesToCopyRemain;
|
|
||||||
if (idxCopySrc >= 0) // Bugfix: Original implementation may calculate negative indices.
|
|
||||||
decompressed[idx - 1] = decompressed[idxCopySrc];
|
|
||||||
} while (bytesToCopyRemain != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytesToCopy = decompressor.GetBytesToCopy(8);
|
|
||||||
if (bytesToCopy == 0)
|
|
||||||
break;
|
|
||||||
v12 = decompressor.GetBytesToCopy(8);
|
|
||||||
v13 = v12 + 18;
|
|
||||||
bytesToCopyRemain = v12 + 17;
|
|
||||||
if (v13 != 0)
|
|
||||||
{
|
|
||||||
++bytesToCopyRemain;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
idxCopySrc = idx++ - bytesToCopy;
|
|
||||||
--bytesToCopyRemain;
|
|
||||||
decompressed[idx - 1] = decompressed[idxCopySrc];
|
|
||||||
} while (bytesToCopyRemain != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return decompressed.AsSpan(0, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
private static void TransferBuffer(Compressor compressor)
|
|
||||||
{
|
|
||||||
int bufferCursor;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
bufferCursor = _bufferCursor;
|
|
||||||
if (bufferCursor != 0)
|
|
||||||
{
|
|
||||||
_numBytesTransferred += bufferCursor;
|
|
||||||
compressor.Compress(false);
|
|
||||||
compressor.Shift(_bufferCursor - 1, 8);
|
|
||||||
for (i = 0; i < _bufferCursor; ++i)
|
|
||||||
compressor.Write(_buffer[i]);
|
|
||||||
_bufferCursor = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Write(Compressor compressor, byte c)
|
|
||||||
{
|
|
||||||
_buffer[_bufferCursor++] = c;
|
|
||||||
if (_bufferCursor >= _buffer.Length)
|
|
||||||
TransferBuffer(compressor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- CLASSES, STRUCTS & ENUMS -------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
private class Compressor
|
|
||||||
{
|
|
||||||
internal byte[] Compressed = new byte[1024];
|
|
||||||
internal int Cursor = 1;
|
|
||||||
|
|
||||||
private int _cursorCompress = 0;
|
|
||||||
private int _shift = 0;
|
|
||||||
|
|
||||||
internal void Compress(bool bShift)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
int cursor;
|
|
||||||
int cursorCompress;
|
|
||||||
|
|
||||||
if (bShift)
|
|
||||||
{
|
|
||||||
Compressed[_cursorCompress] |= (byte)(0x80 >> _shift);
|
|
||||||
}
|
|
||||||
shift = _shift + 1;
|
|
||||||
_shift = shift;
|
|
||||||
if (shift == 8)
|
|
||||||
{
|
|
||||||
cursor = Cursor;
|
|
||||||
_cursorCompress = Cursor++;
|
|
||||||
cursorCompress = _cursorCompress;
|
|
||||||
Cursor = cursor + 1;
|
|
||||||
Compressed[cursorCompress] = 0;
|
|
||||||
_shift = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Shift(int value, int shiftPlus1)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
int prevShift;
|
|
||||||
|
|
||||||
shift = shiftPlus1 - 1;
|
|
||||||
if (shiftPlus1 != 0)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Compress(((value >> shift) & 1) != 0);
|
|
||||||
prevShift = shift--;
|
|
||||||
} while (prevShift != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Write(byte c)
|
|
||||||
{
|
|
||||||
Compressed[Cursor++] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Decompressor
|
|
||||||
{
|
|
||||||
private readonly byte[] _compressed;
|
|
||||||
private int _compressedCursor = 0;
|
|
||||||
private byte _field_C;
|
|
||||||
private byte _field_D;
|
|
||||||
|
|
||||||
internal Decompressor(ReadOnlySpan<byte> compressed)
|
|
||||||
{
|
|
||||||
_compressed = compressed.ToArray();
|
|
||||||
byte c = Read();
|
|
||||||
_field_C = (byte)(2 * c | 1);
|
|
||||||
_field_D = (byte)((uint)c >> 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal byte Read()
|
|
||||||
{
|
|
||||||
return _compressed[_compressedCursor++];
|
|
||||||
}
|
|
||||||
|
|
||||||
internal int GetBytesToCopy(int numCalls)
|
|
||||||
{
|
|
||||||
if (numCalls == 0)
|
|
||||||
return 0;
|
|
||||||
int bytesToCopy = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
numCalls--;
|
|
||||||
bytesToCopy = sub_4C0BA0() + 2 * bytesToCopy;
|
|
||||||
} while (numCalls != 0);
|
|
||||||
return bytesToCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal int sub_4C0BA0()
|
|
||||||
{
|
|
||||||
byte field_D = _field_D;
|
|
||||||
_field_D = (byte)(_field_C >> 7);
|
|
||||||
_field_C *= 2;
|
|
||||||
if (_field_C == 0)
|
|
||||||
{
|
|
||||||
byte c = Read();
|
|
||||||
_field_C = (byte)(2 * c | 1);
|
|
||||||
_field_D = (byte)(c >> 7);
|
|
||||||
}
|
|
||||||
return field_D;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,7 +10,9 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Syroot.BinaryData.Memory" Version="5.2.0-alpha1" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
|
||||||
|
<ProjectReference Include="..\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />
|
||||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||||
<None Update="ServerConfig.json">
|
<None Update="ServerConfig.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
@ -5,11 +5,11 @@ namespace Syroot.Worms.Mgame
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents instances of common <see cref="Encoding"/> pages.
|
/// Represents instances of common <see cref="Encoding"/> pages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class Encodings
|
public static class Encodings
|
||||||
{
|
{
|
||||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
internal static readonly Encoding Win949;
|
public static readonly Encoding Win949;
|
||||||
|
|
||||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ namespace Syroot.Worms.Mgame
|
|||||||
private static int _field_C = 0;
|
private static int _field_C = 0;
|
||||||
private static int _field_10 = 0;
|
private static int _field_10 = 0;
|
||||||
|
|
||||||
private static int[] _bufferDwords = new int[512];
|
private static readonly int[] _bufferDwords = new int[512];
|
||||||
|
|
||||||
private static byte[] _buffer = new byte[256];
|
private static byte[] _buffer = new byte[256];
|
||||||
private static int _bufferCursor = 0;
|
private static int _bufferCursor = 0;
|
||||||
@ -39,7 +39,7 @@ namespace Syroot.Worms.Mgame
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="decompressed">The data to compress.</param>
|
/// <param name="decompressed">The data to compress.</param>
|
||||||
/// <returns>The compressed data.</returns>
|
/// <returns>The compressed data.</returns>
|
||||||
public static ReadOnlySpan<byte> Compress(ReadOnlySpan<byte> decompressed)
|
public static Span<byte> Compress(ReadOnlySpan<byte> decompressed)
|
||||||
{
|
{
|
||||||
Compressor compressor = new Compressor();
|
Compressor compressor = new Compressor();
|
||||||
int idx;
|
int idx;
|
||||||
@ -129,10 +129,9 @@ namespace Syroot.Worms.Mgame
|
|||||||
compressor.Shift(0, 8);
|
compressor.Shift(0, 8);
|
||||||
|
|
||||||
return compressor.Compressed.AsSpan(0, compressor.Cursor);
|
return compressor.Compressed.AsSpan(0, compressor.Cursor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReadOnlySpan<byte> Decompress(ReadOnlySpan<byte> compressed)
|
public static Span<byte> Decompress(ReadOnlySpan<byte> compressed)
|
||||||
{
|
{
|
||||||
Decompressor decompressor = new Decompressor(compressed);
|
Decompressor decompressor = new Decompressor(compressed);
|
||||||
byte[] decompressed = new byte[2048];
|
byte[] decompressed = new byte[2048];
|
||||||
@ -150,7 +149,7 @@ namespace Syroot.Worms.Mgame
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while (decompressor.sub_4C0BA0() == 0)
|
while (decompressor.Sub_4C0BA0() == 0)
|
||||||
{
|
{
|
||||||
bytesToCopy = decompressor.GetBytesToCopy(8);
|
bytesToCopy = decompressor.GetBytesToCopy(8);
|
||||||
if (bytesToCopy != -1)
|
if (bytesToCopy != -1)
|
||||||
@ -309,12 +308,12 @@ namespace Syroot.Worms.Mgame
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
numCalls--;
|
numCalls--;
|
||||||
bytesToCopy = sub_4C0BA0() + 2 * bytesToCopy;
|
bytesToCopy = Sub_4C0BA0() + 2 * bytesToCopy;
|
||||||
} while (numCalls != 0);
|
} while (numCalls != 0);
|
||||||
return bytesToCopy;
|
return bytesToCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal int sub_4C0BA0()
|
internal int Sub_4C0BA0()
|
||||||
{
|
{
|
||||||
byte field_D = _field_D;
|
byte field_D = _field_D;
|
||||||
_field_D = (byte)(_field_C >> 7);
|
_field_D = (byte)(_field_C >> 7);
|
||||||
|
@ -4,9 +4,7 @@
|
|||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Syroot.BinaryData" Version="5.1.0-beta1" />
|
<PackageReference Include="Syroot.BinaryData" Version="5.1.0" />
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Syroot.Worms.Armageddon.ProjectX\Syroot.Worms.Armageddon.ProjectX.csproj" />
|
<ProjectReference Include="..\Syroot.Worms.Armageddon.ProjectX\Syroot.Worms.Armageddon.ProjectX.csproj" />
|
||||||
<ProjectReference Include="..\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
|
<ProjectReference Include="..\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
|
||||||
<ProjectReference Include="..\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />
|
<ProjectReference Include="..\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Syroot.BinaryData.Serialization" Version="5.0.0" />
|
<PackageReference Include="Syroot.BinaryData.Serialization" Version="5.0.0" />
|
||||||
<PackageReference Include="Syroot.BinaryData" Version="5.1.0-beta1" />
|
<PackageReference Include="Syroot.BinaryData" Version="5.1.0" />
|
||||||
<PackageReference Include="System.Drawing.Common" Version="4.5.1" />
|
<PackageReference Include="System.Drawing.Common" Version="4.5.1" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user