GameStates GameState { get; }
- GameNet GameNet { get; }
+ IGameNet GameNet { get; }
IEnumerable<IClientPlayer> Players { get; }
--- /dev/null
+namespace Impostor.Api.Innersloth.Data
+{
+ public enum DeathReason
+ {
+ Exile = 0,
+ Kill = 1,
+ Disconnect = 2
+ }
+}
\ No newline at end of file
+++ /dev/null
-using Impostor.Api.Games;
-using Impostor.Api.Innersloth.Net;
-using Impostor.Api.Innersloth.Net.Objects;
-using Impostor.Api.Innersloth.Net.Objects.Components;
-
-namespace Impostor.Api.Innersloth.Data
-{
- /// <summary>
- /// Holds all data that is serialized over the network through GameData packets.
- /// </summary>
- public class GameNet
- {
- private readonly IGame _game;
-
- public GameNet(IGame game)
- {
- _game = game;
- }
-
- public InnerLobbyBehaviour LobbyBehaviour { get; private set; }
-
- public InnerGameData GameData { get; private set; }
-
- public InnerVoteBanSystem VoteBan { get; private set; }
-
- public InnerShipStatus ShipStatus { get; private set; }
-
- internal void OnSpawn(InnerNetObject netObj)
- {
- switch (netObj)
- {
- case InnerLobbyBehaviour lobby:
- {
- LobbyBehaviour = lobby;
- break;
- }
-
- case InnerGameData data:
- {
- GameData = data;
- break;
- }
-
- case InnerVoteBanSystem voteBan:
- {
- VoteBan = voteBan;
- break;
- }
-
- case InnerShipStatus shipStatus:
- {
- ShipStatus = shipStatus;
- break;
- }
-
- case 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);
- }
-
- break;
- }
- }
- }
-
- internal void OnDestroy(InnerNetObject netObj)
- {
- switch (netObj)
- {
- case InnerLobbyBehaviour lobby:
- {
- LobbyBehaviour = null;
- break;
- }
-
- case InnerGameData:
- {
- GameData = null;
- break;
- }
-
- case InnerVoteBanSystem:
- {
- VoteBan = null;
- break;
- }
-
- case InnerShipStatus:
- {
- ShipStatus = null;
- break;
- }
-
- case InnerPlayerControl control:
- {
- // Remove InnerPlayerControl <-> IClientPlayer.
- var clientPlayer = _game.GetClientPlayer(control.OwnerId);
- if (clientPlayer != null)
- {
- clientPlayer.Character = null;
- }
-
- break;
- }
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-namespace Impostor.Api.Innersloth.GameData
-{
- public static class GameDataTag
- {
- public const byte DataFlag = 1;
- public const byte RpcFlag = 2;
- public const byte SpawnFlag = 4;
- public const byte DespawnFlag = 5;
- public const byte SceneChangeFlag = 6;
- public const byte ReadyFlag = 7;
- public const byte ChangeSettingsFlag = 8;
- }
-}
\ No newline at end of file
-using Impostor.Api.Innersloth.Data;
-
-using System;
+using System;
using System.IO;
+using Impostor.Api.Innersloth.Data;
+using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth
{
public const int LatestVersion = 2;
public byte Version { get; set; }
+
public byte MaxPlayers { get; set; }
+
public GameKeywords Keywords { get; set; }
+
public byte MapId { get; set; }
+
public float PlayerSpeedMod { get; set; }
+
public float CrewLightMod { get; set; }
+
public float ImpostorLightMod { get; set; }
+
public float KillCooldown { get; set; }
+
public int NumCommonTasks { get; set; }
+
public int NumLongTasks { get; set; }
+
public int NumShortTasks { get; set; }
+
public int NumEmergencyMeetings { get; set; }
+
public int EmergencyCooldown { get; set; }
+
public int NumImpostors { get; set; }
+
public bool GhostsDoTasks { get; set; }
+
public int KillDistance { get; set; }
+
public int DiscussionTime { get; set; }
+
public int VotingTime { get; set; }
+
public bool ConfirmImpostor { get; set; }
+
public bool VisualTasks { get; set; }
+
public bool IsDefaults { get; set; }
public void Serialize(BinaryWriter writer, byte version)
writer.Write((uint)DiscussionTime);
writer.Write((uint)VotingTime);
writer.Write((bool)IsDefaults);
+
if (version > 1)
{
writer.Write((byte)EmergencyCooldown);
writer.Write((bool)ConfirmImpostor);
writer.Write((bool)VisualTasks);
}
+
+ if (Version > 3)
+ {
+ throw new ImpostorException($"Unknown GameOptionsData version {Version}.");
+ }
}
- public static GameOptionsData Deserialize(ReadOnlyMemory<byte> memory)
+ public void Deserialize(ReadOnlyMemory<byte> memory)
{
var bytes = memory.Span;
- var result = new GameOptionsData();
- result.Version = bytes.ReadByte();
- result.MaxPlayers = bytes.ReadByte();
- result.Keywords = (GameKeywords)bytes.ReadUInt32();
- result.MapId = bytes.ReadByte();
- result.PlayerSpeedMod = bytes.ReadSingle();
+ Version = bytes.ReadByte();
+ MaxPlayers = bytes.ReadByte();
+ Keywords = (GameKeywords)bytes.ReadUInt32();
+ MapId = bytes.ReadByte();
+ PlayerSpeedMod = bytes.ReadSingle();
- result.CrewLightMod = bytes.ReadSingle();
- result.ImpostorLightMod = bytes.ReadSingle();
- result.KillCooldown = bytes.ReadSingle();
+ CrewLightMod = bytes.ReadSingle();
+ ImpostorLightMod = bytes.ReadSingle();
+ KillCooldown = bytes.ReadSingle();
- result.NumCommonTasks = bytes.ReadByte();
- result.NumLongTasks = bytes.ReadByte();
- result.NumShortTasks = bytes.ReadByte();
+ NumCommonTasks = bytes.ReadByte();
+ NumLongTasks = bytes.ReadByte();
+ NumShortTasks = bytes.ReadByte();
- result.NumEmergencyMeetings = bytes.ReadInt32();
+ NumEmergencyMeetings = bytes.ReadInt32();
- result.NumImpostors = bytes.ReadByte();
- result.KillDistance = bytes.ReadByte();
- result.DiscussionTime = bytes.ReadInt32();
- result.VotingTime = bytes.ReadInt32();
+ NumImpostors = bytes.ReadByte();
+ KillDistance = bytes.ReadByte();
+ DiscussionTime = bytes.ReadInt32();
+ VotingTime = bytes.ReadInt32();
- result.IsDefaults = bytes.ReadBoolean();
+ IsDefaults = bytes.ReadBoolean();
- if (result.Version > 1)
+ if (Version > 1)
{
- result.EmergencyCooldown = bytes.ReadByte();
+ EmergencyCooldown = bytes.ReadByte();
}
- if (result.Version > 2)
+ if (Version > 2)
{
- result.ConfirmImpostor = bytes.ReadBoolean();
- result.VisualTasks = bytes.ReadBoolean();
+ ConfirmImpostor = bytes.ReadBoolean();
+ VisualTasks = bytes.ReadBoolean();
}
- return result;
+ if (Version > 3)
+ {
+ throw new ImpostorException($"Unknown GameOptionsData version {Version}.");
+ }
+ }
+
+ public static GameOptionsData DeserializeCreate(IMessageReader reader)
+ {
+ var options = new GameOptionsData();
+ options.Deserialize(reader.ReadBytesAndSize());
+ return options;
}
}
}
\ No newline at end of file
--- /dev/null
+namespace Impostor.Api.Innersloth.Net
+{
+ public static class GameDataTag
+ {
+ public const byte DataFlag = 1;
+ public const byte RpcFlag = 2;
+ public const byte SpawnFlag = 4;
+ public const byte DespawnFlag = 5;
+ public const byte SceneChangeFlag = 6;
+ public const byte ReadyFlag = 7;
+ public const byte ChangeSettingsFlag = 8;
+ }
+}
\ No newline at end of file
--- /dev/null
+using Impostor.Api.Innersloth.Net.Objects;
+using Impostor.Api.Innersloth.Net.Objects.Components;
+
+namespace Impostor.Api.Innersloth.Net
+{
+ public interface IGameNet
+ {
+ InnerLobbyBehaviour LobbyBehaviour { get; }
+
+ InnerGameData GameData { get; }
+
+ InnerVoteBanSystem VoteBan { get; }
+
+ InnerShipStatus ShipStatus { get; }
+ }
+}
\ No newline at end of file
public SpawnFlags SpawnFlags { get; internal set; }
- public abstract void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader);
+ public abstract void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader);
public abstract bool Serialize(IMessageWriter writer, bool initialState);
return new Vector2(XRange.Lerp(v1), YRange.Lerp(v2));
}
- public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
{
- if (callId == 0)
+ if (call == 0)
{
SnapTo(ReadVector2(reader), reader.ReadUInt16());
}
else
{
- _logger.LogWarning("InnerCustomNetworkTransform: Unknown rpc call {0}", callId);
+ _logger.LogWarning("InnerCustomNetworkTransform: Unknown rpc call {0}", call);
}
}
{
public class InnerPlayerPhysics : InnerNetObject
{
- public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
{
throw new System.NotImplementedException();
}
_votes = new Dictionary<int, int[]>();
}
- public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
{
throw new NotImplementedException();
}
using System;
using System.Collections.Generic;
+using Impostor.Api.Innersloth.Data;
using Impostor.Api.Net.Messages;
namespace Impostor.Api.Innersloth.Net.Objects
public bool IsImpostor { get; internal set; }
- public bool IsDead { get; private set; }
+ public bool IsDead { get; internal set; }
+
+ public DeathReason LastDeathReason { get; internal set; }
public List<TaskInfo> Tasks { get; private set; }
return _allPlayers.TryGetValue(id, out var player) ? player : null;
}
- public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
{
throw new NotImplementedException();
}
Components.Add(this);
}
- public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public partial class InnerMeetingHud : InnerNetObject
{
private readonly IGame _game;
- private readonly GameNet _gameNet;
+ private readonly IGameNet _gameNet;
private PlayerVoteArea[] _playerStates;
public InnerMeetingHud(IGame game)
.ToArray();
}
- public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
{
throw new NotImplementedException();
}
using System;
using Impostor.Api.Games;
+using Impostor.Api.Innersloth.Data;
using Impostor.Api.Innersloth.Net.Objects.Components;
using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
namespace Impostor.Api.Innersloth.Net.Objects
{
public class InnerPlayerControl : InnerNetObject
{
+ private readonly ILogger<InnerPlayerControl> _logger;
private readonly IGame _game;
- public InnerPlayerControl(IGame game, IServiceProvider serviceProvider)
+ public InnerPlayerControl(ILogger<InnerPlayerControl> logger, IServiceProvider serviceProvider, IGame game)
{
+ _logger = logger;
_game = game;
Components.Add(this);
public InnerGameData.PlayerInfo PlayerInfo { get; internal set; }
- public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
+ private void Die(DeathReason reason)
{
- switch (callId)
+ PlayerInfo.IsDead = true;
+ PlayerInfo.LastDeathReason = reason;
+ }
+
+ public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
+ {
+ switch (call)
{
- case 3:
+ case RpcCalls.PlayAnimation:
+ {
+ var animation = reader.ReadByte();
+ break;
+ }
+
+ case RpcCalls.CompleteTask:
+ {
+ var index = reader.ReadPackedUInt32();
+ break;
+ }
+
+ case RpcCalls.SyncSettings:
+ {
+ _game.Options.Deserialize(reader.ReadBytesAndSize());
+ Console.WriteLine(_game.Options.PlayerSpeedMod);
+ break;
+ }
+
+ // Set Impostors.
+ case RpcCalls.SetInfected:
{
var length = reader.ReadPackedInt32();
break;
}
- case 6:
+ // Player was voted out.
+ case RpcCalls.Exiled:
+ {
+ Console.WriteLine(PlayerInfo.PlayerName + " was voted out.");
+ break;
+ }
+
+ // Validates the player name at the host.
+ case RpcCalls.CheckName:
+ {
+ if (!target.IsHost)
+ {
+
+ }
+ var name = reader.ReadString();
+ break;
+ }
+
+ case RpcCalls.SetName:
{
PlayerInfo.PlayerName = reader.ReadString();
break;
}
default:
+ _logger.LogWarning("InnerPlayerControl: Unknown rpc call {0}", call);
break;
}
}
Components.Add(this);
}
- public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
+ public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
{
- switch (callId)
+ switch (call)
{
- case 27:
+ case RpcCalls.CloseDoorsOfType:
{
if (!sender.Character.PlayerInfo.IsImpostor)
{
break;
}
- case 28:
+ case RpcCalls.RepairSystem:
{
var systemType = (SystemTypes)reader.ReadByte();
var player = _game.FindObjectByNetId<InnerPlayerControl>(reader.ReadPackedUInt32());
--- /dev/null
+namespace Impostor.Api.Innersloth.Net
+{
+ public enum RpcCalls : byte
+ {
+ PlayAnimation = 0,
+ CompleteTask = 1,
+ SyncSettings = 2,
+ SetInfected = 3,
+ Exiled = 4,
+ CheckName = 5,
+ SetName = 6,
+ CheckColor = 7,
+ SetColor = 8,
+ SetHat = 9,
+ SetSkin = 10,
+ ReportDeadBody = 11,
+ MurderPlayer = 12,
+ SendChat = 13,
+ StartMeeting = 14,
+ SetScanner = 15,
+ SendChatNote = 16,
+ SetPet = 17,
+ SetStartCounter = 18,
+ EnterVent = 19,
+ ExitVent = 20,
+ SnapTo = 21,
+ Close = 22,
+ VotingComplete = 23,
+ CastVote = 24,
+ ClearVote = 25,
+ AddVote = 26,
+ CloseDoorsOfType = 27,
+ RepairSystem = 28,
+ SetTasks = 29,
+ UpdateGameData = 30,
+ }
+}
\ No newline at end of file
/// </summary>
LimboStates Limbo { get; set; }
- InnerPlayerControl Character { get; set; }
+ InnerPlayerControl Character { get; }
+
+ public bool IsHost { get; }
ValueTask KickAsync();
public static GameOptionsData Deserialize(IMessageReader reader)
{
- return GameOptionsData.Deserialize(reader.ReadBytesAndSize());
+ return GameOptionsData.DeserializeCreate(reader);
}
}
}
\ No newline at end of file
public static void Deserialize(IMessageReader reader, out GameOptionsData options)
{
reader.ReadPackedInt32(); // Hardcoded 0.
- options = GameOptionsData.Deserialize(reader.ReadBytesAndSize());
+ options = GameOptionsData.DeserializeCreate(reader);
}
}
}
\ No newline at end of file
/// <inheritdoc />
public LimboStates Limbo { get; set; }
- // TODO: Correct visibility to set internal only.
- public InnerPlayerControl Character { get; set; }
+ public InnerPlayerControl Character { get; internal set; }
public bool IsHost => Game?.Host == this;
using Impostor.Api.Games;
+using Impostor.Api.Innersloth.Net;
using Impostor.Api.Net;
namespace Impostor.Server.Net.State
internal partial class Game
{
IClientPlayer IGame.Host => Host;
+
+ IGameNet IGame.GameNet => GameNet;
}
}
\ No newline at end of file
using System.Threading.Tasks;
using Impostor.Api;
using Impostor.Api.Innersloth.Data;
-using Impostor.Api.Innersloth.GameData;
using Impostor.Api.Innersloth.Net;
using Impostor.Api.Innersloth.Net.Objects;
+using Impostor.Api.Innersloth.Net.Objects.Components;
using Impostor.Api.Net.Messages;
using Impostor.Api.Net.Messages.C2S;
using Impostor.Api.Net.Messages.S2C;
private int _gamedataInitialized;
private bool _gamedataFakeReceived;
+ internal void OnSpawn(InnerNetObject netObj)
+ {
+ switch (netObj)
+ {
+ case InnerLobbyBehaviour lobby:
+ {
+ GameNet.LobbyBehaviour = lobby;
+ break;
+ }
+
+ case InnerGameData data:
+ {
+ GameNet.GameData = data;
+ break;
+ }
+
+ case InnerVoteBanSystem voteBan:
+ {
+ GameNet.VoteBan = voteBan;
+ break;
+ }
+
+ case InnerShipStatus shipStatus:
+ {
+ GameNet.ShipStatus = shipStatus;
+ break;
+ }
+
+ case InnerPlayerControl control:
+ {
+ // Hook up InnerPlayerControl <-> IClientPlayer.
+ if (TryGetPlayer(control.OwnerId, out var player))
+ {
+ player.Character = control;
+ }
+
+ // Hook up InnerPlayerControl <-> InnerPlayerControl.PlayerInfo.
+ control.PlayerInfo = GameNet.GameData.GetPlayerById(control.PlayerId);
+
+ if (control.PlayerInfo == null)
+ {
+ GameNet.GameData.AddPlayer(control);
+ }
+
+ break;
+ }
+ }
+ }
+
+ internal void OnDestroy(InnerNetObject netObj)
+ {
+ switch (netObj)
+ {
+ case InnerLobbyBehaviour lobby:
+ {
+ GameNet.LobbyBehaviour = null;
+ break;
+ }
+
+ case InnerGameData:
+ {
+ GameNet.GameData = null;
+ break;
+ }
+
+ case InnerVoteBanSystem:
+ {
+ GameNet.VoteBan = null;
+ break;
+ }
+
+ case InnerShipStatus:
+ {
+ GameNet.ShipStatus = null;
+ break;
+ }
+
+ case InnerPlayerControl control:
+ {
+ // Remove InnerPlayerControl <-> IClientPlayer.
+ if (TryGetPlayer(control.OwnerId, out var player))
+ {
+ player.Character = null;
+ }
+
+ break;
+ }
+ }
+ }
+
private async ValueTask InitGameDataAsync(ClientPlayer player)
{
if (Interlocked.Exchange(ref _gamedataInitialized, 1) != 0)
// TODO: Remove try catch.
try
{
- obj.HandleRpc(sender, reader.ReadByte(), reader);
+ obj.HandleRpc(sender, target, (RpcCalls) reader.ReadByte(), reader);
}
catch (NotImplementedException)
{
obj.Deserialize(sender, readerSub, true);
}
- GameNet.OnSpawn(obj);
+ OnSpawn(obj);
}
continue;
}
RemoveNetObject(obj);
- GameNet.OnDestroy(obj);
+ OnDestroy(obj);
_logger.LogDebug("Destroyed InnerNetObject {0} ({1}), OwnerId {2}", obj.GetType().Name, netId, obj.OwnerId);
}
else
using Impostor.Api.Games;
using Impostor.Api.Innersloth;
using Impostor.Api.Innersloth.Data;
+using Impostor.Api.Innersloth.Net;
using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
using Impostor.Api.Net.Messages.S2C;
-using Impostor.Hazel;
-using Impostor.Server.Net.Hazel;
using Impostor.Server.Net.Manager;
-using Impostor.Server.Net.Redirector;
using Microsoft.Extensions.Logging;
-using Serilog;
-using ILogger = Serilog.ILogger;
namespace Impostor.Server.Net.State
{
Code = code;
HostId = -1;
GameState = GameStates.NotStarted;
- GameNet = new GameNet(this);
+ GameNet = new GameNet();
Options = options;
_clientManager = clientManager;
_eventManager = eventManager;
public GameStates GameState { get; private set; }
- public GameNet GameNet { get; }
+ internal GameNet GameNet { get; }
public GameOptionsData Options { get; }
--- /dev/null
+using Impostor.Api.Innersloth.Net;
+using Impostor.Api.Innersloth.Net.Objects;
+using Impostor.Api.Innersloth.Net.Objects.Components;
+
+namespace Impostor.Server.Net.State
+{
+ /// <summary>
+ /// Holds all data that is serialized over the network through GameData packets.
+ /// </summary>
+ public class GameNet : IGameNet
+ {
+ public InnerLobbyBehaviour LobbyBehaviour { get; internal set; }
+
+ public InnerGameData GameData { get; internal set; }
+
+ public InnerVoteBanSystem VoteBan { get; internal set; }
+
+ public InnerShipStatus ShipStatus { get; internal set; }
+ }
+}
\ No newline at end of file