Skip to content

Commit

Permalink
Add force match command
Browse files Browse the repository at this point in the history
  • Loading branch information
Beyley committed Sep 2, 2023
1 parent bb6e7f8 commit d597a6f
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 15 deletions.
10 changes: 6 additions & 4 deletions Refresh.GameServer/Endpoints/Game/UserEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,14 @@ public SerializedUserList GetMultipleUsers(RequestContext context, GameDatabaseC
/// <returns>The string shown in-game.</returns>
[GameEndpoint("filter", Method.Post)]
[AllowEmptyBody]
public string Filter(RequestContext context, CommandService command, string body, GameUser user)
public string Filter(RequestContext context, CommandService commandService, string body, GameUser user, GameDatabaseContext database)
{
Debug.Assert(user != null);
Debug.Assert(body != null);

//TODO: Add filtering

if (command.IsPublishing(user.UserId))
if (commandService.IsPublishing(user.UserId))
{
context.Logger.LogInfo(BunkumContext.Filter, $"Publish filter {body}");
}
Expand All @@ -186,9 +186,11 @@ public string Filter(RequestContext context, CommandService command, string body

try
{
Command parsedCommand = command.ParseCommand(body);
Command command = commandService.ParseCommand(body);

context.Logger.LogInfo(BunkumContext.Commands, $"User used command \"{parsedCommand.Name}\" with args \"{parsedCommand.Arguments}\"");
context.Logger.LogInfo(BunkumContext.Commands, $"User used command \"{command.Name}\" with args \"{command.Arguments}\"");

commandService.HandleCommand(command, database, user);
}
catch
{
Expand Down
2 changes: 1 addition & 1 deletion Refresh.GameServer/RefreshGameServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ protected virtual void SetupServices()
this._server.AddRateLimitService(new RateLimitSettings(60, 400, 30, "global"));
this._server.AddService<CategoryService>();
this._server.AddService<FriendStorageService>();
this._server.AddService<CommandService>();
this._server.AddService<MatchService>();
this._server.AddService<CommandService>();
this._server.AddService<ImportService>();
this._server.AddService<DocumentationService>();
this._server.AddAutoDiscover(serverBrand: "Refresh",
Expand Down
35 changes: 34 additions & 1 deletion Refresh.GameServer/Services/CommandService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@
using JetBrains.Annotations;
using MongoDB.Bson;
using NotEnoughLogs;
using Refresh.GameServer.Database;
using Refresh.GameServer.Types.Commands;
using Refresh.GameServer.Types.UserData;

namespace Refresh.GameServer.Services;

public class CommandService : EndpointService
{
public CommandService(LoggerContainer<BunkumContext> logger) : base(logger) {}
private readonly MatchService _match;

public CommandService(LoggerContainer<BunkumContext> logger, MatchService match) : base(logger) {
this._match = match;
}

private readonly HashSet<ObjectId> _usersPublishing = new();

Expand Down Expand Up @@ -67,4 +73,31 @@ public Command ParseCommand(string str)

return new Command(str[1..idx], str[(idx + 1)..]);
}

public void HandleCommand(Command command, GameDatabaseContext database, GameUser user)
{
switch (command.Name)
{
case "forcematch": {
if (command.Arguments == null)
{
throw new Exception("User not provided for force match command");
}

GameUser? target = database.GetUserByUsername(command.Arguments);

if (target != null)
{
this._match.SetForceMatch(user.UserId, target.UserId);
}

break;
}
case "clearforcematch": {
this._match.ClearForceMatch(user.UserId);

break;
}
}
}
}
23 changes: 23 additions & 0 deletions Refresh.GameServer/Services/MatchService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using NotEnoughLogs;
using System.Reflection;
using Bunkum.HttpServer.Responses;
using MongoDB.Bson;
using Refresh.GameServer.Authentication;
using Refresh.GameServer.Database;
using Refresh.GameServer.Types.Matching;
Expand All @@ -16,6 +17,8 @@ public partial class MatchService : EndpointService
private readonly List<IMatchMethod> _matchMethods = new();

private readonly List<GameRoom> _rooms = new();

private readonly Dictionary<ObjectId, ObjectId> _forceMatches = new();

public IEnumerable<GameRoom> Rooms
{
Expand Down Expand Up @@ -122,4 +125,24 @@ public Response ExecuteMethod(string methodStr, SerializedRoomData roomData, Gam

return method.Execute(this, this.Logger, database, user, token, roomData);
}

public void SetForceMatch(ObjectId user, ObjectId target)
{
this._forceMatches[user] = target;
}

public ObjectId? GetForceMatch(ObjectId user)
{
if (this._forceMatches.TryGetValue(user, out ObjectId target))
{
return target;
}

return null;
}

public void ClearForceMatch(ObjectId user)
{
this._forceMatches.Remove(user);
}
}
19 changes: 18 additions & 1 deletion Refresh.GameServer/Types/Matching/MatchMethods/FindRoomMethod.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Bunkum.CustomHttpListener.Parsing;
using Bunkum.HttpServer;
using Bunkum.HttpServer.Responses;
using MongoDB.Bson;
using NotEnoughLogs;
using Refresh.GameServer.Authentication;
using Refresh.GameServer.Database;
Expand Down Expand Up @@ -42,17 +43,33 @@ public Response Execute(MatchService service, LoggerContainer<BunkumContext> log
(levelId == null || r.LevelId == levelId))
.OrderByDescending(r => r.RoomMood)
.ToList();

//When a user is behind a Strict NAT layer, we can only connect them to players with Open NAT types
if (body.NatType != null && body.NatType[0] == NatType.Strict)
{
rooms = rooms.Where(r => r.NatType == NatType.Open).ToList();
}

ObjectId? forceMatch = service.GetForceMatch(user.UserId);

//If the user has a forced match
if (forceMatch != null)
{
//Filter the rooms to only the rooms that contain the player we are wanting to force match to
rooms = rooms.Where(r => r.PlayerIds.Any(player => player.Id != null && player.Id == forceMatch.Value)).ToList();
}

if (rooms.Count <= 0)
{
return NotFound; // TODO: update this response, shouldn't be 404
}

//If the user has a forced match and we found a room
if (forceMatch != null)
{
//Clear the user's force match
service.ClearForceMatch(user.UserId);
}

GameRoom room = rooms[Random.Shared.Next(0, rooms.Count)];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public Response Execute(MatchService service, LoggerContainer<BunkumContext> log
SerializedRoomData body)
{
if (body.Players == null) return BadRequest;
GameRoom room = service.GetOrCreateRoomByPlayer(user, token.TokenPlatform, token.TokenGame, body.NatType[0]);
GameRoom room = service.GetOrCreateRoomByPlayer(user, token.TokenPlatform, token.TokenGame, body.NatType == null ? NatType.Open : body.NatType[0]);

room.LastContact = DateTimeOffset.Now;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class UpdateRoomDataMethod : IMatchMethod
public Response Execute(MatchService service, LoggerContainer<BunkumContext> logger,
GameDatabaseContext database, GameUser user, Token token, SerializedRoomData body)
{
GameRoom room = service.GetOrCreateRoomByPlayer(user, token.TokenPlatform, token.TokenGame, body.NatType[0]);
GameRoom room = service.GetOrCreateRoomByPlayer(user, token.TokenPlatform, token.TokenGame, body.NatType == null ? NatType.Open : body.NatType[0]);
if (room.HostId.Id != user.UserId) return Unauthorized;

room.LastContact = DateTimeOffset.Now;
Expand Down
15 changes: 9 additions & 6 deletions RefreshTests.GameServer/Tests/Commands/CommandParseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ public class CommandParseTests : GameServerTest
[Test]
public void ParsingTest()
{
CommandService service = new(new LoggerContainer<BunkumContext>());

LoggerContainer<BunkumContext> logger = new();
CommandService service = new(logger, new MatchService(logger));

Assert.That(service.ParseCommand("/parse test"), Is.EqualTo(new Command("parse", "test")));
Assert.That(service.ParseCommand("/noargs"), Is.EqualTo(new Command("noargs", null)));
Assert.That(service.ParseCommand("/noargs "), Is.EqualTo(new Command("noargs", null)));
Expand All @@ -20,16 +21,18 @@ public void ParsingTest()
[Test]
public void NoSlashThrows()
{
CommandService service = new(new LoggerContainer<BunkumContext>());

LoggerContainer<BunkumContext> logger = new();
CommandService service = new(logger, new MatchService(logger));

Assert.That(() => service.ParseCommand("parse test"), Throws.Exception);
}

[Test]
public void BlankCommandThrows()
{
CommandService service = new(new LoggerContainer<BunkumContext>());

LoggerContainer<BunkumContext> logger = new();
CommandService service = new(logger, new MatchService(logger));

Assert.That(() => service.ParseCommand("/ test"), Throws.Exception);
}
}

0 comments on commit d597a6f

Please sign in to comment.