using System.Threading.Tasks;
using Impostor.Api.Innersloth;
using Impostor.Api.Innersloth.Data;
+using Impostor.Api.Innersloth.Net;
using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
int HostId { get; }
+ IClientPlayer GetClientPlayer(int clientId);
+
+ T FindObjectByNetId<T>(uint netId)
+ where T : InnerNetObject;
+
/// <summary>
/// Send the message to all players.
/// </summary>
-using Impostor.Api.Innersloth.Net;
+using Impostor.Api.Games;
+using Impostor.Api.Innersloth.Net;
using Impostor.Api.Innersloth.Net.Objects;
namespace Impostor.Api.Innersloth.Data
/// </summary>
public class GameNet
{
- public InnerGameData GameData { get; internal set; }
+ private readonly IGame _game;
+
+ public GameNet(IGame game)
+ {
+ _game = game;
+ }
+
+ public InnerGameData GameData { get; private set; }
internal void OnSpawn(InnerNetObject netObj)
{
{
GameData = data;
}
+ else if (netObj is InnerPlayerControl control)
+ {
+ // Hook up InnerPlayerControl <-> IClientPlayer.
+ var clientPlayer = _game.GetClientPlayer(control.OwnerId);
+ if (clientPlayer != null)
+ {
+ clientPlayer.Character = control;
+ }
+
+ // Hook up InnerPlayerControl <-> InnerPlayerControl.PlayerInfo.
+ control.PlayerInfo = GameData.GetPlayerById(control.PlayerId);
+
+ if (control.PlayerInfo == null)
+ {
+ GameData.AddPlayer(control);
+ }
+ }
}
internal void OnDestroy(InnerNetObject netObj)
{
GameData = null;
}
+ else if (netObj is InnerPlayerControl control)
+ {
+ // Remove InnerPlayerControl <-> IClientPlayer.
+ var clientPlayer = _game.GetClientPlayer(control.OwnerId);
+ if (clientPlayer != null)
+ {
+ clientPlayer.Character = null;
+ }
+ }
}
}
}
\ No newline at end of file
-using Impostor.Api.Net.Messages;
+using Impostor.Api.Net;
+using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth.Net
{
public SpawnFlags SpawnFlags { get; internal set; }
- public abstract void HandleRpc(byte callId, IMessageReader reader);
+ public abstract void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader);
public abstract bool Serialize(IMessageWriter writer, bool initialState);
- public abstract void Deserialize(IMessageReader reader, bool initialState);
+ public abstract void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState);
}
}
\ No newline at end of file
using System.Numerics;
+using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
using Microsoft.Extensions.Logging;
return new Vector2(XRange.Lerp(v1), YRange.Lerp(v2));
}
- public override void HandleRpc(byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
{
if (callId == 0)
{
return true;
}
- public override void Deserialize(IMessageReader reader, bool initialState)
+ public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
{
var sequenceId = reader.ReadUInt16();
-using Impostor.Api.Net.Messages;
+using Impostor.Api.Net;
+using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth.Net.Objects.Components
{
public class InnerPlayerPhysics : InnerNetObject
{
- public override void HandleRpc(byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
throw new System.NotImplementedException();
}
- public override void Deserialize(IMessageReader reader, bool initialState)
+ public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
using System;
using System.Collections.Generic;
+using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth.Net.Objects.Components
_votes = new Dictionary<int, int[]>();
}
- public override void HandleRpc(byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
{
throw new NotImplementedException();
}
throw new NotImplementedException();
}
- public override void Deserialize(IMessageReader reader, bool initialState)
+ public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
{
var votes = _votes;
var unknown = reader.ReadByte();
public byte PlayerId { get; }
- public string PlayerName { get; private set; }
+ public string PlayerName { get; internal set; }
- public byte ColorId { get; private set; }
+ public byte ColorId { get; internal set; }
- public uint HatId { get; private set; }
+ public uint HatId { get; internal set; }
- public uint PetId { get; private set; }
+ public uint PetId { get; internal set; }
- public uint SkinId { get; private set; }
+ public uint SkinId { get; internal set; }
- public bool Disconnected { get; private set; }
+ public bool Disconnected { get; internal set; }
- public bool IsImpostor { get; private set; }
+ public bool IsImpostor { get; internal set; }
public bool IsDead { get; private set; }
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using Impostor.Api.Games;
using Impostor.Api.Innersloth.Net.Objects.Components;
+using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth.Net.Objects
public partial class InnerGameData : InnerNetObject
{
private readonly IGame _game;
- private readonly List<PlayerInfo> _allPlayers;
+ private readonly ConcurrentDictionary<byte, PlayerInfo> _allPlayers;
public InnerGameData(IGame game)
{
_game = game;
- _allPlayers = new List<PlayerInfo>();
+ _allPlayers = new ConcurrentDictionary<byte, PlayerInfo>();
Components.Add(this);
Components.Add(new InnerVoteBanSystem());
public int PlayerCount => _allPlayers.Count;
- public IReadOnlyList<PlayerInfo> Players => _allPlayers;
+ public IReadOnlyDictionary<byte, PlayerInfo> Players => _allPlayers;
- public PlayerInfo GetPlayerById(byte id)
+ internal void AddPlayer(InnerPlayerControl control)
{
- foreach (var player in _allPlayers)
+ var playerId = control.PlayerId;
+ var playerInfo = new PlayerInfo(control.PlayerId);
+
+ if (_allPlayers.TryAdd(playerId, playerInfo))
{
- if (player.PlayerId == id)
- {
- return player;
- }
+ control.PlayerInfo = playerInfo;
}
+ }
- return null;
+ public PlayerInfo GetPlayerById(byte id)
+ {
+ return _allPlayers.TryGetValue(id, out var player) ? player : null;
}
- public override void HandleRpc(byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
{
throw new NotImplementedException();
}
throw new NotImplementedException();
}
- public override void Deserialize(IMessageReader reader, bool initialState)
+ public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
{
if (initialState)
{
for (var i = 0; i < num; i++)
{
var playerInfo = new PlayerInfo(reader.ReadByte());
+
playerInfo.Deserialize(reader);
- _allPlayers.Add(playerInfo);
+
+ if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo))
+ {
+ throw new ImpostorException("Failed to add player to InnerGameData.");
+ }
}
}
else
using Impostor.Api.Games;
+using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth.Net.Objects
Components.Add(this);
}
- public override void HandleRpc(byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
throw new System.NotImplementedException();
}
- public override void Deserialize(IMessageReader reader, bool initialState)
+ public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
using System;
+using System.Linq;
using Impostor.Api.Games;
using Impostor.Api.Innersloth.Data;
+using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth.Net.Objects
private void PopulateButtons(byte reporter)
{
- _playerStates = new PlayerVoteArea[_gameNet.GameData.PlayerCount];
-
- for (var i = 0; i < _playerStates.Length; i++)
- {
- var player = _gameNet.GameData.Players[i];
- var playerVoteArea = _playerStates[i] = new PlayerVoteArea(this, player.PlayerId);
-
- playerVoteArea.SetDead(player.PlayerId == reporter, player.Disconnected || player.IsDead);
- }
+ _playerStates = _gameNet.GameData.Players
+ .Select(x =>
+ {
+ var area = new PlayerVoteArea(this, x.Key);
+ area.SetDead(x.Value.PlayerId == reporter, x.Value.Disconnected || x.Value.IsDead);
+ return area;
+ })
+ .ToArray();
}
- public override void HandleRpc(byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
{
throw new NotImplementedException();
}
throw new NotImplementedException();
}
- public override void Deserialize(IMessageReader reader, bool initialState)
+ public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
{
if (initialState)
{
using System;
using Impostor.Api.Games;
using Impostor.Api.Innersloth.Net.Objects.Components;
+using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
using Microsoft.Extensions.DependencyInjection;
public byte PlayerId { get; private set; }
- public override void HandleRpc(byte callId, IMessageReader reader)
+ public InnerGameData.PlayerInfo PlayerInfo { get; internal set; }
+
+ public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
{
- throw new NotImplementedException();
+ switch (callId)
+ {
+ case 3:
+ {
+ var length = reader.ReadPackedInt32();
+
+ for (var i = 0; i < length; i++)
+ {
+ var playerId = reader.ReadByte();
+ var player = _game.GameNet.GameData.GetPlayerById(playerId);
+
+ player.IsImpostor = true;
+ }
+
+ break;
+ }
+
+ case 6:
+ {
+ PlayerInfo.PlayerName = reader.ReadString();
+ break;
+ }
+
+ default:
+ break;
+ }
}
public override bool Serialize(IMessageWriter writer, bool initialState)
throw new NotImplementedException();
}
- public override void Deserialize(IMessageReader reader, bool initialState)
+ public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
{
if (initialState)
{
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Impostor.Api.Games;
using Impostor.Api.Innersloth.Net.Objects.Systems;
using Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus;
+using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth.Net.Objects
_systems.Add(SystemTypes.Sabotage, new SabotageSystemType(new[]
{
- (IActivatable) _systems[SystemTypes.Comms],
- (IActivatable) _systems[SystemTypes.Reactor],
- (IActivatable) _systems[SystemTypes.LifeSupp],
- (IActivatable) _systems[SystemTypes.Electrical],
+ (IActivatable)_systems[SystemTypes.Comms],
+ (IActivatable)_systems[SystemTypes.Reactor],
+ (IActivatable)_systems[SystemTypes.LifeSupp],
+ (IActivatable)_systems[SystemTypes.Electrical],
}));
Components.Add(this);
}
- public override void HandleRpc(byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
{
- throw new System.NotImplementedException();
+ switch (callId)
+ {
+ case 27:
+ {
+ // Close doors.
+ if (!sender.Character.PlayerInfo.IsImpostor)
+ {
+ Console.WriteLine($"OOPS Fake Impostor: {sender.Character.PlayerInfo.PlayerName} did doors");
+ }
+
+ break;
+ }
+
+ case 28:
+ {
+ var systemType = (SystemTypes)reader.ReadByte();
+ var player = _game.FindObjectByNetId<InnerPlayerControl>(reader.ReadPackedUInt32());
+ var amount = reader.ReadByte();
+
+ if (systemType == SystemTypes.Sabotage && !player.PlayerInfo.IsImpostor)
+ {
+ Console.WriteLine($"OOPS Fake Impostor: {player.PlayerInfo.PlayerName} did {(SystemTypes) amount}");
+ }
+
+ break;
+ }
+ }
}
public override bool Serialize(IMessageWriter writer, bool initialState)
throw new System.NotImplementedException();
}
- public override void Deserialize(IMessageReader reader, bool initialState)
+ public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
{
if (initialState)
{
foreach (var systemType in SystemTypeHelpers.AllTypes)
{
// TODO: Not sure what is going on here, check.
- if ((count & 1 << (int) (systemType & (SystemTypes.ShipTasks | SystemTypes.Doors))) != 0L)
+ if ((count & 1 << (int)(systemType & (SystemTypes.ShipTasks | SystemTypes.Doors))) != 0L)
{
if (_systems.TryGetValue(systemType, out var system))
{
using System.Threading.Tasks;
using Impostor.Api.Games;
+using Impostor.Api.Innersloth.Net.Objects;
namespace Impostor.Api.Net
{
/// </summary>
LimboStates Limbo { get; set; }
+ InnerPlayerControl Character { get; set; }
+
ValueTask KickAsync();
ValueTask BanAsync();
using System.Threading.Tasks;
+using Impostor.Api.Innersloth.Net.Objects;
using Impostor.Api.Net;
namespace Impostor.Server.Net.State
/// <inheritdoc />
public LimboStates Limbo { get; set; }
+ // TODO: Correct visibility to set internal only.
+ public InnerPlayerControl Character { get; set; }
+
public bool IsHost => Game?.Host == this;
public string Scene { get; internal set; }
var netId = reader.ReadPackedUInt32();
if (_allObjectsFast.TryGetValue(netId, out var obj))
{
- obj.Deserialize(reader, false);
+ obj.Deserialize(sender, reader, false);
}
else
{
var netId = reader.ReadPackedUInt32();
if (_allObjectsFast.TryGetValue(netId, out var obj))
{
- // Console.WriteLine(reader.ReadByte());
- // obj.HandleRpc(reader.ReadByte(), reader);
+ // TODO: Remove try catch.
+ try
+ {
+ obj.HandleRpc(sender, reader.ReadByte(), reader);
+ }
+ catch (NotImplementedException)
+ {
+ }
}
else
{
var readerSub = reader.ReadMessage();
if (readerSub.Length > 0)
{
- obj.Deserialize(readerSub, true);
+ obj.Deserialize(sender, readerSub, true);
}
GameNet.OnSpawn(obj);
}
- if ((innerNetObject.SpawnFlags & SpawnFlags.IsClientCharacter) != SpawnFlags.None)
- {
- if (TryGetPlayer(ownerClientId, out var clientById))
- {
- _logger.LogTrace("Spawn character");
- }
- else
- {
- _logger.LogTrace("Spawn unowned character");
- }
- }
-
continue;
}
}
RemoveNetObject(obj);
- GameNet.OnSpawn(obj);
+ GameNet.OnDestroy(obj);
_logger.LogDebug("Destroyed InnerNetObject {0} ({1}), OwnerId {2}", obj.GetType().Name, netId, obj.OwnerId);
}
else
obj.NetId = uint.MaxValue;
}
+
+ public T FindObjectByNetId<T>(uint netId)
+ where T : InnerNetObject
+ {
+ if (_allObjectsFast.TryGetValue(netId, out var obj))
+ {
+ return (T) obj;
+ }
+
+ return null;
+ }
}
}
\ No newline at end of file
Code = code;
HostId = -1;
GameState = GameStates.NotStarted;
- GameNet = new GameNet();
+ GameNet = new GameNet(this);
Options = options;
_clientManager = clientManager;
_eventManager = eventManager;
return false;
}
+ public IClientPlayer GetClientPlayer(int clientId)
+ {
+ return _players.TryGetValue(clientId, out var clientPlayer) ? clientPlayer : null;
+ }
+
public ValueTask EndAsync()
{
return _gameManager.RemoveAsync(Code);