From e769b874c8fb300828a03941cf41efbfd1776280 Mon Sep 17 00:00:00 2001 From: js6pak Date: Thu, 4 Mar 2021 09:11:50 +0000 Subject: [PATCH] Add create game api (#241) --- .../Games/Extensions/GameManagerExtensions.cs | 2 +- src/Impostor.Api/Games/IGame.cs | 14 +++- .../Games/Managers/IGameManager.cs | 4 ++ .../Innersloth/GameOptionsData.cs | 65 +++++++------------ src/Impostor.Api/Innersloth/MapTypes.cs | 2 +- .../Messages/S2C/Message16GetGameListS2C.cs | 6 +- src/Impostor.Plugins.Example/ExamplePlugin.cs | 15 ++++- src/Impostor.Server/Net/Client.cs | 2 +- .../Net/Manager/GameManager.cs | 2 +- src/Impostor.Server/Net/State/Game.Api.cs | 16 ++++- src/Impostor.Server/Net/State/Game.cs | 2 + 11 files changed, 78 insertions(+), 52 deletions(-) diff --git a/src/Impostor.Api/Games/Extensions/GameManagerExtensions.cs b/src/Impostor.Api/Games/Extensions/GameManagerExtensions.cs index 9a5a2b4..6a95b3d 100644 --- a/src/Impostor.Api/Games/Extensions/GameManagerExtensions.cs +++ b/src/Impostor.Api/Games/Extensions/GameManagerExtensions.cs @@ -8,7 +8,7 @@ namespace Impostor.Api.Games { public static int GetGameCount(this IGameManager manager, MapFlags map) { - return manager.Games.Count(game => map.HasFlag((MapFlags)(1 << game.Options.MapId))); + return manager.Games.Count(game => map.HasFlag((MapFlags)(1 << (byte)game.Options.Map))); } } } \ No newline at end of file diff --git a/src/Impostor.Api/Games/IGame.cs b/src/Impostor.Api/Games/IGame.cs index 7c6140c..57c3fcd 100644 --- a/src/Impostor.Api/Games/IGame.cs +++ b/src/Impostor.Api/Games/IGame.cs @@ -24,10 +24,15 @@ namespace Impostor.Api.Games int PlayerCount { get; } - IClientPlayer Host { get; } + IClientPlayer? Host { get; } bool IsPublic { get; } + /// + /// Gets or sets display name on game list. + /// + string? DisplayName { get; set; } + IDictionary Items { get; } int HostId { get; } @@ -55,6 +60,13 @@ namespace Impostor.Api.Games /// A representing the asynchronous operation. ValueTask SyncSettingsAsync(); + /// + /// Sets game's privacy. + /// + /// Privacy to set. + /// A representing the asynchronous operation. + ValueTask SetPrivacyAsync(bool isPublic); + /// /// Send the message to all players. /// diff --git a/src/Impostor.Api/Games/Managers/IGameManager.cs b/src/Impostor.Api/Games/Managers/IGameManager.cs index 10a05f0..7ee403f 100644 --- a/src/Impostor.Api/Games/Managers/IGameManager.cs +++ b/src/Impostor.Api/Games/Managers/IGameManager.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.Threading.Tasks; +using Impostor.Api.Innersloth; namespace Impostor.Api.Games.Managers { @@ -7,5 +9,7 @@ namespace Impostor.Api.Games.Managers IEnumerable Games { get; } IGame? Find(GameCode code); + + ValueTask CreateAsync(GameOptionsData options); } } \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/GameOptionsData.cs b/src/Impostor.Api/Innersloth/GameOptionsData.cs index 7f7e0c5..3d64844 100644 --- a/src/Impostor.Api/Innersloth/GameOptionsData.cs +++ b/src/Impostor.Api/Innersloth/GameOptionsData.cs @@ -14,112 +14,97 @@ namespace Impostor.Api.Innersloth /// /// Gets or sets host's version of the game. /// - public byte Version { get; set; } + public byte Version { get; set; } = LatestVersion; /// /// Gets or sets the maximum amount of players for this lobby. /// - public byte MaxPlayers { get; set; } + public byte MaxPlayers { get; set; } = 10; /// /// Gets or sets the language of the lobby as per enum. /// - public GameKeywords Keywords { get; set; } + public GameKeywords Keywords { get; set; } = GameKeywords.English; /// - /// Gets or sets the MapId selected for this lobby + /// Gets or sets the Map selected for this lobby. /// - /// - /// Skeld = 0, MiraHQ = 1, Polus = 2. - /// - internal byte MapId { get; set; } - - /// - /// Gets or sets the map selected for this lobby - /// - public MapTypes Map - { - get => (MapTypes)MapId; - set => MapId = (byte)value; - } + public MapTypes Map { get; set; } = MapTypes.Skeld; /// /// Gets or sets the Player speed modifier. /// - public float PlayerSpeedMod { get; set; } + public float PlayerSpeedMod { get; set; } = 1f; /// /// Gets or sets the Light modifier for the players that are members of the crew as a multiplier value. /// - public float CrewLightMod { get; set; } + public float CrewLightMod { get; set; } = 1f; /// /// Gets or sets the Light modifier for the players that are Impostors as a multiplier value. /// - public float ImpostorLightMod { get; set; } + public float ImpostorLightMod { get; set; } = 1f; /// /// Gets or sets the Impostor cooldown to kill in seconds. /// - public float KillCooldown { get; set; } + public float KillCooldown { get; set; } = 15f; /// /// Gets or sets the number of common tasks. /// - public int NumCommonTasks { get; set; } + public int NumCommonTasks { get; set; } = 1; /// /// Gets or sets the number of long tasks. /// - public int NumLongTasks { get; set; } + public int NumLongTasks { get; set; } = 1; /// /// Gets or sets the number of short tasks. /// - public int NumShortTasks { get; set; } + public int NumShortTasks { get; set; } = 2; /// /// Gets or sets the maximum amount of emergency meetings each player can call during the game in seconds. /// - public int NumEmergencyMeetings { get; set; } + public int NumEmergencyMeetings { get; set; } = 1; /// /// Gets or sets the cooldown between each time any player can call an emergency meeting in seconds. /// - public int EmergencyCooldown { get; set; } + public int EmergencyCooldown { get; set; } = 15; /// /// Gets or sets the number of impostors for this lobby. /// - public int NumImpostors { get; set; } + public int NumImpostors { get; set; } = 1; /// /// Gets or sets a value indicating whether ghosts (dead crew members) can do tasks. /// - public bool GhostsDoTasks { get; set; } + public bool GhostsDoTasks { get; set; } = true; /// /// Gets or sets the Kill as per values in . /// - /// - /// Short = 0, Normal = 1, Long = 2. - /// - public KillDistances KillDistance { get; set; } + public KillDistances KillDistance { get; set; } = KillDistances.Normal; /// /// Gets or sets the time for discussion before voting time in seconds. /// - public int DiscussionTime { get; set; } + public int DiscussionTime { get; set; } = 15; /// /// Gets or sets the time for voting in seconds. /// - public int VotingTime { get; set; } + public int VotingTime { get; set; } = 120; /// /// Gets or sets a value indicating whether an ejected player is an impostor or not. /// - public bool ConfirmImpostor { get; set; } + public bool ConfirmImpostor { get; set; } = true; /// /// Gets or sets a value indicating whether players are able to see tasks being performed by other players. @@ -127,7 +112,7 @@ namespace Impostor.Api.Innersloth /// /// By being set to true, tasks such as Empty Garbage, Submit Scan, Clear asteroids, Prime shields execution will be visible to other players. /// - public bool VisualTasks { get; set; } + public bool VisualTasks { get; set; } = true; /// /// Gets or sets a value indicating whether the vote is anonymous. @@ -137,12 +122,12 @@ namespace Impostor.Api.Innersloth /// /// Gets or sets the task bar update mode as per values in . /// - public TaskBarUpdate TaskBarUpdate { get; set; } + public TaskBarUpdate TaskBarUpdate { get; set; } = TaskBarUpdate.Always; /// /// Gets or sets a value indicating whether the GameOptions are the default ones. /// - public bool IsDefaults { get; set; } + public bool IsDefaults { get; set; } = true; /// /// Deserialize a packet/message to a new GameOptionsData object. @@ -166,7 +151,7 @@ namespace Impostor.Api.Innersloth writer.Write((byte)version); writer.Write((byte)MaxPlayers); writer.Write((uint)Keywords); - writer.Write((byte)MapId); + writer.Write((byte)Map); writer.Write((float)PlayerSpeedMod); writer.Write((float)CrewLightMod); writer.Write((float)ImpostorLightMod); @@ -223,7 +208,7 @@ namespace Impostor.Api.Innersloth Version = bytes.ReadByte(); MaxPlayers = bytes.ReadByte(); Keywords = (GameKeywords)bytes.ReadUInt32(); - MapId = bytes.ReadByte(); + Map = (MapTypes)bytes.ReadByte(); PlayerSpeedMod = bytes.ReadSingle(); CrewLightMod = bytes.ReadSingle(); diff --git a/src/Impostor.Api/Innersloth/MapTypes.cs b/src/Impostor.Api/Innersloth/MapTypes.cs index 8dc07b5..2b5ede9 100644 --- a/src/Impostor.Api/Innersloth/MapTypes.cs +++ b/src/Impostor.Api/Innersloth/MapTypes.cs @@ -1,6 +1,6 @@ namespace Impostor.Api.Innersloth { - public enum MapTypes + public enum MapTypes : byte { Skeld = 0, MiraHQ = 1, diff --git a/src/Impostor.Api/Net/Messages/S2C/Message16GetGameListS2C.cs b/src/Impostor.Api/Net/Messages/S2C/Message16GetGameListS2C.cs index 93386d7..0d742ed 100644 --- a/src/Impostor.Api/Net/Messages/S2C/Message16GetGameListS2C.cs +++ b/src/Impostor.Api/Net/Messages/S2C/Message16GetGameListS2C.cs @@ -25,10 +25,10 @@ namespace Impostor.Api.Net.Messages.S2C writer.Write(game.PublicIp.Address); writer.Write((ushort)game.PublicIp.Port); writer.Write(game.Code); - writer.Write(game.Host.Client.Name); + writer.Write(game.DisplayName ?? game.Host?.Client.Name ?? string.Empty); writer.Write((byte)game.PlayerCount); writer.WritePacked(1); // TODO: What does Age do? - writer.Write((byte)game.Options.MapId); + writer.Write((byte)game.Options.Map); writer.Write((byte)game.Options.NumImpostors); writer.Write((byte)game.Options.MaxPlayers); writer.EndMessage(); @@ -43,4 +43,4 @@ namespace Impostor.Api.Net.Messages.S2C throw new System.NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/src/Impostor.Plugins.Example/ExamplePlugin.cs b/src/Impostor.Plugins.Example/ExamplePlugin.cs index dafba7c..139e42c 100644 --- a/src/Impostor.Plugins.Example/ExamplePlugin.cs +++ b/src/Impostor.Plugins.Example/ExamplePlugin.cs @@ -1,4 +1,6 @@ using System.Threading.Tasks; +using Impostor.Api.Games.Managers; +using Impostor.Api.Innersloth; using Impostor.Api.Plugins; using Microsoft.Extensions.Logging; @@ -12,16 +14,23 @@ namespace Impostor.Plugins.Example public class ExamplePlugin : PluginBase { private readonly ILogger _logger; + private readonly IGameManager _gameManager; - public ExamplePlugin(ILogger logger) + public ExamplePlugin(ILogger logger, IGameManager gameManager) { _logger = logger; + _gameManager = gameManager; } - public override ValueTask EnableAsync() + public override async ValueTask EnableAsync() { _logger.LogInformation("Example is being enabled."); - return default; + + var game = await _gameManager.CreateAsync(new GameOptionsData()); + game.DisplayName = "Example game"; + await game.SetPrivacyAsync(true); + + _logger.LogInformation("Created game {0}.", game.Code.Code); } public override ValueTask DisableAsync() diff --git a/src/Impostor.Server/Net/Client.cs b/src/Impostor.Server/Net/Client.cs index 143a0d1..87fc56c 100644 --- a/src/Impostor.Server/Net/Client.cs +++ b/src/Impostor.Server/Net/Client.cs @@ -332,7 +332,7 @@ namespace Impostor.Server.Net { using var message = MessageWriter.Get(MessageType.Reliable); - var games = _gameManager.FindListings((MapFlags)options.MapId, options.NumImpostors, options.Keywords); + var games = _gameManager.FindListings((MapFlags)options.Map, options.NumImpostors, options.Keywords); var skeldGameCount = _gameManager.GetGameCount(MapFlags.Skeld); var miraHqGameCount = _gameManager.GetGameCount(MapFlags.MiraHQ); diff --git a/src/Impostor.Server/Net/Manager/GameManager.cs b/src/Impostor.Server/Net/Manager/GameManager.cs index a37829e..8d883a4 100644 --- a/src/Impostor.Server/Net/Manager/GameManager.cs +++ b/src/Impostor.Server/Net/Manager/GameManager.cs @@ -98,7 +98,7 @@ namespace Impostor.Server.Net.Manager x.Value.PlayerCount < x.Value.Options.MaxPlayers)) { // Check for options. - if (!map.HasFlag((MapFlags)(1 << game.Options.MapId))) + if (!map.HasFlag((MapFlags)(1 << (byte)game.Options.Map))) { continue; } diff --git a/src/Impostor.Server/Net/State/Game.Api.cs b/src/Impostor.Server/Net/State/Game.Api.cs index 1a623be..a299691 100644 --- a/src/Impostor.Server/Net/State/Game.Api.cs +++ b/src/Impostor.Server/Net/State/Game.Api.cs @@ -6,13 +6,15 @@ using Impostor.Api.Games; using Impostor.Api.Innersloth; using Impostor.Api.Net; using Impostor.Api.Net.Inner; +using Impostor.Api.Net.Messages; +using Impostor.Hazel; using Impostor.Server.Net.Inner; namespace Impostor.Server.Net.State { internal partial class Game : IGame { - IClientPlayer IGame.Host => Host; + IClientPlayer? IGame.Host => Host; IGameNet IGame.GameNet => GameNet; @@ -44,5 +46,17 @@ namespace Impostor.Server.Net.State await FinishRpcAsync(writer); } } + + public async ValueTask SetPrivacyAsync(bool isPublic) + { + IsPublic = isPublic; + + using (var writer = MessageWriter.Get(MessageType.Reliable)) + { + WriteAlterGameMessage(writer, false, IsPublic); + + await SendToAllAsync(writer); + } + } } } diff --git a/src/Impostor.Server/Net/State/Game.cs b/src/Impostor.Server/Net/State/Game.cs index a1aeb48..6ca2fd6 100644 --- a/src/Impostor.Server/Net/State/Game.cs +++ b/src/Impostor.Server/Net/State/Game.cs @@ -60,6 +60,8 @@ namespace Impostor.Server.Net.State public bool IsPublic { get; private set; } + public string? DisplayName { get; set; } + public int HostId { get; private set; } public GameStates GameState { get; private set; } -- 2.39.5