Merge pull request #683 from Impostor/feature/16.0.0

Add support for 16.0.0
This commit is contained in:
miniduikboot authored and GitHub committed 2025-04-03 21:31:35 +02:00
commit da8353655d
7 files changed
+137 -3

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>11</LangVersion>
<VersionPrefix>1.10.2</VersionPrefix>
<VersionPrefix>1.10.3</VersionPrefix>
<VersionSuffix>dev</VersionSuffix>
<EnforceCodeStyleInBuild Condition="$(MSBuildProjectName)!='Hazel'">true</EnforceCodeStyleInBuild>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
@@ -0,0 +1,14 @@
namespace Impostor.Api.Innersloth.GameOptions;
// TODO: generate this enum based on game data
/// <summary>
/// Tag that can be added to indicate the expected skill level of players in this lobby.
/// </summary>
public enum GameTags
{
None = 0,
Beginner = 1,
Intermediate = 2,
Expert = 3,
}
@@ -2,7 +2,7 @@ namespace Impostor.Api.Innersloth.GameOptions;
public class HideNSeekGameOptions : IGameOptions
{
public const int LatestVersion = 8;
public const int LatestVersion = 9;
public HideNSeekGameOptions(byte version = LatestVersion)
{
@@ -93,6 +93,11 @@ public class HideNSeekGameOptions : IGameOptions
public float MaxPingTime { get; set; } = 6f;
/// <summary>
/// Gets or sets the experience level of people in the lobby: Beginner, Intermediate or Expert.
/// </summary>
public GameTags Tag { get; set; } = 0;
public static HideNSeekGameOptions Deserialize(IMessageReader reader, byte version)
{
var options = new HideNSeekGameOptions(version);
@@ -133,6 +138,11 @@ public class HideNSeekGameOptions : IGameOptions
MaxPingTime = reader.ReadSingle();
CrewmateTimeInVent = reader.ReadSingle();
if (Version >= 9)
{
Tag = (GameTags)reader.ReadByte();
}
if (Version > LatestVersion)
{
IGameOptions.ThrowUnknownVersion<HideNSeekGameOptions>(Version);
@@ -172,6 +182,11 @@ public class HideNSeekGameOptions : IGameOptions
writer.Write(MaxPingTime);
writer.Write(CrewmateTimeInVent);
if (Version >= 9)
{
writer.Write((byte)Tag);
}
if (Version > LatestVersion)
{
IGameOptions.ThrowUnknownVersion<HideNSeekGameOptions>(Version);
@@ -4,7 +4,7 @@ namespace Impostor.Api.Innersloth.GameOptions;
public class NormalGameOptions : IGameOptions
{
public const int LatestVersion = 8;
public const int LatestVersion = 9;
public NormalGameOptions(byte version = LatestVersion)
{
@@ -128,6 +128,11 @@ public class NormalGameOptions : IGameOptions
/// </summary>
public TaskBarUpdate TaskBarUpdate { get; set; } = TaskBarUpdate.Always;
/// <summary>
/// Gets or sets the experience level of people in the lobby: Beginner, Intermediate or Expert.
/// </summary>
public GameTags Tag { get; set; } = 0;
public RoleOptionsCollection RoleOptions { get; set; }
public static NormalGameOptions Deserialize(IMessageReader reader, byte version)
@@ -173,6 +178,11 @@ public class NormalGameOptions : IGameOptions
AnonymousVotes = reader.ReadBoolean();
TaskBarUpdate = (TaskBarUpdate)reader.ReadByte();
if (Version >= 9)
{
Tag = (GameTags)reader.ReadByte();
}
RoleOptions.Deserialize(reader);
if (Version > LatestVersion)
@@ -217,6 +227,11 @@ public class NormalGameOptions : IGameOptions
writer.Write(AnonymousVotes);
writer.Write((byte)TaskBarUpdate);
if (Version >= 9)
{
writer.Write((byte)Tag);
}
RoleOptions.Serialize(writer);
if (Version > LatestVersion)
@@ -0,0 +1,24 @@
using System;
using Impostor.Api.Innersloth.GameOptions;
using Impostor.Hazel;
namespace Impostor.Server.Extensions;
public static class IGameOptionsExtensions
{
public static byte[] ToBytes(this IGameOptions gameOptions)
{
using var writer = MessageWriter.Get(MessageType.Unreliable);
writer.Write(gameOptions.Version);
writer.StartMessage(0);
writer.Write((byte)gameOptions.GameMode);
gameOptions.Serialize(writer);
writer.EndMessage();
return writer.ToByteArray(false);
}
public static string ToBase64String(this IGameOptions gameOptions)
{
return Convert.ToBase64String(gameOptions.ToBytes());
}
}
@@ -9,6 +9,7 @@ using Impostor.Api.Config;
using Impostor.Api.Games;
using Impostor.Api.Games.Managers;
using Impostor.Api.Innersloth;
using Impostor.Server.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
@@ -50,6 +51,7 @@ public sealed class GamesController : ControllerBase
[HttpGet]
public IActionResult Index(int mapId, GameKeywords lang, int numImpostors, [FromHeader] AuthenticationHeaderValue authorization)
{
// NOTE: this method is no longer used by Among Us 16.0.0 and is only kept for backwards compatibility
if (authorization.Scheme != "Bearer" || authorization.Parameter == null)
{
return BadRequest();
@@ -75,6 +77,7 @@ public sealed class GamesController : ControllerBase
[HttpPost]
public IActionResult Post(int gameId)
{
// NOTE: this method is no longer used by Among Us 16.0.0 and is only kept for backwards compatibility
var code = new GameCode(gameId);
var game = _gameManager.Find(code);
@@ -97,6 +100,38 @@ public sealed class GamesController : ControllerBase
return Ok(_hostServer);
}
[HttpGet("{gameId}")]
public IActionResult Show([FromRoute] 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 FindGameByCodeResponse(new MatchmakerError(DisconnectReason.GameNotFound)));
}
return Ok(new FindGameByCodeResponse(GameListing.From(game)));
}
[HttpGet("filtered")]
public IActionResult ShowFilteredLobbies()
{
// TODO: implement this stub
var response = new
{
games = Array.Empty<GameListing>(),
metadata = new
{
allGamesCount = _gameManager.Games.Count(),
matchingGamesCount = 0,
},
};
return Ok(response);
}
private static uint ConvertAddressToNumber(IPAddress address)
{
#pragma warning disable CS0618 // Among Us only supports IPv4
@@ -151,6 +186,21 @@ public sealed class GamesController : ControllerBase
public required DisconnectReason Reason { get; init; }
}
private class FindGameByCodeResponse
{
[SetsRequiredMembers]
public FindGameByCodeResponse(MatchmakerError error) => (Errors, Game) = (new[] { error }, null);
[SetsRequiredMembers]
public FindGameByCodeResponse(GameListing game) => (Errors, Game) = (null, game);
[JsonPropertyName("Errors")]
public required MatchmakerError[]? Errors { get; init; }
[JsonPropertyName("Game")]
public required GameListing? Game { get; init; }
}
private class GameListing
{
[JsonPropertyName("IP")]
@@ -168,12 +218,18 @@ public sealed class GamesController : ControllerBase
[JsonPropertyName("HostName")]
public required string HostName { get; init; }
[JsonPropertyName("TrueHostName")]
public required string TrueHostName { get; init; }
[JsonPropertyName("HostPlatformName")]
public required string HostPlatformName { get; init; }
[JsonPropertyName("Platform")]
public required Platforms Platform { get; init; }
[JsonPropertyName("QuickChat")]
public required QuickChatModes QuickChat { get; init; }
[JsonPropertyName("Age")]
public required int Age { get; init; }
@@ -189,6 +245,9 @@ public sealed class GamesController : ControllerBase
[JsonPropertyName("Language")]
public required GameKeywords Language { get; init; }
[JsonPropertyName("Options")]
public required string Options { get; init; }
public static GameListing From(IGame game)
{
var platform = game.Host?.Client.PlatformSpecificData;
@@ -200,13 +259,16 @@ public sealed class GamesController : ControllerBase
GameId = game.Code,
PlayerCount = game.PlayerCount,
HostName = game.DisplayName ?? game.Host?.Client.Name ?? "Unknown host",
TrueHostName = game.DisplayName ?? game.Host?.Client.Name ?? "Unknown host",
HostPlatformName = platform?.PlatformName ?? string.Empty,
Platform = platform?.Platform ?? Platforms.Unknown,
QuickChat = game.Host?.Client.ChatMode ?? QuickChatModes.QuickChatOnly,
Age = 0,
MaxPlayers = game.Options.MaxPlayers,
NumImpostors = game.Options.NumImpostors,
MapId = game.Options.Map,
Language = game.Options.Keywords,
Options = game.Options.ToBase64String(),
};
}
}
@@ -22,6 +22,10 @@ internal class CompatibilityManager : ICompatibilityManager
new GameVersion(2024, 4, 2), // 2024.9.4
new GameVersion(2024, 8, 10), // 2024.10.29
},
new[]
{
new GameVersion(2024, 8, 11), // 16.0.0 (2025-03-25)
},
};
private readonly List<CompatibilityGroup> _compatibilityGroups = new();