mirror of
https://github.com/Impostor/Impostor.git
synced 2026-10-19 15:51:42 +00:00
Merge Impostor.Http into core (#533)
This commit is contained in:
1 parent
c6121eed49
commit
5325a81cb6
26 files changed
+750
-118
No files matched your search
+2
-6
@@ -40,14 +40,10 @@ FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet:7.0
|
||||
WORKDIR /app
|
||||
COPY --from=build /app ./
|
||||
|
||||
# Add Impostor.Http as a default built-in plugin
|
||||
ADD https://github.com/Impostor/Impostor.Http/releases/download/v0.5.0/Impostor.Http.dll /app/builtin-plugins/
|
||||
# Make it listen to 0.0.0.0 to expose it to the outside world.
|
||||
ENV IMPOSTOR_HTTP_HttpServer__ListenIp=0.0.0.0
|
||||
# Make the HttpServer listen to 0.0.0.0 to expose it to the outside world.
|
||||
ENV IMPOSTOR_HttpServer__ListenIp=0.0.0.0
|
||||
# Override ASPNETCORE_URLS to stop warning.
|
||||
ENV ASPNETCORE_URLS=
|
||||
# Enable the built-in plugin folder. Use a high number to prevent conflicts with existing configurations
|
||||
ENV IMPOSTOR_PluginLoader__Paths__76=/app/builtin-plugins
|
||||
|
||||
EXPOSE 22023/tcp 22023/udp
|
||||
ENTRYPOINT ["./Impostor.Server"]
|
||||
@@ -23,5 +23,12 @@
|
||||
public const string VersionServerTooOld = "Your client is too new, please update your Impostor server to play.";
|
||||
|
||||
public const string VersionUnsupported = "Your client version is unsupported, please update your Game and/or Impostor server.";
|
||||
|
||||
private const string UpgradingDocsLink = "https://github.com/Impostor/Impostor/blob/master/docs/Upgrading.md";
|
||||
|
||||
public const string UdpMatchmakingUnsupported = $"""
|
||||
Sorry, UDP Matchmaking is no longer supported.
|
||||
See <link={UpgradingDocsLink}#impostor-190>Impostor documentation</link> on how to migrate to HTTP Matchmaking
|
||||
""";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace Impostor.Api.Config;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for HttpServer.
|
||||
/// </summary>
|
||||
public class HttpServerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of this config section.
|
||||
/// </summary>
|
||||
public const string Section = "HttpServer";
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IP address the HTTP Matchmaking server will listen on.
|
||||
/// </summary>
|
||||
/// Use "127.0.0.1" if you are running behind a reverse proxy or just testing locally.
|
||||
/// Use "0.0.0.0" if you are directly exposing this server to the internet (not recommended).
|
||||
public string ListenIp { get; set; } = "127.0.0.1";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the port the HTTP Matchmaking server will listen on.
|
||||
/// </summary>
|
||||
/// For port forwarding purposes, this is a TCP port.
|
||||
public ushort ListenPort { get; set; } = 22023;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using Impostor.Api.Games;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Impostor.Api.Http;
|
||||
|
||||
/// <summary>
|
||||
/// Register a method to filter listings on.
|
||||
/// </summary>
|
||||
public interface IListingFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Return a filter to filter listings on.
|
||||
/// </summary>
|
||||
/// <param name="context">HTTP Context of this request.</param>
|
||||
/// <returns>A function that looks at a game and returns true iff the connecting player is compatible with this game.</returns>
|
||||
Func<IGame, bool> GetFilter(HttpContext context);
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
namespace Impostor.Api.Plugins;
|
||||
|
||||
public interface IPluginHttpStartup : IPluginStartup
|
||||
{
|
||||
void ConfigureWebApplication(IApplicationBuilder builder);
|
||||
}
|
||||
@@ -8,6 +8,16 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Direct",
|
||||
"requested": "[7.0.0, )",
|
||||
@@ -34,6 +44,14 @@
|
||||
"StyleCop.Analyzers.Unstable": "1.2.0.435"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
@@ -64,6 +82,11 @@
|
||||
"type": "Transitive",
|
||||
"resolved": "1.2.0.435",
|
||||
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,23 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.0",
|
||||
@@ -523,6 +540,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Hazel.Abstractions": "[1.0.0, )",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
}
|
||||
@@ -530,7 +548,7 @@
|
||||
"impostor.server": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Api": "[1.7.3-dev, )",
|
||||
"Impostor.Api": "[1.8.4-dev, )",
|
||||
"Impostor.Hazel": "[1.0.0, )",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Hosting": "[7.0.0, )",
|
||||
|
||||
@@ -27,6 +27,23 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
@@ -78,10 +95,16 @@
|
||||
"resolved": "2.12.0",
|
||||
"contentHash": "xaiJLIdu6rYMKfQMYUZgTy8YK7SMZjB4Yk50C/u//Z4OsvxkUfSPJy4nknfvwAC34yr13q7kcyh4grbwhSxyZg=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g=="
|
||||
},
|
||||
"impostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Hazel.Abstractions": "[1.0.0, )",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
}
|
||||
@@ -89,7 +112,7 @@
|
||||
"impostor.client": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Api": "[1.7.3-dev, )",
|
||||
"Impostor.Api": "[1.8.4-dev, )",
|
||||
"Impostor.Hazel": "[1.0.0, )"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,23 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
@@ -70,10 +87,16 @@
|
||||
"resolved": "2.12.0",
|
||||
"contentHash": "xaiJLIdu6rYMKfQMYUZgTy8YK7SMZjB4Yk50C/u//Z4OsvxkUfSPJy4nknfvwAC34yr13q7kcyh4grbwhSxyZg=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g=="
|
||||
},
|
||||
"impostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Hazel.Abstractions": "[1.0.0, )",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,23 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
@@ -48,10 +65,16 @@
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g=="
|
||||
},
|
||||
"impostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Hazel.Abstractions": "[1.0.0, )",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,23 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
@@ -48,10 +65,16 @@
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g=="
|
||||
},
|
||||
"impostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Hazel.Abstractions": "[1.0.0, )",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Impostor.Api.Config;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Games.Managers;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Impostor.Server.Http;
|
||||
|
||||
/// <summary>
|
||||
/// This controller has method to get a list of public games, join by game and create new games.
|
||||
/// </summary>
|
||||
[Route("/api/games")]
|
||||
[ApiController]
|
||||
public sealed class GamesController : ControllerBase
|
||||
{
|
||||
private readonly IGameManager _gameManager;
|
||||
private readonly ListingManager _listingManager;
|
||||
private readonly HostServer _hostServer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GamesController"/> class.
|
||||
/// </summary>
|
||||
/// <param name="gameManager">GameManager containing a list of games.</param>
|
||||
/// <param name="listingManager">ListingManager responsible for filtering.</param>
|
||||
/// <param name="serverConfig">Impostor configuration section containing the public ip address of this server.</param>
|
||||
public GamesController(IGameManager gameManager, ListingManager listingManager, IOptions<ServerConfig> serverConfig)
|
||||
{
|
||||
_gameManager = gameManager;
|
||||
_listingManager = listingManager;
|
||||
var config = serverConfig.Value;
|
||||
_hostServer = HostServer.From(IPAddress.Parse(config.ResolvePublicIp()), config.PublicPort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of active games.
|
||||
/// </summary>
|
||||
/// <param name="mapId">Maps that are requested.</param>
|
||||
/// <param name="lang">Preferred chat language.</param>
|
||||
/// <param name="numImpostors">Amount of impostors. 0 is any.</param>
|
||||
/// <param name="authorization">Authorization header containing the matchmaking token.</param>
|
||||
/// <returns>An array of game listings.</returns>
|
||||
[HttpGet]
|
||||
public IActionResult Index(int mapId, GameKeywords lang, int numImpostors, [FromHeader] AuthenticationHeaderValue authorization)
|
||||
{
|
||||
if (authorization.Scheme != "Bearer" || authorization.Parameter == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var token = JsonSerializer.Deserialize<TokenController.Token>(Convert.FromBase64String(authorization.Parameter));
|
||||
if (token == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var clientVersion = new GameVersion(token.Content.ClientVersion);
|
||||
|
||||
var listings = _listingManager.FindListings(HttpContext, mapId, numImpostors, lang, clientVersion);
|
||||
return Ok(listings.Select(GameListing.From));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the address a certain game is hosted at.
|
||||
/// </summary>
|
||||
/// <param name="gameId">The id of the game that should be retrieved.</param>
|
||||
/// <returns>The server this game is hosted on.</returns>
|
||||
[HttpPost]
|
||||
public IActionResult Post(int gameId)
|
||||
{
|
||||
var code = new GameCode(gameId);
|
||||
var game = _gameManager.Find(code);
|
||||
|
||||
// If the game was not found, print an error message.
|
||||
if (game == null)
|
||||
{
|
||||
return NotFound(new MatchmakerResponse(new MatchmakerError(DisconnectReason.GameNotFound)));
|
||||
}
|
||||
|
||||
return Ok(HostServer.From(game.PublicIp));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the address to host a new game on.
|
||||
/// </summary>
|
||||
/// <returns>The address of this server.</returns>
|
||||
[HttpPut]
|
||||
public IActionResult Put()
|
||||
{
|
||||
return Ok(_hostServer);
|
||||
}
|
||||
|
||||
private static uint ConvertAddressToNumber(IPAddress address)
|
||||
{
|
||||
#pragma warning disable CS0618 // Among Us only supports IPv4
|
||||
return (uint)address.Address;
|
||||
#pragma warning restore CS0618
|
||||
}
|
||||
|
||||
private class HostServer
|
||||
{
|
||||
[JsonPropertyName("Ip")]
|
||||
public required long Ip { get; init; }
|
||||
|
||||
[JsonPropertyName("Port")]
|
||||
public required ushort Port { get; init; }
|
||||
|
||||
public static HostServer From(IPAddress ipAddress, ushort port)
|
||||
{
|
||||
return new HostServer
|
||||
{
|
||||
Ip = ConvertAddressToNumber(ipAddress),
|
||||
Port = port,
|
||||
};
|
||||
}
|
||||
|
||||
public static HostServer From(IPEndPoint endPoint)
|
||||
{
|
||||
return From(endPoint.Address, (ushort)endPoint.Port);
|
||||
}
|
||||
}
|
||||
|
||||
private class MatchmakerResponse
|
||||
{
|
||||
[SetsRequiredMembers]
|
||||
public MatchmakerResponse(MatchmakerError error)
|
||||
{
|
||||
Errors = new[] { error };
|
||||
}
|
||||
|
||||
[JsonPropertyName("Errors")]
|
||||
public required MatchmakerError[] Errors { get; init; }
|
||||
}
|
||||
|
||||
private class MatchmakerError
|
||||
{
|
||||
[SetsRequiredMembers]
|
||||
public MatchmakerError(DisconnectReason reason)
|
||||
{
|
||||
Reason = reason;
|
||||
}
|
||||
|
||||
[JsonPropertyName("Reason")]
|
||||
public required DisconnectReason Reason { get; init; }
|
||||
}
|
||||
|
||||
private class GameListing
|
||||
{
|
||||
[JsonPropertyName("IP")]
|
||||
public required uint Ip { get; init; }
|
||||
|
||||
[JsonPropertyName("Port")]
|
||||
public required ushort Port { get; init; }
|
||||
|
||||
[JsonPropertyName("GameId")]
|
||||
public required int GameId { get; init; }
|
||||
|
||||
[JsonPropertyName("PlayerCount")]
|
||||
public required int PlayerCount { get; init; }
|
||||
|
||||
[JsonPropertyName("HostName")]
|
||||
public required string HostName { get; init; }
|
||||
|
||||
[JsonPropertyName("HostPlatformName")]
|
||||
public required string HostPlatformName { get; init; }
|
||||
|
||||
[JsonPropertyName("Platform")]
|
||||
public required Platforms Platform { get; init; }
|
||||
|
||||
[JsonPropertyName("Age")]
|
||||
public required int Age { get; init; }
|
||||
|
||||
[JsonPropertyName("MaxPlayers")]
|
||||
public required int MaxPlayers { get; init; }
|
||||
|
||||
[JsonPropertyName("NumImpostors")]
|
||||
public required int NumImpostors { get; init; }
|
||||
|
||||
[JsonPropertyName("MapId")]
|
||||
public required MapTypes MapId { get; init; }
|
||||
|
||||
[JsonPropertyName("Language")]
|
||||
public required GameKeywords Language { get; init; }
|
||||
|
||||
public static GameListing From(IGame game)
|
||||
{
|
||||
var platform = game.Host?.Client.PlatformSpecificData;
|
||||
|
||||
return new GameListing
|
||||
{
|
||||
Ip = ConvertAddressToNumber(game.PublicIp.Address),
|
||||
Port = (ushort)game.PublicIp.Port,
|
||||
GameId = game.Code,
|
||||
PlayerCount = game.PlayerCount,
|
||||
HostName = game.DisplayName ?? game.Host?.Client.Name ?? "Unknown host",
|
||||
HostPlatformName = platform?.PlatformName ?? string.Empty,
|
||||
Platform = platform?.Platform ?? Platforms.Unknown,
|
||||
Age = 0,
|
||||
MaxPlayers = game.Options.MaxPlayers,
|
||||
NumImpostors = game.Options.NumImpostors,
|
||||
MapId = game.Options.Map,
|
||||
Language = game.Options.Keywords,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Impostor.Api.Config;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Games.Managers;
|
||||
using Impostor.Api.Http;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net.Manager;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Impostor.Server.Http;
|
||||
|
||||
/// <summary>
|
||||
/// Perform game listing filtering.
|
||||
/// </summary>
|
||||
public sealed class ListingManager
|
||||
{
|
||||
private readonly IGameManager _gameManager;
|
||||
private readonly IEnumerable<IListingFilter> _listingFilters;
|
||||
private readonly ICompatibilityManager _compatibilityManager;
|
||||
private readonly CompatibilityConfig _compatibilityConfig;
|
||||
|
||||
public ListingManager(IGameManager gameManager, IEnumerable<IListingFilter> listingFilters, ICompatibilityManager compatibilityManager, IOptions<CompatibilityConfig> compatibilityConfig)
|
||||
{
|
||||
_gameManager = gameManager;
|
||||
_listingFilters = listingFilters;
|
||||
_compatibilityManager = compatibilityManager;
|
||||
_compatibilityConfig = compatibilityConfig.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find listings that match the requested settings.
|
||||
/// </summary>
|
||||
/// <param name="ctx">The context of this http request.</param>
|
||||
/// <param name="map">The selected maps.</param>
|
||||
/// <param name="impostorCount">The amount of impostors. 0 is any.</param>
|
||||
/// <param name="language">Chat language of the game.</param>
|
||||
/// <param name="gameVersion">Game version of the client.</param>
|
||||
/// <param name="maxListings">Maximum amount of games to return.</param>
|
||||
/// <returns>Listings that match the required criteria.</returns>
|
||||
public IEnumerable<IGame> FindListings(HttpContext ctx, int map, int impostorCount, GameKeywords language, GameVersion gameVersion, int maxListings = 10)
|
||||
{
|
||||
var resultCount = 0;
|
||||
|
||||
var filters = _listingFilters.Select(f => f.GetFilter(ctx)).ToArray();
|
||||
|
||||
var compatibleGames = new List<IGame>();
|
||||
|
||||
// We want to add 2 types of games
|
||||
// 1. Desireable games that the player wants to play (right language, right map, desired impostor amount)
|
||||
// 2. Failing that, display compatible games the player could join (public games with spots available)
|
||||
|
||||
// .Where filters out games that can't be joined.
|
||||
foreach (var game in this._gameManager.Games)
|
||||
{
|
||||
if (!game.IsPublic || game.GameState != GameStates.NotStarted || game.PlayerCount >= game.Options.MaxPlayers)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_compatibilityConfig.AllowVersionMixing &&
|
||||
game.Host != null &&
|
||||
_compatibilityManager.CanJoinGame(game.Host.Client.GameVersion, gameVersion) != GameJoinError.None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!filters.All(filter => filter(game)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsGameDesired(game, map, impostorCount, language))
|
||||
{
|
||||
// Add to result immediately.
|
||||
yield return game;
|
||||
|
||||
// Break out if we have enough.
|
||||
if (++resultCount == maxListings)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add to result to add afterwards. Adding is pointless if we already have enough compatible games to fill the list
|
||||
if (compatibleGames.Count < (maxListings - resultCount))
|
||||
{
|
||||
compatibleGames.Add(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var game in compatibleGames)
|
||||
{
|
||||
yield return game;
|
||||
|
||||
if (++resultCount == maxListings)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsGameDesired(IGame game, int map, int impostorCount, GameKeywords language)
|
||||
{
|
||||
if ((map & (1 << (int)game.Options.Map)) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (language != game.Options.Keywords)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (impostorCount != 0 && game.Options.NumImpostors != impostorCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Impostor.Server.Http;
|
||||
|
||||
/// <summary>
|
||||
/// This controller has a method to get an auth token.
|
||||
/// </summary>
|
||||
[Route("/api/user")]
|
||||
[ApiController]
|
||||
public sealed class TokenController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Get an authentication token.
|
||||
/// </summary>
|
||||
/// <param name="request">Token parameters that need to be put into the token.</param>
|
||||
/// <returns>A bare minimum authentication token that the client will accept.</returns>
|
||||
[HttpPost]
|
||||
public IActionResult GetToken([FromBody] TokenRequest request)
|
||||
{
|
||||
var token = new Token
|
||||
{
|
||||
Content = new TokenPayload
|
||||
{
|
||||
ProductUserId = request.ProductUserId,
|
||||
ClientVersion = request.ClientVersion,
|
||||
},
|
||||
Hash = "impostor_was_here",
|
||||
};
|
||||
|
||||
// Wrap into a Base64 sandwich
|
||||
var serialized = JsonSerializer.SerializeToUtf8Bytes(token);
|
||||
return this.Ok(Convert.ToBase64String(serialized));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Body of the token request endpoint.
|
||||
/// </summary>
|
||||
public class TokenRequest
|
||||
{
|
||||
[JsonPropertyName("Puid")]
|
||||
public required string ProductUserId { get; init; }
|
||||
|
||||
[JsonPropertyName("Username")]
|
||||
public required string Username { get; init; }
|
||||
|
||||
[JsonPropertyName("ClientVersion")]
|
||||
public required int ClientVersion { get; init; }
|
||||
|
||||
[JsonPropertyName("Language")]
|
||||
public required Language Language { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Token that is returned to the user with a "signature".
|
||||
/// </summary>
|
||||
public sealed class Token
|
||||
{
|
||||
[JsonPropertyName("Content")]
|
||||
public required TokenPayload Content { get; init; }
|
||||
|
||||
[JsonPropertyName("Hash")]
|
||||
public required string Hash { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Actual token contents.
|
||||
/// </summary>
|
||||
public sealed class TokenPayload
|
||||
{
|
||||
private static readonly DateTime DefaultExpiryDate = new(2012, 12, 21);
|
||||
|
||||
[JsonPropertyName("Puid")]
|
||||
public required string ProductUserId { get; init; }
|
||||
|
||||
[JsonPropertyName("ClientVersion")]
|
||||
public required int ClientVersion { get; init; }
|
||||
|
||||
[JsonPropertyName("ExpiresAt")]
|
||||
public DateTime ExpiresAt { get; init; } = DefaultExpiryDate;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -30,28 +30,10 @@
|
||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.435">
|
||||
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.507">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="config.json">
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Include="config.*.json">
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Include="config-full.json">
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -5,7 +5,6 @@ using Impostor.Api;
|
||||
using Impostor.Api.Config;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Innersloth.GameOptions;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Custom;
|
||||
using Impostor.Api.Net.Messages;
|
||||
@@ -260,9 +259,8 @@ namespace Impostor.Server.Net
|
||||
|
||||
case MessageFlags.GetGameListV2:
|
||||
{
|
||||
Message16GetGameListC2S.Deserialize(reader, out var options, out _, out _, out var filterOptions);
|
||||
await OnRequestGameListAsync(options, filterOptions);
|
||||
break;
|
||||
await DisconnectAsync(DisconnectReason.Custom, DisconnectMessages.UdpMatchmakingUnsupported);
|
||||
return;
|
||||
}
|
||||
|
||||
case MessageFlags.SetActivePodType:
|
||||
@@ -352,22 +350,6 @@ namespace Impostor.Server.Net
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the connected client requests the game listing.
|
||||
/// </summary>
|
||||
/// <param name="options">Options specific to the game mode. At this moment, the client can only specify the map, impostor count and chat language.</param>
|
||||
/// <param name="filterOptions">Filter options not specific to the game mode.</param>
|
||||
private ValueTask OnRequestGameListAsync(IGameOptions options, GameFilterOptions filterOptions)
|
||||
{
|
||||
using var message = MessageWriter.Get(MessageType.Reliable);
|
||||
|
||||
var games = _gameManager.FindListings((MapFlags)options.Map, options.NumImpostors, options.Keywords, this.GameVersion, filterOptions.FilterTags);
|
||||
|
||||
Message16GetGameListS2C.Serialize(message, games);
|
||||
|
||||
return Connection.SendAsync(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the connected client requests the PlatformSpecificData.
|
||||
/// </summary>
|
||||
|
||||
@@ -61,56 +61,6 @@ namespace Impostor.Server.Net.Manager
|
||||
return game;
|
||||
}
|
||||
|
||||
public IEnumerable<Game> FindListings(
|
||||
MapFlags map,
|
||||
int impostorCount,
|
||||
GameKeywords language,
|
||||
GameVersion gameVersion,
|
||||
HashSet<string> filterTags,
|
||||
int count = 10)
|
||||
{
|
||||
var results = 0;
|
||||
|
||||
// Find games that have not started yet.
|
||||
foreach (var (_, game) in _games.Where(x =>
|
||||
x.Value.IsPublic &&
|
||||
x.Value.GameState == GameStates.NotStarted &&
|
||||
x.Value.PlayerCount < x.Value.Options.MaxPlayers &&
|
||||
(_compatibilityConfig.AllowVersionMixing || x.Value.Host == null ||
|
||||
this._compatibilityManager.CanJoinGame(x.Value.Host.Client.GameVersion, gameVersion) == GameJoinError.None)))
|
||||
{
|
||||
// Check for options.
|
||||
if (!map.HasFlag((MapFlags)(1 << (byte)game.Options.Map)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!language.HasFlag(game.Options.Keywords))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (impostorCount != 0 && game.Options.NumImpostors != impostorCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!game.FilterOptions.FilterTags.SetEquals(filterTags))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add to result.
|
||||
yield return game;
|
||||
|
||||
// Break out if we have enough.
|
||||
if (++results == count)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask RemoveAsync(GameCode gameCode)
|
||||
{
|
||||
if (_games.TryGetValue(gameCode, out var game) && game.PlayerCount > 0)
|
||||
|
||||
@@ -27,19 +27,6 @@ namespace Impostor.Server.Plugins
|
||||
CheckPaths(pluginPaths);
|
||||
CheckPaths(libraryPaths);
|
||||
|
||||
// Add library path for ASP.NET Core. This is useful for plugins that depend on ASP.NET Core,
|
||||
// like Impostor.Http. The path contains the .NET version number, so it changes regularly.
|
||||
var aspNetPath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
|
||||
.Replace("Microsoft.NETCore.App", "Microsoft.AspNetCore.App");
|
||||
if (Directory.Exists(aspNetPath))
|
||||
{
|
||||
libraryPaths.Add(aspNetPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Information("ASP.NET Core not installed, this may cause issues if you have plugins that depend on it");
|
||||
}
|
||||
|
||||
var rootFolder = Directory.GetCurrentDirectory();
|
||||
|
||||
pluginPaths.Add(Path.Combine(rootFolder, "plugins"));
|
||||
@@ -126,7 +113,8 @@ namespace Impostor.Server.Plugins
|
||||
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
services.AddHostedService(provider => ActivatorUtilities.CreateInstance<PluginLoaderService>(provider, orderedPlugins));
|
||||
services.AddSingleton<PluginLoaderService>(provider => ActivatorUtilities.CreateInstance<PluginLoaderService>(provider, orderedPlugins));
|
||||
services.AddSingleton<IHostedService>(p => p.GetRequiredService<PluginLoaderService>());
|
||||
|
||||
foreach (var plugin in orderedPlugins)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace Impostor.Server.Plugins
|
||||
_plugins = plugins;
|
||||
}
|
||||
|
||||
public IReadOnlyList<PluginInformation> Plugins => _plugins;
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Loading plugins.");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using Impostor.Api.Config;
|
||||
@@ -9,9 +10,11 @@ using Impostor.Api.Games;
|
||||
using Impostor.Api.Games.Managers;
|
||||
using Impostor.Api.Net.Custom;
|
||||
using Impostor.Api.Net.Manager;
|
||||
using Impostor.Api.Plugins;
|
||||
using Impostor.Api.Utils;
|
||||
using Impostor.Hazel.Extensions;
|
||||
using Impostor.Server.Events;
|
||||
using Impostor.Server.Http;
|
||||
using Impostor.Server.Net;
|
||||
using Impostor.Server.Net.Custom;
|
||||
using Impostor.Server.Net.Factories;
|
||||
@@ -20,6 +23,9 @@ using Impostor.Server.Net.Messages;
|
||||
using Impostor.Server.Plugins;
|
||||
using Impostor.Server.Recorder;
|
||||
using Impostor.Server.Utils;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
@@ -73,8 +79,10 @@ namespace Impostor.Server
|
||||
var configuration = CreateConfiguration(args);
|
||||
var pluginConfig = configuration.GetSection("PluginLoader")
|
||||
.Get<PluginConfig>() ?? new PluginConfig();
|
||||
var httpConfig = configuration.GetSection(HttpServerConfig.Section)
|
||||
.Get<HttpServerConfig>() ?? new HttpServerConfig();
|
||||
|
||||
return Host.CreateDefaultBuilder(args)
|
||||
var hostBuilder = Host.CreateDefaultBuilder(args)
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
#if DEBUG
|
||||
.UseEnvironment(Environment.GetEnvironmentVariable("IMPOSTOR_ENV") ?? "Development")
|
||||
@@ -100,6 +108,7 @@ namespace Impostor.Server
|
||||
services.Configure<CompatibilityConfig>(host.Configuration.GetSection(CompatibilityConfig.Section));
|
||||
services.Configure<ServerConfig>(host.Configuration.GetSection(ServerConfig.Section));
|
||||
services.Configure<TimeoutConfig>(host.Configuration.GetSection(TimeoutConfig.Section));
|
||||
services.Configure<HttpServerConfig>(host.Configuration.GetSection(HttpServerConfig.Section));
|
||||
|
||||
services.AddSingleton<ICompatibilityManager, CompatibilityManager>();
|
||||
services.AddSingleton<ClientManager>();
|
||||
@@ -126,6 +135,7 @@ namespace Impostor.Server
|
||||
|
||||
services.AddSingleton<GameManager>();
|
||||
services.AddSingleton<IGameManager>(p => p.GetRequiredService<GameManager>());
|
||||
services.AddSingleton<ListingManager>();
|
||||
|
||||
services.AddEventPools();
|
||||
services.AddHazel();
|
||||
@@ -180,6 +190,7 @@ namespace Impostor.Server
|
||||
#else
|
||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
|
||||
#endif
|
||||
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
|
||||
.Enrich.FromLogContext()
|
||||
.WriteTo.Console()
|
||||
.ReadFrom.Configuration(context.Configuration, ConfigurationAssemblySource.AlwaysScanDllFiles);
|
||||
@@ -188,6 +199,46 @@ namespace Impostor.Server
|
||||
})
|
||||
.UseConsoleLifetime()
|
||||
.UsePluginLoader(pluginConfig);
|
||||
|
||||
if (httpConfig.Enabled)
|
||||
{
|
||||
hostBuilder.ConfigureWebHostDefaults(builder =>
|
||||
{
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
services.AddControllers();
|
||||
});
|
||||
|
||||
builder.Configure(app =>
|
||||
{
|
||||
var pluginLoaderService = app.ApplicationServices.GetRequiredService<PluginLoaderService>();
|
||||
foreach (var pluginInformation in pluginLoaderService.Plugins)
|
||||
{
|
||||
if (pluginInformation.Startup is IPluginHttpStartup httpStartup)
|
||||
{
|
||||
httpStartup.ConfigureWebApplication(app);
|
||||
}
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
});
|
||||
|
||||
builder.ConfigureKestrel(serverOptions =>
|
||||
{
|
||||
serverOptions.Listen(IPAddress.Parse(httpConfig.ListenIp), httpConfig.ListenPort, listenOptions =>
|
||||
{
|
||||
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return hostBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,11 @@
|
||||
"ListenIp": "0.0.0.0",
|
||||
"ListenPort": 22023
|
||||
},
|
||||
"HttpServer": {
|
||||
"Enabled": true,
|
||||
"ListenIp": "127.0.0.1",
|
||||
"ListenPort": 22023
|
||||
},
|
||||
"AntiCheat": {
|
||||
"Enabled": true,
|
||||
"BanIpFromGame": true
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
"ListenIp": "0.0.0.0",
|
||||
"ListenPort": 22023
|
||||
},
|
||||
"HttpServer": {
|
||||
"Enabled": true,
|
||||
"ListenIp": "127.0.0.1",
|
||||
"ListenPort": 22023
|
||||
},
|
||||
"AntiCheat": {
|
||||
"Enabled": true,
|
||||
"BanIpFromGame": true
|
||||
|
||||
@@ -90,15 +90,32 @@
|
||||
},
|
||||
"StyleCop.Analyzers.Unstable": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.2.0.435, )",
|
||||
"resolved": "1.2.0.435",
|
||||
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
|
||||
"requested": "[1.2.0.507, )",
|
||||
"resolved": "1.2.0.507",
|
||||
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
|
||||
},
|
||||
"Impostor.Hazel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
@@ -367,6 +384,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Hazel.Abstractions": "[1.0.0, )",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
}
|
||||
|
||||
@@ -61,6 +61,23 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.CodeCoverage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.4.1",
|
||||
@@ -1398,6 +1415,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Hazel.Abstractions": "[1.0.0, )",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
}
|
||||
@@ -1405,7 +1423,7 @@
|
||||
"impostor.server": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Api": "[1.7.3-dev, )",
|
||||
"Impostor.Api": "[1.8.4-dev, )",
|
||||
"Impostor.Hazel": "[1.0.0, )",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Hosting": "[7.0.0, )",
|
||||
|
||||
@@ -27,6 +27,23 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "x56AEsY5fKU2Z5O7ZrzEqKfr62kq/C05Aevcciwz5yMfOQlpwuFI1awgNGJsoe+bcx+XnFc3+l+eadtY72aZsg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
@@ -355,6 +372,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Hazel.Abstractions": "[1.0.0, )",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[7.0.0, )"
|
||||
}
|
||||
@@ -362,7 +380,7 @@
|
||||
"impostor.server": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Api": "[1.7.3-dev, )",
|
||||
"Impostor.Api": "[1.8.4-dev, )",
|
||||
"Impostor.Hazel": "[1.0.0, )",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "[7.0.0, )",
|
||||
"Microsoft.Extensions.Hosting": "[7.0.0, )",
|
||||
|
||||
Reference in new issue
Block a user