Skip to content

Commit 3be7d6b

Browse files
committed
Add game code plugin
1 parent 4b8a02c commit 3be7d6b

27 files changed

+380
-77
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Impostor.Api.Events;
2+
using Impostor.Api.Games;
3+
4+
namespace Impostor.Api.Extension.Events;
5+
6+
public class GameCodeCreateEvent(GameCreationEvent? creationEvent = null) : IEvent
7+
{
8+
public GameCreationEvent? CreationEvent { get; } = creationEvent;
9+
public EventOutcome<GameCode>? Result { get; set; }
10+
}

src/Impostor.Api.Extension/packages.lock.json

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
"Microsoft.Extensions.Hosting.Abstractions": "8.0.1"
1414
}
1515
},
16+
"JetBrains.Annotations": {
17+
"type": "Transitive",
18+
"resolved": "2024.3.0",
19+
"contentHash": "ox5pkeLQXjvJdyAB4b2sBYAlqZGLh3PjSnP1bQNVx72ONuTJ9+34/+Rq91Fc0dG29XG9RgZur9+NcP4riihTug=="
20+
},
1621
"Microsoft.AspNetCore.Hosting.Server.Abstractions": {
1722
"type": "Transitive",
1823
"resolved": "2.3.0",
@@ -121,6 +126,7 @@
121126
"impostor.api": {
122127
"type": "Project",
123128
"dependencies": {
129+
"JetBrains.Annotations": "[2024.3.0, )",
124130
"Microsoft.Extensions.Hosting.Abstractions": "[9.0.2, )",
125131
"Microsoft.Extensions.Logging.Abstractions": "[9.0.2, )",
126132
"NextFast.Hazel.Abstractions": "[1.0.2-ci.8, )",

src/Impostor.Api/Events/Attributes/EventListenerAttribute.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
2+
using JetBrains.Annotations;
23

34
namespace Impostor.Api.Events;
45

6+
[MeansImplicitUse]
57
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
68
public class EventListenerAttribute : Attribute
79
{

src/Impostor.Api/Events/EventResult.cs

+16
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,23 @@ public enum EventResultType
1010
Success,
1111
}
1212

13+
public class NumberEventOutcome<T>(T result) : IEventResult where T : unmanaged
14+
{
15+
public T Result { get; init; } = result;
16+
17+
public static implicit operator T (NumberEventOutcome<T> result) => result.Result;
18+
}
19+
20+
public class EventOutcome<T>(T result) : IEventResult
21+
{
22+
public T Result { get; init; } = result;
23+
24+
public static implicit operator T (EventOutcome<T> result) => result.Result;
25+
}
26+
1327
public class TypeResult(EventResultType resultType) : IEventResult
1428
{
1529
public EventResultType Type { get; init; } = resultType;
30+
31+
public static implicit operator EventResultType (TypeResult result) => result.Type;
1632
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Impostor.Api.Events;
2+
using Impostor.Api.Games.Managers;
3+
using Impostor.Api.Innersloth;
4+
using Impostor.Api.Innersloth.GameOptions;
5+
using Impostor.Api.Net;
6+
7+
namespace Impostor.Api.Extension.Events;
8+
9+
public class GameCreationEvent(IClient? client, IGameManager gameManager, IGameOptions gameOptions, GameFilterOptions filterOptions) : IEvent
10+
{
11+
12+
public IClient? Creator { get; } = client;
13+
14+
public IGameManager GameManager { get; } = gameManager;
15+
16+
public IGameOptions GameOptions { get; } = gameOptions;
17+
18+
public GameFilterOptions FilterOptions { get; } = filterOptions;
19+
20+
public NumberEventOutcome<bool> Cancel { get; set; } = new(false);
21+
}

src/Impostor.Api/Events/Game/IGameCreationEvent.cs

-24
This file was deleted.

src/Impostor.Api/Events/IEvent.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
namespace Impostor.Api.Events;
22

3-
public interface IEvent
4-
{
5-
}
3+
public interface IEvent;
+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
namespace Impostor.Api.Games;
1+
using System.Threading.Tasks;
2+
using Impostor.Api.Extension.Events;
3+
4+
namespace Impostor.Api.Games;
25

36
public interface IGameCodeFactory
47
{
5-
GameCode Create();
8+
ValueTask<GameCode> CreateAsync(GameCreationEvent? creationEvent);
9+
ValueTask<GameCode> Create();
610
}

src/Impostor.Api/Impostor.Api.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
</ItemGroup>
2424

2525
<ItemGroup>
26+
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
2627
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.2"/>
2728
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.2"/>
2829
<PackageReference Include="NextFast.Hazel.Abstractions" Version="1.0.2-ci.8"/>

src/Impostor.Api/packages.lock.json

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
"version": 1,
33
"dependencies": {
44
"net9.0": {
5+
"JetBrains.Annotations": {
6+
"type": "Direct",
7+
"requested": "[2024.3.0, )",
8+
"resolved": "2024.3.0",
9+
"contentHash": "ox5pkeLQXjvJdyAB4b2sBYAlqZGLh3PjSnP1bQNVx72ONuTJ9+34/+Rq91Fc0dG29XG9RgZur9+NcP4riihTug=="
10+
},
511
"Microsoft.Extensions.Hosting.Abstractions": {
612
"type": "Direct",
713
"requested": "[9.0.2, )",

src/Impostor.Server/Events/Game/GameCreationEvent.cs

-38
This file was deleted.

src/Impostor.Server/Events/Register/RegisteredEventListener.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static IReadOnlyList<RegisteredEventListener> FromType(Type type)
5050
return Instances.GetOrAdd(type, t =>
5151
{
5252
return t.GetMethods()
53-
.Where(m => !m.IsStatic && m.GetCustomAttributes(typeof(EventListenerAttribute), false).Any())
53+
.Where(m => !m.IsStatic && m.GetCustomAttributes(typeof(EventListenerAttribute), false).Length != 0)
5454
.SelectMany(m => FromMethod(t, m))
5555
.ToArray();
5656
});
+15-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
1-
using Impostor.Api.Games;
1+
using System.Threading.Tasks;
2+
using Impostor.Api.Events.Managers;
3+
using Impostor.Api.Extension.Events;
4+
using Impostor.Api.Games;
25

36
namespace Impostor.Server.Net;
47

5-
public class GameCodeFactory : IGameCodeFactory
8+
public class GameCodeFactory(IEventManager eventManager) : IGameCodeFactory
69
{
7-
public GameCode Create()
10+
public async ValueTask<GameCode> CreateAsync(GameCreationEvent? creationEvent = null)
811
{
12+
var @event = new GameCodeCreateEvent(creationEvent);
13+
await eventManager.CallAsync(@event);
914
return GameCode.Create();
1015
}
16+
17+
public async ValueTask<GameCode> Create()
18+
{
19+
var @event = new GameCodeCreateEvent();
20+
await eventManager.CallAsync(@event);
21+
return @event.Result ?? GameCode.Create();
22+
}
1123
}

src/Impostor.Server/Net/Manager/GameManager.cs

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Impostor.Api;
77
using Impostor.Api.Config;
88
using Impostor.Api.Events.Managers;
9+
using Impostor.Api.Extension.Events;
910
using Impostor.Api.Games;
1011
using Impostor.Api.Games.Managers;
1112
using Impostor.Api.Innersloth;
@@ -102,19 +103,19 @@ public async ValueTask RemoveAsync(GameCode gameCode)
102103
return null;
103104
}
104105

105-
var @event = new GameCreationEvent(this, owner);
106+
var @event = new GameCreationEvent(owner, this, options, filterOptions);
106107
await _eventManager.CallAsync(@event);
107108

108-
if (@event.IsCancelled)
109+
if (@event.Cancel)
109110
{
110111
return null;
111112
}
112113

113-
var (success, game) = await TryCreateAsync(options, filterOptions, owner, @event.GameCode);
114+
var (success, game) = await TryCreateAsync(options, filterOptions, owner, @event);
114115

115116
for (var i = 0; i < 10 && !success; i++)
116117
{
117-
(success, game) = await TryCreateAsync(options, filterOptions, owner);
118+
(success, game) = await TryCreateAsync(options, filterOptions, owner, @event);
118119
}
119120

120121
if (owner != null)
@@ -131,9 +132,9 @@ public async ValueTask RemoveAsync(GameCode gameCode)
131132
}
132133

133134
private async ValueTask<(bool Success, Game? Game)> TryCreateAsync(IGameOptions options,
134-
GameFilterOptions filterOptions, IClient? owner, GameCode? desiredGameCode = null)
135+
GameFilterOptions filterOptions, IClient? owner, GameCreationEvent? creationEvent = null)
135136
{
136-
var gameCode = desiredGameCode ?? _gameCodeFactory.Create();
137+
var gameCode = await _gameCodeFactory.CreateAsync(creationEvent);
137138
var game = ActivatorUtilities.CreateInstance<Game>(_serviceProvider, gameCode, options, filterOptions);
138139

139140
if (!_games.TryAdd(gameCode, game))

src/Impostor.Server/packages.lock.json

+6
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@
143143
"resolved": "2.5.1",
144144
"contentHash": "zy8TMeTP+1FH2NrLaNZtdRbBdq7u5MI+NFZQOBSM69u5RFkciinwzV2eveY6Kjf5MzgsYvvl6kTStsj3JrXqkg=="
145145
},
146+
"JetBrains.Annotations": {
147+
"type": "Transitive",
148+
"resolved": "2024.3.0",
149+
"contentHash": "ox5pkeLQXjvJdyAB4b2sBYAlqZGLh3PjSnP1bQNVx72ONuTJ9+34/+Rq91Fc0dG29XG9RgZur9+NcP4riihTug=="
150+
},
146151
"Microsoft.AspNetCore.Hosting.Abstractions": {
147152
"type": "Transitive",
148153
"resolved": "2.3.0",
@@ -520,6 +525,7 @@
520525
"impostor.api": {
521526
"type": "Project",
522527
"dependencies": {
528+
"JetBrains.Annotations": "[2024.3.0, )",
523529
"Microsoft.Extensions.Hosting.Abstractions": "[9.0.2, )",
524530
"Microsoft.Extensions.Logging.Abstractions": "[9.0.2, )",
525531
"NextFast.Hazel.Abstractions": "[1.0.2-ci.8, )",

src/Impostor.sln

+11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{3283
1515
EndProject
1616
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SelfHttpMatchmaker", "Plugins\SelfHttpMatchmaker\SelfHttpMatchmaker.csproj", "{7E912EBE-52F5-4D6D-9203-38069456D9B9}"
1717
EndProject
18+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameCodePlugin", "Plugins\GameCodePlugin\GameCodePlugin.csproj", "{F19C0CC2-55FE-41D9-9372-8361EAE1B356}"
19+
EndProject
1820
Global
1921
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2022
Debug|Any CPU = Debug|Any CPU
@@ -63,6 +65,14 @@ Global
6365
{7E912EBE-52F5-4D6D-9203-38069456D9B9}.Release|Any CPU.Build.0 = Release|Any CPU
6466
{7E912EBE-52F5-4D6D-9203-38069456D9B9}.Release|x86.ActiveCfg = Release|Any CPU
6567
{7E912EBE-52F5-4D6D-9203-38069456D9B9}.Release|x86.Build.0 = Release|Any CPU
68+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356}.Debug|Any CPU.Build.0 = Debug|Any CPU
70+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356}.Debug|x86.ActiveCfg = Debug|Any CPU
71+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356}.Debug|x86.Build.0 = Debug|Any CPU
72+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356}.Release|Any CPU.ActiveCfg = Release|Any CPU
73+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356}.Release|Any CPU.Build.0 = Release|Any CPU
74+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356}.Release|x86.ActiveCfg = Release|Any CPU
75+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356}.Release|x86.Build.0 = Release|Any CPU
6676
EndGlobalSection
6777
GlobalSection(SolutionProperties) = preSolution
6878
HideSolutionNode = FALSE
@@ -72,5 +82,6 @@ Global
7282
EndGlobalSection
7383
GlobalSection(NestedProjects) = preSolution
7484
{7E912EBE-52F5-4D6D-9203-38069456D9B9} = {32836008-CC0F-4EAB-B460-4C082AF42C6C}
85+
{F19C0CC2-55FE-41D9-9372-8361EAE1B356} = {32836008-CC0F-4EAB-B460-4C082AF42C6C}
7586
EndGlobalSection
7687
EndGlobal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using Impostor.Api.Events;
3+
using Impostor.Api.Extension.Events;
4+
using Impostor.Api.Games;
5+
6+
namespace GameCodePlugin;
7+
8+
#pragma warning disable CA1822
9+
public class GameCodeEventListener : IEventListener
10+
{
11+
[EventListener]
12+
13+
public void OnCreateCode(GameCodeCreateEvent @event)
14+
{
15+
var state = GameCodePlugin.Codes.FirstOrDefault(used => !used);
16+
if (state == null) return;
17+
@event.Result = new EventOutcome<GameCode>(state.Code);
18+
state.Used = true;
19+
}
20+
21+
[EventListener]
22+
public void OnReleaseCode(IGameDestroyedEvent @event)
23+
{
24+
var code = @event.Game.Code;
25+
var state = GameCodePlugin.Codes.FirstOrDefault(state => state.Code == code);
26+
if (state == null) return;
27+
state.Used = false;
28+
}
29+
}

0 commit comments

Comments
 (0)