namespace Impostor.Api.Events.Announcements
{
/// <summary>
- /// Event fired after client requests a announcement.
+ /// Event fired after client requests a announcement.
/// </summary>
public interface IAnnouncementRequestEvent : IEvent
{
public interface IResponse
{
/// <summary>
- /// Gets or sets FreeWeekendState, currently unused by the client.
+ /// Gets or sets FreeWeekendState, currently unused by the client.
/// </summary>
public FreeWeekendState FreeWeekendState { get; set; }
/// <summary>
- /// Gets or sets a value indicating whether announcement should be loaded from client's cache, can save some bytes.
+ /// Gets or sets a value indicating whether announcement should be loaded from client's cache, can save some bytes.
/// </summary>
public bool UseCached { get; set; }
/// <summary>
- /// Gets or sets announcement, should be null when <see cref="UseCached"/> is set to true.
+ /// Gets or sets announcement, should be null when <see cref="UseCached" /> is set to true.
/// </summary>
public Announcement? Announcement { get; set; }
}
/// <summary>
- /// Gets client's last announcement id.
+ /// Gets client's last announcement id.
/// </summary>
public int Id { get; }
/// <summary>
- /// Gets client's language.
+ /// Gets client's language.
/// </summary>
public Language Language { get; }
/// <summary>
- /// Gets or sets plugin made response.
+ /// Gets or sets plugin made response.
/// </summary>
public IResponse Response { get; set; }
}
public Type? Event { get; set; }
/// <summary>
- /// If set to true, the listener will be called regardless of the <see cref="IEventCancelable.IsCancelled"/>.
+ /// If set to true, the listener will be called regardless of the <see cref="IEventCancelable.IsCancelled" />.
/// </summary>
public bool IgnoreCancelled { get; set; }
}
-}
\ No newline at end of file
+}
namespace Impostor.Api.Events
{
/// <summary>
- /// Called whenever a new <see cref="IGame"/> is created.
+ /// Called whenever a new <see cref="IGame" /> is created.
/// </summary>
public interface IGameCreatedEvent : IGameEvent
{
namespace Impostor.Api.Events
{
/// <summary>
- /// Called whenever a new <see cref="IGame"/> is destroyed.
+ /// Called whenever a new <see cref="IGame" /> is destroyed.
/// </summary>
public interface IGameDestroyedEvent : IGameEvent
{
public interface IGameEvent : IEvent
{
/// <summary>
- /// Gets the <see cref="IGame"/> this event belongs to.
+ /// Gets the <see cref="IGame" /> this event belongs to.
/// </summary>
IGame Game { get; }
}
/// <summary>
/// Called when the game is going to start.
/// When this is called, not all players are initialized properly yet.
- /// If you want to get correct player states, use <see cref="IGameStartedEvent"/>.
+ /// If you want to get correct player states, use <see cref="IGameStartedEvent" />.
/// </summary>
public interface IGameStartingEvent : IGameEvent
{
-using Impostor.Api.Innersloth;
-using Impostor.Api.Net.Inner.Objects;
+using Impostor.Api.Net.Inner.Objects;
namespace Impostor.Api.Events.Player
{
public interface IPlayerEvent : IGameEvent
{
/// <summary>
- /// Gets the <see cref="IClientPlayer"/> that triggered this <see cref="IPlayerEvent"/>.
+ /// Gets the <see cref="IClientPlayer" /> that triggered this <see cref="IPlayerEvent" />.
/// </summary>
IClientPlayer ClientPlayer { get; }
/// <summary>
- /// Gets the networked <see cref="IInnerPlayerControl"/> that triggered this <see cref="IPlayerEvent"/>.
- /// This <see cref="IInnerPlayerControl"/> belongs to the <see cref="IClientPlayer"/>.
+ /// Gets the networked <see cref="IInnerPlayerControl" /> that triggered this <see cref="IPlayerEvent" />.
+ /// This <see cref="IInnerPlayerControl" /> belongs to the <see cref="IClientPlayer" />.
/// </summary>
IInnerPlayerControl PlayerControl { get; }
}
-}
\ No newline at end of file
+}
public interface IEvent
{
}
-}
\ No newline at end of file
+}
/// </summary>
bool IsCancelled { get; set; }
}
-}
\ No newline at end of file
+}
public interface IEventListener
{
}
-}
\ No newline at end of file
+}
where TListener : IEventListener;
/// <summary>
- /// Returns true if an event with the type <see cref="TEvent"/> is registered.
+ /// Returns true if an event with the type <see cref="TEvent" /> is registered.
/// </summary>
- /// <returns>True if the <see cref="TEvent"/> is registered.</returns>
+ /// <returns>True if the <see cref="TEvent" /> is registered.</returns>
/// <typeparam name="TEvent">Type of the event.</typeparam>
bool IsRegistered<TEvent>()
where TEvent : IEvent;
/// <summary>
- /// Call all the event listeners for the type <see cref="TEvent"/>.
+ /// Call all the event listeners for the type <see cref="TEvent" />.
/// </summary>
/// <param name="event">The event argument.</param>
/// <typeparam name="TEvent">Type of the event.</typeparam>
- /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+ /// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
ValueTask CallAsync<TEvent>(TEvent @event)
where TEvent : IEvent;
}
-}
\ No newline at end of file
+}
namespace Impostor.Api
{
/// <summary>
- /// Priovides a StreamReader-like api throught extensions
+ /// Priovides a StreamReader-like api throught extensions
/// </summary>
public static class SpanReaderExtensions
{
}
/// <summary>
- /// Advances the position of <see cref="input"/> by the size of <see cref="T"/>.
+ /// Advances the position of <see cref="input" /> by the size of <see cref="T" />.
/// </summary>
/// <typeparam name="T">Type that will be read.</typeparam>
/// <param name="input">input "stream"/span.</param>
return original;
}
}
-}
\ No newline at end of file
+}
return SystemTypeHelpers.Names[(int)type];
}
}
-}
\ No newline at end of file
+}
return game.SendToAsync(writer, player.Client);
}
}
-}
\ No newline at end of file
+}
return manager.Games.Count(game => map.HasFlag((MapFlags)(1 << (byte)game.Options.Map)));
}
}
-}
\ No newline at end of file
+}
public static GameCode From(string value) => new GameCode(value);
- /// <inheritdoc/>
+ /// <inheritdoc />
public bool Equals(GameCode other)
{
return Code == other.Code && Value == other.Value;
}
- /// <inheritdoc/>
+ /// <inheritdoc />
public override bool Equals(object? obj)
{
return obj is GameCode other && Equals(other);
}
- /// <inheritdoc/>
+ /// <inheritdoc />
public override int GetHashCode()
{
return HashCode.Combine(Code, Value);
return Code;
}
}
-}
\ No newline at end of file
+}
/// Custom error by a plugin.
/// </summary>
/// <remarks>
- /// A custom message can be set in <see cref="GameJoinResult.Message"/>.
+ /// A custom message can be set in <see cref="GameJoinResult.Message" />.
/// </remarks>
Custom,
}
-}
\ No newline at end of file
+}
return new GameJoinResult(error);
}
}
-}
\ No newline at end of file
+}
bool IsPublic { get; }
/// <summary>
- /// Gets or sets display name on game list.
+ /// Gets or sets display name on game list.
/// </summary>
string? DisplayName { get; set; }
where T : IInnerNetObject;
/// <summary>
- /// Adds an <see cref="IPAddress"/> to the ban list of this game.
- /// Prevents all future joins from this <see cref="IPAddress"/>.
- ///
- /// This does not kick the player with that <see cref="IPAddress"/> from the lobby.
+ /// Adds an <see cref="IPAddress" /> to the ban list of this game.
+ /// Prevents all future joins from this <see cref="IPAddress" />.
+ /// This does not kick the player with that <see cref="IPAddress" /> from the lobby.
/// </summary>
/// <param name="ipAddress">
- /// The <see cref="IPAddress"/> to ban.
+ /// The <see cref="IPAddress" /> to ban.
/// </param>
void BanIp(IPAddress ipAddress);
/// <summary>
- /// Syncs the internal <see cref="GameOptionsData"/> to all players.
+ /// Syncs the internal <see cref="GameOptionsData" /> to all players.
/// Necessary to do if you modified it, otherwise it won't be used.
/// </summary>
- /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+ /// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
ValueTask SyncSettingsAsync();
/// <summary>
/// Sets game's privacy.
/// </summary>
/// <param name="isPublic">Privacy to set.</param>
- /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+ /// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
ValueTask SetPrivacyAsync(bool isPublic);
/// <summary>
/// </summary>
/// <param name="writer">Message to send.</param>
/// <param name="states">Required limbo state of the player.</param>
- /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+ /// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
ValueTask SendToAllAsync(IMessageWriter writer, LimboStates states = LimboStates.NotLimbo);
/// <summary>
/// <param name="writer">Message to send.</param>
/// <param name="senderId">The player to exclude from sending the message.</param>
/// <param name="states">Required limbo state of the player.</param>
- /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+ /// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
ValueTask SendToAllExceptAsync(IMessageWriter writer, int senderId, LimboStates states = LimboStates.NotLimbo);
/// <summary>
/// </summary>
/// <param name="writer">Message to send.</param>
/// <param name="id">ID of the client.</param>
- /// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
+ /// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
ValueTask SendToAsync(IMessageWriter writer, int id);
}
}
{
GameCode Create();
}
-}
\ No newline at end of file
+}
ValueTask<IGame> CreateAsync(GameOptionsData options);
}
-}
\ No newline at end of file
+}
{
ChangePrivacy = 1,
}
-}
\ No newline at end of file
+}
{
DidVote = 0,
}
-}
\ No newline at end of file
+}
Kill = 1,
Disconnect = 2,
}
-}
\ No newline at end of file
+}
Polish = 128,
English = 256,
}
-}
\ No newline at end of file
+}
public class GameOptionsData
{
/// <summary>
- /// The latest major version of the game client.
+ /// The latest major version of the game client.
/// </summary>
public const int LatestVersion = 4;
/// <summary>
- /// Gets or sets host's version of the game.
+ /// Gets or sets host's version of the game.
/// </summary>
public byte Version { get; set; } = LatestVersion;
/// <summary>
- /// Gets or sets the maximum amount of players for this lobby.
+ /// Gets or sets the maximum amount of players for this lobby.
/// </summary>
public byte MaxPlayers { get; set; } = 10;
/// <summary>
- /// Gets or sets the language of the lobby as per <see cref="GameKeywords"/> enum.
+ /// Gets or sets the language of the lobby as per <see cref="GameKeywords" /> enum.
/// </summary>
public GameKeywords Keywords { get; set; } = GameKeywords.English;
/// <summary>
- /// Gets or sets the Map selected for this lobby.
+ /// Gets or sets the Map selected for this lobby.
/// </summary>
public MapTypes Map { get; set; } = MapTypes.Skeld;
/// <summary>
- /// Gets or sets the Player speed modifier.
+ /// Gets or sets the Player speed modifier.
/// </summary>
public float PlayerSpeedMod { get; set; } = 1f;
/// <summary>
- /// Gets or sets the Light modifier for the players that are members of the crew as a multiplier value.
+ /// Gets or sets the Light modifier for the players that are members of the crew as a multiplier value.
/// </summary>
public float CrewLightMod { get; set; } = 1f;
/// <summary>
- /// Gets or sets the Light modifier for the players that are Impostors as a multiplier value.
+ /// Gets or sets the Light modifier for the players that are Impostors as a multiplier value.
/// </summary>
public float ImpostorLightMod { get; set; } = 1f;
/// <summary>
- /// Gets or sets the Impostor cooldown to kill in seconds.
+ /// Gets or sets the Impostor cooldown to kill in seconds.
/// </summary>
public float KillCooldown { get; set; } = 15f;
/// <summary>
- /// Gets or sets the number of common tasks.
+ /// Gets or sets the number of common tasks.
/// </summary>
public int NumCommonTasks { get; set; } = 1;
/// <summary>
- /// Gets or sets the number of long tasks.
+ /// Gets or sets the number of long tasks.
/// </summary>
public int NumLongTasks { get; set; } = 1;
/// <summary>
- /// Gets or sets the number of short tasks.
+ /// Gets or sets the number of short tasks.
/// </summary>
public int NumShortTasks { get; set; } = 2;
/// <summary>
- /// Gets or sets the maximum amount of emergency meetings each player can call during the game in seconds.
+ /// Gets or sets the maximum amount of emergency meetings each player can call during the game in seconds.
/// </summary>
public int NumEmergencyMeetings { get; set; } = 1;
/// <summary>
- /// Gets or sets the cooldown between each time any player can call an emergency meeting in seconds.
+ /// Gets or sets the cooldown between each time any player can call an emergency meeting in seconds.
/// </summary>
public int EmergencyCooldown { get; set; } = 15;
/// <summary>
- /// Gets or sets the number of impostors for this lobby.
+ /// Gets or sets the number of impostors for this lobby.
/// </summary>
public int NumImpostors { get; set; } = 1;
/// <summary>
- /// Gets or sets a value indicating whether ghosts (dead crew members) can do tasks.
+ /// Gets or sets a value indicating whether ghosts (dead crew members) can do tasks.
/// </summary>
public bool GhostsDoTasks { get; set; } = true;
/// <summary>
- /// Gets or sets the Kill as per values in <see cref="KillDistances"/>.
+ /// Gets or sets the Kill as per values in <see cref="KillDistances" />.
/// </summary>
public KillDistances KillDistance { get; set; } = KillDistances.Normal;
/// <summary>
- /// Gets or sets the time for discussion before voting time in seconds.
+ /// Gets or sets the time for discussion before voting time in seconds.
/// </summary>
public int DiscussionTime { get; set; } = 15;
/// <summary>
- /// Gets or sets the time for voting in seconds.
+ /// Gets or sets the time for voting in seconds.
/// </summary>
public int VotingTime { get; set; } = 120;
/// <summary>
- /// Gets or sets a value indicating whether an ejected player is an impostor or not.
+ /// Gets or sets a value indicating whether an ejected player is an impostor or not.
/// </summary>
public bool ConfirmImpostor { get; set; } = true;
/// <summary>
- /// Gets or sets a value indicating whether players are able to see tasks being performed by other players.
+ /// Gets or sets a value indicating whether players are able to see tasks being performed by other players.
/// </summary>
/// <remarks>
- /// By being set to true, tasks such as Empty Garbage, Submit Scan, Clear asteroids, Prime shields execution will be visible to other players.
+ /// By being set to true, tasks such as Empty Garbage, Submit Scan, Clear asteroids, Prime shields execution will be visible to other players.
/// </remarks>
public bool VisualTasks { get; set; } = true;
/// <summary>
- /// Gets or sets a value indicating whether the vote is anonymous.
+ /// Gets or sets a value indicating whether the vote is anonymous.
/// </summary>
public bool AnonymousVotes { get; set; }
/// <summary>
- /// Gets or sets the task bar update mode as per values in <see cref="Innersloth.TaskBarUpdate"/>.
+ /// Gets or sets the task bar update mode as per values in <see cref="Innersloth.TaskBarUpdate" />.
/// </summary>
public TaskBarUpdate TaskBarUpdate { get; set; } = TaskBarUpdate.Always;
/// <summary>
- /// Gets or sets a value indicating whether the GameOptions are the default ones.
+ /// Gets or sets a value indicating whether the GameOptions are the default ones.
/// </summary>
public bool IsDefaults { get; set; } = true;
/// <summary>
- /// Deserialize a packet/message to a new GameOptionsData object.
+ /// Deserialize a packet/message to a new GameOptionsData object.
/// </summary>
/// <param name="reader">Message reader object containing the raw message.</param>
/// <returns>GameOptionsData object.</returns>
}
/// <summary>
- /// Serializes this instance of GameOptionsData object to a specified BinaryWriter.
+ /// Serializes this instance of GameOptionsData object to a specified BinaryWriter.
/// </summary>
/// <param name="writer">The stream to write the message to.</param>
/// <param name="version">The version of the game.</param>
}
/// <summary>
- /// Deserialize a ReadOnlyMemory object to this instance of the GameOptionsData object.
+ /// Deserialize a ReadOnlyMemory object to this instance of the GameOptionsData object.
/// </summary>
/// <param name="memory">Memory containing the message/packet.</param>
public void Deserialize(ReadOnlyMemory<byte> memory)
Ended = 3,
Destroyed = 4,
}
-}
\ No newline at end of file
+}
return (year * 25000) + (month * 1800) + (day * 50) + rev;
}
}
-}
\ No newline at end of file
+}
MiraHQ = 2,
Polus = 4,
}
-}
\ No newline at end of file
+}
MiraHQ = 1,
Polus = 2,
}
-}
\ No newline at end of file
+}
SystemTypes.LifeSupp => "O2",
SystemTypes.LowerEngine => "Lower Engine",
SystemTypes.LockerRoom => "Locker Room",
- _ => x.ToString()
+ _ => x.ToString(),
};
}).ToArray();
}
}
-}
\ No newline at end of file
+}
Sabotage = 17,
/// <summary>
- /// Decontam on Mira and bottom decontam on Polus
+ /// Decontam on Mira and bottom decontam on Polus
/// </summary>
Decontamination = 18,
Dropship = 25,
/// <summary>
- /// Top decontam on Polus
+ /// Top decontam on Polus
/// </summary>
Decontamination2 = 26,
RecordTemperature = 41,
RebootWifi = 42,
}
-}
\ No newline at end of file
+}
return i == ' ' || (i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z') || (i >= '0' && i <= '9') || (i >= 'À' && i <= 'ÿ') || (i >= 'Ѐ' && i <= 'џ') || (i >= 'ㄱ' && i <= 'ㆎ') || (i >= '가' && i <= '힣');
}
}
-}
\ No newline at end of file
+}
string Name { get; }
/// <summary>
- /// Gets mods sent by client in modded handshake.
+ /// Gets mods sent by client in modded handshake.
/// </summary>
ISet<Mod> Mods { get; }
IDictionary<object, object> Items { get; }
/// <summary>
- /// Gets or sets the current game data of the <see cref="IClient"/>.
+ /// Gets or sets the current game data of the <see cref="IClient" />.
/// </summary>
IClientPlayer? Player { get; }
ValueTask HandleDisconnectAsync(string reason);
/// <summary>
- /// Disconnect the client with a <see cref="DisconnectReason"/>.
+ /// 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"/>.
+ /// Only used when <see cref="reason" /> is set to <see cref="DisconnectReason.Custom" />.
/// </param>
/// <returns>
- /// A <see cref="ValueTask"/> representing the asynchronous operation.
+ /// A <see cref="ValueTask" /> representing the asynchronous operation.
/// </returns>
ValueTask DisconnectAsync(DisconnectReason reason, string? message = null);
}
namespace Impostor.Api.Net
{
/// <summary>
- /// Represents a player in <see cref="IGame"/>.
+ /// Represents a player in <see cref="IGame" />.
/// </summary>
public interface IClientPlayer
{
IClient Client { get; }
/// <summary>
- /// Gets the game where the <see cref="IClientPlayer"/> belongs to.
+ /// Gets the game where the <see cref="IClientPlayer" /> belongs to.
/// </summary>
IGame Game { get; }
public bool IsHost { get; }
/// <summary>
- /// Checks if the specified <see cref="IInnerNetObject"/> is owned by <see cref="IClientPlayer"/>.
+ /// 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>
+ /// <param name="netObject">The <see cref="IInnerNetObject" />.</param>
+ /// <returns>Returns true if owned by <see cref="IClientPlayer" />.</returns>
bool IsOwner(IInnerNetObject netObject);
ValueTask KickAsync();
/// <returns></returns>
ValueTask DisconnectAsync(string? reason);
}
-}
\ No newline at end of file
+}
public int OwnerId { get; }
}
-}
\ No newline at end of file
+}
Vector2 Velocity { get; }
/// <summary>
- /// Snaps the current to the given position <see cref="IInnerPlayerControl"/>.
+ /// 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>
public interface IInnerPlayerControl : IInnerNetObject
{
/// <summary>
- /// Gets the <see cref="PlayerId"/> assigned by the client of the host of the game.
+ /// 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"/>.
+ /// 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"/>.
+ /// 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"/>.
+ /// 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"/>.
+ /// Sets the name of the current <see cref="IInnerPlayerControl" />.
/// Visible to all players.
/// </summary>
/// <param name="name">A name for the player.</param>
ValueTask SetNameAsync(string name);
/// <summary>
- /// Sets the color of the current <see cref="IInnerPlayerControl"/>.
+ /// Sets the color of the current <see cref="IInnerPlayerControl" />.
/// Visible to all players.
/// </summary>
/// <param name="colorType">A color for the player.</param>
ValueTask SetColorAsync(ColorType colorType);
/// <summary>
- /// Sets the hat of the current <see cref="IInnerPlayerControl"/>.
+ /// Sets the hat of the current <see cref="IInnerPlayerControl" />.
/// Visible to all players.
/// </summary>
/// <param name="hatType">An hat for the player.</param>
ValueTask SetHatAsync(HatType hatType);
/// <summary>
- /// Sets the pet of the current <see cref="IInnerPlayerControl"/>.
+ /// Sets the pet of the current <see cref="IInnerPlayerControl" />.
/// Visible to all players.
/// </summary>
/// <param name="petType">A pet for the player.</param>
ValueTask SetPetAsync(PetType petType);
/// <summary>
- /// Sets the skin of the current <see cref="IInnerPlayerControl"/>.
+ /// Sets the skin of the current <see cref="IInnerPlayerControl" />.
/// Visible to all players.
/// </summary>
/// <param name="skinType">A skin for the player.</param>
ValueTask SetSkinAsync(SkinType skinType);
/// <summary>
- /// Send a chat message as the current <see cref="IInnerPlayerControl"/>.
+ /// Send a chat message as the current <see cref="IInnerPlayerControl" />.
/// Visible to all players.
/// </summary>
/// <param name="text">The message to send.</param>
ValueTask SendChatAsync(string text);
/// <summary>
- /// Send a chat message as the current <see cref="IInnerPlayerControl"/>.
+ /// Send a chat message as the current <see cref="IInnerPlayerControl" />.
/// Visible to only the current.
/// </summary>
/// <param name="text">The message to send.</param>
ValueTask SendChatToPlayerAsync(string text, IInnerPlayerControl? player = null);
/// <summary>
- /// Murder <paramref name="target"/> player.
+ /// Murder <paramref name="target" /> player.
/// </summary>
/// <param name="target">Target player to murder.</param>
/// <exception cref="ImpostorProtocolException">Thrown when player is not the impostor.</exception>
using Impostor.Api.Innersloth;
-using Impostor.Api.Net.Messages;
namespace Impostor.Api.Net.Inner.Objects
{
WaitingForHost = 4,
All = PreSpawn | NotLimbo | WaitingForHost,
}
-}
\ No newline at end of file
+}
{
IEnumerable<IClient> Clients { get; }
}
-}
\ No newline at end of file
+}
/// <summary>
/// Deserialize a packet.
/// </summary>
- /// <param name="reader"><see cref="IMessageReader"/> with <see cref="IMessageReader.Tag"/> 0.</param>
+ /// <param name="reader"><see cref="IMessageReader" /> with <see cref="IMessageReader.Tag" /> 0.</param>
/// <param name="chatType">The chat type selected in the client of the player.</param>
- /// <returns>Deserialized <see cref="GameOptionsData"/>.</returns>
+ /// <returns>Deserialized <see cref="GameOptionsData" />.</returns>
public static GameOptionsData Deserialize(IMessageReader reader, out ChatType chatType)
{
var gameOptionsData = GameOptionsData.DeserializeCreate(reader);
-using Impostor.Api.Games;
+using System;
+using Impostor.Api.Games;
namespace Impostor.Api.Net.Messages.C2S
{
{
public static void Serialize(IMessageWriter writer)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public static void Deserialize(IMessageReader reader, out GameCode gameCode)
-namespace Impostor.Api.Net.Messages.C2S
+using System;
+
+namespace Impostor.Api.Net.Messages.C2S
{
public class Message04RemovePlayerC2S
{
public static void Serialize(IMessageWriter writer)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public static void Deserialize(IMessageReader reader, out int playerId, out byte reason)
reason = reader.ReadByte();
}
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Innersloth;
+using System;
+using Impostor.Api.Innersloth;
namespace Impostor.Api.Net.Messages.C2S
{
{
public static void Serialize(IMessageWriter writer)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public static void Deserialize(IMessageReader reader, out GameOverReason gameOverReason)
reader.ReadBoolean(); // showAd
}
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Innersloth;
+using System;
+using Impostor.Api.Innersloth;
namespace Impostor.Api.Net.Messages.C2S
{
{
public static void Serialize(IMessageWriter writer)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public static void Deserialize(IMessageReader reader, out AlterGameTags gameTag, out bool isPublic)
isPublic = slice.ReadBoolean();
}
}
-}
\ No newline at end of file
+}
-namespace Impostor.Api.Net.Messages.C2S
+using System;
+
+namespace Impostor.Api.Net.Messages.C2S
{
public class Message11KickPlayerC2S
{
public static void Serialize(IMessageWriter writer)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public static void Deserialize(IMessageReader reader, out int playerId, out bool isBan)
isBan = reader.ReadBoolean();
}
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Innersloth;
+using System;
+using Impostor.Api.Innersloth;
namespace Impostor.Api.Net.Messages.C2S
{
{
public static void Serialize(IMessageWriter writer)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public static void Deserialize(IMessageReader reader, out GameOptionsData options, out ChatType chatType)
byte[] Buffer { get; }
/// <summary>
- /// Gets the offset of our current <see cref="IMessageReader"/> in the entire <see cref="Buffer"/>.
+ /// Gets the offset of our current <see cref="IMessageReader" /> in the entire <see cref="Buffer" />.
/// </summary>
int Offset { get; }
void Write(string value);
/// <summary>
- /// Writes a <see cref="IPAddress"/> to the message.
+ /// Writes a <see cref="IPAddress" /> to the message.
/// </summary>
/// <param name="value">Value to write.</param>
void Write(IPAddress value);
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!
+ /// 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"/>.
+ /// 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>
+ /// <returns>A <see cref="IMessageWriter" /> from the pool.</returns>
IMessageWriter Get(MessageType sendOption = MessageType.Unreliable);
}
}
public const byte GetGameList = 9;
public const byte GetGameListV2 = 16;
}
-}
\ No newline at end of file
+}
/// </remarks>
Reliable,
}
-}
\ No newline at end of file
+}
throw new NotImplementedException();
}
}
-}
\ No newline at end of file
+}
public static void Deserialize(IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Innersloth;
+using System;
+using Impostor.Api.Innersloth;
namespace Impostor.Api.Net.Messages.S2C
{
public static void Deserialize(IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
-}
\ No newline at end of file
+}
-namespace Impostor.Api.Net.Messages.S2C
+using System;
+
+namespace Impostor.Api.Net.Messages.S2C
{
public static class Message07JoinedGameS2C
{
public static void Deserialize(IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Innersloth;
+using System;
+using Impostor.Api.Innersloth;
namespace Impostor.Api.Net.Messages.S2C
{
public static void Deserialize(IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
-}
\ No newline at end of file
+}
-namespace Impostor.Api.Net.Messages.S2C
+using System;
+
+namespace Impostor.Api.Net.Messages.S2C
{
public class Message11KickPlayerS2C
{
public static void Deserialize(IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
-}
\ No newline at end of file
+}
-namespace Impostor.Api.Net.Messages.S2C
+using System;
+
+namespace Impostor.Api.Net.Messages.S2C
{
public class Message12WaitForHostS2C
{
public static void Deserialize(IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
-}
\ No newline at end of file
+}
-using System.Net;
+using System;
+using System.Net;
namespace Impostor.Api.Net.Messages.S2C
{
public static void Deserialize(IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
-}
\ No newline at end of file
+}
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Impostor.Api.Games;
namespace Impostor.Api.Net.Messages.S2C
public static void Deserialize(IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
}
ValueTask ReloadAsync();
}
-}
\ No newline at end of file
+}
void ConfigureServices(IServiceCollection services);
}
-}
\ No newline at end of file
+}
public string Version { get; }
}
-}
\ No newline at end of file
+}
return default;
}
}
-}
\ No newline at end of file
+}
using System.Runtime.CompilerServices;
-[assembly:InternalsVisibleTo("Impostor.Server")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("Impostor.Server")]
namespace Impostor.Api.Reactor
{
/// <summary>
- /// Plugin side used in modded handshake
+ /// Plugin side used in modded handshake
/// </summary>
public enum PluginSide : byte
{
/// <summary>
- /// Required by both sides, reject connection if missing on the other side
+ /// Required by both sides, reject connection if missing on the other side
/// </summary>
Both,
/// <summary>
- /// Required only by client
+ /// Required only by client
/// </summary>
ClientOnly,
/// <summary>
- /// Required only by server
+ /// Required only by server
/// </summary>
ServerOnly,
}
public static class Mathf
{
/// <summary>
- /// <para>Clamps the given value between the given minimum float and maximum float values. Returns the given value if it is within the min and max range.</para>
+ /// <para>Clamps the given value between the given minimum float and maximum float values. Returns the given value if it is within the min and max range.</para>
/// </summary>
/// <param name="value">The floating point value to restrict inside the range defined by the min and max values.</param>
/// <param name="min">The minimum floating point value to compare against.</param>
/// <param name="max">The maximum floating point value to compare against.</param>
/// <returns>
- /// <para>The float result between the min and max values.</para>
+ /// <para>The float result between the min and max values.</para>
/// </returns>
public static float Clamp(float value, float min, float max)
{
}
/// <summary>
- /// <para>Clamps value between 0 and 1 and returns value.</para>
+ /// <para>Clamps value between 0 and 1 and returns value.</para>
/// </summary>
/// <param name="value">Value.</param>
/// <returns>Clamped value.</returns>
}
/// <summary>
- /// <para>Linearly interpolates between a and b by t.</para>
+ /// <para>Linearly interpolates between a and b by t.</para>
/// </summary>
/// <param name="a">The start value.</param>
/// <param name="b">The end value.</param>
/// <param name="t">The interpolation value between the two floats.</param>
/// <returns>
- /// <para>The interpolated float result between the two float values.</para>
+ /// <para>The interpolated float result between the two float values.</para>
/// </returns>
public static float Lerp(float a, float b, float t) => a + ((b - a) * Clamp01(t));
public bool ReadBoolean()
{
- byte val = FastByte();
+ var val = FastByte();
return val != 0;
}
float output = 0;
fixed (byte* bufPtr = &this.Buffer[Position])
{
- byte* outPtr = (byte*)&output;
+ var outPtr = (byte*)&output;
*outPtr = *bufPtr;
*(outPtr + 1) = *(bufPtr + 1);
public uint ReadPackedUInt32()
{
- bool readMore = true;
- int shift = 0;
+ var readMore = true;
+ var shift = 0;
uint output = 0;
while (readMore)
{
- byte b = FastByte();
+ var b = FastByte();
if (b >= 0x80)
{
readMore = true;
public bool ReadBoolean()
{
- byte val = FastByte();
+ var val = FastByte();
return val != 0;
}
float output = 0;
fixed (byte* bufPtr = &this.Buffer[Position])
{
- byte* outPtr = (byte*)&output;
+ var outPtr = (byte*)&output;
*outPtr = *bufPtr;
*(outPtr + 1) = *(bufPtr + 1);
public uint ReadPackedUInt32()
{
- bool readMore = true;
- int shift = 0;
+ var readMore = true;
+ var shift = 0;
uint output = 0;
while (readMore)
{
- byte b = FastByte();
+ var b = FastByte();
if (b >= 0x80)
{
readMore = true;
using System;
using System.Buffers.Binary;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.IO;
using System.Runtime.CompilerServices;
-using System.Text;
using Microsoft.Extensions.ObjectPool;
namespace Impostor.Benchmarks.Data
{
if (includeHeader)
{
- byte[] output = new byte[this.Length];
+ var output = new byte[this.Length];
System.Buffer.BlockCopy(this.Buffer, 0, output, 0, this.Length);
return output;
}
switch (this.SendOption)
{
case MessageType.Reliable:
- {
- byte[] output = new byte[this.Length - 3];
- System.Buffer.BlockCopy(this.Buffer, 3, output, 0, this.Length - 3);
- return output;
- }
+ {
+ var output = new byte[this.Length - 3];
+ System.Buffer.BlockCopy(this.Buffer, 3, output, 0, this.Length - 3);
+ return output;
+ }
case MessageType.Unreliable:
- {
- byte[] output = new byte[this.Length - 1];
- System.Buffer.BlockCopy(this.Buffer, 1, output, 0, this.Length - 1);
- return output;
- }
+ {
+ var output = new byte[this.Length - 1];
+ System.Buffer.BlockCopy(this.Buffer, 1, output, 0, this.Length - 1);
+ return output;
+ }
default:
throw new ArgumentOutOfRangeException();
}
public void EndMessage()
{
var lastMessageStart = messageStarts.Pop();
- ushort length = (ushort)(this.Position - lastMessageStart - 3); // Minus length and type byte
+ var length = (ushort)(this.Position - lastMessageStart - 3); // Minus length and type byte
this.Buffer[lastMessageStart] = (byte)length;
this.Buffer[lastMessageStart + 1] = (byte)(length >> 8);
}
{
fixed (byte* ptr = &this.Buffer[this.Position])
{
- byte* valuePtr = (byte*)&value;
+ var valuePtr = (byte*)&value;
*ptr = *valuePtr;
*(ptr + 1) = *(valuePtr + 1);
{
do
{
- byte b = (byte)(value & 0xFF);
+ var b = (byte)(value & 0xFF);
if (value >= 0x80)
{
b |= 0x80;
public void Write(MessageWriter msg, bool includeHeader)
{
- int offset = 0;
+ var offset = 0;
if (!includeHeader)
{
switch (msg.SendOption)
byte b;
unsafe
{
- int i = 1;
- byte* bp = (byte*)&i;
+ var i = 1;
+ var bp = (byte*)&i;
b = *bp;
}
using System;
using System.Buffers.Binary;
-using Impostor.Hazel;
namespace Impostor.Benchmarks.Data.Span
{
using Impostor.Benchmarks.Data;
using Impostor.Benchmarks.Data.Pool;
using Impostor.Benchmarks.Extensions;
-using Impostor.Hazel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.ObjectPool;
-using MessageWriter = Impostor.Benchmarks.Data.MessageWriter;
namespace Impostor.Benchmarks.Tests
{
message.StartMessage(1);
message.Write((ushort)3100);
message.Write((byte)100);
- message.Write((int) int.MaxValue);
+ message.Write((int)int.MaxValue);
message.WritePacked(int.MaxValue);
message.EndMessage();
-using System;
-using System.Net;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Impostor.Api.Innersloth;
Message00HostGameC2S.Serialize(writeGameCreate, new GameOptionsData
{
MaxPlayers = 4,
- NumImpostors = 2
+ NumImpostors = 2,
});
// TODO: ObjectPool for MessageReaders
/// </summary>
/// <remarks>
/// <para>
- /// Connection is the base class for all connections that Hazel can make. It provides common functionality and a
+ /// Connection is the base class for all connections that Hazel can make. It provides common functionality and a
/// standard interface to allow connections to be swapped easily.
/// </para>
/// <para>
/// </list>
/// </para>
/// </remarks>
- /// <threadsafety static="true" instance="true"/>
+ /// <threadsafety static="true" instance="true" />
public abstract class Connection : IDisposable
{
private static readonly ILogger Logger = Log.ForContext<Connection>();
/// </summary>
/// <remarks>
/// <para>
- /// DataReceived is invoked everytime a message is received from the end point of this connection, the message
- /// that was received can be found in the <see cref="DataReceivedEventArgs"/> alongside other information from the
+ /// DataReceived is invoked everytime a message is received from the end point of this connection, the message
+ /// that was received can be found in the <see cref="DataReceivedEventArgs" /> alongside other information from the
/// event.
/// </para>
/// <include file="DocInclude/common.xml" path="docs/item[@name='Event_Thread_Safety_Warning']/*" />
/// </remarks>
/// <example>
- /// <code language="C#" source="DocInclude/TcpClientExample.cs"/>
+ /// <code language="C#" source="DocInclude/TcpClientExample.cs" />
/// </example>
public Func<DataReceivedEventArgs, ValueTask> DataReceived;
public int TestLagMs = -1;
public int TestDropRate = 0;
protected int testDropCount = 0;
-
+
/// <summary>
/// Called when the end point disconnects or an error occurs.
/// </summary>
/// <remarks>
/// <para>
- /// Disconnected is invoked when the connection is closed due to an exception occuring or because the remote
- /// end point disconnected. If it was invoked due to an exception occuring then the exception is available
- /// in the <see cref="DisconnectedEventArgs"/> passed with the event.
+ /// Disconnected is invoked when the connection is closed due to an exception occuring or because the remote
+ /// end point disconnected. If it was invoked due to an exception occuring then the exception is available
+ /// in the <see cref="DisconnectedEventArgs" /> passed with the event.
/// </para>
/// <include file="DocInclude/common.xml" path="docs/item[@name='Event_Thread_Safety_Warning']/*" />
/// </remarks>
/// <example>
- /// <code language="C#" source="DocInclude/TcpClientExample.cs"/>
+ /// <code language="C#" source="DocInclude/TcpClientExample.cs" />
/// </example>
public Func<DisconnectedEventArgs, ValueTask> Disconnected;
/// The remote end point of this Connection.
/// </summary>
/// <remarks>
- /// This is the end point that this connection is connected to (i.e. the other device). This returns an abstract
- /// <see cref="ConnectionEndPoint"/> which can then be cast to an appropriate end point depending on the
+ /// This is the end point that this connection is connected to (i.e. the other device). This returns an abstract
+ /// <see cref="ConnectionEndPoint" /> which can then be cast to an appropriate end point depending on the
/// connection type.
/// </remarks>
public IPEndPoint EndPoint { get; protected set; }
/// </summary>
/// <remarks>
/// All implementers should be aware that when this is set to ConnectionState.Connected it will
- /// release all threads that are blocked on <see cref="WaitOnConnect"/>.
+ /// release all threads that are blocked on <see cref="WaitOnConnect" />.
/// </remarks>
public ConnectionState State
{
{
return this._state;
}
-
+
protected set
{
this._state = value;
protected ConnectionState _state;
protected virtual void SetState(ConnectionState state) { }
-
+
/// <summary>
/// Constructor that initializes the ConnecitonStatistics object.
/// </summary>
/// <remarks>
- /// This constructor initialises <see cref="Statistics"/> with empty statistics and sets <see cref="State"/> to
- /// <see cref="ConnectionState.NotConnected"/>.
+ /// This constructor initialises <see cref="Statistics" /> with empty statistics and sets <see cref="State" /> to
+ /// <see cref="ConnectionState.NotConnected" />.
/// </remarks>
protected Connection()
{
}
/// <summary>
- /// Sends a number of bytes to the end point of the connection using the specified <see cref="MessageType"/>.
+ /// Sends a number of bytes to the end point of the connection using the specified <see cref="MessageType" />.
/// </summary>
/// <param name="msg">The message to send.</param>
/// <remarks>
/// <include file="DocInclude/common.xml" path="docs/item[@name='Connection_SendBytes_General']/*" />
/// <para>
/// The messageType parameter is only a request to use those options and the actual method used to send the
- /// data is up to the implementation. There are circumstances where this parameter may be ignored but in
+ /// data is up to the implementation. There are circumstances where this parameter may be ignored but in
/// general any implementer should aim to always follow the user's request.
/// </para>
/// </remarks>
public abstract ValueTask SendAsync(IMessageWriter msg);
/// <summary>
- /// Sends a number of bytes to the end point of the connection using the specified <see cref="MessageType"/>.
+ /// Sends a number of bytes to the end point of the connection using the specified <see cref="MessageType" />.
/// </summary>
/// <param name="bytes">The bytes of the message to send.</param>
/// <param name="messageType">The option specifying how the message should be sent.</param>
/// <include file="DocInclude/common.xml" path="docs/item[@name='Connection_SendBytes_General']/*" />
/// <para>
/// The messageType parameter is only a request to use those options and the actual method used to send the
- /// data is up to the implementation. There are circumstances where this parameter may be ignored but in
+ /// data is up to the implementation. There are circumstances where this parameter may be ignored but in
/// general any implementer should aim to always follow the user's request.
/// </para>
/// </remarks>
/// Invokes the DataReceived event.
/// </summary>
/// <param name="msg">The bytes received.</param>
- /// <param name="messageType">The <see cref="MessageType"/> the message was received with.</param>
+ /// <param name="messageType">The <see cref="MessageType" /> the message was received with.</param>
/// <remarks>
- /// Invokes the <see cref="DataReceived"/> event on this connection to alert subscribers a new message has been
+ /// Invokes the <see cref="DataReceived" /> event on this connection to alert subscribers a new message has been
/// received. The bytes and the send option that the message was sent with should be passed in to give to the
/// subscribers.
/// </remarks>
/// <param name="e">The exception, if any, that occurred to cause this.</param>
/// <param name="reader">Extra disconnect data</param>
/// <remarks>
- /// Invokes the <see cref="Disconnected"/> event to alert subscribres this connection has been disconnected either
- /// by the end point or because an error occurred. If an error occurred the error should be passed in in order to
+ /// Invokes the <see cref="Disconnected" /> event to alert subscribres this connection has been disconnected either
+ /// by the end point or because an error occurred. If an error occurred the error should be passed in in order to
/// pass to the subscribers, otherwise null can be passed in.
/// </remarks>
protected async ValueTask InvokeDisconnected(string e, IMessageReader reader)
}
/// <summary>
- /// For times when you want to force the disconnect handler to fire as well as close it.
- /// If you only want to close it, just use Dispose.
+ /// For times when you want to force the disconnect handler to fire as well as close it.
+ /// If you only want to close it, just use Dispose.
/// </summary>
public abstract ValueTask Disconnect(string reason, MessageWriter writer = null);
-
+
/// <summary>
/// Disposes of this NetworkConnection.
/// </summary>
/// </summary>
/// <remarks>
/// <para>
- /// ConnectionListeners are server side objects that listen for clients and create matching server side connections
+ /// ConnectionListeners are server side objects that listen for clients and create matching server side connections
/// for each client in a similar way to TCP does. These connections should be ready for communication immediately.
/// </para>
/// <para>
- /// Each time a client connects the <see cref="NewConnection"/> event will be invoked to alert all subscribers to
- /// the new connection. A disconnected event is then present on the <see cref="Connection"/> that is passed to the
+ /// Each time a client connects the <see cref="NewConnection" /> event will be invoked to alert all subscribers to
+ /// the new connection. A disconnected event is then present on the <see cref="Connection" /> that is passed to the
/// subscribers.
/// </para>
/// </remarks>
- /// <threadsafety static="true" instance="true"/>
+ /// <threadsafety static="true" instance="true" />
public abstract class ConnectionListener : IAsyncDisposable
{
private static readonly ILogger Logger = Log.ForContext<ConnectionListener>();
/// </summary>
/// <remarks>
/// <para>
- /// NewConnection is invoked each time a client connects to the listener. The
- /// <see cref="NewConnectionEventArgs"/> contains the new <see cref="Connection"/> for communication with this
+ /// NewConnection is invoked each time a client connects to the listener. The
+ /// <see cref="NewConnectionEventArgs" /> contains the new <see cref="Connection" /> for communication with this
/// client.
/// </para>
/// <para>
- /// Hazel may or may not store connections so it is your responsibility to keep track and properly Dispose of
- /// connections to your server.
+ /// Hazel may or may not store connections so it is your responsibility to keep track and properly Dispose of
+ /// connections to your server.
/// </para>
/// <include file="DocInclude/common.xml" path="docs/item[@name='Event_Thread_Safety_Warning']/*" />
/// </remarks>
/// <example>
- /// <code language="C#" source="DocInclude/TcpListenerExample.cs"/>
+ /// <code language="C#" source="DocInclude/TcpListenerExample.cs" />
/// </example>
public Func<NewConnectionEventArgs, ValueTask> NewConnection;
/// </summary>
/// <remarks>
/// <para>
- /// This instructs the listener to begin listening for new clients connecting to the server. When a new client
- /// connects the <see cref="NewConnection"/> event will be invoked containing the connection to the new client.
+ /// This instructs the listener to begin listening for new clients connecting to the server. When a new client
+ /// connects the <see cref="NewConnection" /> event will be invoked containing the connection to the new client.
/// </para>
/// <para>
- /// To stop listening you should call <see cref="DisposeAsync()"/>.
+ /// To stop listening you should call <see cref="DisposeAsync()" />.
/// </para>
/// </remarks>
/// <example>
- /// <code language="C#" source="DocInclude/TcpListenerExample.cs"/>
+ /// <code language="C#" source="DocInclude/TcpListenerExample.cs" />
/// </example>
public abstract Task StartAsync();
/// <param name="msg">The user sent bytes that were received as part of the handshake.</param>
/// <param name="connection">The connection to pass in the arguments.</param>
/// <remarks>
- /// Implementers should call this to invoke the <see cref="NewConnection"/> event before data is received so that
+ /// Implementers should call this to invoke the <see cref="NewConnection" /> event before data is received so that
/// subscribers do not miss any data that may have been sent immediately after connecting.
/// </remarks>
internal async Task InvokeNewConnection(IMessageReader msg, Connection connection)
namespace Impostor.Hazel
{
/// <summary>
- /// Represents the state a <see cref="Connection"/> is currently in.
+ /// Represents the state a <see cref="Connection" /> is currently in.
/// </summary>
public enum ConnectionState
{
/// The Connection has either not been established yet or has been disconnected.
/// </summary>
NotConnected,
-
+
/// <summary>
/// The Connection is currently connecting to an endpoint.
/// </summary>
using System.Threading;
[assembly: InternalsVisibleTo("Hazel.Tests")]
+
namespace Impostor.Hazel
{
/// <summary>
- /// Holds statistics about the traffic through a <see cref="Connection"/>.
+ /// Holds statistics about the traffic through a <see cref="Connection" />.
/// </summary>
- /// <threadsafety static="true" instance="true"/>
+ /// <threadsafety static="true" instance="true" />
public class ConnectionStatistics
{
private const int ExpectedMTU = 1200;
/// The number of messages sent larger than 576 bytes. This is smaller than most default MTUs.
/// </summary>
/// <remarks>
- /// This is the number of unreliable messages that were sent from the <see cref="Connection"/>, incremented
- /// each time that LogUnreliableSend is called by the Connection. Messages that caused an error are not
+ /// This is the number of unreliable messages that were sent from the <see cref="Connection" />, incremented
+ /// each time that LogUnreliableSend is called by the Connection. Messages that caused an error are not
/// counted and messages are only counted once all other operations in the send are complete.
/// </remarks>
public int FragmentableMessagesSent
/// The number of unreliable messages sent.
/// </summary>
/// <remarks>
- /// This is the number of unreliable messages that were sent from the <see cref="Connection"/>, incremented
- /// each time that LogUnreliableSend is called by the Connection. Messages that caused an error are not
+ /// This is the number of unreliable messages that were sent from the <see cref="Connection" />, incremented
+ /// each time that LogUnreliableSend is called by the Connection. Messages that caused an error are not
/// counted and messages are only counted once all other operations in the send are complete.
/// </remarks>
public int UnreliableMessagesSent
/// The number of reliable messages sent.
/// </summary>
/// <remarks>
- /// This is the number of reliable messages that were sent from the <see cref="Connection"/>, incremented
- /// each time that LogReliableSend is called by the Connection. Messages that caused an error are not
+ /// This is the number of reliable messages that were sent from the <see cref="Connection" />, incremented
+ /// each time that LogReliableSend is called by the Connection. Messages that caused an error are not
/// counted and messages are only counted once all other operations in the send are complete.
/// </remarks>
public int ReliableMessagesSent
/// The number of fragmented messages sent.
/// </summary>
/// <remarks>
- /// This is the number of fragmented messages that were sent from the <see cref="Connection"/>, incremented
- /// each time that LogFragmentedSend is called by the Connection. Messages that caused an error are not
+ /// This is the number of fragmented messages that were sent from the <see cref="Connection" />, incremented
+ /// each time that LogFragmentedSend is called by the Connection. Messages that caused an error are not
/// counted and messages are only counted once all other operations in the send are complete.
/// </remarks>
public int FragmentedMessagesSent
/// The number of acknowledgement messages sent.
/// </summary>
/// <remarks>
- /// This is the number of acknowledgements that were sent from the <see cref="Connection"/>, incremented
- /// each time that LogAcknowledgementSend is called by the Connection. Messages that caused an error are not
+ /// This is the number of acknowledgements that were sent from the <see cref="Connection" />, incremented
+ /// each time that LogAcknowledgementSend is called by the Connection. Messages that caused an error are not
/// counted and messages are only counted once all other operations in the send are complete.
/// </remarks>
public int AcknowledgementMessagesSent
/// The number of hello messages sent.
/// </summary>
/// <remarks>
- /// This is the number of hello messages that were sent from the <see cref="Connection"/>, incremented
- /// each time that LogHelloSend is called by the Connection. Messages that caused an error are not
+ /// This is the number of hello messages that were sent from the <see cref="Connection" />, incremented
+ /// each time that LogHelloSend is called by the Connection. Messages that caused an error are not
/// counted and messages are only counted once all other operations in the send are complete.
/// </remarks>
public int HelloMessagesSent
/// </summary>
/// <remarks>
/// <para>
- /// This is the number of bytes of data (i.e. user bytes) that were sent from the <see cref="Connection"/>,
- /// accumulated each time that LogSend is called by the Connection. Messages that caused an error are not
+ /// This is the number of bytes of data (i.e. user bytes) that were sent from the <see cref="Connection" />,
+ /// accumulated each time that LogSend is called by the Connection. Messages that caused an error are not
/// counted and messages are only counted once all other operations in the send are complete.
/// </para>
/// <para>
- /// For the number of bytes including protocol bytes see <see cref="TotalBytesSent"/>.
+ /// For the number of bytes including protocol bytes see <see cref="TotalBytesSent" />.
/// </para>
/// </remarks>
public long DataBytesSent
/// </summary>
/// <remarks>
/// <para>
- /// This is the total number of bytes (the data bytes plus protocol bytes) that were sent from the
- /// <see cref="Connection"/>, accumulated each time that LogSend is called by the Connection. Messages that
- /// caused an error are not counted and messages are only counted once all other operations in the send are
+ /// This is the total number of bytes (the data bytes plus protocol bytes) that were sent from the
+ /// <see cref="Connection" />, accumulated each time that LogSend is called by the Connection. Messages that
+ /// caused an error are not counted and messages are only counted once all other operations in the send are
/// complete.
/// </para>
/// <para>
- /// For the number of data bytes excluding protocol bytes see <see cref="DataBytesSent"/>.
+ /// For the number of data bytes excluding protocol bytes see <see cref="DataBytesSent" />.
/// </para>
/// </remarks>
public long TotalBytesSent
return UnreliableMessagesReceived + ReliableMessagesReceived + FragmentedMessagesReceived + AcknowledgementMessagesReceived + helloMessagesReceived;
}
}
-
+
/// <summary>
/// The number of unreliable messages received.
/// </summary>
/// <remarks>
- /// This is the number of unreliable messages that were received by the <see cref="Connection"/>, incremented
+ /// This is the number of unreliable messages that were received by the <see cref="Connection" />, incremented
/// each time that LogUnreliableReceive is called by the Connection. Messages are counted before the receive event is invoked.
/// </remarks>
public int UnreliableMessagesReceived
/// The number of reliable messages received.
/// </summary>
/// <remarks>
- /// This is the number of reliable messages that were received by the <see cref="Connection"/>, incremented
+ /// This is the number of reliable messages that were received by the <see cref="Connection" />, incremented
/// each time that LogReliableReceive is called by the Connection. Messages are counted before the receive event is invoked.
/// </remarks>
public int ReliableMessagesReceived
/// The number of fragmented messages received.
/// </summary>
/// <remarks>
- /// This is the number of fragmented messages that were received by the <see cref="Connection"/>, incremented
+ /// This is the number of fragmented messages that were received by the <see cref="Connection" />, incremented
/// each time that LogFragmentedReceive is called by the Connection. Messages are counted before the receive event is invoked.
/// </remarks>
public int FragmentedMessagesReceived
/// The number of acknowledgement messages received.
/// </summary>
/// <remarks>
- /// This is the number of acknowledgement messages that were received by the <see cref="Connection"/>, incremented
+ /// This is the number of acknowledgement messages that were received by the <see cref="Connection" />, incremented
/// each time that LogAcknowledgemntReceive is called by the Connection. Messages are counted before the receive event is invoked.
/// </remarks>
public int AcknowledgementMessagesReceived
/// The number of ping messages received.
/// </summary>
/// <remarks>
- /// This is the number of hello messages that were received by the <see cref="Connection"/>, incremented
+ /// This is the number of hello messages that were received by the <see cref="Connection" />, incremented
/// each time that LogHelloReceive is called by the Connection. Messages are counted before the receive event is invoked.
/// </remarks>
public int PingMessagesReceived
/// The number of hello messages received.
/// </summary>
/// <remarks>
- /// This is the number of hello messages that were received by the <see cref="Connection"/>, incremented
+ /// This is the number of hello messages that were received by the <see cref="Connection" />, incremented
/// each time that LogHelloReceive is called by the Connection. Messages are counted before the receive event is invoked.
/// </remarks>
public int HelloMessagesReceived
/// </summary>
/// <remarks>
/// <para>
- /// This is the number of bytes of data (i.e. user bytes) that were received by the <see cref="Connection"/>,
+ /// This is the number of bytes of data (i.e. user bytes) that were received by the <see cref="Connection" />,
/// accumulated each time that LogReceive is called by the Connection. Messages are counted before the receive
/// event is invoked.
/// </para>
/// <para>
- /// For the number of bytes including protocol bytes see <see cref="TotalBytesReceived"/>.
+ /// For the number of bytes including protocol bytes see <see cref="TotalBytesReceived" />.
/// </para>
/// </remarks>
public long DataBytesReceived
/// </summary>
/// <remarks>
/// <para>
- /// This is the total number of bytes (the data bytes plus protocol bytes) that were received by the
- /// <see cref="Connection"/>, accumulated each time that LogReceive is called by the Connection. Messages are
+ /// This is the total number of bytes (the data bytes plus protocol bytes) that were received by the
+ /// <see cref="Connection" />, accumulated each time that LogReceive is called by the Connection. Messages are
/// counted before the receive event is invoked.
/// </para>
/// <para>
- /// For the number of data bytes excluding protocol bytes see <see cref="DataBytesReceived"/>.
+ /// For the number of data bytes excluding protocol bytes see <see cref="DataBytesReceived" />.
/// </para>
/// </remarks>
public long TotalBytesReceived
public readonly IMessageReader Message;
/// <summary>
- /// The <see cref="Type"/> the data was sent with.
+ /// The <see cref="Type" /> the data was sent with.
/// </summary>
public readonly MessageType Type;
-
+
public DataReceivedEventArgs(Connection sender, IMessageReader msg, MessageType type)
{
this.Sender = sender;
public class DisconnectedEventArgs : EventArgs
{
/// <summary>
- /// Optional disconnect reason. May be null.
+ /// Optional disconnect reason. May be null.
/// </summary>
public readonly string Reason;
/// <summary>
- /// Optional data sent with a disconnect message. May be null.
- /// You must not recycle this. If you need the message outside of a callback, you should copy it.
+ /// Optional data sent with a disconnect message. May be null.
+ /// You must not recycle this. If you need the message outside of a callback, you should copy it.
/// </summary>
public readonly IMessageReader Message;
[Serializable]
public class HazelException : Exception
{
- internal HazelException(string msg) : base (msg)
+ internal HazelException(string msg) : base(msg)
{
-
}
- internal HazelException(string msg, Exception e) : base (msg, e)
+ internal HazelException(string msg, Exception e) : base(msg, e)
{
-
}
}
}
/// Represents the IP version that a connection or listener will use.
/// </summary>
/// <remarks>
- /// If you wand a client to connect or be able to connect using IPv6 then you should use <see cref="IPv4AndIPv6"/>,
- /// this sets the underlying sockets to use IPv6 but still allow IPv4 sockets to connect for backwards compatability
+ /// If you wand a client to connect or be able to connect using IPv6 then you should use <see cref="IPv4AndIPv6" />,
+ /// this sets the underlying sockets to use IPv6 but still allow IPv4 sockets to connect for backwards compatability
/// and hence it is the default IPMode in most cases.
/// </remarks>
public enum IPMode
IPv4,
/// <summary>
- /// Instruction to use IPv6 only, IPv4 connections will not be able to connect. IPv4 addresses can be connected
+ /// Instruction to use IPv6 only, IPv4 connections will not be able to connect. IPv4 addresses can be connected
/// by converting to IPv6 addresses.
/// </summary>
- IPv6
+ IPv6,
}
}
/// <summary>
/// Interface for all items that can be returned to an object pool.
/// </summary>
- /// <threadsafety static="true" instance="true"/>
+ /// <threadsafety static="true" instance="true" />
public interface IRecyclable
{
/// <summary>
public bool ReadBoolean()
{
- byte val = FastByte();
+ var val = FastByte();
return val != 0;
}
public uint ReadPackedUInt32()
{
- bool readMore = true;
- int shift = 0;
+ var readMore = true;
+ var shift = 0;
uint output = 0;
while (readMore)
{
- byte b = FastByte();
+ var b = FastByte();
if (b >= 0x80)
{
readMore = true;
public void CopyTo(IMessageWriter writer)
{
- writer.Write((ushort) Length);
- writer.Write((byte) Tag);
+ writer.Write((ushort)Length);
+ writer.Write((byte)Tag);
writer.Write(Buffer.AsMemory(Offset, Length));
}
System.Buffer.BlockCopy(Buffer, offsetEnd, Buffer, offsetStart, lengthToCopy);
- ((MessageReader) message).Parent.AdjustLength(message.Offset, message.Length + 3);
+ ((MessageReader)message).Parent.AdjustLength(message.Offset, message.Length + 3);
}
private void AdjustLength(int offset, int amount)
public Vector2 ReadVector2()
{
const float range = 50f;
-
- var x = ReadUInt16() / (float) ushort.MaxValue;
- var y = ReadUInt16() / (float) ushort.MaxValue;
+
+ var x = ReadUInt16() / (float)ushort.MaxValue;
+ var y = ReadUInt16() / (float)ushort.MaxValue;
return new Vector2(Mathf.Lerp(-range, range, x), Mathf.Lerp(-range, range, y));
}
-using Impostor.Api.Games;
-using Impostor.Api.Net.Messages;
-
-using System;
+using System;
using System.Collections.Generic;
using System.Net;
using System.Numerics;
using System.Text;
+using Impostor.Api.Games;
using Impostor.Api.Net.Inner;
+using Impostor.Api.Net.Messages;
using Impostor.Api.Unity;
namespace Impostor.Hazel
{
if (includeHeader)
{
- byte[] output = new byte[this.Length];
+ var output = new byte[this.Length];
System.Buffer.BlockCopy(this.Buffer, 0, output, 0, this.Length);
return output;
}
switch (this.SendOption)
{
case MessageType.Reliable:
- {
- byte[] output = new byte[this.Length - 3];
- System.Buffer.BlockCopy(this.Buffer, 3, output, 0, this.Length - 3);
- return output;
- }
+ {
+ var output = new byte[this.Length - 3];
+ System.Buffer.BlockCopy(this.Buffer, 3, output, 0, this.Length - 3);
+ return output;
+ }
case MessageType.Unreliable:
- {
- byte[] output = new byte[this.Length - 1];
- System.Buffer.BlockCopy(this.Buffer, 1, output, 0, this.Length - 1);
- return output;
- }
+ {
+ var output = new byte[this.Length - 1];
+ System.Buffer.BlockCopy(this.Buffer, 1, output, 0, this.Length - 1);
+ return output;
+ }
default:
throw new ArgumentOutOfRangeException();
}
throw new NotImplementedException();
}
- ///
/// <param name="sendOption">The option specifying how the message should be sent.</param>
public static MessageWriter Get(MessageType sendOption = MessageType.Unreliable)
{
public void Write(Vector2 vector)
{
- Write((ushort)(Mathf.ReverseLerp(vector.X) * (double) ushort.MaxValue));
- Write((ushort)(Mathf.ReverseLerp(vector.Y) * (double) ushort.MaxValue));
+ Write((ushort)(Mathf.ReverseLerp(vector.X) * (double)ushort.MaxValue));
+ Write((ushort)(Mathf.ReverseLerp(vector.Y) * (double)ushort.MaxValue));
}
///
public void EndMessage()
{
var lastMessageStart = messageStarts.Pop();
- ushort length = (ushort)(this.Position - lastMessageStart - 3); // Minus length and type byte
+ var length = (ushort)(this.Position - lastMessageStart - 3); // Minus length and type byte
this.Buffer[lastMessageStart] = (byte)length;
this.Buffer[lastMessageStart + 1] = (byte)(length >> 8);
}
{
fixed (byte* ptr = &this.Buffer[this.Position])
{
- byte* valuePtr = (byte*)&value;
+ var valuePtr = (byte*)&value;
*ptr = *valuePtr;
*(ptr + 1) = *(valuePtr + 1);
{
do
{
- byte b = (byte)(value & 0xFF);
+ var b = (byte)(value & 0xFF);
if (value >= 0x80)
{
b |= 0x80;
public void Write(MessageWriter msg, bool includeHeader)
{
- int offset = 0;
+ var offset = 0;
if (!includeHeader)
{
switch (msg.SendOption)
byte b;
unsafe
{
- int i = 1;
- byte* bp = (byte*)&i;
+ var i = 1;
+ var bp = (byte*)&i;
b = *bp;
}
ReceivedZeroBytes,
PingsWithoutResponse,
ReliablePacketWithoutResponse,
- ConnectionDisconnected
+ ConnectionDisconnected,
}
/// <summary>
- /// Abstract base class for a <see cref="Connection"/> to a remote end point via a network protocol like TCP or UDP.
+ /// Abstract base class for a <see cref="Connection" /> to a remote end point via a network protocol like TCP or UDP.
/// </summary>
- /// <threadsafety static="true" instance="true"/>
+ /// <threadsafety static="true" instance="true" />
public abstract class NetworkConnection : Connection
{
/// <summary>
- /// An event that gives us a chance to send well-formed disconnect messages to clients when an internal disconnect happens.
+ /// An event that gives us a chance to send well-formed disconnect messages to clients when an internal disconnect happens.
/// </summary>
public Func<HazelInternalErrors, MessageWriter> OnInternalDisconnect;
/// The remote end point of this connection.
/// </summary>
/// <remarks>
- /// This is the end point of the other device given as an <see cref="System.Net.EndPoint"/> rather than a generic
- /// <see cref="ConnectionEndPoint"/> as the base <see cref="Connection"/> does.
+ /// This is the end point of the other device given as an <see cref="System.Net.EndPoint" /> rather than a generic
+ /// <see cref="ConnectionEndPoint" /> as the base <see cref="Connection" /> does.
/// </remarks>
public IPEndPoint RemoteEndPoint { get; protected set; }
}
/// <summary>
- /// Called when socket is disconnected internally
+ /// Called when socket is disconnected internally
/// </summary>
internal async ValueTask DisconnectInternal(HazelInternalErrors error, string reason)
{
var handler = this.OnInternalDisconnect;
if (handler != null)
{
- MessageWriter messageToRemote = handler(error);
+ var messageToRemote = handler(error);
if (messageToRemote != null)
{
try
namespace Impostor.Hazel
{
/// <summary>
- /// Abstract base class for a <see cref="ConnectionListener"/> for network based connections.
+ /// Abstract base class for a <see cref="ConnectionListener" /> for network based connections.
/// </summary>
- /// <threadsafety static="true" instance="true"/>
+ /// <threadsafety static="true" instance="true" />
public abstract class NetworkConnectionListener : ConnectionListener
{
/// <summary>
public struct NewConnectionEventArgs
{
/// <summary>
- /// The data received from the client in the handshake.
- /// This data is yours. Remember to recycle it.
+ /// The data received from the client in the handshake.
+ /// This data is yours. Remember to recycle it.
/// </summary>
public readonly IMessageReader HandshakeData;
/// <summary>
- /// The <see cref="Connection"/> to the new client.
+ /// The <see cref="Connection" /> to the new client.
/// </summary>
public readonly Connection Connection;
/// A fairly simple object pool for items that will be created a lot.
/// </summary>
/// <typeparam name="T">The type that is pooled.</typeparam>
- /// <threadsafety static="true" instance="true"/>
+ /// <threadsafety static="true" instance="true" />
public sealed class ObjectPoolCustom<T> where T : IRecyclable
{
private int numberCreated;
/// </summary>
/// <returns></returns>
private readonly Func<T> objectFactory;
-
+
/// <summary>
/// Internal constructor for our ObjectPool.
/// </summary>
internal T GetObject()
{
#if HAZEL_BAG
- if (!pool.TryTake(out T item))
+ if (!pool.TryTake(out var item))
{
Interlocked.Increment(ref numberCreated);
item = objectFactory.Invoke();
/// <param name="item">The item to return.</param>
internal void PutObject(T item)
{
- if (inuse.TryRemove(item, out bool b))
+ if (inuse.TryRemove(item, out var b))
{
#if HAZEL_BAG
pool.Add(item);
Hello = 8,
/// <summary>
- /// A single byte of continued existence
+ /// A single byte of continued existence
/// </summary>
Ping = 12,
return;
}
- if (numBytes < 3
+ if (numBytes < 3
|| buffer[0] != 4 || buffer[1] != 2)
{
this.StartListen();
return;
}
- IPEndPoint ipEnd = (IPEndPoint)endpt;
- string data = UTF8Encoding.UTF8.GetString(buffer, 2, numBytes - 2);
- int dataHash = data.GetHashCode();
+ var ipEnd = (IPEndPoint)endpt;
+ var data = UTF8Encoding.UTF8.GetString(buffer, 2, numBytes - 2);
+ var dataHash = data.GetHashCode();
lock (packets)
{
- bool found = false;
- for (int i = 0; i < this.packets.Count; ++i)
+ var found = false;
+ for (var i = 0; i < this.packets.Count; ++i)
{
var pkt = this.packets[i];
if (pkt == null || pkt.Data == null)
{
if (this.socket != null)
{
- try { this.socket.Shutdown(SocketShutdown.Both); } catch { }
- try { this.socket.Close(); } catch { }
- try { this.socket.Dispose(); } catch { }
+ try { this.socket.Shutdown(SocketShutdown.Both); }
+ catch { }
+
+ try { this.socket.Close(); }
+ catch { }
+
+ try { this.socket.Dispose(); }
+ catch { }
+
this.socket = null;
}
}
}
-}
\ No newline at end of file
+}
///
public void SetData(string data)
{
- int len = UTF8Encoding.UTF8.GetByteCount(data);
+ var len = UTF8Encoding.UTF8.GetByteCount(data);
this.data = new byte[len + 2];
this.data[0] = 4;
this.data[1] = 2;
{
if (this.socket != null)
{
- try { this.socket.Shutdown(SocketShutdown.Both); } catch { }
- try { this.socket.Close(); } catch { }
- try { this.socket.Dispose(); } catch { }
+ try { this.socket.Shutdown(SocketShutdown.Both); }
+ catch { }
+
+ try { this.socket.Close(); }
+ catch { }
+
+ try { this.socket.Dispose(); }
+ catch { }
+
this.socket = null;
}
}
}
-}
\ No newline at end of file
+}
using System;
-using System.Buffers;
using System.Net;
using System.Net.Sockets;
using System.Threading;
-using System.Threading.Channels;
using System.Threading.Tasks;
using Impostor.Api.Net.Messages;
using Microsoft.Extensions.ObjectPool;
/// <summary>
/// Represents a client's connection to a server that uses the UDP protocol.
/// </summary>
- /// <inheritdoc/>
+ /// <inheritdoc />
public sealed class UdpClientConnection : UdpConnection
{
private static readonly ILogger Logger = Log.ForContext<UdpClientConnection>();
/// <summary>
/// Creates a new UdpClientConnection.
/// </summary>
- /// <param name="remoteEndPoint">A <see cref="NetworkEndPoint"/> to connect to.</param>
+ /// <param name="remoteEndPoint">A <see cref="NetworkEndPoint" /> to connect to.</param>
public UdpClientConnection(IPEndPoint remoteEndPoint, ObjectPool<MessageReader> readerPool, IPMode ipMode = IPMode.IPv4) : base(null, readerPool)
{
EndPoint = remoteEndPoint;
_socket = new UdpClient
{
- DontFragment = false
+ DontFragment = false,
};
_reliablePacketTimer = new Timer(ManageReliablePacketsInternal, null, 100, Timeout.Infinite);
{
State = ConnectionState.NotConnected;
- try { _socket.Close(); } catch { }
- try { _socket.Dispose(); } catch { }
+ try { _socket.Close(); }
+ catch { }
+
+ try { _socket.Dispose(); }
+ catch { }
_reliablePacketTimer.Dispose();
_connectWaitLock.Dispose();
{
partial class UdpConnection
{
-
/// <summary>
/// Class to hold packet data
/// </summary>
ResetKeepAliveTimer();
}
}
+
private int keepAliveInterval = 1500;
public int MissingPingsUntilDisconnect { get; set; } = 6;
// pings should cause a disconnect.
private async ValueTask SendPing()
{
- ushort id = (ushort)Interlocked.Increment(ref lastIDAllocated);
+ var id = (ushort)Interlocked.Increment(ref lastIDAllocated);
- byte[] bytes = new byte[3];
+ var bytes = new byte[3];
bytes[0] = (byte)UdpSendOption.Ping;
bytes[1] = (byte)(id >> 8);
bytes[2] = (byte)id;
}
}
}
-}
\ No newline at end of file
+}
/// </summary>
/// <remarks>
/// <para>
- /// For reliable delivery data is resent at specified intervals unless an acknowledgement is received from the
+ /// For reliable delivery data is resent at specified intervals unless an acknowledgement is received from the
/// receiving device. The ResendTimeout specifies the interval between the packets being resent, each time a packet
- /// is resent the interval is increased for that packet until the duration exceeds the <see cref="DisconnectTimeout"/> value.
+ /// is resent the interval is increased for that packet until the duration exceeds the <see cref="DisconnectTimeout" /> value.
/// </para>
/// <para>
- /// Setting this to its default of 0 will mean the timeout is 2 times the value of the average ping, usually
+ /// Setting this to its default of 0 will mean the timeout is 2 times the value of the average ping, usually
/// resulting in a more dynamic resend that responds to endpoints on slower or faster connections.
/// </para>
/// </remarks>
public volatile int ResendTimeout = 0;
/// <summary>
- /// Max number of times to resend. 0 == no limit
+ /// Max number of times to resend. 0 == no limit
/// </summary>
public volatile int ResendLimit = 0;
/// <summary>
- /// A compounding multiplier to back off resend timeout.
- /// Applied to ping before first timeout when ResendTimeout == 0.
+ /// A compounding multiplier to back off resend timeout.
+ /// Applied to ping before first timeout when ResendTimeout == 0.
/// </summary>
public volatile float ResendPingMultiplier = 2;
internal ConcurrentDictionary<ushort, Packet> reliableDataPacketsSent = new ConcurrentDictionary<ushort, Packet>();
/// <summary>
- /// Packet ids that have not been received, but are expected.
+ /// Packet ids that have not been received, but are expected.
/// </summary>
private HashSet<ushort> reliableDataPacketsMissing = new HashSet<ushort>();
/// Returns the average ping to this endpoint.
/// </summary>
/// <remarks>
- /// This returns the average ping for a one-way trip as calculated from the reliable packets that have been sent
+ /// This returns the average ping for a one-way trip as calculated from the reliable packets that have been sent
/// and acknowledged by the endpoint.
/// </remarks>
public float AveragePingMs = 500;
/// The maximum times a message should be resent before marking the endpoint as disconnected.
/// </summary>
/// <remarks>
- /// Reliable packets will be resent at an interval defined in <see cref="ResendTimeout"/> for the number of times
+ /// Reliable packets will be resent at an interval defined in <see cref="ResendTimeout" /> for the number of times
/// specified here. Once a packet has been retransmitted this number of times and has not been acknowledged the
/// connection will be marked as disconnected and the <see cref="Connection.Disconnected">Disconnected</see> event
/// will be invoked.
var connection = this.Connection;
if (!this.Acknowledged && connection != null)
{
- long lifetime = this.Stopwatch.ElapsedMilliseconds;
+ var lifetime = this.Stopwatch.ElapsedMilliseconds;
if (lifetime >= connection.DisconnectTimeout)
{
- if (connection.reliableDataPacketsSent.TryRemove(this.Id, out Packet self))
+ if (connection.reliableDataPacketsSent.TryRemove(this.Id, out var self))
{
await connection.DisconnectInternal(HazelInternalErrors.ReliablePacketWithoutResponse, $"Reliable packet {self.Id} (size={this.Length}) was not ack'd after {lifetime}ms ({self.Retransmissions} resends)");
if (connection.ResendLimit != 0
&& this.Retransmissions > connection.ResendLimit)
{
- if (connection.reliableDataPacketsSent.TryRemove(this.Id, out Packet self))
+ if (connection.reliableDataPacketsSent.TryRemove(this.Id, out var self))
{
await connection.DisconnectInternal(HazelInternalErrors.ReliablePacketWithoutResponse, $"Reliable packet {self.Id} (size={this.Length}) was not ack'd after {self.Retransmissions} resends ({lifetime}ms)");
internal async ValueTask<int> ManageReliablePackets()
{
- int output = 0;
+ var output = 0;
if (this.reliableDataPacketsSent.Count > 0)
{
foreach (var kvp in this.reliableDataPacketsSent)
{
- Packet pkt = kvp.Value;
+ var pkt = kvp.Value;
try
{
/// <param name="ackCallback">The callback to make once the packet has been acknowledged.</param>
protected void AttachReliableID(byte[] buffer, int offset, int sendLength, Action ackCallback = null)
{
- ushort id = (ushort)Interlocked.Increment(ref lastIDAllocated);
+ var id = (ushort)Interlocked.Increment(ref lastIDAllocated);
buffer[offset] = (byte)(id >> 8);
buffer[offset + 1] = (byte)id;
- Packet packet = Packet.GetObject();
+ var packet = Packet.GetObject();
packet.Set(
id,
this,
//Inform keepalive not to send for a while
ResetKeepAliveTimer();
- byte[] bytes = new byte[data.Length + 3];
+ var bytes = new byte[data.Length + 3];
//Add message type
bytes[0] = sendOption;
*
* So...
*/
-
+
var result = true;
lock (reliableDataPacketsMissing)
{
//Calculate overwritePointer
- ushort overwritePointer = (ushort)(reliableReceiveLast - 32768);
+ var overwritePointer = (ushort)(reliableReceiveLast - 32768);
//Calculate if it is a new packet by examining if it is within the range
bool isNew;
if (overwritePointer < reliableReceiveLast)
- isNew = id > reliableReceiveLast || id <= overwritePointer; //Figure (2)
+ isNew = id > reliableReceiveLast || id <= overwritePointer; //Figure (2)
else
- isNew = id > reliableReceiveLast && id <= overwritePointer; //Figure (3)
-
+ isNew = id > reliableReceiveLast && id <= overwritePointer; //Figure (3)
+
//If it's new or we've not received anything yet
if (isNew)
{
// Mark items between the most recent receive and the id received as missing
if (id > reliableReceiveLast)
{
- for (ushort i = (ushort)(reliableReceiveLast + 1); i < id; i++)
+ for (var i = (ushort)(reliableReceiveLast + 1); i < id; i++)
{
reliableDataPacketsMissing.Add(i);
}
}
else
{
- int cnt = (ushort.MaxValue - reliableReceiveLast) + id;
+ var cnt = (ushort.MaxValue - reliableReceiveLast) + id;
for (ushort i = 1; i < cnt; ++i)
{
reliableDataPacketsMissing.Add((ushort)(i + reliableReceiveLast));
//Update the most recently received
reliableReceiveLast = id;
}
-
+
//Else it could be a missing packet
else
{
}
}
}
-
+
//Send an acknowledgement
await SendAck(id);
{
this.pingsSinceAck = 0;
- ushort id = (ushort)((bytes[1] << 8) + bytes[2]);
+ var id = (ushort)((bytes[1] << 8) + bytes[2]);
AcknowledgeMessageId(id);
if (bytes.Length == 4)
{
- byte recentPackets = bytes[3];
- for (int i = 1; i <= 8; ++i)
+ var recentPackets = bytes[3];
+ for (var i = 1; i <= 8; ++i)
{
if ((recentPackets & 1) != 0)
{
private void AcknowledgeMessageId(ushort id)
{
// Dispose of timer and remove from dictionary
- if (reliableDataPacketsSent.TryRemove(id, out Packet packet))
+ if (reliableDataPacketsSent.TryRemove(id, out var packet))
{
float rt = packet.Stopwatch.ElapsedMilliseconds;
this.AveragePingMs = Math.Max(50, this.AveragePingMs * .7f + rt * .3f);
}
}
- else if (this.activePingPackets.TryRemove(id, out PingPacket pingPkt))
+ else if (this.activePingPackets.TryRemove(id, out var pingPkt))
{
float rt = pingPkt.Stopwatch.ElapsedMilliseconds;
byte recentPackets = 0;
lock (this.reliableDataPacketsMissing)
{
- for (int i = 1; i <= 8; ++i)
+ for (var i = 1; i <= 8; ++i)
{
if (!this.reliableDataPacketsMissing.Contains((ushort)(id - i)))
{
}
}
- byte[] bytes = new byte[]
+ var bytes = new byte[]
{
(byte)UdpSendOption.Acknowledgement,
(byte)(id >> 8),
(byte)(id >> 0),
- recentPackets
+ recentPackets,
};
try
Pipeline = Channel.CreateUnbounded<byte[]>(new UnboundedChannelOptions
{
SingleReader = true,
- SingleWriter = true
+ SingleWriter = true,
});
}
/// <param name="length"></param>
protected abstract ValueTask WriteBytesToConnection(byte[] bytes, int length);
- /// <inheritdoc/>
+ /// <inheritdoc />
public override async ValueTask SendAsync(IMessageWriter msg)
{
if (this._state != ConnectionState.Connected)
throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?");
- byte[] buffer = new byte[msg.Length];
+ var buffer = new byte[msg.Length];
Buffer.BlockCopy(msg.Buffer, 0, buffer, 0, msg.Length);
switch (msg.SendOption)
}
}
- /// <inheritdoc/>
+ /// <inheritdoc />
/// <remarks>
/// <include file="DocInclude/common.xml" path="docs/item[@name='Connection_SendBytes_General']/*" />
/// <para>
- /// Udp connections can currently send messages using <see cref="SendOption.None"/> and
- /// <see cref="SendOption.Reliable"/>. Fragmented messages are not currently supported and will default to
- /// <see cref="SendOption.None"/> until implemented.
+ /// Udp connections can currently send messages using <see cref="SendOption.None" /> and
+ /// <see cref="SendOption.Reliable" />. Fragmented messages are not currently supported and will default to
+ /// <see cref="SendOption.None" /> until implemented.
/// </para>
/// </remarks>
public override async ValueTask SendBytes(byte[] bytes, MessageType sendOption = MessageType.Unreliable)
//Add header information and send
await HandleSend(bytes, (byte)sendOption);
}
-
+
/// <summary>
/// Handles the reliable/fragmented sending from this connection.
/// </summary>
/// <param name="data">The data being sent.</param>
- /// <param name="sendOption">The <see cref="SendOption"/> specified as its byte value.</param>
+ /// <param name="sendOption">The <see cref="SendOption" /> specified as its byte value.</param>
/// <param name="ackCallback">The callback to invoke when this packet is acknowledged.</param>
/// <returns>The bytes that should actually be sent.</returns>
protected async ValueTask HandleSend(byte[] data, byte sendOption, Action ackCallback = null)
case (byte)UdpSendOption.Hello:
await ReliableSend(sendOption, data, ackCallback);
break;
-
+
//Treat all else as unreliable
default:
await UnreliableSend(sendOption, data);
{
await DisconnectRemote("The remote sent a disconnect request", reader);
}
+
break;
-
+
//Treat everything else as unreliable
default:
using (var reader = message.Copy(1))
{
await InvokeDataReceived(reader, MessageType.Unreliable);
}
+
Statistics.LogUnreliableReceive(message.Length - 1, message.Length);
break;
}
/// <param name="length"></param>
async ValueTask UnreliableSend(byte sendOption, byte[] data, int offset, int length)
{
- byte[] bytes = new byte[length + 1];
+ var bytes = new byte[length + 1];
//Add message type
bytes[0] = sendOption;
return HandleSend(actualBytes, (byte)UdpSendOption.Hello, acknowledgeCallback);
}
-
- /// <inheritdoc/>
+
+ /// <inheritdoc />
protected override void Dispose(bool disposing)
{
if (disposing)
using System.Net;
using System.Net.Sockets;
using System.Threading;
-using System.Threading.Channels;
using System.Threading.Tasks;
using Microsoft.Extensions.ObjectPool;
using Serilog;
private static readonly ILogger Logger = Log.ForContext<UdpConnectionListener>();
/// <summary>
- /// A callback for early connection rejection.
- /// * Return false to reject connection.
- /// * A null response is ok, we just won't send anything.
+ /// A callback for early connection rejection.
+ /// * Return false to reject connection.
+ /// * A null response is ok, we just won't send anything.
/// </summary>
public AcceptConnectionCheck AcceptConnection;
+
public delegate bool AcceptConnectionCheck(IPEndPoint endPoint, byte[] input, out byte[] response);
private readonly UdpClient _socket;
private Task _executingTask;
/// <summary>
- /// Creates a new UdpConnectionListener for the given <see cref="IPAddress"/>, port and <see cref="IPMode"/>.
+ /// Creates a new UdpConnectionListener for the given <see cref="IPAddress" />, port and <see cref="IPMode" />.
/// </summary>
/// <param name="endPoint">The endpoint to listen on.</param>
/// <param name="ipMode"></param>
}
public int ConnectionCount => this._allConnections.Count;
-
+
private async void ManageReliablePackets(object state)
{
foreach (var kvp in _allConnections)
_timer.Dispose();
}
}
-}
\ No newline at end of file
+}
/// <summary>
/// Represents a servers's connection to a client that uses the UDP protocol.
/// </summary>
- /// <inheritdoc/>
+ /// <inheritdoc />
internal sealed class UdpServerConnection : UdpConnection
{
/// <summary>
/// The connection listener that we use the socket of.
/// </summary>
/// <remarks>
- /// Udp server connections utilize the same socket in the listener for sends/receives, this is the listener that
+ /// Udp server connections utilize the same socket in the listener for sends/receives, this is the listener that
/// created this connection and is hence the listener this conenction sends and receives via.
/// </remarks>
public UdpConnectionListener Listener { get; private set; }
if (this._state != ConnectionState.Connected) return false;
this._state = ConnectionState.NotConnected;
}
-
+
var bytes = EmptyDisconnectBytes;
if (data != null && data.Length > 0)
{
"--name",
() => AmongUsModifier.DefaultRegionName,
"Name for server region"
- )
+ ),
};
rootCommand.Handler = CommandHandler.Create<string, string>((address, name) =>
var libraries = new List<string>
{
- steamApps
+ steamApps,
};
var vdf = Path.Combine(steamApps, "libraryfolders.vdf");
var ip = ipAddress.ToString();
var region = new RegionInfo(RegionName, ip, new[]
{
- new ServerInfo($"{RegionName}-Master-1", ip, port)
+ new ServerInfo($"{RegionName}-Master-1", ip, port),
});
region.Serialize(writer);
public event EventHandler<ErrorEventArgs> Error;
public event EventHandler<SavedEventArgs> Saved;
}
-}
\ No newline at end of file
+}
}
}
}
-}
\ No newline at end of file
+}
public string Message { get; }
}
-}
\ No newline at end of file
+}
public string IpAddress { get; }
public ushort Port { get; }
}
-}
\ No newline at end of file
+}
return new RegionInfo(name, ping, servers);
}
}
-}
\ No newline at end of file
+}
Ip = ip;
Port = port;
}
-
+
public void Serialize(BinaryWriter writer)
{
writer.Write(Name);
var ip = new IPAddress(reader.ReadBytes(4)).ToString();
var port = reader.ReadUInt16();
var unknown = reader.ReadInt32();
-
+
return new ServerInfo(name, ip, port);
}
}
-}
\ No newline at end of file
+}
this.lblUrl.Name = "lblUrl";
this.lblUrl.Size = new System.Drawing.Size(212, 13);
this.lblUrl.TabIndex = 5;
- this.lblUrl.Text = "https://github.com/AeonLucid/Impostor";
+ this.lblUrl.Text = "https://github.com/Impostor/Impostor";
this.lblUrl.Click += new System.EventHandler(this.lblUrl_Click);
//
// label3
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox comboIp;
}
-}
\ No newline at end of file
+}
private void lblUrl_Click(object sender, EventArgs e)
{
- Process.Start("https://github.com/AeonLucid/Impostor");
+ Process.Start("https://github.com/Impostor/Impostor");
}
private void RefreshComboIps()
}
}
}
-}
\ No newline at end of file
+}
Application.Run(new FrmMain());
}
}
-}
\ No newline at end of file
+}
public class DebugPlugin : PluginBase
{
}
-}
\ No newline at end of file
+}
});
}
}
-}
\ No newline at end of file
+}
var game = await _gameManager.CreateAsync(new GameOptionsData());
game.DisplayName = "Example game";
await game.SetPrivacyAsync(true);
-
+
_logger.LogInformation("Created game {0}.", game.Code.Code);
}
[EventListener]
public void OnPlayerStartMeetingEvent(IPlayerStartMeetingEvent e)
{
- _logger.LogDebug($"Player {e.PlayerControl.PlayerInfo.PlayerName} start meeting, reason: " + (e.Body==null ? "Emergency call button" : "Found the body of the player "+e.Body.PlayerInfo.PlayerName));
+ _logger.LogDebug($"Player {e.PlayerControl.PlayerInfo.PlayerName} start meeting, reason: " + (e.Body == null ? "Emergency call button" : "Found the body of the player " + e.Body.PlayerInfo.PlayerName));
}
}
}
public const string UsernameIllegalCharacters = "Your username contains illegal characters, please remove them.";
}
-}
\ No newline at end of file
+}
public const int SpawnTimeout = 2500;
public const int ConnectionTimeout = 2500;
}
-}
\ No newline at end of file
+}
namespace Impostor.Server.Events
{
/// <summary>
- /// Disposes multiple <see cref="IDisposable"/>.
+ /// Disposes multiple <see cref="IDisposable" />.
/// </summary>
internal class MultiDisposable : IDisposable
{
throw new InvalidOperationException($"The method {method.GetFriendlyName()} must return void or ValueTask.");
}
- return Expression.Lambda<Func<object?, object, IServiceProvider, ValueTask>>(invoke, instance, eventParameter, provider)
+ return Expression.Lambda<Func<object?, object, IServiceProvider, ValueTask>>(invoke, instance, eventParameter, provider)
.Compile();
}
}
}
}
}
-}
\ No newline at end of file
+}
return await nodeLocator.FindAsync(gameCode) != null;
}
}
-}
\ No newline at end of file
+}
return str;
}
}
-}
\ No newline at end of file
+}
{
ClientBase Create(IHazelConnection connection, string name, int clientVersion, ISet<Mod> mods);
}
-}
\ No newline at end of file
+}
return GameCode.Create();
}
}
-}
\ No newline at end of file
+}
return result;
}
}
-}
\ No newline at end of file
+}
-using System.Collections.Generic;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Impostor.Api.Net;
using Impostor.Api.Net.Inner;
using Impostor.Api.Net.Messages;
-using System.Collections.Generic;
-using System.Numerics;
+using System.Numerics;
using System.Threading.Tasks;
using Impostor.Api;
using Impostor.Api.Events.Managers;
using System;
-using System.Collections.Generic;
using System.Threading.Tasks;
using Impostor.Api.Events.Managers;
using Impostor.Api.Innersloth;
-using System.Threading.Tasks;
+using System;
+using System.Threading.Tasks;
using Impostor.Api.Games;
using Impostor.Api.Net;
using Impostor.Api.Net.Inner.Objects;
public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public override ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public override ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
}
}
using System;
-using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
{
bool IsActive { get; }
}
-}
\ No newline at end of file
+}
void Deserialize(IMessageReader reader, bool initialState);
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Net.Messages;
+using System;
+using Impostor.Api.Net.Messages;
namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
{
public void Serialize(IMessageWriter writer, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void Deserialize(IMessageReader reader, bool initialState)
IsActive = reader.ReadBoolean();
}
}
-}
\ No newline at end of file
+}
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Impostor.Api.Net.Messages;
namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
public void Serialize(IMessageWriter writer, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void Deserialize(IMessageReader reader, bool initialState)
}
}
}
-}
\ No newline at end of file
+}
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Impostor.Api.Net.Messages;
namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
public void Serialize(IMessageWriter writer, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void Deserialize(IMessageReader reader, bool initialState)
}
}
}
-}
\ No newline at end of file
+}
public void Serialize(IMessageWriter writer, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void Deserialize(IMessageReader reader, bool initialState)
}
}
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Net.Messages;
+using System;
+using Impostor.Api.Net.Messages;
namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
{
public void Serialize(IMessageWriter writer, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void Deserialize(IMessageReader reader, bool initialState)
Timer = reader.ReadSingle();
}
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Net.Messages;
+using System;
+using Impostor.Api.Net.Messages;
namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
{
public void Serialize(IMessageWriter writer, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void Deserialize(IMessageReader reader, bool initialState)
InUse = reader.ReadByte();
}
}
-}
\ No newline at end of file
+}
-using Impostor.Api.Net.Messages;
+using System;
+using Impostor.Api.Net.Messages;
namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
{
public void Serialize(IMessageWriter writer, bool initialState)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void Deserialize(IMessageReader reader, bool initialState)
Value = reader.ReadByte();
}
}
-}
\ No newline at end of file
+}
None = 0,
IsClientCharacter = 1,
}
-}
\ No newline at end of file
+}
{
IEnumerable<IClient> IClientManager.Clients => _clients.Values;
}
-}
\ No newline at end of file
+}
// TODO: Prevent duplicates when using server redirector using INodeProvider.
var (success, game) = await TryCreateAsync(options);
- for (int i = 0; i < 10 && !success; i++)
+ for (var i = 0; i < 10 && !success; i++)
{
(success, game) = await TryCreateAsync(options);
}
using Impostor.Server.Net.Hazel;
using Impostor.Server.Net.Manager;
using Serilog;
-using ILogger = Serilog.ILogger;
namespace Impostor.Server.Net.Redirector
{
{
IPEndPoint Get();
}
-}
\ No newline at end of file
+}
}
}
}
-}
\ No newline at end of file
+}
using System;
using System.Collections.Generic;
-using System.Threading;
using System.Threading.Tasks;
using Impostor.Api;
-using Impostor.Api.Innersloth;
using Impostor.Api.Net.Inner;
using Impostor.Api.Net.Messages;
-using Impostor.Api.Net.Messages.S2C;
using Impostor.Api.Unity;
-using Impostor.Hazel;
using Impostor.Server.Events.Meeting;
using Impostor.Server.Events.Player;
using Impostor.Server.Net.Inner;
writer.StartMessage(GameDataTag.RpcFlag);
writer.WritePacked(targetNetId);
- writer.Write((byte) callId);
+ writer.Write((byte)callId);
return writer;
}
Assembly Load(AssemblyLoadContext context);
}
-}
\ No newline at end of file
+}
return _assembly;
}
}
-}
\ No newline at end of file
+}
public List<string> LibraryPaths { get; set; } = new List<string>();
}
-}
\ No newline at end of file
+}
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Impostor.Api.Plugins;
using System.Runtime.CompilerServices;
-[assembly:InternalsVisibleTo("Impostor.Benchmarks")]
-[assembly:InternalsVisibleTo("Impostor.Tests")]
-[assembly:InternalsVisibleTo("Impostor.Tools.ServerReplay")]
+[assembly: InternalsVisibleTo("Impostor.Benchmarks")]
+[assembly: InternalsVisibleTo("Impostor.Tests")]
+[assembly: InternalsVisibleTo("Impostor.Tools.ServerReplay")]
namespace Impostor.Server.Recorder
{
/// <summary>
- /// Records all packets received in <see cref="ClientRecorder.HandleMessageAsync"/>.
+ /// Records all packets received in <see cref="ClientRecorder.HandleMessageAsync" />.
/// </summary>
internal class PacketRecorder : BackgroundService
{
return true;
}
}
-}
\ No newline at end of file
+}
namespace Impostor.Server.Recorder
{
/// <summary>
- /// Version of the server replay data format.
+ /// Version of the server replay data format.
/// </summary>
public enum ServerReplayVersion
{
/// <summary>
- /// Initial version
+ /// Initial version
/// </summary>
Initial = 1,
/// <summary>
- /// Latest version
+ /// Latest version
/// </summary>
Latest = Initial,
}
using System.Collections.Generic;
-using System.Net.Sockets;
using System.Threading.Tasks;
using Impostor.Api.Events;
using Impostor.Api.Events.Managers;
{
public class EventManagerTests
{
- public static readonly IEnumerable<object[]> TestModes = new []
+ public static readonly IEnumerable<object[]> TestModes = new[]
{
new object[] { TestMode.Service },
- new object[] { TestMode.Temporary }
+ new object[] { TestMode.Temporary },
};
[Theory]
await eventManager.CallAsync(new SetValueEvent(1));
- Assert.Equal(new []
+ Assert.Equal(new[]
{
EventPriority.Monitor,
EventPriority.Highest,
EventPriority.High,
EventPriority.Normal,
EventPriority.Low,
- EventPriority.Lowest
+ EventPriority.Lowest,
}, listener.Priorities);
}
await eventManager.CallAsync(new SetValueEvent(1));
- Assert.Equal(new []
+ Assert.Equal(new[]
{
EventPriority.Monitor,
- EventPriority.Highest
+ EventPriority.Highest,
}, listener.Priorities);
}
public enum TestMode
{
Service,
- Temporary
+ Temporary,
}
public interface ISetValueEvent : IEventCancelable
using Impostor.Api.Innersloth;
-
using Xunit;
namespace Impostor.Tests
Assert.Equal(codeInt, GameCodeParser.GameNameToInt(code));
}
}
-}
\ No newline at end of file
+}
public void ReadProperString()
{
const string Test1 = "Hello";
- string Test2 = new string(' ', 1024);
+ var Test2 = new string(' ', 1024);
var msg = new MessageWriter(2048);
msg.StartMessage(1);
msg.Write(Test1);
var msg = new MessageWriter(2048);
msg.StartMessage(1);
- msg.StartMessage(2);
- msg.Write(Test1);
- msg.Write(Test2);
- msg.StartMessage(2);
- msg.Write(Test1);
- msg.Write(Test2);
- msg.StartMessage(2);
- msg.Write(Test1);
- msg.Write(Test2);
- msg.EndMessage();
- msg.EndMessage();
- msg.EndMessage();
+ msg.StartMessage(2);
+ msg.Write(Test1);
+ msg.Write(Test2);
+ msg.StartMessage(2);
+ msg.Write(Test1);
+ msg.Write(Test2);
+ msg.StartMessage(2);
+ msg.Write(Test1);
+ msg.Write(Test2);
+ msg.EndMessage();
+ msg.EndMessage();
+ msg.EndMessage();
msg.EndMessage();
// Read message.
0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x20, 0x70, 0x61,
0x63, 0x6B, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x20,
0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x6F, 0x70,
- 0x79, 0x69, 0x6E, 0x67, 0x2E
+ 0x79, 0x69, 0x6E, 0x67, 0x2E,
};
var readerPool = CreateReaderPool();
var messageWriter = new MessageWriter(1024);
messageWriter.StartMessage(0);
- messageWriter.StartMessage(1);
- messageWriter.Write("HiTest1");
- messageWriter.StartMessage(2);
- messageWriter.Write("RemoveMe!");
- messageWriter.EndMessage();
- messageWriter.EndMessage();
- messageWriter.StartMessage(2);
- messageWriter.Write("HiTest2");
- messageWriter.EndMessage();
+ messageWriter.StartMessage(1);
+ messageWriter.Write("HiTest1");
+ messageWriter.StartMessage(2);
+ messageWriter.Write("RemoveMe!");
+ messageWriter.EndMessage();
+ messageWriter.EndMessage();
+ messageWriter.StartMessage(2);
+ messageWriter.Write("HiTest2");
+ messageWriter.EndMessage();
messageWriter.EndMessage();
// Copy buffer.
}
}
}
-}
\ No newline at end of file
+}
public static string HexDump(byte[] bytes, int bytesPerLine = 16)
{
if (bytes == null) return "<null>";
- int bytesLength = bytes.Length;
+ var bytesLength = bytes.Length;
- char[] HexChars = "0123456789ABCDEF".ToCharArray();
+ var HexChars = "0123456789ABCDEF".ToCharArray();
- int firstHexColumn =
- 8 // 8 characters for the address
- + 3; // 3 spaces
+ var firstHexColumn =
+ 8 // 8 characters for the address
+ + 3; // 3 spaces
- int firstCharColumn = firstHexColumn
- + bytesPerLine * 3 // - 2 digit for the hexadecimal value and 1 space
- + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th
- + 2; // 2 spaces
+ var firstCharColumn = firstHexColumn
+ + bytesPerLine * 3 // - 2 digit for the hexadecimal value and 1 space
+ + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th
+ + 2; // 2 spaces
- int lineLength = firstCharColumn
- + bytesPerLine // - characters to show the ascii value
- + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2)
+ var lineLength = firstCharColumn
+ + bytesPerLine // - characters to show the ascii value
+ + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2)
- char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray();
- int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
- StringBuilder result = new StringBuilder(expectedLines * lineLength);
+ var line = (new string(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray();
+ var expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
+ var result = new StringBuilder(expectedLines * lineLength);
- for (int i = 0; i < bytesLength; i += bytesPerLine)
+ for (var i = 0; i < bytesLength; i += bytesPerLine)
{
line[0] = HexChars[(i >> 28) & 0xF];
line[1] = HexChars[(i >> 24) & 0xF];
line[6] = HexChars[(i >> 4) & 0xF];
line[7] = HexChars[(i >> 0) & 0xF];
- int hexColumn = firstHexColumn;
- int charColumn = firstCharColumn;
+ var hexColumn = firstHexColumn;
+ var charColumn = firstCharColumn;
- for (int j = 0; j < bytesPerLine; j++)
+ for (var j = 0; j < bytesPerLine; j++)
{
if (j > 0 && (j & 7) == 0) hexColumn++;
if (i + j >= bytesLength)
}
else
{
- byte b = bytes[i + j];
+ var b = bytes[i + j];
line[hexColumn] = HexChars[(b >> 4) & 0xF];
line[hexColumn + 1] = HexChars[b & 0xF];
line[charColumn] = (b < 32 ? '·' : (char)b);
}
+
hexColumn += 3;
charColumn++;
}
+
result.Append(line);
}
+
return result.ToString();
}
}
-}
\ No newline at end of file
+}
private static readonly Dictionary<byte, string> TagMap = new Dictionary<byte, string>
{
- {0, "HostGame"},
- {1, "JoinGame"},
- {2, "StartGame"},
- {3, "RemoveGame"},
- {4, "RemovePlayer"},
- {5, "GameData"},
- {6, "GameDataTo"},
- {7, "JoinedGame"},
- {8, "EndGame"},
- {9, "GetGameList"},
- {10, "AlterGame"},
- {11, "KickPlayer"},
- {12, "WaitForHost"},
- {13, "Redirect"},
- {14, "ReselectServer"},
- {16, "GetGameListV2"}
+ { 0, "HostGame" },
+ { 1, "JoinGame" },
+ { 2, "StartGame" },
+ { 3, "RemoveGame" },
+ { 4, "RemovePlayer" },
+ { 5, "GameData" },
+ { 6, "GameDataTo" },
+ { 7, "JoinedGame" },
+ { 8, "EndGame" },
+ { 9, "GetGameList" },
+ { 10, "AlterGame" },
+ { 11, "KickPlayer" },
+ { 12, "WaitForHost" },
+ { 13, "Redirect" },
+ { 14, "ReselectServer" },
+ { 16, "GetGameListV2" },
};
private static IServiceProvider _serviceProvider;
_serviceProvider = services.BuildServiceProvider();
_readerPool = _serviceProvider.GetRequiredService<ObjectPool<MessageReader>>();
-
+
var devices = LivePacketDevice.AllLocalMachine;
if (devices.Count == 0)
{
var ip = packet.Ethernet.IpV4;
var ipSrc = ip.Source.ToString();
var udp = ip.Udp;
-
+
// True if this is our own packet.
using (var stream = udp.Payload.ToMemoryStream())
{
reader.Update(stream.ToArray());
var option = reader.Buffer[0];
- if (option == (byte) MessageType.Reliable)
+ if (option == (byte)MessageType.Reliable)
{
reader.Seek(reader.Position + 3);
}
- else if (option == (byte) UdpSendOption.Acknowledgement ||
- option == (byte) UdpSendOption.Ping ||
- option == (byte) UdpSendOption.Hello ||
- option == (byte) UdpSendOption.Disconnect)
+ else if (option == (byte)UdpSendOption.Acknowledgement ||
+ option == (byte)UdpSendOption.Ping ||
+ option == (byte)UdpSendOption.Hello ||
+ option == (byte)UdpSendOption.Disconnect)
{
return;
}
{
reader.Seek(reader.Position + 1);
}
-
+
var isSent = ipSrc.StartsWith("192.");
-
+
while (true)
{
if (reader.Position >= reader.Length)
{
HandleToClient(ipSrc, message);
}
-
+
if (message.Position < message.Length)
{
Console.ForegroundColor = ConsoleColor.Red;
{
Console.WriteLine("- PlayerId " + packet.ReadPackedInt32());
}
+
break;
case 10:
Console.WriteLine("- GameCode " + packet.ReadInt32());
return Result;
}
}
-}
\ No newline at end of file
+}
services.AddSingleton(new ServerEnvironment
{
- IsReplay = true
+ IsReplay = true,
});
services.AddSingleton<FakeDateTimeProvider>();