namespace Impostor.Api.Innersloth.Customization
{
- public enum ColorType : byte
+ public enum ColorType
{
Red = 0,
Blue = 1,
using Impostor.Api.Net.Inner.Objects;
+using Impostor.Api.Net.Inner.Objects.ShipStatus;
namespace Impostor.Api.Net.Inner
{
-namespace Impostor.Api.Net.Inner
+using Impostor.Api.Games;
+
+namespace Impostor.Api.Net.Inner
{
public interface IInnerNetObject
{
public uint NetId { get; }
public int OwnerId { get; }
+
+ public IGame Game { get; }
}
}
+++ /dev/null
-namespace Impostor.Api.Net.Inner.Objects
-{
- public interface IInnerShipStatus : IInnerNetObject
- {
- }
-}
--- /dev/null
+namespace Impostor.Api.Net.Inner.Objects.ShipStatus
+{
+ public interface IInnerAirshipStatus : IInnerShipStatus
+ {
+ }
+}
--- /dev/null
+namespace Impostor.Api.Net.Inner.Objects.ShipStatus
+{
+ public interface IInnerMiraShipStatus : IInnerShipStatus
+ {
+ }
+}
--- /dev/null
+namespace Impostor.Api.Net.Inner.Objects.ShipStatus
+{
+ public interface IInnerPolusShipStatus : IInnerShipStatus
+ {
+ }
+}
--- /dev/null
+namespace Impostor.Api.Net.Inner.Objects.ShipStatus
+{
+ public interface IInnerShipStatus : IInnerNetObject
+ {
+ }
+}
--- /dev/null
+namespace Impostor.Api.Net.Inner.Objects.ShipStatus
+{
+ public interface IInnerSkeldShipStatus : IInnerShipStatus
+ {
+ }
+}
CloseDoorsOfType = 27,
RepairSystem = 28,
SetTasks = 29,
- UpdateGameData = 30,
ClimbLadder = 31,
UsePlatform = 32,
}
using System.Threading.Tasks;
+using Impostor.Api.Games;
using Impostor.Api.Net;
using Impostor.Api.Net.Inner;
using Impostor.Api.Net.Messages;
{
private const int HostInheritId = -2;
+ protected InnerNetObject(Game game)
+ {
+ Game = game;
+ }
+
public uint NetId { get; internal set; }
public int OwnerId { get; internal set; }
+ public Game Game { get; }
+
+ IGame IInnerNetObject.Game => Game;
+
public SpawnFlags SpawnFlags { get; internal set; }
public bool IsOwnedBy(IClientPlayer player)
public abstract ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState);
public abstract ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader);
+
+ public virtual ValueTask OnSpawnAsync()
+ {
+ return default;
+ }
}
}
var minSid = (ushort)(_lastSequenceId + 5U);
// Snap in the server.
- await SnapToAsync(_game.GetClientPlayer(OwnerId)!, position, minSid);
+ await SnapToAsync(Game.GetClientPlayer(OwnerId)!, position, minSid);
// Broadcast to all clients.
- using (var writer = _game.StartRpc(NetId, RpcCalls.SnapTo))
+ using (var writer = Game.StartRpc(NetId, RpcCalls.SnapTo))
{
writer.Write(position);
writer.Write(_lastSequenceId);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
}
}
}
{
private readonly ILogger<InnerCustomNetworkTransform> _logger;
private readonly InnerPlayerControl _playerControl;
- private readonly Game _game;
private readonly IEventManager _eventManager;
private readonly ObjectPool<PlayerMovementEvent> _pool;
private ushort _lastSequenceId;
- public InnerCustomNetworkTransform(ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, Game game, IEventManager eventManager, ObjectPool<PlayerMovementEvent> pool)
+ public InnerCustomNetworkTransform(Game game, ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, IEventManager eventManager, ObjectPool<PlayerMovementEvent> pool) : base(game)
{
_logger = logger;
_playerControl = playerControl;
- _game = game;
- _game = game;
_eventManager = eventManager;
_pool = pool;
}
Velocity = velocity;
var playerMovementEvent = _pool.Get();
- playerMovementEvent.Reset(_game, sender, _playerControl);
+ playerMovementEvent.Reset(Game, sender, _playerControl);
await _eventManager.CallAsync(playerMovementEvent);
_pool.Return(playerMovementEvent);
}
private readonly ILogger<InnerPlayerPhysics> _logger;
private readonly InnerPlayerControl _playerControl;
private readonly IEventManager _eventManager;
- private readonly Game _game;
- public InnerPlayerPhysics(ILogger<InnerPlayerPhysics> logger, InnerPlayerControl playerControl, IEventManager eventManager, Game game)
+ public InnerPlayerPhysics(Game game, ILogger<InnerPlayerPhysics> logger, InnerPlayerControl playerControl, IEventManager eventManager) : base(game)
{
_logger = logger;
_playerControl = playerControl;
_eventManager = eventManager;
- _game = game;
}
public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
public override async ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
{
- if (!await ValidateOwnership(call, sender) || !await ValidateImpostor(call, sender, _playerControl.PlayerInfo))
+ if (!await ValidateOwnership(call, sender))
{
return false;
}
- int ventId;
-
switch (call)
{
case RpcCalls.EnterVent:
- Rpc19EnterVent.Deserialize(reader, out ventId);
- await _eventManager.CallAsync(new PlayerVentEvent(_game, sender, _playerControl, (VentLocation)ventId, true));
- break;
-
case RpcCalls.ExitVent:
- Rpc19EnterVent.Deserialize(reader, out ventId);
- await _eventManager.CallAsync(new PlayerVentEvent(_game, sender, _playerControl, (VentLocation)ventId, false));
+ if (!await ValidateImpostor(call, sender, _playerControl.PlayerInfo))
+ {
+ return false;
+ }
+
+ int ventId;
+
+ switch (call)
+ {
+ case RpcCalls.EnterVent:
+ Rpc19EnterVent.Deserialize(reader, out ventId);
+ break;
+ case RpcCalls.ExitVent:
+ Rpc20ExitVent.Deserialize(reader, out ventId);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(call), call, null);
+ }
+
+ await _eventManager.CallAsync(new PlayerVentEvent(Game, sender, _playerControl, (VentLocation)ventId, call == RpcCalls.EnterVent));
break;
case RpcCalls.ClimbLadder:
- Rpc31ClimbLadder.Deserialize(reader, out byte ladderId, out byte lastClimbLadderSid);
+ Rpc31ClimbLadder.Deserialize(reader, out var ladderId, out var lastClimbLadderSid);
break;
default:
private readonly ILogger<InnerVoteBanSystem> _logger;
private readonly Dictionary<int, int[]> _votes;
- public InnerVoteBanSystem(ILogger<InnerVoteBanSystem> logger)
+ public InnerVoteBanSystem(Game game, ILogger<InnerVoteBanSystem> logger) : base(game)
{
_logger = logger;
_votes = new Dictionary<int, int[]>();
internal partial class InnerGameData : InnerNetObject, IInnerGameData
{
private readonly ILogger<InnerGameData> _logger;
- private readonly Game _game;
private readonly ConcurrentDictionary<byte, InnerPlayerInfo> _allPlayers;
- public InnerGameData(ILogger<InnerGameData> logger, Game game, IServiceProvider serviceProvider)
+ public InnerGameData(Game game, ILogger<InnerGameData> logger, IServiceProvider serviceProvider) : base(game)
{
_logger = logger;
- _game = game;
_allPlayers = new ConcurrentDictionary<byte, InnerPlayerInfo>();
Components.Add(this);
- Components.Add(ActivatorUtilities.CreateInstance<InnerVoteBanSystem>(serviceProvider));
+ Components.Add(ActivatorUtilities.CreateInstance<InnerVoteBanSystem>(serviceProvider, game));
}
public int PlayerCount => _allPlayers.Count;
}
else
{
- // It'll send an message per dirty player
- // throw new NotImplementedException("This shouldn't happen, according to Among Us disassembly.");
+ 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.");
+ }
+ }
+ }
}
}
break;
}
- case RpcCalls.UpdateGameData:
- {
- while (reader.Position < reader.Length)
- {
- using var message = reader.ReadMessage();
- var player = GetPlayerById(message.Tag);
- if (player != null)
- {
- player.Deserialize(message);
- }
- else
- {
- var playerInfo = new InnerPlayerInfo(message.Tag);
-
- playerInfo.Deserialize(reader);
-
- if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo))
- {
- throw new ImpostorException("Failed to add player to InnerGameData.");
- }
- }
- }
-
- break;
- }
-
default:
return await UnregisteredCall(call, sender);
}
using System;
using System.Threading.Tasks;
-using Impostor.Api.Games;
using Impostor.Api.Net;
using Impostor.Api.Net.Inner;
using Impostor.Api.Net.Inner.Objects;
{
internal class InnerLobbyBehaviour : InnerNetObject, IInnerLobbyBehaviour
{
- private readonly IGame _game;
-
- public InnerLobbyBehaviour(IGame game)
+ public InnerLobbyBehaviour(Game game) : base(game)
{
- _game = game;
-
Components.Add(this);
}
{
private readonly ILogger<InnerMeetingHud> _logger;
private readonly IEventManager _eventManager;
- private readonly Game _game;
- private readonly GameNet _gameNet;
[AllowNull]
private PlayerVoteArea[] _playerStates;
- public InnerMeetingHud(ILogger<InnerMeetingHud> logger, IEventManager eventManager, Game game)
+ public InnerMeetingHud(Game game, ILogger<InnerMeetingHud> logger, IEventManager eventManager) : base(game)
{
_logger = logger;
_eventManager = eventManager;
- _game = game;
- _gameNet = game.GameNet;
_playerStates = null;
Components.Add(this);
private void PopulateButtons(byte reporter)
{
- _playerStates = _gameNet.GameData!.Players
+ _playerStates = Game.GameNet.GameData!.Players
.Select(x =>
{
var area = new PlayerVoteArea(this, x.Key);
{
if (playerId != byte.MaxValue)
{
- var player = _game.GameNet.GameData!.GetPlayerById(playerId);
+ var player = Game.GameNet.GameData!.GetPlayerById(playerId);
if (player?.Controller != null)
{
player.Controller.Die(DeathReason.Exile);
- await _eventManager.CallAsync(new PlayerExileEvent(_game, sender, player.Controller));
+ await _eventManager.CallAsync(new PlayerExileEvent(Game, sender, player.Controller));
}
}
- await _eventManager.CallAsync(new MeetingEndedEvent(_game, this));
+ await _eventManager.CallAsync(new MeetingEndedEvent(Game, this));
}
private async ValueTask<bool> HandleCastVote(ClientPlayer sender, ClientPlayer? target, byte playerId, sbyte suspectPlayerId)
{
PlayerInfo.PlayerName = name;
- using var writer = _game.StartRpc(NetId, RpcCalls.SetName);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetName);
writer.Write(name);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
}
public async ValueTask SetColorAsync(ColorType color)
{
PlayerInfo.Color = color;
- using var writer = _game.StartRpc(NetId, RpcCalls.SetColor);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetColor);
Rpc08SetColor.Serialize(writer, color);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
}
public async ValueTask SetHatAsync(HatType hat)
{
PlayerInfo.Hat = hat;
- using var writer = _game.StartRpc(NetId, RpcCalls.SetHat);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetHat);
Rpc09SetHat.Serialize(writer, hat);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
}
public async ValueTask SetPetAsync(PetType pet)
{
PlayerInfo.Pet = pet;
- using var writer = _game.StartRpc(NetId, RpcCalls.SetPet);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetPet);
Rpc17SetPet.Serialize(writer, pet);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
}
public async ValueTask SetSkinAsync(SkinType skin)
{
PlayerInfo.Skin = skin;
- using var writer = _game.StartRpc(NetId, RpcCalls.SetSkin);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetSkin);
Rpc10SetSkin.Serialize(writer, skin);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
}
public async ValueTask SendChatAsync(string text)
{
- using var writer = _game.StartRpc(NetId, RpcCalls.SendChat);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SendChat);
writer.Write(text);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
}
public async ValueTask SendChatToPlayerAsync(string text, IInnerPlayerControl? player = null)
player = this;
}
- using var writer = _game.StartRpc(NetId, RpcCalls.SendChat);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SendChat);
writer.Write(text);
- await _game.FinishRpcAsync(writer, player.OwnerId);
+ await Game.FinishRpcAsync(writer, player.OwnerId);
}
public async ValueTask MurderPlayerAsync(IInnerPlayerControl target)
((InnerPlayerControl)target).Die(DeathReason.Kill);
- using var writer = _game.StartRpc(NetId, RpcCalls.MurderPlayer);
+ using var writer = Game.StartRpc(NetId, RpcCalls.MurderPlayer);
Rpc12MurderPlayer.Serialize(writer, target);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
- await _eventManager.CallAsync(new PlayerMurderEvent(_game, _game.GetClientPlayer(OwnerId)!, this, target));
+ await _eventManager.CallAsync(new PlayerMurderEvent(Game, Game.GetClientPlayer(OwnerId)!, this, target));
}
public async ValueTask ExileAsync()
Die(DeathReason.Exile);
// Send RPC.
- using var writer = _game.StartRpc(NetId, RpcCalls.Exiled);
+ using var writer = Game.StartRpc(NetId, RpcCalls.Exiled);
Rpc04Exiled.Serialize(writer);
- await _game.FinishRpcAsync(writer);
+ await Game.FinishRpcAsync(writer);
// Notify plugins.
- await _eventManager.CallAsync(new PlayerExileEvent(_game, _game.GetClientPlayer(OwnerId)!, this));
+ await _eventManager.CallAsync(new PlayerExileEvent(Game, Game.GetClientPlayer(OwnerId)!, this));
}
}
}
private readonly ILogger<InnerPlayerControl> _logger;
private readonly IEventManager _eventManager;
- private readonly Game _game;
private readonly IDateTimeProvider _dateTimeProvider;
- public InnerPlayerControl(ILogger<InnerPlayerControl> logger, IServiceProvider serviceProvider, IEventManager eventManager, Game game, IDateTimeProvider dateTimeProvider)
+ public InnerPlayerControl(Game game, ILogger<InnerPlayerControl> logger, IServiceProvider serviceProvider, IEventManager eventManager, IDateTimeProvider dateTimeProvider) : base(game)
{
_logger = logger;
_eventManager = eventManager;
- _game = game;
_dateTimeProvider = dateTimeProvider;
- Physics = ActivatorUtilities.CreateInstance<InnerPlayerPhysics>(serviceProvider, this, _eventManager, _game);
- NetworkTransform = ActivatorUtilities.CreateInstance<InnerCustomNetworkTransform>(serviceProvider, this, _game);
+ Physics = ActivatorUtilities.CreateInstance<InnerPlayerPhysics>(serviceProvider, this, _eventManager, game);
+ NetworkTransform = ActivatorUtilities.CreateInstance<InnerCustomNetworkTransform>(serviceProvider, this, game);
Components.Add(this);
Components.Add(Physics);
return false;
}
- Rpc02SyncSettings.Deserialize(reader, _game.Options);
+ Rpc02SyncSettings.Deserialize(reader, Game.Options);
break;
}
return false;
}
- Rpc12MurderPlayer.Deserialize(reader, _game, out var murdered);
+ Rpc12MurderPlayer.Deserialize(reader, Game, out var murdered);
return await HandleMurderPlayer(sender, murdered);
}
if (task != null)
{
task.Complete = true;
- await _eventManager.CallAsync(new PlayerCompletedTaskEvent(_game, sender, this, task));
+ await _eventManager.CallAsync(new PlayerCompletedTaskEvent(Game, sender, this, task));
}
else
{
{
for (var i = 0; i < infectedIds.Length; i++)
{
- var player = _game.GameNet.GameData!.GetPlayerById(infectedIds.Span[i]);
+ var player = Game.GameNet.GameData!.GetPlayerById(infectedIds.Span[i]);
if (player != null)
{
player.IsImpostor = true;
}
}
- if (_game.GameState == GameStates.Starting)
+ if (Game.GameState == GameStates.Starting)
{
- await _game.StartedAsync();
+ await Game.StartedAsync();
}
}
private async ValueTask<bool> HandleSetName(ClientPlayer sender, string name)
{
- if (_game.GameState == GameStates.Started)
+ if (Game.GameState == GameStates.Started)
{
if (await sender.Client.ReportCheatAsync(RpcCalls.SetColor, "Client tried to set a name midgame"))
{
if (sender.IsOwner(this))
{
- if (_game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.PlayerName == name))
+ if (Game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.PlayerName == name))
{
if (await sender.Client.ReportCheatAsync(RpcCalls.SetName, "Client sent name that is already used"))
{
var expected = RequestedPlayerName.Dequeue();
- if (_game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.PlayerName == expected))
+ if (Game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.PlayerName == expected))
{
var i = 1;
while (true)
{
string text = expected + " " + i;
- if (_game.Players.All(x => x.Character == null || x.Character == this || x.Character.PlayerInfo.PlayerName != text))
+ if (Game.Players.All(x => x.Character == null || x.Character == this || x.Character.PlayerInfo.PlayerName != text))
{
expected = text;
break;
private async ValueTask<bool> HandleSetColor(ClientPlayer sender, ColorType color)
{
- if (_game.GameState == GameStates.Started)
+ if (Game.GameState == GameStates.Started)
{
if (await sender.Client.ReportCheatAsync(RpcCalls.SetColor, "Client tried to set a color midgame"))
{
if (sender.IsOwner(this))
{
- if (_game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.Color == color))
+ if (Game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.Color == color))
{
if (await sender.Client.ReportCheatAsync(RpcCalls.SetColor, "Client sent a color that is already used"))
{
var expected = RequestedColorId.Dequeue();
- while (_game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.Color == expected))
+ while (Game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.Color == expected))
{
expected = (ColorType)(((byte)expected + 1) % ColorsCount);
}
private async ValueTask<bool> HandleSetHat(ClientPlayer sender, HatType hat)
{
- if (_game.GameState == GameStates.Started && await sender.Client.ReportCheatAsync(RpcCalls.SetHat, "Client tried to change hat while not in lobby"))
+ if (Game.GameState == GameStates.Started && await sender.Client.ReportCheatAsync(RpcCalls.SetHat, "Client tried to change hat while not in lobby"))
{
return false;
}
private async ValueTask<bool> HandleSetSkin(ClientPlayer sender, SkinType skin)
{
- if (_game.GameState == GameStates.Started && await sender.Client.ReportCheatAsync(RpcCalls.SetSkin, "Client tried to change skin while not in lobby"))
+ if (Game.GameState == GameStates.Started && await sender.Client.ReportCheatAsync(RpcCalls.SetSkin, "Client tried to change skin while not in lobby"))
{
return false;
}
private async ValueTask<bool> HandleMurderPlayer(ClientPlayer sender, IInnerPlayerControl? target)
{
- if (!PlayerInfo.CanMurder(_game, _dateTimeProvider))
+ if (!PlayerInfo.CanMurder(Game, _dateTimeProvider))
{
if (await sender.Client.ReportCheatAsync(RpcCalls.MurderPlayer, "Client tried to murder too fast"))
{
if (target != null && !target.PlayerInfo.IsDead)
{
((InnerPlayerControl)target).Die(DeathReason.Kill);
- await _eventManager.CallAsync(new PlayerMurderEvent(_game, sender, this, target));
+ await _eventManager.CallAsync(new PlayerMurderEvent(Game, sender, this, target));
}
return true;
private async ValueTask<bool> HandleSendChat(ClientPlayer sender, string message)
{
- var @event = new PlayerChatEvent(_game, sender, this, message);
+ var @event = new PlayerChatEvent(Game, sender, this, message);
await _eventManager.CallAsync(@event);
return !@event.IsCancelled;
private async ValueTask HandleStartMeeting(byte targetId)
{
- var deadPlayer = _game.GameNet.GameData!.GetPlayerById(targetId)?.Controller;
- await _eventManager.CallAsync(new PlayerStartMeetingEvent(_game, _game.GetClientPlayer(this.OwnerId)!, this, deadPlayer));
+ var deadPlayer = Game.GameNet.GameData!.GetPlayerById(targetId)?.Controller;
+ await _eventManager.CallAsync(new PlayerStartMeetingEvent(Game, Game.GetClientPlayer(this.OwnerId)!, this, deadPlayer));
}
private async ValueTask<bool> HandleSetPet(ClientPlayer sender, PetType pet)
{
- if (_game.GameState == GameStates.Started && await sender.Client.ReportCheatAsync(RpcCalls.SetPet, "Client tried to change pet while not in lobby"))
+ if (Game.GameState == GameStates.Started && await sender.Client.ReportCheatAsync(RpcCalls.SetPet, "Client tried to change pet while not in lobby"))
{
return false;
}
if (startCounter != -1)
{
- await _eventManager.CallAsync(new PlayerSetStartCounterEvent(_game, sender, this, (byte)startCounter));
+ await _eventManager.CallAsync(new PlayerSetStartCounterEvent(Game, sender, this, (byte)startCounter));
}
return true;
public void Deserialize(IMessageReader reader)
{
PlayerName = reader.ReadString();
- Color = (ColorType)reader.ReadByte();
+ Color = (ColorType)reader.ReadPackedInt32();
Hat = (HatType)reader.ReadPackedUInt32();
Pet = (PetType)reader.ReadPackedUInt32();
Skin = (SkinType)reader.ReadPackedUInt32();
+
var flag = reader.ReadByte();
Disconnected = (flag & 1) > 0;
IsImpostor = (flag & 2) > 0;
IsDead = (flag & 4) > 0;
+
var taskCount = reader.ReadByte();
+
+ if (Tasks.Count != taskCount)
+ {
+ Tasks = new List<InnerGameData.TaskInfo>(taskCount);
+ }
+
for (var i = 0; i < taskCount; i++)
{
Tasks[i] ??= new InnerGameData.TaskInfo();
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Impostor.Api;
-using Impostor.Api.Innersloth;
-using Impostor.Api.Net;
-using Impostor.Api.Net.Inner;
-using Impostor.Api.Net.Inner.Objects;
-using Impostor.Api.Net.Messages;
-using Impostor.Api.Net.Messages.Rpcs;
-using Impostor.Server.Net.Inner.Objects.Systems;
-using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
-using Impostor.Server.Net.State;
-using Microsoft.Extensions.Logging;
-
-namespace Impostor.Server.Net.Inner.Objects
-{
- internal class InnerShipStatus : InnerNetObject, IInnerShipStatus
- {
- private readonly ILogger<InnerShipStatus> _logger;
- private readonly Game _game;
- private readonly Dictionary<SystemTypes, ISystemType> _systems;
-
- public InnerShipStatus(ILogger<InnerShipStatus> logger, Game game)
- {
- _logger = logger;
- _game = game;
-
- _systems = new Dictionary<SystemTypes, ISystemType>
- {
- [SystemTypes.Electrical] = new SwitchSystem(),
- [SystemTypes.MedBay] = new MedScanSystem(),
- [SystemTypes.Reactor] = game.Options.Map == MapTypes.Airship ? new HeliSabotageSystemType() : new ReactorSystemType(),
- [SystemTypes.LifeSupp] = new LifeSuppSystemType(),
- [SystemTypes.Security] = new SecurityCameraSystemType(),
- [SystemTypes.Comms] = new HudOverrideSystemType(),
- [SystemTypes.Doors] = new DoorsSystemType(_game),
- };
-
- _systems.Add(SystemTypes.Sabotage, new SabotageSystemType(new[]
- {
- (IActivatable)_systems[SystemTypes.Comms], (IActivatable)_systems[SystemTypes.Reactor], (IActivatable)_systems[SystemTypes.LifeSupp], (IActivatable)_systems[SystemTypes.Electrical],
- }));
-
- Components.Add(this);
- }
-
- public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
- {
- throw new NotImplementedException();
- }
-
- public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
- {
- if (!await ValidateHost(CheatContext.Deserialize, sender) || !await ValidateBroadcast(CheatContext.Deserialize, sender, target))
- {
- return;
- }
-
- while (reader.Position < reader.Length)
- {
- IMessageReader messageReader = reader.ReadMessage();
- SystemTypes type = (SystemTypes)messageReader.Tag;
- if (_systems.TryGetValue(type, out var value))
- {
- value.Deserialize(messageReader, initialState);
- }
- }
- }
-
- public override async ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
- {
- if (!await ValidateCmd(call, sender, target))
- {
- return false;
- }
-
- switch (call)
- {
- case RpcCalls.CloseDoorsOfType:
- {
- if (!await ValidateImpostor(call, sender, sender.Character!.PlayerInfo))
- {
- return false;
- }
-
- Rpc27CloseDoorsOfType.Deserialize(reader, out var systemType);
- break;
- }
-
- case RpcCalls.RepairSystem:
- {
- Rpc28RepairSystem.Deserialize(reader, _game, out var systemType, out var player, out var amount);
-
- if (systemType == SystemTypes.Sabotage && !await ValidateImpostor(call, sender, sender.Character!.PlayerInfo))
- {
- return false;
- }
-
- break;
- }
-
- default:
- return await UnregisteredCall(call, sender);
- }
-
- return true;
- }
- }
-}
--- /dev/null
+using System.Collections.Generic;
+using Impostor.Api.Innersloth;
+using Impostor.Api.Net.Inner.Objects.ShipStatus;
+using Impostor.Server.Net.Inner.Objects.Systems;
+using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
+using Impostor.Server.Net.State;
+
+namespace Impostor.Server.Net.Inner.Objects.ShipStatus
+{
+ internal class InnerAirshipStatus : InnerShipStatus, IInnerAirshipStatus
+ {
+ public InnerAirshipStatus(Game game) : base(game)
+ {
+ }
+
+ public override Dictionary<int, bool> Doors { get; } = new Dictionary<int, bool>(21);
+
+ protected override void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
+ {
+ base.AddSystems(systems);
+
+ systems.Add(SystemTypes.Doors, new DoorsSystemType(Doors));
+ systems.Add(SystemTypes.Comms, new HudOverrideSystemType());
+ systems.Add(SystemTypes.GapRoom, new MovingPlatformBehaviour());
+ systems.Add(SystemTypes.Reactor, new HeliSabotageSystemType());
+ systems.Add(SystemTypes.Decontamination, new ElectricalDoors(Doors));
+ systems.Add(SystemTypes.Decontamination2, new AutoDoorsSystemType(Doors));
+ systems.Add(SystemTypes.Security, new SecurityCameraSystemType());
+ }
+ }
+}
--- /dev/null
+using System.Collections.Generic;
+using Impostor.Api.Innersloth;
+using Impostor.Api.Net.Inner.Objects.ShipStatus;
+using Impostor.Server.Net.Inner.Objects.Systems;
+using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
+using Impostor.Server.Net.State;
+
+namespace Impostor.Server.Net.Inner.Objects.ShipStatus
+{
+ internal class InnerMiraShipStatus : InnerShipStatus, IInnerMiraShipStatus
+ {
+ public InnerMiraShipStatus(Game game) : base(game)
+ {
+ }
+
+ public override Dictionary<int, bool> Doors { get; } = new Dictionary<int, bool>(0);
+
+ protected override void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
+ {
+ base.AddSystems(systems);
+
+ systems.Add(SystemTypes.Comms, new HudOverrideSystemType());
+ systems.Add(SystemTypes.Reactor, new ReactorSystemType());
+ systems.Add(SystemTypes.LifeSupp, new LifeSuppSystemType());
+ }
+ }
+}
--- /dev/null
+using System.Collections.Generic;
+using Impostor.Api.Innersloth;
+using Impostor.Api.Net.Inner.Objects.ShipStatus;
+using Impostor.Server.Net.Inner.Objects.Systems;
+using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
+using Impostor.Server.Net.State;
+
+namespace Impostor.Server.Net.Inner.Objects.ShipStatus
+{
+ internal class InnerPolusShipStatus : InnerShipStatus, IInnerPolusShipStatus
+ {
+ public InnerPolusShipStatus(Game game) : base(game)
+ {
+ }
+
+ public override Dictionary<int, bool> Doors { get; } = new Dictionary<int, bool>(12);
+
+ protected override void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
+ {
+ base.AddSystems(systems);
+
+ systems.Add(SystemTypes.Doors, new DoorsSystemType(Doors));
+ systems.Add(SystemTypes.Comms, new HudOverrideSystemType());
+ systems.Add(SystemTypes.Security, new SecurityCameraSystemType());
+ systems.Add(SystemTypes.Laboratory, new ReactorSystemType());
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Impostor.Api;
+using Impostor.Api.Innersloth;
+using Impostor.Api.Net;
+using Impostor.Api.Net.Inner;
+using Impostor.Api.Net.Inner.Objects.ShipStatus;
+using Impostor.Api.Net.Messages;
+using Impostor.Api.Net.Messages.Rpcs;
+using Impostor.Server.Net.Inner.Objects.Systems;
+using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
+using Impostor.Server.Net.State;
+
+namespace Impostor.Server.Net.Inner.Objects.ShipStatus
+{
+ internal abstract class InnerShipStatus : InnerNetObject, IInnerShipStatus
+ {
+ private readonly Dictionary<SystemTypes, ISystemType> _systems = new Dictionary<SystemTypes, ISystemType>();
+
+ protected InnerShipStatus(Game game) : base(game)
+ {
+ Components.Add(this);
+ }
+
+ public abstract Dictionary<int, bool> Doors { get; }
+
+ public override ValueTask OnSpawnAsync()
+ {
+ for (var i = 0; i < Doors.Count; i++)
+ {
+ Doors.Add(i, false);
+ }
+
+ AddSystems(_systems);
+ _systems.Add(SystemTypes.Sabotage, new SabotageSystemType(_systems.Values.OfType<IActivatable>().ToArray()));
+
+ return base.OnSpawnAsync();
+ }
+
+ public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
+ {
+ if (!await ValidateHost(CheatContext.Deserialize, sender) || !await ValidateBroadcast(CheatContext.Deserialize, sender, target))
+ {
+ return;
+ }
+
+ while (reader.Position < reader.Length)
+ {
+ var messageReader = reader.ReadMessage();
+ var type = (SystemTypes)messageReader.Tag;
+ if (_systems.TryGetValue(type, out var value))
+ {
+ value.Deserialize(messageReader, initialState);
+ }
+ }
+ }
+
+ public override async ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
+ {
+ if (!await ValidateCmd(call, sender, target))
+ {
+ return false;
+ }
+
+ switch (call)
+ {
+ case RpcCalls.CloseDoorsOfType:
+ {
+ if (!await ValidateImpostor(call, sender, sender.Character!.PlayerInfo))
+ {
+ return false;
+ }
+
+ Rpc27CloseDoorsOfType.Deserialize(reader, out var systemType);
+ break;
+ }
+
+ case RpcCalls.RepairSystem:
+ {
+ Rpc28RepairSystem.Deserialize(reader, Game, out var systemType, out var player, out var amount);
+
+ if (systemType == SystemTypes.Sabotage && !await ValidateImpostor(call, sender, sender.Character!.PlayerInfo))
+ {
+ return false;
+ }
+
+ break;
+ }
+
+ default:
+ return await UnregisteredCall(call, sender);
+ }
+
+ return true;
+ }
+
+ protected virtual void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
+ {
+ systems.Add(SystemTypes.Electrical, new SwitchSystem());
+ systems.Add(SystemTypes.MedBay, new MedScanSystem());
+ }
+ }
+}
--- /dev/null
+using System.Collections.Generic;
+using Impostor.Api.Innersloth;
+using Impostor.Api.Net.Inner.Objects.ShipStatus;
+using Impostor.Server.Net.Inner.Objects.Systems;
+using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
+using Impostor.Server.Net.State;
+
+namespace Impostor.Server.Net.Inner.Objects.ShipStatus
+{
+ internal class InnerSkeldShipStatus : InnerShipStatus, IInnerSkeldShipStatus
+ {
+ public InnerSkeldShipStatus(Game game) : base(game)
+ {
+ }
+
+ public override Dictionary<int, bool> Doors { get; } = new Dictionary<int, bool>(13);
+
+ protected override void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
+ {
+ base.AddSystems(systems);
+
+ systems.Add(SystemTypes.Doors, new AutoDoorsSystemType(Doors));
+ systems.Add(SystemTypes.Comms, new HudOverrideSystemType());
+ systems.Add(SystemTypes.Security, new SecurityCameraSystemType());
+ systems.Add(SystemTypes.Reactor, new ReactorSystemType());
+ systems.Add(SystemTypes.LifeSupp, new LifeSuppSystemType());
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
+{
+ public class AutoDoorsSystemType : ISystemType
+ {
+ private readonly Dictionary<int, bool> _doors;
+
+ public AutoDoorsSystemType(Dictionary<int, bool> doors)
+ {
+ _doors = doors;
+ }
+
+ public void Serialize(IMessageWriter writer, bool initialState)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IMessageReader reader, bool initialState)
+ {
+ if (initialState)
+ {
+ for (var i = 0; i < _doors.Count; i++)
+ {
+ _doors[i] = reader.ReadBoolean();
+ }
+ }
+ else
+ {
+ var num = reader.ReadPackedUInt32();
+
+ for (var i = 0; i < _doors.Count; i++)
+ {
+ if ((num & 1 << i) != 0)
+ {
+ _doors[i] = reader.ReadBoolean();
+ }
+ }
+ }
+ }
+ }
+}
-using System;
+using System;
using System.Collections.Generic;
-using Impostor.Api.Games;
using Impostor.Api.Innersloth;
using Impostor.Api.Net.Messages;
{
public class DoorsSystemType : ISystemType
{
- // TODO: AutoDoors
+ private readonly Dictionary<SystemTypes, float> _timers = new Dictionary<SystemTypes, float>();
private readonly Dictionary<int, bool> _doors;
- public DoorsSystemType(IGame game)
+ public DoorsSystemType(Dictionary<int, bool> doors)
{
- var doorCount = game.Options.Map switch
- {
- MapTypes.Skeld => 13,
- MapTypes.MiraHQ => 2,
- MapTypes.Polus => 12,
- MapTypes.Airship => 21, // TODO do the toilet doors count? 21 yes, 17 no
- _ => throw new ArgumentOutOfRangeException(),
- };
-
- _doors = new Dictionary<int, bool>(doorCount);
-
- for (var i = 0; i < doorCount; i++)
- {
- _doors.Add(i, false);
- }
+ _doors = doors;
}
public void Serialize(IMessageWriter writer, bool initialState)
public void Deserialize(IMessageReader reader, bool initialState)
{
- if (initialState)
+ var num = reader.ReadByte();
+ for (var i = 0; i < num; i++)
{
- for (var i = 0; i < _doors.Count; i++)
- {
- _doors[i] = reader.ReadBoolean();
- }
+ var systemType = (SystemTypes)reader.ReadByte();
+ var value = reader.ReadSingle();
+
+ _timers[systemType] = value;
}
- else
- {
- var num = reader.ReadPackedUInt32();
- for (var i = 0; i < _doors.Count; i++)
- {
- if ((num & 1 << i) != 0)
- {
- _doors[i] = reader.ReadBoolean();
- }
- }
+ for (var j = 0; j < _doors.Count; j++)
+ {
+ _doors[j] = reader.ReadBoolean();
}
}
}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
+{
+ public class ElectricalDoors : ISystemType
+ {
+ private readonly Dictionary<int, bool> _doors;
+
+ public ElectricalDoors(Dictionary<int, bool> doors)
+ {
+ _doors = doors;
+ }
+
+ public void Serialize(IMessageWriter writer, bool initialState)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IMessageReader reader, bool initialState)
+ {
+ var num = reader.ReadUInt32();
+ for (var i = 0; i < _doors.Count; i++)
+ {
+ _doors[i] = (num & (ulong)(1L << (i & 31))) > 0UL;
+ }
+ }
+ }
+}
using System;
using System.Collections.Generic;
using Impostor.Api.Net.Messages;
-using Microsoft.Extensions.Logging;
namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
{
--- /dev/null
+using System;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
+{
+ public class MovingPlatformBehaviour : ISystemType, IActivatable
+ {
+ public bool IsActive { get; private set; }
+
+ public void Serialize(IMessageWriter writer, bool initialState)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(IMessageReader reader, bool initialState)
+ {
+ var sid = reader.ReadByte();
+ var targetId = reader.ReadUInt32();
+ var isLeft = reader.ReadBoolean();
+ }
+ }
+}
using Impostor.Api.Net.Inner;
using Impostor.Api.Net.Messages;
using Impostor.Hazel;
-using Impostor.Server.Net.Inner;
namespace Impostor.Server.Net.State
{
using Impostor.Server.Net.Inner;
using Impostor.Server.Net.Inner.Objects;
using Impostor.Server.Net.Inner.Objects.Components;
+using Impostor.Server.Net.Inner.Objects.ShipStatus;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
private static readonly Type[] SpawnableObjects =
{
- typeof(InnerShipStatus), // ShipStatus
+ typeof(InnerSkeldShipStatus),
typeof(InnerMeetingHud),
typeof(InnerLobbyBehaviour),
typeof(InnerGameData),
typeof(InnerPlayerControl),
- typeof(InnerShipStatus), // HeadQuarters
- typeof(InnerShipStatus), // PlanetMap
- typeof(InnerShipStatus), // AprilShipStatus
- typeof(InnerShipStatus), // Airship
+ typeof(InnerMiraShipStatus),
+ typeof(InnerPolusShipStatus),
+ typeof(InnerSkeldShipStatus), // April fools skeld
+ typeof(InnerAirshipStatus),
};
private readonly List<InnerNetObject> _allObjects = new List<InnerNetObject>();
break;
}
}
+
+ await netObj.OnSpawnAsync();
}
private async ValueTask OnDestroyAsync(InnerNetObject netObj)
using Impostor.Api.Net.Inner;
using Impostor.Api.Net.Inner.Objects;
+using Impostor.Api.Net.Inner.Objects.ShipStatus;
namespace Impostor.Server.Net.State
{
using Impostor.Server.Net.Inner.Objects;
using Impostor.Server.Net.Inner.Objects.Components;
+using Impostor.Server.Net.Inner.Objects.ShipStatus;
namespace Impostor.Server.Net.State
{