summaryrefslogtreecommitdiff
path: root/Impostor-dev/src/Impostor.Api/Net
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2020-12-30 20:59:04 +0800
committerchai <chaifix@163.com>2020-12-30 20:59:04 +0800
commite9ea621b93fbb58d9edfca8375918791637bbd52 (patch)
tree19ce3b1c1f2d51eda6878c9d0f2c9edc27f13650 /Impostor-dev/src/Impostor.Api/Net
+init
Diffstat (limited to 'Impostor-dev/src/Impostor.Api/Net')
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/IClient.cs76
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/IClientPlayer.cs43
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/IConnection.cs7
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/IHazelConnection.cs41
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/IGameNet.cs18
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/IInnerNetObject.cs9
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/Components/IInnerCustomNetworkTransform.cs15
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/Components/IInnerPlayerPhysics.cs6
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerGameData.cs6
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerLobbyBehaviour.cs6
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerMeetingHud.cs6
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerPlayerControl.cs116
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerPlayerInfo.cs53
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerShipStatus.cs7
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerVoteBanSystem.cs7
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Inner/Objects/ITaskInfo.cs14
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/LimboStates.cs13
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Manager/IClientManager.cs9
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message00HostGameC2S.cs27
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message01JoinGameC2S.cs20
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message04RemovePlayerC2S.cs16
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message08EndGameC2S.cs18
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message10AlterGameC2S.cs20
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message11KickPlayerC2S.cs16
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message16GetGameListC2S.cs18
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/IMessageReader.cs68
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/IMessageWriter.cs127
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/IMessageWriterProvider.cs16
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/MessageFlags.cs22
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/MessageType.cs32
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message00HostGameS2C.cs20
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message01JoinGameS2C.cs50
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message04RemovePlayerS2C.cs29
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message07JoinedGameS2C.cs31
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message10AlterGameS2C.cs26
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message11KickPlayerS2C.cs24
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message12WaitForHostS2C.cs23
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message13RedirectS2C.cs25
-rw-r--r--Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message16GetGameListS2C.cs46
39 files changed, 1126 insertions, 0 deletions
diff --git a/Impostor-dev/src/Impostor.Api/Net/IClient.cs b/Impostor-dev/src/Impostor.Api/Net/IClient.cs
new file mode 100644
index 0000000..48efeda
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/IClient.cs
@@ -0,0 +1,76 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Impostor.Api.Innersloth;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Api.Net
+{
+ /// <summary>
+ /// Represents a connected game client.
+ /// </summary>
+ public interface IClient
+ {
+ /// <summary>
+ /// Gets or sets the unique ID of the client.
+ /// </summary>
+ /// <remarks>
+ /// This ID is generated when the client is registered in the client manager and should not be used
+ /// to store persisted data.
+ /// </remarks>
+ int Id { get; set; }
+
+ /// <summary>
+ /// Gets the name that was provided by the player in the client.
+ /// </summary>
+ /// <remarks>
+ /// The name is provided by the player and should not be used to store persisted data.
+ /// </remarks>
+ string Name { get; }
+
+ /// <summary>
+ /// Gets the connection of the client.
+ /// </summary>
+ /// <remarks>
+ /// Null when the client was not registered by the matchmaker.
+ /// </remarks>
+ IHazelConnection? Connection { get; }
+
+ /// <summary>
+ /// Gets a key/value collection that can be used to share data between messages.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The stored data will not be saved.
+ /// After the connection has been closed all data will be lost.
+ /// </para>
+ /// <para>
+ /// Note that the values will not be disposed after the connection has been closed.
+ /// This has to be implemented by the plugin.
+ /// </para>
+ /// </remarks>
+ IDictionary<object, object> Items { get; }
+
+ /// <summary>
+ /// Gets or sets the current game data of the <see cref="IClient"/>.
+ /// </summary>
+ IClientPlayer? Player { get; }
+
+ ValueTask HandleMessageAsync(IMessageReader message, MessageType messageType);
+
+ ValueTask HandleDisconnectAsync(string reason);
+
+ /// <summary>
+ /// Disconnect the client with a <see cref="DisconnectReason"/>.
+ /// </summary>
+ /// <param name="reason">
+ /// The message to show to the player.
+ /// </param>
+ /// <param name="message">
+ /// Only used when <see cref="reason"/> is set to <see cref="DisconnectReason.Custom"/>.
+ /// </param>
+ /// <returns>
+ /// A <see cref="ValueTask"/> representing the asynchronous operation.
+ /// </returns>
+ ValueTask DisconnectAsync(DisconnectReason reason, string? message = null);
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/IClientPlayer.cs b/Impostor-dev/src/Impostor.Api/Net/IClientPlayer.cs
new file mode 100644
index 0000000..6070210
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/IClientPlayer.cs
@@ -0,0 +1,43 @@
+using System.Threading.Tasks;
+using Impostor.Api.Games;
+using Impostor.Api.Net.Inner;
+using Impostor.Api.Net.Inner.Objects;
+
+namespace Impostor.Api.Net
+{
+ /// <summary>
+ /// Represents a player in <see cref="IGame"/>.
+ /// </summary>
+ public interface IClientPlayer
+ {
+ /// <summary>
+ /// Gets the client that belongs to the player.
+ /// </summary>
+ IClient Client { get; }
+
+ /// <summary>
+ /// Gets the game where the <see cref="IClientPlayer"/> belongs to.
+ /// </summary>
+ IGame Game { get; }
+
+ /// <summary>
+ /// Gets or sets the current limbo state of the player.
+ /// </summary>
+ LimboStates Limbo { get; set; }
+
+ IInnerPlayerControl? Character { get; }
+
+ public bool IsHost { get; }
+
+ /// <summary>
+ /// Checks if the specified <see cref="IInnerNetObject"/> is owned by <see cref="IClientPlayer"/>.
+ /// </summary>
+ /// <param name="netObject">The <see cref="IInnerNetObject"/>.</param>
+ /// <returns>Returns true if owned by <see cref="IClientPlayer"/>.</returns>
+ bool IsOwner(IInnerNetObject netObject);
+
+ ValueTask KickAsync();
+
+ ValueTask BanAsync();
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/IConnection.cs b/Impostor-dev/src/Impostor.Api/Net/IConnection.cs
new file mode 100644
index 0000000..94f9b8b
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/IConnection.cs
@@ -0,0 +1,7 @@
+namespace Impostor.Api.Net
+{
+ public interface IConnection
+ {
+
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/IHazelConnection.cs b/Impostor-dev/src/Impostor.Api/Net/IHazelConnection.cs
new file mode 100644
index 0000000..4e6c4b3
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/IHazelConnection.cs
@@ -0,0 +1,41 @@
+using System.Net;
+using System.Threading.Tasks;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Api.Net
+{
+ /// <summary>
+ /// Represents the connection of the client.
+ /// </summary>
+ public interface IHazelConnection
+ {
+ /// <summary>
+ /// Gets the IP endpoint of the client.
+ /// </summary>
+ IPEndPoint EndPoint { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether the client is connected to the server.
+ /// </summary>
+ bool IsConnected { get; }
+
+ /// <summary>
+ /// Gets the client of the connection.
+ /// </summary>
+ IClient? Client { get; set; }
+
+ /// <summary>
+ /// Sends a message writer to the connection.
+ /// </summary>
+ /// <param name="writer">The message.</param>
+ /// <returns></returns>
+ ValueTask SendAsync(IMessageWriter writer);
+
+ /// <summary>
+ /// Disconnects the client and invokes the disconnect handler.
+ /// </summary>
+ /// <param name="reason">A reason.</param>
+ /// <returns></returns>
+ ValueTask DisconnectAsync(string? reason);
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/IGameNet.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/IGameNet.cs
new file mode 100644
index 0000000..933a4de
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/IGameNet.cs
@@ -0,0 +1,18 @@
+using Impostor.Api.Net.Inner.Objects;
+
+namespace Impostor.Api.Net.Inner
+{
+ /// <summary>
+ /// Holds all data that is serialized over the network through GameData packets.
+ /// </summary>
+ public interface IGameNet
+ {
+ IInnerLobbyBehaviour LobbyBehaviour { get; }
+
+ IInnerGameData GameData { get; }
+
+ IInnerVoteBanSystem VoteBan { get; }
+
+ IInnerShipStatus ShipStatus { get; }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/IInnerNetObject.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/IInnerNetObject.cs
new file mode 100644
index 0000000..c171377
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/IInnerNetObject.cs
@@ -0,0 +1,9 @@
+namespace Impostor.Api.Net.Inner
+{
+ public interface IInnerNetObject
+ {
+ public uint NetId { get; }
+
+ public int OwnerId { get; }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/Components/IInnerCustomNetworkTransform.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/Components/IInnerCustomNetworkTransform.cs
new file mode 100644
index 0000000..6d867e7
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/Components/IInnerCustomNetworkTransform.cs
@@ -0,0 +1,15 @@
+using System.Numerics;
+using System.Threading.Tasks;
+
+namespace Impostor.Api.Net.Inner.Objects.Components
+{
+ public interface IInnerCustomNetworkTransform : IInnerNetObject
+ {
+ /// <summary>
+ /// Snaps the current to the given position <see cref="IInnerPlayerControl"/>.
+ /// </summary>
+ /// <param name="position">The target position.</param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SnapToAsync(Vector2 position);
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/Components/IInnerPlayerPhysics.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/Components/IInnerPlayerPhysics.cs
new file mode 100644
index 0000000..9378c5b
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/Components/IInnerPlayerPhysics.cs
@@ -0,0 +1,6 @@
+namespace Impostor.Api.Net.Inner.Objects.Components
+{
+ public interface IInnerPlayerPhysics : IInnerNetObject
+ {
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerGameData.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerGameData.cs
new file mode 100644
index 0000000..6e41020
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerGameData.cs
@@ -0,0 +1,6 @@
+namespace Impostor.Api.Net.Inner.Objects
+{
+ public interface IInnerGameData : IInnerNetObject
+ {
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerLobbyBehaviour.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerLobbyBehaviour.cs
new file mode 100644
index 0000000..f05f4cf
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerLobbyBehaviour.cs
@@ -0,0 +1,6 @@
+namespace Impostor.Api.Net.Inner.Objects
+{
+ public interface IInnerLobbyBehaviour : IInnerNetObject
+ {
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerMeetingHud.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerMeetingHud.cs
new file mode 100644
index 0000000..9c89d05
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerMeetingHud.cs
@@ -0,0 +1,6 @@
+namespace Impostor.Api.Net.Inner.Objects
+{
+ public interface IInnerMeetingHud
+ {
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerPlayerControl.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerPlayerControl.cs
new file mode 100644
index 0000000..04558b9
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerPlayerControl.cs
@@ -0,0 +1,116 @@
+using System.Threading.Tasks;
+using Impostor.Api.Innersloth.Customization;
+using Impostor.Api.Net.Inner.Objects.Components;
+
+namespace Impostor.Api.Net.Inner.Objects
+{
+ public interface IInnerPlayerControl : IInnerNetObject
+ {
+ /// <summary>
+ /// Gets the <see cref="PlayerId"/> assigned by the client of the host of the game.
+ /// </summary>
+ byte PlayerId { get; }
+
+ /// <summary>
+ /// Gets the <see cref="IInnerPlayerPhysics"/> of the <see cref="IInnerPlayerControl"/>.
+ /// Contains vent logic.
+ /// </summary>
+ IInnerPlayerPhysics Physics { get; }
+
+ /// <summary>
+ /// Gets the <see cref="IInnerCustomNetworkTransform"/> of the <see cref="IInnerPlayerControl"/>.
+ /// Contains position data about the player.
+ /// </summary>
+ IInnerCustomNetworkTransform NetworkTransform { get; }
+
+ /// <summary>
+ /// Gets the <see cref="IInnerPlayerInfo"/> of the <see cref="IInnerPlayerControl"/>.
+ /// Contains metadata about the player.
+ /// </summary>
+ IInnerPlayerInfo PlayerInfo { get; }
+
+ /// <summary>
+ /// Sets the name of the current <see cref="IInnerPlayerControl"/>.
+ /// Visible to all players.
+ /// </summary>
+ /// <param name="name">A name for the player.</param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SetNameAsync(string name);
+
+ /// <summary>
+ /// Sets the color of the current <see cref="IInnerPlayerControl"/>.
+ /// Visible to all players.
+ /// </summary>
+ /// <param name="colorId">A color for the player.</param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SetColorAsync(byte colorId);
+
+ /// <param name="colorType">A color for the player.</param>
+ /// <inheritdoc cref="SetColorAsync(byte)" />
+ ValueTask SetColorAsync(ColorType colorType);
+
+ /// <summary>
+ /// Sets the hat of the current <see cref="IInnerPlayerControl"/>.
+ /// Visible to all players.
+ /// </summary>
+ /// <param name="hatId">An hat for the player.</param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SetHatAsync(uint hatId);
+
+ /// <param name="hatType">An hat for the player.</param>
+ /// <inheritdoc cref="SetHatAsync(uint)" />
+ ValueTask SetHatAsync(HatType hatType);
+
+ /// <summary>
+ /// Sets the pet of the current <see cref="IInnerPlayerControl"/>.
+ /// Visible to all players.
+ /// </summary>
+ /// <param name="petId">A pet for the player.</param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SetPetAsync(uint petId);
+
+ /// <param name="petType">A pet for the player.</param>
+ /// <inheritdoc cref="SetPetAsync(uint)" />
+ ValueTask SetPetAsync(PetType petType);
+
+ /// <summary>
+ /// Sets the skin of the current <see cref="IInnerPlayerControl"/>.
+ /// Visible to all players.
+ /// </summary>
+ /// <param name="skinId">A skin for the player.</param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SetSkinAsync(uint skinId);
+
+ /// <param name="skinType">A skin for the player.</param>
+ /// <inheritdoc cref="SetSkinAsync(uint)" />
+ ValueTask SetSkinAsync(SkinType skinType);
+
+ /// <summary>
+ /// Send a chat message as the current <see cref="IInnerPlayerControl"/>.
+ /// Visible to all players.
+ /// </summary>
+ /// <param name="text">The message to send.</param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SendChatAsync(string text);
+
+ /// <summary>
+ /// Send a chat message as the current <see cref="IInnerPlayerControl"/>.
+ /// Visible to only the current.
+ /// </summary>
+ /// <param name="text">The message to send.</param>
+ /// <param name="player">
+ /// The player that should receive this chat message.
+ /// When left as null, will send message to self.
+ /// </param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SendChatToPlayerAsync(string text, IInnerPlayerControl? player = null);
+
+ /// <summary>
+ /// Sets the current to be murdered by an impostor <see cref="IInnerPlayerControl"/>.
+ /// Visible to all players.
+ /// </summary>
+ /// /// <param name="impostor">The Impostor who kill.</param>
+ /// <returns>Task that must be awaited.</returns>
+ ValueTask SetMurderedByAsync(IClientPlayer impostor);
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerPlayerInfo.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerPlayerInfo.cs
new file mode 100644
index 0000000..6cb3302
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerPlayerInfo.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Inner.Objects
+{
+ public interface IInnerPlayerInfo
+ {
+ /// <summary>
+ /// Gets the name of the player as decided by the host.
+ /// </summary>
+ string PlayerName { get; }
+
+ /// <summary>
+ /// Gets the color of the player.
+ /// </summary>
+ byte ColorId { get; }
+
+ /// <summary>
+ /// Gets the hat of the player.
+ /// </summary>
+ uint HatId { get; }
+
+ /// <summary>
+ /// Gets the pet of the player.
+ /// </summary>
+ uint PetId { get; }
+
+ /// <summary>
+ /// Gets the skin of the player.
+ /// </summary>
+ uint SkinId { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether the player is an impostor.
+ /// </summary>
+ bool IsImpostor { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether the player is a dead in the current game.
+ /// </summary>
+ bool IsDead { get; }
+
+ /// <summary>
+ /// Gets the reason why the player is dead in the current game.
+ /// </summary>
+ DeathReason LastDeathReason { get; }
+
+ IEnumerable<ITaskInfo> Tasks { get; }
+
+ DateTimeOffset LastMurder { get; }
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerShipStatus.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerShipStatus.cs
new file mode 100644
index 0000000..c0a05ae
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerShipStatus.cs
@@ -0,0 +1,7 @@
+namespace Impostor.Api.Net.Inner.Objects
+{
+ public interface IInnerShipStatus : IInnerNetObject
+ {
+
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerVoteBanSystem.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerVoteBanSystem.cs
new file mode 100644
index 0000000..d0a816d
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/IInnerVoteBanSystem.cs
@@ -0,0 +1,7 @@
+namespace Impostor.Api.Net.Inner.Objects
+{
+ public interface IInnerVoteBanSystem : IInnerNetObject
+ {
+
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/ITaskInfo.cs b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/ITaskInfo.cs
new file mode 100644
index 0000000..2b6dd86
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Inner/Objects/ITaskInfo.cs
@@ -0,0 +1,14 @@
+using Impostor.Api.Innersloth;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Api.Net.Inner.Objects
+{
+ public interface ITaskInfo
+ {
+ uint Id { get; }
+
+ TaskTypes Type { get; }
+
+ bool Complete { get; }
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/LimboStates.cs b/Impostor-dev/src/Impostor.Api/Net/LimboStates.cs
new file mode 100644
index 0000000..44c493e
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/LimboStates.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Impostor.Api.Net
+{
+ [Flags]
+ public enum LimboStates
+ {
+ PreSpawn = 1,
+ NotLimbo = 2,
+ WaitingForHost = 4,
+ All = PreSpawn | NotLimbo | WaitingForHost,
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Manager/IClientManager.cs b/Impostor-dev/src/Impostor.Api/Net/Manager/IClientManager.cs
new file mode 100644
index 0000000..92bf89f
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Manager/IClientManager.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Impostor.Api.Net.Manager
+{
+ public interface IClientManager
+ {
+ IEnumerable<IClient> Clients { get; }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message00HostGameC2S.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message00HostGameC2S.cs
new file mode 100644
index 0000000..4f5b39c
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message00HostGameC2S.cs
@@ -0,0 +1,27 @@
+using System.IO;
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Messages.C2S
+{
+ public static class Message00HostGameC2S
+ {
+ public static void Serialize(IMessageWriter writer, GameOptionsData gameOptionsData)
+ {
+ writer.StartMessage(MessageFlags.HostGame);
+
+ using (var memory = new MemoryStream())
+ using (var writerBin = new BinaryWriter(memory))
+ {
+ gameOptionsData.Serialize(writerBin, GameOptionsData.LatestVersion);
+ writer.WriteBytesAndSize(memory.ToArray());
+ }
+
+ writer.EndMessage();
+ }
+
+ public static GameOptionsData Deserialize(IMessageReader reader)
+ {
+ return GameOptionsData.DeserializeCreate(reader);
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message01JoinGameC2S.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message01JoinGameC2S.cs
new file mode 100644
index 0000000..f121b97
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message01JoinGameC2S.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Impostor.Api.Net.Messages.C2S
+{
+ public static class Message01JoinGameC2S
+ {
+ public static void Serialize(IMessageWriter writer)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public static void Deserialize(IMessageReader reader, out int gameCode, out byte unknown)
+ {
+ var slice = reader.ReadBytes(sizeof(Int32) + sizeof(byte)).Span;
+
+ gameCode = slice.ReadInt32();
+ unknown = slice.ReadByte();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message04RemovePlayerC2S.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message04RemovePlayerC2S.cs
new file mode 100644
index 0000000..99cdcfa
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message04RemovePlayerC2S.cs
@@ -0,0 +1,16 @@
+namespace Impostor.Api.Net.Messages.C2S
+{
+ public class Message04RemovePlayerC2S
+ {
+ public static void Serialize(IMessageWriter writer)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public static void Deserialize(IMessageReader reader, out int playerId, out byte reason)
+ {
+ playerId = reader.ReadPackedInt32();
+ reason = reader.ReadByte();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message08EndGameC2S.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message08EndGameC2S.cs
new file mode 100644
index 0000000..7ca5e3a
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message08EndGameC2S.cs
@@ -0,0 +1,18 @@
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Messages.C2S
+{
+ public class Message08EndGameC2S
+ {
+ public static void Serialize(IMessageWriter writer)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public static void Deserialize(IMessageReader reader, out GameOverReason gameOverReason)
+ {
+ gameOverReason = (GameOverReason)reader.ReadByte();
+ reader.ReadBoolean(); // showAd
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message10AlterGameC2S.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message10AlterGameC2S.cs
new file mode 100644
index 0000000..330f3b5
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message10AlterGameC2S.cs
@@ -0,0 +1,20 @@
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Messages.C2S
+{
+ public class Message10AlterGameC2S
+ {
+ public static void Serialize(IMessageWriter writer)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public static void Deserialize(IMessageReader reader, out AlterGameTags gameTag, out bool isPublic)
+ {
+ var slice = reader.ReadBytes(sizeof(byte) + sizeof(byte)).Span;
+
+ gameTag = (AlterGameTags)slice.ReadByte();
+ isPublic = slice.ReadBoolean();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message11KickPlayerC2S.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message11KickPlayerC2S.cs
new file mode 100644
index 0000000..7c5b8b9
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message11KickPlayerC2S.cs
@@ -0,0 +1,16 @@
+namespace Impostor.Api.Net.Messages.C2S
+{
+ public class Message11KickPlayerC2S
+ {
+ public static void Serialize(IMessageWriter writer)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public static void Deserialize(IMessageReader reader, out int playerId, out bool isBan)
+ {
+ playerId = reader.ReadPackedInt32();
+ isBan = reader.ReadBoolean();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message16GetGameListC2S.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message16GetGameListC2S.cs
new file mode 100644
index 0000000..2b7e12a
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/C2S/Message16GetGameListC2S.cs
@@ -0,0 +1,18 @@
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Messages.C2S
+{
+ public class Message16GetGameListC2S
+ {
+ public static void Serialize(IMessageWriter writer)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public static void Deserialize(IMessageReader reader, out GameOptionsData options)
+ {
+ reader.ReadPackedInt32(); // Hardcoded 0.
+ options = GameOptionsData.DeserializeCreate(reader);
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageReader.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageReader.cs
new file mode 100644
index 0000000..87c06c4
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageReader.cs
@@ -0,0 +1,68 @@
+using System;
+
+namespace Impostor.Api.Net.Messages
+{
+ public interface IMessageReader : IDisposable
+ {
+ /// <summary>
+ /// Gets the tag of the message.
+ /// </summary>
+ byte Tag { get; }
+
+ /// <summary>
+ /// Gets the buffer of the message.
+ /// </summary>
+ byte[] Buffer { get; }
+
+ /// <summary>
+ /// Gets the offset of our current <see cref="IMessageReader"/> in the entire <see cref="Buffer"/>.
+ /// </summary>
+ int Offset { get; }
+
+ /// <summary>
+ /// Gets the current position of the reader.
+ /// </summary>
+ int Position { get; }
+
+ /// <summary>
+ /// Gets the length of the buffer.
+ /// </summary>
+ int Length { get; }
+
+ IMessageReader ReadMessage();
+
+ bool ReadBoolean();
+
+ sbyte ReadSByte();
+
+ byte ReadByte();
+
+ ushort ReadUInt16();
+
+ short ReadInt16();
+
+ uint ReadUInt32();
+
+ int ReadInt32();
+
+ float ReadSingle();
+
+ string ReadString();
+
+ ReadOnlyMemory<byte> ReadBytesAndSize();
+
+ ReadOnlyMemory<byte> ReadBytes(int length);
+
+ int ReadPackedInt32();
+
+ uint ReadPackedUInt32();
+
+ void CopyTo(IMessageWriter writer);
+
+ void Seek(int position);
+
+ void RemoveMessage(IMessageReader message);
+
+ IMessageReader Copy(int offset = 0);
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageWriter.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageWriter.cs
new file mode 100644
index 0000000..4f6765b
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageWriter.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Net;
+using Impostor.Api.Games;
+
+namespace Impostor.Api.Net.Messages
+{
+ /// <summary>
+ /// Base message writer.
+ /// </summary>
+ public interface IMessageWriter : IDisposable
+ {
+ public byte[] Buffer { get; }
+
+ public int Length { get; set; }
+
+ public int Position { get; set; }
+
+ public MessageType SendOption { get; }
+
+ /// <summary>
+ /// Writes a boolean to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(bool value);
+
+ /// <summary>
+ /// Writes a sbyte to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(sbyte value);
+
+ /// <summary>
+ /// Writes a byte to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(byte value);
+
+ /// <summary>
+ /// Writes a short to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(short value);
+
+ /// <summary>
+ /// Writes an ushort to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(ushort value);
+
+ /// <summary>
+ /// Writes an uint to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(uint value);
+
+ /// <summary>
+ /// Writes an int to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(int value);
+
+ /// <summary>
+ /// Writes a float to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(float value);
+
+ /// <summary>
+ /// Writes a string to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(string value);
+
+ /// <summary>
+ /// Writes a <see cref="IPAddress"/> to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(IPAddress value);
+
+ /// <summary>
+ /// Writes an packed int to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void WritePacked(int value);
+
+ /// <summary>
+ /// Writes an packed uint to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void WritePacked(uint value);
+
+ /// <summary>
+ /// Writes raw bytes to the message.
+ /// </summary>
+ /// <param name="data">Bytes to write.</param>
+ void Write(ReadOnlyMemory<byte> data);
+
+ /// <summary>
+ /// Writes a game code to the message.
+ /// </summary>
+ /// <param name="value">Value to write.</param>
+ void Write(GameCode value);
+
+ void WriteBytesAndSize(byte[] bytes);
+
+ void WriteBytesAndSize(byte[] bytes, int length);
+
+ void WriteBytesAndSize(byte[] bytes, int offset, int length);
+
+ /// <summary>
+ /// Starts a new message.
+ /// </summary>
+ /// <param name="typeFlag">Message flag header.</param>
+ void StartMessage(byte typeFlag);
+
+ /// <summary>
+ /// Mark the end of the message.
+ /// </summary>
+ void EndMessage();
+
+ /// <summary>
+ /// Clear the message writer.
+ /// </summary>
+ /// <param name="type">New type of the message.</param>
+ void Clear(MessageType type);
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageWriterProvider.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageWriterProvider.cs
new file mode 100644
index 0000000..f398939
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/IMessageWriterProvider.cs
@@ -0,0 +1,16 @@
+namespace Impostor.Api.Net.Messages
+{
+ public interface IMessageWriterProvider
+ {
+ /// <summary>
+ /// Retrieves a <see cref="IMessageWriter"/> from the internal pool.
+ /// Make sure to call <see cref="IMessageWriter.Dispose"/> when you are done!
+ /// </summary>
+ /// <param name="sendOption">
+ /// Whether to send the message as <see cref="MessageType.Reliable"/> or <see cref="MessageType.Unreliable"/>.
+ /// Reliable packets will ensure delivery while unreliable packets may be lost.
+ /// </param>
+ /// <returns>A <see cref="IMessageWriter"/> from the pool.</returns>
+ IMessageWriter Get(MessageType sendOption = MessageType.Unreliable);
+ }
+}
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/MessageFlags.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/MessageFlags.cs
new file mode 100644
index 0000000..aea0c60
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/MessageFlags.cs
@@ -0,0 +1,22 @@
+namespace Impostor.Api.Net.Messages
+{
+ public static class MessageFlags
+ {
+ public const byte HostGame = 0;
+ public const byte JoinGame = 1;
+ public const byte StartGame = 2;
+ public const byte RemoveGame = 3;
+ public const byte RemovePlayer = 4;
+ public const byte GameData = 5;
+ public const byte GameDataTo = 6;
+ public const byte JoinedGame = 7;
+ public const byte EndGame = 8;
+ public const byte AlterGame = 10;
+ public const byte KickPlayer = 11;
+ public const byte WaitForHost = 12;
+ public const byte Redirect = 13;
+ public const byte ReselectServer = 14;
+ public const byte GetGameList = 9;
+ public const byte GetGameListV2 = 16;
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/MessageType.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/MessageType.cs
new file mode 100644
index 0000000..1604358
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/MessageType.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Impostor.Api.Net.Messages
+{
+ /// <summary>
+ /// Specifies how a message should be sent between connections.
+ /// </summary>
+ [Flags]
+ public enum MessageType : byte
+ {
+ /// <summary>
+ /// Requests unreliable delivery with no fragmentation.
+ /// </summary>
+ /// <remarks>
+ /// Sending data using unreliable delivery means that data is not guaranteed to arrive at it's destination nor is
+ /// it guaranteed to arrive only once. However, unreliable delivery can be faster than other methods and it
+ /// typically requires a smaller number of protocol bytes than other methods. There is also typically less
+ /// processing involved and less memory needed as packets are not stored once sent.
+ /// </remarks>
+ Unreliable,
+
+ /// <summary>
+ /// Requests data be sent reliably but with no fragmentation.
+ /// </summary>
+ /// <remarks>
+ /// Sending data reliably means that data is guaranteed to arrive and to arrive only once. Reliable delivery
+ /// typically requires more processing, more memory (as packets need to be stored in case they need resending),
+ /// a larger number of protocol bytes and can be slower than unreliable delivery.
+ /// </remarks>
+ Reliable,
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message00HostGameS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message00HostGameS2C.cs
new file mode 100644
index 0000000..8402d10
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message00HostGameS2C.cs
@@ -0,0 +1,20 @@
+using System;
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public static class Message00HostGameS2C
+ {
+ public static void Serialize(IMessageWriter writer, int gameCode)
+ {
+ writer.StartMessage(MessageFlags.HostGame);
+ writer.Write(gameCode);
+ writer.EndMessage();
+ }
+
+ public static GameOptionsData Deserialize(IMessageReader reader)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message01JoinGameS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message01JoinGameS2C.cs
new file mode 100644
index 0000000..c455201
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message01JoinGameS2C.cs
@@ -0,0 +1,50 @@
+using System;
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public class Message01JoinGameS2C
+ {
+ public static void SerializeJoin(IMessageWriter writer, bool clear, int gameCode, int playerId, int hostId)
+ {
+ if (clear)
+ {
+ writer.Clear(MessageType.Reliable);
+ }
+
+ writer.StartMessage(MessageFlags.JoinGame);
+ writer.Write(gameCode);
+ writer.Write(playerId);
+ writer.Write(hostId);
+ writer.EndMessage();
+ }
+
+ public static void SerializeError(IMessageWriter writer, bool clear, DisconnectReason reason, string? message = null)
+ {
+ if (clear)
+ {
+ writer.Clear(MessageType.Reliable);
+ }
+
+ writer.StartMessage(MessageFlags.JoinGame);
+ writer.Write((int)reason);
+
+ if (reason == DisconnectReason.Custom)
+ {
+ if (message == null)
+ {
+ throw new ArgumentNullException(nameof(message));
+ }
+
+ writer.Write(message);
+ }
+
+ writer.EndMessage();
+ }
+
+ public static void Deserialize(IMessageReader reader)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message04RemovePlayerS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message04RemovePlayerS2C.cs
new file mode 100644
index 0000000..77b447d
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message04RemovePlayerS2C.cs
@@ -0,0 +1,29 @@
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public class Message04RemovePlayerS2C
+ {
+ public static void Serialize(IMessageWriter writer, bool clear, int gameCode, int playerId, int hostId, DisconnectReason reason)
+ {
+ // Only a subset of DisconnectReason shows an unique message.
+ // ExitGame, Banned and Kicked.
+ if (clear)
+ {
+ writer.Clear(MessageType.Reliable);
+ }
+
+ writer.StartMessage(MessageFlags.RemovePlayer);
+ writer.Write(gameCode);
+ writer.Write(playerId);
+ writer.Write(hostId);
+ writer.Write((byte)reason);
+ writer.EndMessage();
+ }
+
+ public static void Deserialize(IMessageReader reader)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message07JoinedGameS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message07JoinedGameS2C.cs
new file mode 100644
index 0000000..da6eb40
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message07JoinedGameS2C.cs
@@ -0,0 +1,31 @@
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public static class Message07JoinedGameS2C
+ {
+ public static void Serialize(IMessageWriter writer, bool clear, int gameCode, int playerId, int hostId, int[] otherPlayerIds)
+ {
+ if (clear)
+ {
+ writer.Clear(MessageType.Reliable);
+ }
+
+ writer.StartMessage(MessageFlags.JoinedGame);
+ writer.Write(gameCode);
+ writer.Write(playerId);
+ writer.Write(hostId);
+ writer.WritePacked(otherPlayerIds.Length);
+
+ foreach (var id in otherPlayerIds)
+ {
+ writer.WritePacked(id);
+ }
+
+ writer.EndMessage();
+ }
+
+ public static void Deserialize(IMessageReader reader)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message10AlterGameS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message10AlterGameS2C.cs
new file mode 100644
index 0000000..fa155df
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message10AlterGameS2C.cs
@@ -0,0 +1,26 @@
+using Impostor.Api.Innersloth;
+
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public static class Message10AlterGameS2C
+ {
+ public static void Serialize(IMessageWriter writer, bool clear, int gameCode, bool isPublic)
+ {
+ if (clear)
+ {
+ writer.Clear(MessageType.Reliable);
+ }
+
+ writer.StartMessage(MessageFlags.AlterGame);
+ writer.Write(gameCode);
+ writer.Write((byte)AlterGameTags.ChangePrivacy);
+ writer.Write(isPublic);
+ writer.EndMessage();
+ }
+
+ public static void Deserialize(IMessageReader reader)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message11KickPlayerS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message11KickPlayerS2C.cs
new file mode 100644
index 0000000..1e2b6ef
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message11KickPlayerS2C.cs
@@ -0,0 +1,24 @@
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public class Message11KickPlayerS2C
+ {
+ public static void Serialize(IMessageWriter writer, bool clear, int gameCode, int playerId, bool isBan)
+ {
+ if (clear)
+ {
+ writer.Clear(MessageType.Reliable);
+ }
+
+ writer.StartMessage(MessageFlags.KickPlayer);
+ writer.Write(gameCode);
+ writer.WritePacked(playerId);
+ writer.Write(isBan);
+ writer.EndMessage();
+ }
+
+ public static void Deserialize(IMessageReader reader)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message12WaitForHostS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message12WaitForHostS2C.cs
new file mode 100644
index 0000000..5964b1c
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message12WaitForHostS2C.cs
@@ -0,0 +1,23 @@
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public class Message12WaitForHostS2C
+ {
+ public static void Serialize(IMessageWriter writer, bool clear, int gameCode, int playerId)
+ {
+ if (clear)
+ {
+ writer.Clear(MessageType.Reliable);
+ }
+
+ writer.StartMessage(MessageFlags.WaitForHost);
+ writer.Write(gameCode);
+ writer.Write(playerId);
+ writer.EndMessage();
+ }
+
+ public static void Deserialize(IMessageReader reader)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message13RedirectS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message13RedirectS2C.cs
new file mode 100644
index 0000000..4b93b0e
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message13RedirectS2C.cs
@@ -0,0 +1,25 @@
+using System.Net;
+
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public class Message13RedirectS2C
+ {
+ public static void Serialize(IMessageWriter writer, bool clear, IPEndPoint ipEndPoint)
+ {
+ if (clear)
+ {
+ writer.Clear(MessageType.Reliable);
+ }
+
+ writer.StartMessage(MessageFlags.Redirect);
+ writer.Write(ipEndPoint.Address);
+ writer.Write((ushort)ipEndPoint.Port);
+ writer.EndMessage();
+ }
+
+ public static void Deserialize(IMessageReader reader)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message16GetGameListS2C.cs b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message16GetGameListS2C.cs
new file mode 100644
index 0000000..93386d7
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Api/Net/Messages/S2C/Message16GetGameListS2C.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using Impostor.Api.Games;
+
+namespace Impostor.Api.Net.Messages.S2C
+{
+ public class Message16GetGameListS2C
+ {
+ public static void Serialize(IMessageWriter writer, int skeldGameCount, int miraHqGameCount, int polusGameCount, IEnumerable<IGame> games)
+ {
+ writer.StartMessage(MessageFlags.GetGameListV2);
+
+ // Count
+ writer.StartMessage(1);
+ writer.Write(skeldGameCount); // The Skeld
+ writer.Write(miraHqGameCount); // Mira HQ
+ writer.Write(polusGameCount); // Polus
+ writer.EndMessage();
+
+ // Listing
+ writer.StartMessage(0);
+
+ foreach (var game in games)
+ {
+ writer.StartMessage(0);
+ writer.Write(game.PublicIp.Address);
+ writer.Write((ushort)game.PublicIp.Port);
+ writer.Write(game.Code);
+ writer.Write(game.Host.Client.Name);
+ writer.Write((byte)game.PlayerCount);
+ writer.WritePacked(1); // TODO: What does Age do?
+ writer.Write((byte)game.Options.MapId);
+ writer.Write((byte)game.Options.NumImpostors);
+ writer.Write((byte)game.Options.MaxPlayers);
+ writer.EndMessage();
+ }
+
+ writer.EndMessage();
+ writer.EndMessage();
+ }
+
+ public static void Deserialize(IMessageReader reader)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+} \ No newline at end of file