Demote InnerGameData, promote InnerPlayerInfo

In 2024.6.18 Innersloth promoted PlayerInfo to its own network object, and gave it to the server. InnerGameData is now a container that holds these players. This commit implements the changes necessary to handle these separate PlayerInfo network objects.
This commit is contained in:
miniduikboot committed 2024-08-20 21:41:38 +02:00
1 parent 615469c6c8
commit c43fdd2a69
7 files changed
+106 -142

No files matched your search

@@ -1,6 +1,6 @@
namespace Impostor.Api.Net.Inner.Objects
{
public interface IInnerGameData : IInnerNetObject
public interface IInnerGameData
{
}
}
@@ -1,36 +1,12 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Impostor.Api;
using Impostor.Api.Events.Managers;
using Impostor.Api.Net;
using Impostor.Api.Net.Custom;
using Impostor.Api.Net.Inner;
using Impostor.Api.Net.Inner.Objects;
using Impostor.Api.Net.Messages.Rpcs;
using Impostor.Server.Net.Inner.Objects.Components;
using Impostor.Server.Net.State;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Impostor.Server.Net.Inner.Objects
{
internal partial class InnerGameData : InnerNetObject, IInnerGameData
internal partial class InnerGameData : IInnerGameData
{
private readonly ILogger<InnerGameData> _logger;
private readonly IEventManager _eventManager;
private readonly ConcurrentDictionary<byte, InnerPlayerInfo> _allPlayers;
public InnerGameData(ICustomMessageManager<ICustomRpc> customMessageManager, Game game, ILogger<InnerGameData> logger, IEventManager eventManager, IServiceProvider serviceProvider) : base(customMessageManager, game)
{
_logger = logger;
_eventManager = eventManager;
_allPlayers = new ConcurrentDictionary<byte, InnerPlayerInfo>();
Components.Add(this);
Components.Add(ActivatorUtilities.CreateInstance<InnerVoteBanSystem>(serviceProvider, game));
}
private readonly ConcurrentDictionary<byte, InnerPlayerInfo> _allPlayers = new();
public int PlayerCount => _allPlayers.Count;
@@ -46,103 +22,14 @@ namespace Impostor.Server.Net.Inner.Objects
return _allPlayers.TryGetValue(id, out var player) ? player : null;
}
public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
internal bool AddPlayer(InnerPlayerInfo playerInfo)
{
throw new NotImplementedException();
return _allPlayers.TryAdd(playerInfo.PlayerId, playerInfo);
}
public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
internal void RemovePlayer(byte playerId)
{
if (!await ValidateHost(CheatContext.Deserialize, sender))
{
return;
}
while (reader.Position < reader.Length)
{
var inner = reader.ReadMessage();
var playerInfo = this.GetPlayerById(inner.Tag);
if (playerInfo != null)
{
playerInfo.Deserialize(inner);
}
else
{
playerInfo = new InnerPlayerInfo(inner.Tag);
playerInfo.Deserialize(inner);
if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo))
{
throw new ImpostorException("Failed to add player to InnerGameData.");
}
}
}
}
public override async ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
{
if (!await ValidateHost(call, sender))
{
return false;
}
switch (call)
{
case RpcCalls.SetTasks:
{
Rpc29SetTasks.Deserialize(reader, out var playerId, out var taskTypeIds);
SetTasks(playerId, taskTypeIds);
break;
}
default:
return await base.HandleRpcAsync(sender, target, call, reader);
}
return true;
}
internal InnerPlayerInfo? AddPlayer(InnerPlayerControl control)
{
var playerId = control.PlayerId;
var playerInfo = new InnerPlayerInfo(control.PlayerId);
if (_allPlayers.TryAdd(playerId, playerInfo))
{
return playerInfo;
}
return null;
}
internal void RemovePlayer(InnerPlayerControl control)
{
_allPlayers.TryRemove(control.PlayerInfo.PlayerId, out _);
}
private void SetTasks(byte playerId, ReadOnlyMemory<byte> taskTypeIds)
{
var player = GetPlayerById(playerId);
if (player == null)
{
_logger.LogTrace("Could not set tasks for playerId {0}.", playerId);
return;
}
if (player.Disconnected)
{
return;
}
player.Tasks = new List<TaskInfo>(taskTypeIds.Length);
var taskId = 0u;
foreach (var taskTypeId in taskTypeIds.Span)
{
var mapTasks = Game.GameNet!.ShipStatus?.Data.Tasks;
var taskType = (mapTasks != null && mapTasks.ContainsKey(taskTypeId)) ? mapTasks[taskTypeId] : null;
player.Tasks.Add(new TaskInfo(player, _eventManager, taskId++, taskType));
}
_allPlayers.TryRemove(playerId, out _);
}
}
}
@@ -3,7 +3,7 @@ using Impostor.Api.Net.Inner.Objects;
namespace Impostor.Server.Net.Inner.Objects
{
internal partial class InnerPlayerInfo : IInnerPlayerInfo
internal partial class InnerPlayerInfo : InnerNetObject, IInnerPlayerInfo
{
IEnumerable<ITaskInfo> IInnerPlayerInfo.Tasks => Tasks;
}
@@ -1,23 +1,33 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Impostor.Api.Games;
using Impostor.Api.Innersloth;
using Impostor.Api.Innersloth.Customization;
using Impostor.Api.Innersloth.GameOptions;
using Impostor.Api.Net;
using Impostor.Api.Net.Custom;
using Impostor.Api.Utils;
using Impostor.Server.Net.State;
using Microsoft.Extensions.Logging;
namespace Impostor.Server.Net.Inner.Objects
{
internal partial class InnerPlayerInfo
{
public InnerPlayerInfo(byte playerId)
private readonly ILogger<InnerPlayerInfo> _logger;
public InnerPlayerInfo(ICustomMessageManager<ICustomRpc> customMessageManager, Game game, ILogger<InnerPlayerInfo> logger) : base(customMessageManager, game)
{
PlayerId = playerId;
Components.Add(this);
_logger = logger;
}
public InnerPlayerControl? Controller { get; internal set; }
public byte PlayerId { get; }
public byte PlayerId { get; internal set; }
public int ClientId { get; internal set; }
public string PlayerName { get; internal set; } = string.Empty;
@@ -32,6 +42,8 @@ namespace Impostor.Server.Net.Inner.Objects
public RoleTypes? RoleType { get; internal set; }
public RoleTypes? RoleWhenAlive { get; internal set; }
public bool Disconnected { get; internal set; }
public bool IsImpostor => RoleType is RoleTypes.Impostor or RoleTypes.Shapeshifter or RoleTypes.ImpostorGhost;
@@ -71,13 +83,56 @@ namespace Impostor.Server.Net.Inner.Objects
}
}
public void Serialize(IMessageWriter writer)
public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
{
throw new NotImplementedException();
writer.Write(PlayerId);
writer.WritePacked(ClientId);
writer.Write((byte)Outfits.Count);
foreach (var outfit in Outfits)
{
writer.Write((byte)outfit.Key);
outfit.Value.Serialize(writer);
}
writer.WritePacked(PlayerLevel);
var flag = 0;
if (Disconnected)
{
flag = (byte)(flag | 1u);
}
if (IsDead)
{
flag = (byte)(flag | 4u);
}
writer.Write((byte)flag);
writer.Write((ushort)(RoleType ?? 0));
writer.Write(RoleWhenAlive.HasValue);
if (RoleWhenAlive.HasValue)
{
writer.Write((ushort)RoleWhenAlive.Value);
}
writer.Write((byte)Tasks.Count);
for (var i = 0; i < Tasks.Count; i++)
{
Tasks[i].Serialize(writer);
}
writer.Write(string.Empty); // FriendCode
writer.Write(string.Empty); // PUID
return new ValueTask<bool>(true);
}
public void Deserialize(IMessageReader reader)
public override ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
{
PlayerId = reader.ReadByte();
ClientId = reader.ReadPackedInt32();
Outfits.Clear();
var b = reader.ReadByte();
for (var i = 0; i < b; i++)
@@ -93,7 +148,15 @@ namespace Impostor.Server.Net.Inner.Objects
Disconnected = (flag & 1) != 0;
IsDead = (flag & 4) != 0;
_ = (RoleTypes)reader.ReadUInt16(); // ignore the RoleType here and only trust the SetRole rpc
// Ignore the RoleType here and only trust the SetRole RPC, as
// RoleType is not nullable in vanilla, while Impostor checks game
// starts based on assigned roles.
_ = (RoleTypes)reader.ReadUInt16();
if (reader.ReadBoolean())
{
RoleWhenAlive = (RoleTypes)reader.ReadUInt16();
}
var taskCount = reader.ReadByte();
@@ -106,6 +169,12 @@ namespace Impostor.Server.Net.Inner.Objects
{
Tasks[i].Deserialize(reader);
}
// Impostor doesn't expose fields that aren't properly validated
reader.ReadString(); // FriendCode
reader.ReadString(); // PUID
return ValueTask.CompletedTask;
}
}
}
+20 -12
View File
@@ -35,7 +35,6 @@ namespace Impostor.Server.Net.State
[0] = typeof(InnerSkeldShipStatus),
[1] = typeof(InnerMeetingHud),
[2] = typeof(InnerLobbyBehaviour),
[3] = typeof(InnerGameData),
[4] = typeof(InnerPlayerControl),
[5] = typeof(InnerMiraShipStatus),
[6] = typeof(InnerPolusShipStatus),
@@ -43,6 +42,8 @@ namespace Impostor.Server.Net.State
[8] = typeof(InnerAirshipStatus),
[9] = typeof(InnerHideAndSeekManager),
[10] = typeof(InnerNormalGameManager),
[11] = typeof(InnerPlayerInfo),
[12] = typeof(InnerVoteBanSystem),
[13] = typeof(InnerFungleShipStatus),
};
@@ -326,9 +327,17 @@ namespace Impostor.Server.Net.State
break;
}
case InnerGameData data:
case InnerPlayerInfo playerInfo:
{
GameNet.GameData = data;
if (!GameNet.GameData.AddPlayer(playerInfo))
{
_logger.LogWarning(
"Could not add PlayerInfo for playerId {PlayerId} with NetId {newId}, already have NetId {oldNetId}",
playerInfo.PlayerId,
playerInfo.NetId,
GameNet.GameData.GetPlayerById(playerInfo.PlayerId)?.NetId);
}
break;
}
@@ -358,7 +367,7 @@ namespace Impostor.Server.Net.State
}
// Hook up InnerPlayerControl <-> InnerPlayerControl.PlayerInfo.
var playerInfo = GameNet.GameData!.GetPlayerById(control.PlayerId) ?? GameNet.GameData.AddPlayer(control);
var playerInfo = GameNet.GameData.GetPlayerById(control.PlayerId);
if (playerInfo != null)
{
@@ -402,12 +411,6 @@ namespace Impostor.Server.Net.State
break;
}
case InnerGameData:
{
GameNet.GameData = null;
break;
}
case InnerVoteBanSystem:
{
GameNet.VoteBan = null;
@@ -420,13 +423,18 @@ namespace Impostor.Server.Net.State
break;
}
case InnerPlayerControl control:
case InnerPlayerInfo playerInfo:
{
if (GameState != GameStates.Started && GameState != GameStates.Starting)
{
GameNet.GameData?.RemovePlayer(control);
GameNet.GameData.RemovePlayer(playerInfo.PlayerId);
}
break;
}
case InnerPlayerControl control:
{
// Remove InnerPlayerControl <-> IClientPlayer.
if (TryGetPlayer(control.OwnerId, out var player))
{
+1 -1
View File
@@ -12,7 +12,7 @@ namespace Impostor.Server.Net.State
IInnerLobbyBehaviour? IGameNet.LobbyBehaviour => LobbyBehaviour;
IInnerGameData? IGameNet.GameData => GameData;
IInnerGameData IGameNet.GameData => GameData;
IInnerVoteBanSystem? IGameNet.VoteBan => VoteBan;
+1 -1
View File
@@ -11,7 +11,7 @@ namespace Impostor.Server.Net.State
public InnerLobbyBehaviour? LobbyBehaviour { get; internal set; }
public InnerGameData? GameData { get; internal set; }
public InnerGameData GameData { get; internal set; } = new();
public InnerVoteBanSystem? VoteBan { get; internal set; }