mirror of
https://github.com/MSWS/TTT.git
synced 2025-12-05 22:20:25 -08:00
Start work on messaging
This commit is contained in:
@@ -3,8 +3,19 @@ using TTT.Api.Player;
|
||||
namespace TTT.Api;
|
||||
|
||||
public interface IGame {
|
||||
/// <summary>
|
||||
/// The list of players in the game.
|
||||
/// Spectators are not included in this list.
|
||||
/// </summary>
|
||||
ICollection<IPlayer> Players { get; }
|
||||
DateTime StartedAt { get; }
|
||||
|
||||
DateTime? StartedAt { get; }
|
||||
DateTime? FinishedAt { get; }
|
||||
SortedDictionary<DateTime, ISet<IAction>> Actions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to start a game.
|
||||
/// Depending on implementation, this may start a countdown or immediately start the game.
|
||||
/// </summary>
|
||||
void Start();
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using TTT.Api.Player;
|
||||
|
||||
namespace TTT.Api;
|
||||
namespace TTT.Api.Messages;
|
||||
|
||||
public interface IOnlineMessenger : IMessenger {
|
||||
Task<bool> IMessenger.Message(IPlayer player, string message) {
|
||||
@@ -12,4 +12,13 @@ public interface IOnlineMessenger : IMessenger {
|
||||
}
|
||||
|
||||
Task<bool> Message(IOnlinePlayer player, string message);
|
||||
|
||||
async Task<bool> MessageAll(IPlayerFinder finder, string message) {
|
||||
var tasks = finder.GetAllPlayers()
|
||||
.Select(onlinePlayer => Message(onlinePlayer, message))
|
||||
.ToList();
|
||||
|
||||
var results = await Task.WhenAll(tasks);
|
||||
return results.All(r => r);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace TTT.Api.Player;
|
||||
|
||||
public interface IPlayerFinder {
|
||||
internal void addPlayer(IOnlinePlayer player);
|
||||
internal void removePlayer(IOnlinePlayer player);
|
||||
internal protected void addPlayer(IOnlinePlayer player);
|
||||
internal protected void removePlayer(IOnlinePlayer player);
|
||||
|
||||
ISet<IOnlinePlayer> GetAllPlayers();
|
||||
|
||||
|
||||
5
TTT.CS2/Messages/Channel.cs
Normal file
5
TTT.CS2/Messages/Channel.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace TTT.CS2.Messages;
|
||||
|
||||
public enum Channel {
|
||||
CHAT, CONSOLE, HUD
|
||||
}
|
||||
12
TTT.CS2/Messages/ChatMessenger.cs
Normal file
12
TTT.CS2/Messages/ChatMessenger.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using TTT.Api.Events;
|
||||
|
||||
namespace TTT.CS2.Messages;
|
||||
|
||||
public class ChatMessenger(IEventBus bus) : GameMessenger(bus) {
|
||||
override protected Task<bool> SendMessage(CCSPlayerController gamePlayer,
|
||||
string message) {
|
||||
gamePlayer.PrintToChat(message);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
28
TTT.CS2/Messages/GameMessenger.cs
Normal file
28
TTT.CS2/Messages/GameMessenger.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using TTT.Api.Events;
|
||||
using TTT.Api.Messages;
|
||||
using TTT.Api.Player;
|
||||
using TTT.Game.Events.Player;
|
||||
|
||||
namespace TTT.CS2.Messages;
|
||||
|
||||
public abstract class GameMessenger(IEventBus bus) : IOnlineMessenger {
|
||||
public Task<bool> Message(IOnlinePlayer player, string message) {
|
||||
if (!ulong.TryParse(player.Id, out var steamId))
|
||||
return Task.FromResult(false);
|
||||
|
||||
var gamePlayer = Utilities.GetPlayerFromSteamId(steamId);
|
||||
if (gamePlayer == null || !gamePlayer.IsValid || gamePlayer.IsBot)
|
||||
return Task.FromResult(false);
|
||||
|
||||
var messageEvent = new PlayerMessageEvent(player, message);
|
||||
bus.Dispatch(messageEvent);
|
||||
if (messageEvent.IsCanceled) return Task.FromResult(false);
|
||||
|
||||
return SendMessage(gamePlayer, messageEvent.Message);
|
||||
}
|
||||
|
||||
abstract protected Task<bool> SendMessage(CCSPlayerController gamePlayer,
|
||||
string message);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ public class AttackAction(IPlayer attacker, IPlayer? target, string weapon,
|
||||
public int Damage { get; } = damage;
|
||||
public IPlayer Player { get; } = attacker;
|
||||
public IPlayer? Other { get; } = target;
|
||||
public string Id => "core.action.attack";
|
||||
public string Id => "basegame.action.attack";
|
||||
public string Verb => "attacked";
|
||||
public string Details => $"for {Damage} damage with {Weapon}";
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace TTT.Game.Actions;
|
||||
public class DeathAction(IPlayer victim, IPlayer? killer) : IAction {
|
||||
public IPlayer Player { get; } = victim;
|
||||
public IPlayer? Other { get; } = killer;
|
||||
public string Id { get; } = "core.action.death";
|
||||
public string Id { get; } = "basegame.action.death";
|
||||
public string Verb { get; } = killer is null ? "died" : "was killed by";
|
||||
|
||||
public string Details { get; } = string.Empty;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
using TTT.Api;
|
||||
|
||||
namespace TTT.Game.Events.Game;
|
||||
|
||||
public class GameStartEvent(IGame game) : GameEvent(game) {
|
||||
public override string Id => "core.event.game.start";
|
||||
}
|
||||
11
TTT.Game/Events/Game/GameStateUpdateEvent.cs
Normal file
11
TTT.Game/Events/Game/GameStateUpdateEvent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using TTT.Api;
|
||||
using TTT.Api.Events;
|
||||
|
||||
namespace TTT.Game.Events.Game;
|
||||
|
||||
public class GameStateUpdateEvent(IGame game, RoundBasedGame.State newState)
|
||||
: GameEvent(game), ICancelableEvent {
|
||||
public override string Id => "basegame.event.game.update";
|
||||
public bool IsCanceled { get; set; } = false;
|
||||
public RoundBasedGame.State NewState { get; } = newState;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace TTT.Game.Events.Player;
|
||||
|
||||
public class PlayerDamagedEvent(IOnlinePlayer player, IOnlinePlayer? attacker,
|
||||
int dmgDealt, int hpLeft) : PlayerEvent(player), ICancelableEvent {
|
||||
public override string Id => "core.event.player.damaged";
|
||||
public override string Id => "basegame.event.player.damaged";
|
||||
public bool IsCanceled { get; set; } = false;
|
||||
public IOnlinePlayer? Attacker { get; private set; } = attacker;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using TTT.Api.Player;
|
||||
namespace TTT.Game.Events.Player;
|
||||
|
||||
public class PlayerDeathEvent(IPlayer player) : PlayerEvent(player) {
|
||||
public override string Id => "core.event.player.death";
|
||||
public override string Id => "basegame.event.player.death";
|
||||
|
||||
public IPlayer? Assister { get; private set; } = null;
|
||||
public IPlayer? Killer { get; private set; } = null;
|
||||
|
||||
@@ -8,5 +8,5 @@ namespace TTT.Game.Events.Player;
|
||||
/// </summary>
|
||||
/// <param name="player"></param>
|
||||
public class PlayerJoinEvent(IPlayer player) : PlayerEvent(player) {
|
||||
public override string Id => "core.event.player.join";
|
||||
public override string Id => "basegame.event.player.join";
|
||||
}
|
||||
@@ -7,5 +7,5 @@ namespace TTT.Game.Events.Player;
|
||||
/// A game is not necessarily in progress when this event is fired.
|
||||
/// </summary>
|
||||
public class PlayerLeaveEvent(IPlayer player) : PlayerEvent(player) {
|
||||
public override string Id => "core.event.player.leave";
|
||||
public override string Id => "basegame.event.player.leave";
|
||||
}
|
||||
11
TTT.Game/Events/Player/PlayerMessageEvent.cs
Normal file
11
TTT.Game/Events/Player/PlayerMessageEvent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using TTT.Api.Events;
|
||||
using TTT.Api.Player;
|
||||
|
||||
namespace TTT.Game.Events.Player;
|
||||
|
||||
public class PlayerMessageEvent(IPlayer player, string message)
|
||||
: PlayerEvent(player), ICancelableEvent {
|
||||
public override string Id => "basegame.event.player.message";
|
||||
public bool IsCanceled { get; set; } = false;
|
||||
public string Message { get; set; } = message;
|
||||
}
|
||||
@@ -3,6 +3,6 @@ using TTT.Api.Events;
|
||||
namespace TTT.Game.Events.Player;
|
||||
|
||||
public class PlayerRoleAssignEvent : Event, ICancelableEvent {
|
||||
public override string Id => "core.event.player.roleassign";
|
||||
public override string Id => "basegame.event.player.roleassign";
|
||||
public bool IsCanceled { get; set; } = false;
|
||||
}
|
||||
@@ -4,13 +4,10 @@ using TTT.Api.Player;
|
||||
|
||||
namespace TTT.Game.Roles;
|
||||
|
||||
public class DetectiveRole : IRole {
|
||||
public const string ID = "core.role.detective";
|
||||
public string Id => ID;
|
||||
public string Name => "Detective";
|
||||
public Color Color => Color.DodgerBlue;
|
||||
|
||||
public IPlayer? FindPlayerToAssign(ISet<IOnlinePlayer> players) {
|
||||
return players.FirstOrDefault(p => p.Roles.Count == 0);
|
||||
}
|
||||
public class DetectiveRole(float targetRatio = 1f / 8f)
|
||||
: RatioBasedRole(targetRatio) {
|
||||
public const string ID = "basegame.role.detective";
|
||||
public override string Id => ID;
|
||||
public override string Name => "Detective";
|
||||
public override Color Color => Color.DodgerBlue;
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using TTT.Api.Player;
|
||||
namespace TTT.Game.Roles;
|
||||
|
||||
public class InnocentRole : IRole {
|
||||
public const string ID = "core.role.innocent";
|
||||
public const string ID = "basegame.role.innocent";
|
||||
public string Id => ID;
|
||||
public string Name => "Innocent";
|
||||
public Color Color => Color.LimeGreen;
|
||||
|
||||
18
TTT.Game/Roles/RatioBasedRole.cs
Normal file
18
TTT.Game/Roles/RatioBasedRole.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Drawing;
|
||||
using TTT.Api;
|
||||
using TTT.Api.Player;
|
||||
|
||||
namespace TTT.Game.Roles;
|
||||
|
||||
public abstract class RatioBasedRole(float targetRatio) : IRole {
|
||||
public abstract string Id { get; }
|
||||
public abstract string Name { get; }
|
||||
public abstract Color Color { get; }
|
||||
|
||||
public IPlayer? FindPlayerToAssign(ISet<IOnlinePlayer> players) {
|
||||
var currentCount = players.Count(p => p.Roles.Any(r => r.Id == Id));
|
||||
var ratio = currentCount / (float)players.Count;
|
||||
if (ratio >= targetRatio) return null;
|
||||
return players.First(p => p.Roles.Count == 0);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using TTT.Api.Player;
|
||||
namespace TTT.Game.Roles;
|
||||
|
||||
public class SpectatorRole : IRole {
|
||||
public string Id => "core.role.spectator";
|
||||
public string Id => "basegame.role.spectator";
|
||||
public string Name => "Spectator";
|
||||
public Color Color => Color.Gray;
|
||||
|
||||
|
||||
@@ -4,16 +4,10 @@ using TTT.Api.Player;
|
||||
|
||||
namespace TTT.Game.Roles;
|
||||
|
||||
public class TraitorRole(float targetRatio = 1f / 5f) : IRole {
|
||||
public const string ID = "core.role.traitor";
|
||||
public string Id => ID;
|
||||
public string Name => "Traitor";
|
||||
public Color Color => Color.Red;
|
||||
|
||||
public IPlayer? FindPlayerToAssign(ISet<IOnlinePlayer> players) {
|
||||
var traitorCount = players.Count(p => p.Roles.Any(r => r.Id == ID));
|
||||
var ratio = traitorCount / (float)players.Count;
|
||||
if (ratio >= targetRatio) return null;
|
||||
return players.First(p => p.Roles.Count == 0);
|
||||
}
|
||||
public class TraitorRole(float targetRatio = 1f / 5f)
|
||||
: RatioBasedRole(targetRatio) {
|
||||
public const string ID = "basegame.role.traitor";
|
||||
public override string Id => ID;
|
||||
public override string Name => "Traitor";
|
||||
public override Color Color => Color.Red;
|
||||
}
|
||||
53
TTT.Game/RoundBasedGame.cs
Normal file
53
TTT.Game/RoundBasedGame.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using TTT.Api;
|
||||
using TTT.Api.Events;
|
||||
using TTT.Api.Player;
|
||||
using TTT.Game.Events.Game;
|
||||
|
||||
namespace TTT.Game;
|
||||
|
||||
public class RoundBasedGame(IEventBus bus) : IGame {
|
||||
public ICollection<IPlayer> Players { get; } = new List<IPlayer>();
|
||||
|
||||
public DateTime? StartedAt { get; } = null;
|
||||
public DateTime? FinishedAt { get; } = null;
|
||||
public SortedDictionary<DateTime, ISet<IAction>> Actions { get; } = new();
|
||||
|
||||
public void Start() {
|
||||
|
||||
}
|
||||
|
||||
public enum State {
|
||||
/// <summary>
|
||||
/// Waiting for players to join.
|
||||
/// </summary>
|
||||
WAITING,
|
||||
|
||||
/// <summary>
|
||||
/// Waiting for the countdown to finish before starting the game.
|
||||
/// </summary>
|
||||
COUNTDOWN,
|
||||
|
||||
/// <summary>
|
||||
/// Currently playing the game.
|
||||
/// </summary>
|
||||
IN_PROGRESS,
|
||||
|
||||
/// <summary>
|
||||
/// Game has finished.
|
||||
/// </summary>
|
||||
FINISHED
|
||||
}
|
||||
|
||||
private State currentState = State.WAITING;
|
||||
|
||||
public State CurrentState {
|
||||
set {
|
||||
var ev = new GameStateUpdateEvent(this, value);
|
||||
bus.Dispatch(ev);
|
||||
if (ev.IsCanceled) return;
|
||||
currentState = value;
|
||||
}
|
||||
|
||||
get => currentState;
|
||||
}
|
||||
}
|
||||
@@ -11,29 +11,29 @@ namespace GitVersion
|
||||
public const string PreReleaseLabelWithDash = "";
|
||||
// PreReleaseNumber is null and omitted
|
||||
public const int WeightedPreReleaseNumber = 60000;
|
||||
public const int BuildMetaData = 3;
|
||||
public const string BuildMetaDataPadded = "0003";
|
||||
public const string FullBuildMetaData = "3.Branch.main.Sha.c935acb0a88e645f9cfc9eefed037078b9c35179";
|
||||
public const int BuildMetaData = 6;
|
||||
public const string BuildMetaDataPadded = "0006";
|
||||
public const string FullBuildMetaData = "6.Branch.main.Sha.08adb86f65b1b9385eb073addd2096dba435e687";
|
||||
public const string MajorMinorPatch = "0.1.0";
|
||||
public const string SemVer = "0.1.0";
|
||||
public const string LegacySemVer = "0.1.0";
|
||||
public const string LegacySemVerPadded = "0.1.0";
|
||||
public const string AssemblySemVer = "0.1.0.0";
|
||||
public const string AssemblySemFileVer = "0.1.0.0";
|
||||
public const string FullSemVer = "0.1.0+3";
|
||||
public const string InformationalVersion = "0.1.0+3.Branch.main.Sha.c935acb0a88e645f9cfc9eefed037078b9c35179";
|
||||
public const string FullSemVer = "0.1.0+6";
|
||||
public const string InformationalVersion = "0.1.0+6.Branch.main.Sha.08adb86f65b1b9385eb073addd2096dba435e687";
|
||||
public const string BranchName = "main";
|
||||
public const string EscapedBranchName = "main";
|
||||
public const string Sha = "c935acb0a88e645f9cfc9eefed037078b9c35179";
|
||||
public const string ShortSha = "c935acb";
|
||||
public const string Sha = "08adb86f65b1b9385eb073addd2096dba435e687";
|
||||
public const string ShortSha = "08adb86";
|
||||
public const string NuGetVersionV2 = "0.1.0";
|
||||
public const string NuGetVersion = "0.1.0";
|
||||
public const string NuGetPreReleaseTagV2 = "";
|
||||
public const string NuGetPreReleaseTag = "";
|
||||
public const string VersionSourceSha = "dabc2a6913b5b73fa972ef21c1c480615eecff36";
|
||||
public const int CommitsSinceVersionSource = 3;
|
||||
public const string CommitsSinceVersionSourcePadded = "0003";
|
||||
public const int UncommittedChanges = 1;
|
||||
public const int CommitsSinceVersionSource = 6;
|
||||
public const string CommitsSinceVersionSourcePadded = "0006";
|
||||
public const int UncommittedChanges = 30;
|
||||
public const string CommitDate = "2025-07-28";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,28 +8,28 @@
|
||||
"PreReleaseLabelWithDash": "",
|
||||
"PreReleaseNumber": null,
|
||||
"WeightedPreReleaseNumber": 60000,
|
||||
"BuildMetaData": 3,
|
||||
"BuildMetaDataPadded": "0003",
|
||||
"FullBuildMetaData": "3.Branch.main.Sha.c935acb0a88e645f9cfc9eefed037078b9c35179",
|
||||
"BuildMetaData": 6,
|
||||
"BuildMetaDataPadded": "0006",
|
||||
"FullBuildMetaData": "6.Branch.main.Sha.08adb86f65b1b9385eb073addd2096dba435e687",
|
||||
"MajorMinorPatch": "0.1.0",
|
||||
"SemVer": "0.1.0",
|
||||
"LegacySemVer": "0.1.0",
|
||||
"LegacySemVerPadded": "0.1.0",
|
||||
"AssemblySemVer": "0.1.0.0",
|
||||
"AssemblySemFileVer": "0.1.0.0",
|
||||
"FullSemVer": "0.1.0+3",
|
||||
"InformationalVersion": "0.1.0+3.Branch.main.Sha.c935acb0a88e645f9cfc9eefed037078b9c35179",
|
||||
"FullSemVer": "0.1.0+6",
|
||||
"InformationalVersion": "0.1.0+6.Branch.main.Sha.08adb86f65b1b9385eb073addd2096dba435e687",
|
||||
"BranchName": "main",
|
||||
"EscapedBranchName": "main",
|
||||
"Sha": "c935acb0a88e645f9cfc9eefed037078b9c35179",
|
||||
"ShortSha": "c935acb",
|
||||
"Sha": "08adb86f65b1b9385eb073addd2096dba435e687",
|
||||
"ShortSha": "08adb86",
|
||||
"NuGetVersionV2": "0.1.0",
|
||||
"NuGetVersion": "0.1.0",
|
||||
"NuGetPreReleaseTagV2": "",
|
||||
"NuGetPreReleaseTag": "",
|
||||
"VersionSourceSha": "dabc2a6913b5b73fa972ef21c1c480615eecff36",
|
||||
"CommitsSinceVersionSource": 3,
|
||||
"CommitsSinceVersionSourcePadded": "0003",
|
||||
"UncommittedChanges": 1,
|
||||
"CommitsSinceVersionSource": 6,
|
||||
"CommitsSinceVersionSourcePadded": "0006",
|
||||
"UncommittedChanges": 30,
|
||||
"CommitDate": "2025-07-28"
|
||||
}
|
||||
|
||||
20
TTT.Test/Fakes/FakeMessenger.cs
Normal file
20
TTT.Test/Fakes/FakeMessenger.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using TTT.Api;
|
||||
using TTT.Api.Events;
|
||||
using TTT.Api.Player;
|
||||
using TTT.Game.Events.Player;
|
||||
|
||||
namespace TTT.Test.Fakes;
|
||||
|
||||
public class FakeMessenger(IEventBus bus) : IMessenger {
|
||||
public Task<bool> Message(IPlayer player, string message) {
|
||||
if (player is not TestPlayer testPlayer)
|
||||
throw new ArgumentException("Player must be a TestPlayer",
|
||||
nameof(player));
|
||||
|
||||
var messageEvent = new PlayerMessageEvent(testPlayer, message);
|
||||
bus.Dispatch(messageEvent);
|
||||
if (messageEvent.IsCanceled) return Task.FromResult(false);
|
||||
testPlayer.Messages.Add(messageEvent.Message);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,21 @@
|
||||
using TTT.Api.Events;
|
||||
using TTT.Api.Player;
|
||||
using TTT.Game.Events.Player;
|
||||
|
||||
namespace TTT.Test.Fakes;
|
||||
|
||||
public class FakePlayerFinder : IPlayerFinder {
|
||||
public class FakePlayerFinder(IEventBus bus) : IPlayerFinder {
|
||||
private readonly HashSet<IOnlinePlayer> players = [];
|
||||
|
||||
public void addPlayer(IOnlinePlayer player) => players.Add(player);
|
||||
public void addPlayer(IOnlinePlayer player) {
|
||||
players.Add(player);
|
||||
bus.Dispatch(new PlayerJoinEvent(player));
|
||||
}
|
||||
|
||||
public void removePlayer(IOnlinePlayer player) => players.Remove(player);
|
||||
public void removePlayer(IOnlinePlayer player) {
|
||||
players.Remove(player);
|
||||
bus.Dispatch(new PlayerLeaveEvent(player));
|
||||
}
|
||||
|
||||
public ISet<IOnlinePlayer> GetAllPlayers() => players;
|
||||
}
|
||||
34
TTT.Test/Messages/JoinMessageTest.cs
Normal file
34
TTT.Test/Messages/JoinMessageTest.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using TTT.Api;
|
||||
using TTT.Api.Events;
|
||||
using TTT.Game.Events.Player;
|
||||
using TTT.Test.Fakes;
|
||||
using Xunit;
|
||||
|
||||
namespace TTT.Test.Messages;
|
||||
|
||||
public class JoinMessageTest(IEventBus bus, IMessenger msg,
|
||||
FakePlayerFinder finder) {
|
||||
[Fact]
|
||||
public void TestJoinMessage() {
|
||||
// Arrange
|
||||
var listener = new JoinMessageListener(bus, msg);
|
||||
var player = TestPlayer.Random();
|
||||
bus.RegisterListener(listener);
|
||||
|
||||
// Act
|
||||
finder.addPlayer(player);
|
||||
|
||||
// Assert
|
||||
Assert.Single(player.Messages);
|
||||
Assert.Equal("Hello, World!", player.Messages[0]);
|
||||
}
|
||||
|
||||
private class JoinMessageListener(IEventBus bus, IMessenger msg) : IListener {
|
||||
public void Dispose() { bus.UnregisterListener(this); }
|
||||
|
||||
[EventHandler]
|
||||
public void OnJoin(PlayerJoinEvent ev) {
|
||||
msg.Message(ev.Player, "Hello, World!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TTT.Api;
|
||||
using TTT.Api.Events;
|
||||
using TTT.Api.Player;
|
||||
using TTT.Game;
|
||||
@@ -11,5 +12,7 @@ public class Startup {
|
||||
public void ConfigureServices(IServiceCollection services) {
|
||||
services.AddScoped<IEventBus, EventBus>();
|
||||
services.AddScoped<IPlayerFinder, FakePlayerFinder>();
|
||||
services.AddScoped<FakePlayerFinder>();
|
||||
services.AddScoped<IMessenger, FakeMessenger>();
|
||||
}
|
||||
}
|
||||
@@ -27,4 +27,8 @@
|
||||
<PackageReference Include="xunit.v3" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Game\Roles\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -7,4 +7,13 @@ public class TestPlayer(string id, string name) : IOnlinePlayer {
|
||||
public string Id { get; } = id;
|
||||
public string Name { get; } = name;
|
||||
public ICollection<IRole> Roles { get; } = (List<IRole>) [];
|
||||
|
||||
public List<string> Messages { get; } = [];
|
||||
|
||||
public TestPlayer() : this("314159", "Test Player") { }
|
||||
|
||||
public static TestPlayer Random() {
|
||||
return new TestPlayer(new Random().NextInt64().ToString(),
|
||||
"Test Player " + Guid.NewGuid());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user