Implement propret channel join.

This commit is contained in:
Ray Koopa 2019-01-20 20:49:20 +01:00
parent 629103fce5
commit e4104b8309
32 changed files with 346 additions and 123 deletions

View File

@ -0,0 +1,79 @@
using System.Collections.Generic;
using Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel;
namespace Syroot.Worms.Mgame.GameServer
{
internal partial class Client
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void HandleWwpaChannelCmd(CmdQuery packet)
{
switch (packet.Data)
{
case StartSingleGameQueryData startSingleGameQuery:
HandleWwpaChannelCmdStartGame(startSingleGameQuery);
break;
}
}
public void HandleWwpaChannelDisconnect(DisconnectNotice packet) { }
public void HandleWwpaChannelLogin(LoginQuery packet)
{
SendPacket(new LoginReply { Result = LoginResult.Success });
//SendPacket(new NotChannelLoginReply());
}
public void HandleWwpaChannelLogout(LogoutQuery packet)
{
SendPacket(new LogoutReply { Success = true });
}
public void HandleWwpaChannelUnknown11E(Unknown11EQuery packet)
{
SendPacket(new Unknown11FReply
{
UnknownA = 0x11111111,
UnknownB = "Hello",
UnknownC = 0x2222,
UnknownD = 0x3333
});
}
public void HandleWwpaChannelUnknown15A(Unknown15AQuery packet)
{
SendPacket(new Unknown15BReply
{
UnknownA = 0x1111,
UnknownB = 0x22222222,
UnknownC = "Test",
UnknownD = 0x3333,
UnknownE = 0x44444444,
UnknownF = 0x55,
});
}
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
// ---- Cmds ----
private void HandleWwpaChannelCmdStartGame(StartSingleGameQueryData data)
{
SendPacket(new CmdReply(new StartSingleGameReplyData
{
Stuff = new List<StartSingleGameReplyStuff>
{
new StartSingleGameReplyStuff
{
UnknownA = 1,
UnknownB = 2,
UnknownC = 3,
UnknownD = 4,
UnknownE = 5
}
}
}));
}
}
}

View File

@ -1,5 +1,5 @@
using System.Collections.Generic;
using Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua;
using Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server;
namespace Syroot.Worms.Mgame.GameServer
{
@ -7,17 +7,7 @@ namespace Syroot.Worms.Mgame.GameServer
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void HandleWwpaChannelCmd(ChannelCmdQuery packet)
{
switch (packet.Data)
{
case StartSingleGameQueryData startSingleGameQuery:
HandleWwpaStartGameQuery(startSingleGameQuery);
break;
}
}
public void HandleWwpaChannelList(ChannelListQuery packet)
public void HandleWwpaServerChannelList(ChannelListQuery packet)
{
SendPacket(new ChannelListReply
{
@ -90,30 +80,20 @@ namespace Syroot.Worms.Mgame.GameServer
});
}
public void HandleWwpaChannelLogin(ChannelLoginQuery packet)
{
SendPacket(new ChannelLoginReply());
}
public void HandleWwpaConnect(ConnectQuery packet)
public void HandleWwpaServerConnect(ConnectQuery packet)
{
// Client fails to detect reply at rare times due to unknown reasons.
SendPacket(new ConnectReply { ServerVersion = _server.Config.Version });
}
public void HandleWwpaDisconnect(DisconnectNotice packet) { }
public void HandleWwpaServerDisconnect(DisconnectNotice packet) { }
public void HandleWwpaLogin(LoginQuery packet)
public void HandleWwpaServerLogin(LoginQuery packet)
{
SendPacket(new LoginReply { Result = LoginResult.Success });
}
public void HandleWwpaLogoutQuery(LogoutQuery packet)
{
SendPacket(new LogoutReply { Success = true });
}
public void HandleWwpaOptionsQuery(OptionsQuery packet)
public void HandleWwpaServerOptionsQuery(OptionsQuery packet)
{
SendPacket(new OptionsReply
{
@ -123,31 +103,9 @@ namespace Syroot.Worms.Mgame.GameServer
});
}
public void HandleWwpaOptionsSaveQuery(OptionsSaveQuery packet)
public void HandleWwpaServerOptionsSaveQuery(OptionsSaveQuery packet)
{
SendPacket(new OptionsSaveReply { Success = true });
}
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
// ---- ChannelCmds ----
private void HandleWwpaStartGameQuery(StartSingleGameQueryData data)
{
SendPacket(new ChannelCmdReply(new StartSingleGameReplyData
{
Stuff = new List<StartSingleGameReplyStuff>
{
new StartSingleGameReplyStuff
{
UnknownA = 1,
UnknownB = 2,
UnknownC = 3,
UnknownD = 4,
UnknownE = 5
}
}
}));
}
}
}

View File

@ -1,4 +1,6 @@
using System.Net.Sockets;
using System;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
using Syroot.Worms.Mgame.GameServer.Core;
using Syroot.Worms.Mgame.GameServer.Packets;
@ -44,6 +46,9 @@ namespace Syroot.Worms.Mgame.GameServer
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
private string FormatPacket(IPacket packet, string direction)
=> $"{TcpClient.Client.RemoteEndPoint} {direction} {packet.GetType().Name}{ObjectDumper.Dump(packet)}";
{
string packetName = String.Join(' ', packet.GetType().FullName.Split('.').TakeLast(2));
return $"{TcpClient.Client.RemoteEndPoint} {direction} {packetName}{ObjectDumper.Dump(packet)}";
}
}
}

View File

@ -4,10 +4,14 @@ namespace Syroot.Worms.Mgame.GameServer
{
internal class Config
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private IPAddress _ipAddress;
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
/// <summary>
/// Gets or sets the external IP sent to clients to connect to.
/// Gets or sets the IP sent to clients to connect to. Defaults to retrieving the external address.
/// </summary>
public string IP { get; set; }
@ -22,7 +26,20 @@ namespace Syroot.Worms.Mgame.GameServer
public int SendDelay { get; set; }
internal IPAddress IPAddress => IPAddress.Parse(IP);
internal IPAddress IPAddress
{
get
{
// Retrieve external IP if not yet done and given IP is invalid.
if (_ipAddress == null && (IP == null || !IPAddress.TryParse(IP, out _ipAddress)))
{
using (WebClient webClient = new WebClient())
_ipAddress = IPAddress.Parse(webClient.DownloadString("https://ip.syroot.com"));
}
return _ipAddress;
}
}
internal IPEndPoint EndPoint => new IPEndPoint(IPAddress, Port);
}
}

View File

@ -4,36 +4,36 @@ using System.Linq;
using Syroot.BinaryData.Memory;
using Syroot.Worms.Mgame.GameServer.Core.IO;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
// TODO: Ugly, but requires bigger redesign to allow a second identifier in the packets.
/// <summary>
/// Represents the base class for <see cref="ChannelCmdQuery"/> and <see cref="ChannelCmdReply"/> packets.
/// Represents the base class for <see cref="CmdQuery"/> and <see cref="CmdReply"/> packets.
/// </summary>
internal abstract class ChannelCmdPacket : IPacket
internal abstract class CmdPacket : IPacket
{
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
public IChannelCmdData Data { get; set; }
public ICmdData Data { get; set; }
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void Load(ref SpanReader reader)
{
ChannelCmd cmd = reader.ReadEnum<ChannelCmd>();
Cmd cmd = reader.ReadEnum<Cmd>();
Data = GetDataClasses().TryGetValue(cmd, out Type type)
? (IChannelCmdData)Activator.CreateInstance(type)
: new RawChannelCmdData(cmd);
? (ICmdData)Activator.CreateInstance(type)
: new RawCmdData(cmd);
Data.Load(ref reader);
}
public void Save(ref SpanWriter writer)
{
ChannelCmd cmd;
Cmd cmd;
switch (Data)
{
case RawChannelCmdData rawChannelCmdData:
case RawCmdData rawChannelCmdData:
cmd = rawChannelCmdData.Cmd;
break;
default:
@ -47,25 +47,25 @@ namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
// ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------
protected abstract IDictionary<ChannelCmd, Type> GetDataClasses();
protected abstract IDictionary<Cmd, Type> GetDataClasses();
}
internal enum ChannelCmd : int
internal enum Cmd : int
{
StartSingleGameQuery = 5
}
internal interface IChannelCmdData
internal interface ICmdData
{
void Load(ref SpanReader reader);
void Save(ref SpanWriter writer);
}
internal class RawChannelCmdData : IChannelCmdData
internal class RawCmdData : ICmdData
{
public RawChannelCmdData(ChannelCmd cmd) => Cmd = cmd;
public RawCmdData(Cmd cmd) => Cmd = cmd;
internal ChannelCmd Cmd { get; }
internal Cmd Cmd { get; }
internal byte[] Data { get; set; }
public void Load(ref SpanReader reader) => Data = reader.ReadToEnd();

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the client request for a <see cref="CmdReply"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x10A)]
internal class CmdQuery : CmdPacket
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private static readonly Dictionary<Cmd, Type> _queryClasses = new Dictionary<Cmd, Type>
{
[Cmd.StartSingleGameQuery] = typeof(StartSingleGameQueryData)
};
// ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------
protected override IDictionary<Cmd, Type> GetDataClasses() => _queryClasses;
}
}

View File

@ -1,30 +1,30 @@
using System;
using System.Collections.Generic;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the server response to a <see cref="ChannelCmdQuery"/>.
/// Represents the server response to a <see cref="CmdQuery"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x10B)]
internal class ChannelCmdReply : ChannelCmdPacket
internal class CmdReply : CmdPacket
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private static readonly Dictionary<ChannelCmd, Type> _replyClasses = new Dictionary<ChannelCmd, Type>
private static readonly Dictionary<Cmd, Type> _replyClasses = new Dictionary<Cmd, Type>
{
[ChannelCmd.StartSingleGameQuery] = typeof(StartSingleGameReplyData)
[Cmd.StartSingleGameQuery] = typeof(StartSingleGameReplyData)
};
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
internal ChannelCmdReply(IChannelCmdData data)
internal CmdReply(ICmdData data)
{
Data = data;
}
// ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------
protected override IDictionary<ChannelCmd, Type> GetDataClasses() => _replyClasses;
protected override IDictionary<Cmd, Type> GetDataClasses() => _replyClasses;
}
}

View File

@ -1,6 +1,6 @@
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the client notice of disconnecting.

View File

@ -5,13 +5,13 @@ using Syroot.BinaryData.Memory;
using Syroot.Worms.Mgame.GameServer.Core.IO;
using Syroot.Worms.Mgame.GameServer.Packets.Data;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the client request for a <see cref="ChannelConnectReply"/>.
/// Represents the client request for a <see cref="LoginReply"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x101)]
internal class ChannelLoginQuery : IPacket
internal class LoginQuery : IPacket
{
// ---- PROPERTIES ---------------------------------------------------------------------------------------------

View File

@ -0,0 +1,37 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the server response to a <see cref="LoginQuery"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x102)]
internal class LoginReply : IPacket
{
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
public LoginResult Result { get; set; }
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void Load(ref SpanReader reader) => throw new NotImplementedException();
public void Save(ref SpanWriter writer)
{
writer.WriteEnumSafe(Result);
}
}
internal enum LoginResult : int
{
Success = 0,
ChannelFull = 10,
No2PSupport = 11,
InvalidCredentials = 12,
IDAlreadyTaken = 13,
IDDoesNotExist = 14,
PasswordDoesNotMatch = 15,
Fail = 99
}
}

View File

@ -1,6 +1,6 @@
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the client request for a <see cref="LogoutReply"/>.

View File

@ -1,7 +1,7 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the server response to a <see cref="LogoutQuery"/>.

View File

@ -0,0 +1,19 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Invalid description: "Represents the server response to a <see cref="LoginQuery"/>."
/// </summary>
[Obsolete("While this packet exists, it is currently unclear where it is used.")]
[Packet(PacketFormat.Wwpa, 0x145)]
internal class NotLoginReply : IPacket
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void Load(ref SpanReader reader) { }
public void Save(ref SpanWriter writer) { }
}
}

View File

@ -1,11 +1,11 @@
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the <see cref="ChannelCmdQuery"/> client request for a <see cref="StartSingleGameReplyData"/>.
/// </summary>
internal class StartSingleGameQueryData : IChannelCmdData
internal class StartSingleGameQueryData : ICmdData
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------

View File

@ -2,12 +2,12 @@
using System.Collections.Generic;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the <see cref="ChannelCmdQuery"/> server response to a <see cref="StartSingleGameQueryData"/>.
/// </summary>
internal class StartSingleGameReplyData : IChannelCmdData
internal class StartSingleGameReplyData : ICmdData
{
// ---- PROPERTIES ---------------------------------------------------------------------------------------------

View File

@ -0,0 +1,17 @@
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the client request for a <see cref="Unknown11FReply"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x11E)]
internal class Unknown11EQuery : IPacket
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void Load(ref SpanReader reader) { }
public void Save(ref SpanWriter writer) { }
}
}

View File

@ -0,0 +1,34 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the server response to a <see cref="Unknown11EQuery"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x11F)]
internal class Unknown11FReply : IPacket
{
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
public int UnknownA { get; set; }
public string UnknownB { get; set; }
public ushort UnknownC { get; set; }
public ushort UnknownD { get; set; }
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void Load(ref SpanReader reader) => throw new NotImplementedException();
public void Save(ref SpanWriter writer)
{
writer.WriteInt32(UnknownA);
writer.WriteString2(UnknownB);
writer.WriteUInt16(UnknownC);
writer.WriteUInt16(UnknownD);
}
}
}

View File

@ -0,0 +1,17 @@
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the client request for a <see cref="Unknown15BReply"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x15A)]
internal class Unknown15AQuery : IPacket
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void Load(ref SpanReader reader) { }
public void Save(ref SpanWriter writer) { }
}
}

View File

@ -0,0 +1,40 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Channel
{
/// <summary>
/// Represents the server response to a <see cref="Unknown15AQuery"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x15B)]
internal class Unknown15BReply : IPacket
{
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
public ushort UnknownA { get; set; }
public int UnknownB { get; set; } // unused?
public string UnknownC { get; set; }
public ushort UnknownD { get; set; } // x - 1 / 5, unused?
public int UnknownE { get; set; } // unused?
public byte UnknownF { get; set; } // unused?
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void Load(ref SpanReader reader) => throw new NotImplementedException();
public void Save(ref SpanWriter writer)
{
writer.WriteUInt16(UnknownA);
writer.WriteInt32(UnknownB);
writer.WriteString2(UnknownC);
writer.WriteUInt16(UnknownD);
writer.WriteInt32(UnknownE);
writer.WriteByte(UnknownF);
}
}
}

View File

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
{
/// <summary>
/// Represents the client request for a <see cref="ChannelCmdReply"/>.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x10A)]
internal class ChannelCmdQuery : ChannelCmdPacket
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private static readonly Dictionary<ChannelCmd, Type> _queryClasses = new Dictionary<ChannelCmd, Type>
{
[ChannelCmd.StartSingleGameQuery] = typeof(StartSingleGameQueryData)
};
// ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------
protected override IDictionary<ChannelCmd, Type> GetDataClasses() => _queryClasses;
}
}

View File

@ -1,6 +1,6 @@
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the client request for a <see cref="ChannelListReply"/>.

View File

@ -5,7 +5,7 @@ using System.Net;
using Syroot.BinaryData.Memory;
using Syroot.Worms.Mgame.GameServer.Core.IO;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the server reply to a <see cref="ChannelListQuery"/>.

View File

@ -1,6 +1,6 @@
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the client request for a <see cref="ConnectReply"/>.

View File

@ -1,7 +1,7 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the server response to a <see cref="ConnectQuery"/>.

View File

@ -1,12 +1,12 @@
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the server response to a <see cref="ChannelConnectQuery"/>.
/// Represents the client notice of disconnecting.
/// </summary>
[Packet(PacketFormat.Wwpa, 0x145)]
internal class ChannelLoginReply : IPacket
[Packet(PacketFormat.Wwpa, 0x801B)]
internal class DisconnectNotice : IPacket
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using Syroot.BinaryData.Memory;
using Syroot.Worms.Mgame.GameServer.Packets.Data;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the client request for a <see cref="LoginReply"/>.

View File

@ -1,7 +1,7 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the server response to a <see cref="LoginQuery"/>.

View File

@ -1,7 +1,7 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the client request for an <see cref="OptionsReply"/>.

View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the server response to a <see cref="OptionsQuery"/>.

View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the client request for an <see cref="OptionsSaveReply"/>.

View File

@ -1,7 +1,7 @@
using System;
using Syroot.BinaryData.Memory;
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua
namespace Syroot.Worms.Mgame.GameServer.Packets.WorldPartyAqua.Server
{
/// <summary>
/// Represents the server response to an <see cref="OptionsSaveQuery"/>.

View File

@ -1,6 +1,6 @@
{
// Server settings
"IP": "89.244.195.103", // external IP sent to clients to connect to
"IP": "external", // external IP sent to clients to connect to. Specify invalid IP to retrieve external one
"Port": 17022,
"Name": "Mgame Worms Private Server",
"Region": "Global",