1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
using System.Numerics;
using System.Threading.Tasks;
using Impostor.Api;
using Impostor.Api.Innersloth;
using Impostor.Api.Net;
using Impostor.Api.Net.Messages;
using Impostor.Server.Net.State;
using Microsoft.Extensions.Logging;
namespace Impostor.Server.Net.Inner.Objects.Components
{
internal partial class InnerCustomNetworkTransform : InnerNetObject
{
private static readonly FloatRange XRange = new FloatRange(-40f, 40f);
private static readonly FloatRange YRange = new FloatRange(-40f, 40f);
private readonly ILogger<InnerCustomNetworkTransform> _logger;
private readonly InnerPlayerControl _playerControl;
private readonly Game _game;
private ushort _lastSequenceId;
private Vector2 _targetSyncPosition;
private Vector2 _targetSyncVelocity;
public InnerCustomNetworkTransform(ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, Game game)
{
_logger = logger;
_playerControl = playerControl;
_game = game;
}
private static bool SidGreaterThan(ushort newSid, ushort prevSid)
{
var num = (ushort)(prevSid + (uint) short.MaxValue);
return (int) prevSid < (int) num
? newSid > prevSid && newSid <= num
: newSid > prevSid || newSid <= num;
}
private static void WriteVector2(IMessageWriter writer, Vector2 vec)
{
writer.Write((ushort)(XRange.ReverseLerp(vec.X) * (double) ushort.MaxValue));
writer.Write((ushort)(YRange.ReverseLerp(vec.Y) * (double) ushort.MaxValue));
}
private static Vector2 ReadVector2(IMessageReader reader)
{
var v1 = reader.ReadUInt16() / (float) ushort.MaxValue;
var v2 = reader.ReadUInt16() / (float) ushort.MaxValue;
return new Vector2(XRange.Lerp(v1), YRange.Lerp(v2));
}
public override ValueTask HandleRpc(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
{
if (call == RpcCalls.SnapTo)
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} to an unowned {nameof(InnerPlayerControl)}");
}
if (target != null)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} to a specific player instead of broadcast");
}
if (!sender.Character.PlayerInfo.IsImpostor)
{
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} as crewmate");
}
SnapTo(ReadVector2(reader), reader.ReadUInt16());
}
else
{
_logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerCustomNetworkTransform), call);
}
return default;
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
if (initialState)
{
writer.Write(_lastSequenceId);
WriteVector2(writer, _targetSyncPosition);
WriteVector2(writer, _targetSyncVelocity);
return true;
}
// TODO: DirtyBits == 0 return false.
_lastSequenceId++;
writer.Write(_lastSequenceId);
WriteVector2(writer, _targetSyncPosition);
WriteVector2(writer, _targetSyncVelocity);
return true;
}
public override void Deserialize(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
{
var sequenceId = reader.ReadUInt16();
if (initialState)
{
_lastSequenceId = sequenceId;
_targetSyncPosition = ReadVector2(reader);
_targetSyncVelocity = ReadVector2(reader);
}
else
{
if (!sender.IsOwner(this))
{
throw new ImpostorCheatException($"Client attempted to send unowned {nameof(InnerCustomNetworkTransform)} data");
}
if (target != null)
{
throw new ImpostorCheatException($"Client attempted to send {nameof(InnerCustomNetworkTransform)} data to a specific player, must be broadcast");
}
if (!SidGreaterThan(sequenceId, _lastSequenceId))
{
return;
}
_lastSequenceId = sequenceId;
_targetSyncPosition = ReadVector2(reader);
_targetSyncVelocity = ReadVector2(reader);
}
}
private void SnapTo(Vector2 position, ushort minSid)
{
if (!SidGreaterThan(minSid, _lastSequenceId))
{
return;
}
_lastSequenceId = minSid;
_targetSyncPosition = position;
_targetSyncVelocity = Vector2.Zero;
}
}
}
|