Finish up PlayerControl RPCs

This commit is contained in:
AeonLucid committed 2020-10-23 22:27:57 +02:00
1 parent 35792a1641
commit 1b776bfce9
15 files changed
+344 -21

No files matched your search

@@ -0,0 +1,24 @@
using System;
using System.Runtime.Serialization;
namespace Impostor.Api
{
public class ImpostorCheatException : ImpostorException
{
public ImpostorCheatException()
{
}
protected ImpostorCheatException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public ImpostorCheatException(string? message) : base(message)
{
}
public ImpostorCheatException(string? message, Exception? innerException) : base(message, innerException)
{
}
}
}
@@ -0,0 +1,15 @@
using Impostor.Api.Games;
using Impostor.Api.Innersloth.Net;
using Impostor.Api.Net.Messages;
namespace Impostor.Api
{
public static class MessageReaderExtensions
{
public static T ReadNetObject<T>(this IMessageReader reader, IGame game)
where T : InnerNetObject
{
return game.FindObjectByNetId<T>(reader.ReadPackedUInt32());
}
}
}
+1
View File
@@ -6,6 +6,7 @@
<CodeAnalysisRuleSet>ProjectRules.ruleset</CodeAnalysisRuleSet>
<LangVersion>9</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
@@ -0,0 +1,7 @@
namespace Impostor.Api.Innersloth.Data
{
public enum ChatNoteType : byte
{
DidVote = 0,
}
}
@@ -11,7 +11,8 @@ namespace Impostor.Api.Innersloth.Net
public SpawnFlags SpawnFlags { get; internal set; }
public abstract void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader);
public abstract void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call,
IMessageReader reader);
public abstract bool Serialize(IMessageWriter writer, bool initialState);
@@ -44,9 +44,9 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components
return new Vector2(XRange.Lerp(v1), YRange.Lerp(v2));
}
public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader)
{
if (call == 0)
if (call == RpcCalls.SnapTo)
{
SnapTo(ReadVector2(reader), reader.ReadUInt16());
}
@@ -5,7 +5,8 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components
{
public class InnerPlayerPhysics : InnerNetObject
{
public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call,
IMessageReader reader)
{
throw new System.NotImplementedException();
}
@@ -14,7 +14,8 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components
_votes = new Dictionary<int, int[]>();
}
public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call,
IMessageReader reader)
{
throw new NotImplementedException();
}
@@ -37,12 +37,17 @@ namespace Impostor.Api.Innersloth.Net.Objects
}
}
public PlayerInfo GetPlayerById(byte id)
public PlayerInfo? GetPlayerById(byte id)
{
if (id == byte.MaxValue)
{
return null;
}
return _allPlayers.TryGetValue(id, out var player) ? player : null;
}
public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader)
{
throw new NotImplementedException();
}
@@ -15,7 +15,8 @@ namespace Impostor.Api.Innersloth.Net.Objects
Components.Add(this);
}
public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call,
IMessageReader reader)
{
throw new System.NotImplementedException();
}
@@ -36,7 +36,8 @@ namespace Impostor.Api.Innersloth.Net.Objects
.ToArray();
}
public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call,
IMessageReader reader)
{
throw new NotImplementedException();
}
@@ -32,38 +32,49 @@ namespace Impostor.Api.Innersloth.Net.Objects
public InnerGameData.PlayerInfo PlayerInfo { get; internal set; }
private void Die(DeathReason reason)
{
PlayerInfo.IsDead = true;
PlayerInfo.LastDeathReason = reason;
}
public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader)
{
switch (call)
{
case RpcCalls.PlayAnimation:
{
// TODO: Figure out checks
var animation = reader.ReadByte();
break;
}
// Complete a task.
case RpcCalls.CompleteTask:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CompleteTask)} to an unowned {nameof(InnerPlayerControl)}.");
}
var index = reader.ReadPackedUInt32();
break;
}
// Update GameOptions.
case RpcCalls.SyncSettings:
{
if (!sender.IsHost)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SyncSettings)} but was not a host.");
}
_game.Options.Deserialize(reader.ReadBytesAndSize());
Console.WriteLine(_game.Options.PlayerSpeedMod);
break;
}
// Set Impostors.
case RpcCalls.SetInfected:
{
if (!sender.IsHost)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetInfected)} but was not a host.");
}
var length = reader.ReadPackedInt32();
for (var i = 0; i < length; i++)
@@ -80,27 +91,260 @@ namespace Impostor.Api.Innersloth.Net.Objects
// Player was voted out.
case RpcCalls.Exiled:
{
if (!sender.IsHost)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetInfected)} but was not a host.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetInfected)} to a specific player instead of broadcast.");
}
Console.WriteLine(PlayerInfo.PlayerName + " was voted out.");
Die(DeathReason.Exile);
break;
}
// Validates the player name at the host.
case RpcCalls.CheckName:
{
if (!target.IsHost)
if (target == null || !target.IsHost)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckName)} to the wrong player.");
}
var name = reader.ReadString();
break;
}
// Update the name of a player.
case RpcCalls.SetName:
{
if (!sender.IsHost)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} but was not a host.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} to a specific player instead of broadcast.");
}
PlayerInfo.PlayerName = reader.ReadString();
break;
}
// Validates the color at the host.
case RpcCalls.CheckColor:
{
if (target == null || !target.IsHost)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckColor)} to the wrong player.");
}
var color = reader.ReadByte();
break;
}
// Update the color of a player.
case RpcCalls.SetColor:
{
if (!sender.IsHost)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} but was not a host.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} to a specific player instead of broadcast.");
}
PlayerInfo.ColorId = reader.ReadByte();
break;
}
// Update the hat of a player.
case RpcCalls.SetHat:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to a specific player instead of broadcast.");
}
PlayerInfo.HatId = reader.ReadPackedUInt32();
break;
}
case RpcCalls.SetSkin:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetSkin)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to a specific player instead of broadcast.");
}
PlayerInfo.SkinId = reader.ReadPackedUInt32();
break;
}
// TODO: (ANTICHEAT) Location check?
case RpcCalls.ReportDeadBody:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.ReportDeadBody)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.ReportDeadBody)} to a specific player instead of broadcast.");
}
var deadBodyPlayerId = reader.ReadByte();
break;
}
// TODO: (ANTICHEAT) Cooldown check?
case RpcCalls.MurderPlayer:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} to a specific player instead of broadcast.");
}
if (!sender.Character.PlayerInfo.IsImpostor)
{
// TODO: Uncomment
// throw new ImpostorHackException($"Client sent {nameof(RpcCalls.MurderPlayer)} as crewmate.");
}
var player = reader.ReadNetObject<InnerPlayerControl>(_game);
break;
}
case RpcCalls.SendChat:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChat)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChat)} to a specific player instead of broadcast.");
}
var chat = reader.ReadString();
break;
}
case RpcCalls.StartMeeting:
{
if (!sender.IsHost)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.StartMeeting)} but was not a host.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.StartMeeting)} to a specific player instead of broadcast.");
}
var playerId = reader.ReadByte();
var player = _game.GameNet.GameData.GetPlayerById(playerId);
// Meeting started by "player", can also be null.
Console.WriteLine("ads");
break;
}
case RpcCalls.SetScanner:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetScanner)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetScanner)} to a specific player instead of broadcast.");
}
var on = reader.ReadBoolean();
var count = reader.ReadByte();
break;
}
case RpcCalls.SendChatNote:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChatNote)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChatNote)} to a specific player instead of broadcast.");
}
var playerId = reader.ReadByte();
var chatNote = (ChatNoteType)reader.ReadByte();
break;
}
case RpcCalls.SetPet:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetPet)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetPet)} to a specific player instead of broadcast.");
}
PlayerInfo.PetId = reader.ReadPackedUInt32();
break;
}
// TODO: Understand this RPC
case RpcCalls.SetStartCounter:
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetStartCounter)} to an unowned {nameof(InnerPlayerControl)}.");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetStartCounter)} to a specific player instead of broadcast.");
}
// Used to compare with LastStartCounter.
var startCounter = reader.ReadPackedUInt32();
// Is either start countdown or byte.MaxValue
var secondsLeft = reader.ReadByte();
break;
}
default:
_logger.LogWarning("InnerPlayerControl: Unknown rpc call {0}", call);
break;
@@ -121,5 +365,11 @@ namespace Impostor.Api.Innersloth.Net.Objects
PlayerId = reader.ReadByte();
}
private void Die(DeathReason reason)
{
PlayerInfo.IsDead = true;
PlayerInfo.LastDeathReason = reason;
}
}
}
@@ -39,7 +39,8 @@ namespace Impostor.Api.Innersloth.Net.Objects
Components.Add(this);
}
public override void HandleRpc(IClientPlayer sender, IClientPlayer target, RpcCalls call, IMessageReader reader)
public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call,
IMessageReader reader)
{
switch (call)
{
@@ -56,7 +57,7 @@ namespace Impostor.Api.Innersloth.Net.Objects
case RpcCalls.RepairSystem:
{
var systemType = (SystemTypes)reader.ReadByte();
var player = _game.FindObjectByNetId<InnerPlayerControl>(reader.ReadPackedUInt32());
var player = reader.ReadNetObject<InnerPlayerControl>(_game);
var amount = reader.ReadByte();
if (systemType == SystemTypes.Sabotage && !player.PlayerInfo.IsImpostor)
+8
View File
@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Impostor.Api.Games;
using Impostor.Api.Innersloth.Net;
using Impostor.Api.Innersloth.Net.Objects;
namespace Impostor.Api.Net
@@ -28,6 +29,13 @@ namespace Impostor.Api.Net
public bool IsHost { get; }
/// <summary>
/// Checks if the specified <see cref="InnerNetObject"/> is owned by <see cref="IClientPlayer"/>.
/// </summary>
/// <param name="netObject">The <see cref="InnerNetObject"/>.</param>
/// <returns>Returns true if owned by <see cref="IClientPlayer"/>.</returns>
bool IsOwner(InnerNetObject netObject);
ValueTask KickAsync();
ValueTask BanAsync();
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using Impostor.Api.Innersloth.Net;
using Impostor.Api.Innersloth.Net.Objects;
using Impostor.Api.Net;
@@ -26,6 +27,12 @@ namespace Impostor.Server.Net.State
public string Scene { get; internal set; }
/// <inheritdoc />
public bool IsOwner(InnerNetObject netObject)
{
return Client.Id == netObject.OwnerId;
}
/// <inheritdoc />
public ValueTask KickAsync()
{