-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathNetModuleHandler.cs
More file actions
89 lines (80 loc) · 2.94 KB
/
Copy pathNetModuleHandler.cs
File metadata and controls
89 lines (80 loc) · 2.94 KB
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
using System.Runtime.CompilerServices;
using Terraria;
using Terraria.Net;
using TShockAPI;
namespace SkipVersionCheck;
/// <summary>
/// Hooks into Terraria's NetManager to filter outgoing NetModule packets
/// sent to cross-version clients. This prevents the server from sending
/// items/data that the client's version doesn't understand.
/// Ported from the Crossplay plugin by Moneylover3246.
/// </summary>
internal static class NetModuleHandler
{
/// <summary>
/// Replaces the default NetManager.Broadcast to filter per-client.
/// Instead of broadcasting to all, we check each client individually.
/// </summary>
internal static void OnBroadcast(
On.Terraria.Net.NetManager.orig_Broadcast_NetPacket_int orig,
NetManager self,
NetPacket packet,
int ignoreClient)
{
for (int i = 0; i < Main.maxPlayers; i++)
{
if (i != ignoreClient && Netplay.Clients[i].IsConnected())
{
if (!IsInvalidNetPacket(packet, i))
{
self.SendData(Netplay.Clients[i].Socket, packet);
}
}
}
}
/// <summary>
/// Wraps NetManager.SendToClient to filter packets for specific clients.
/// </summary>
internal static void OnSendToClient(
On.Terraria.Net.NetManager.orig_SendToClient orig,
NetManager self,
NetPacket packet,
int playerId)
{
if (!IsInvalidNetPacket(packet, playerId))
{
orig(self, packet, playerId);
}
}
/// <summary>
/// Check if a NetPacket contains data that's incompatible with the
/// target client's version. Currently checks for unsupported item IDs
/// in CreativeUnlocksPlayerReport packets (NetModule ID 5).
/// </summary>
private static bool IsInvalidNetPacket(NetPacket packet, int playerId)
{
// Only filter for cross-version clients
int clientVersion = SkipVersionCheck.Instance?.GetClientVersion(playerId) ?? 0;
if (clientVersion <= 0)
return false; // same version or not tracked
switch (packet.Id)
{
case 5: // CreativeUnlocksPlayerReport — contains item net IDs
{
if (packet.Buffer.Data.Length < 5)
return false;
var itemNetID = Unsafe.As<byte, short>(ref packet.Buffer.Data[3]);
int maxItems = SkipVersionCheck.Instance?.GetMaxItemsForVersion(clientVersion) ?? int.MaxValue;
if (itemNetID > maxItems)
{
TShock.Log.ConsoleDebug(
$"[SkipVersionCheck] Filtered NetModule packet (ID={packet.Id}) " +
$"with item {itemNetID} for client {playerId} (max={maxItems})");
return true;
}
}
break;
}
return false;
}
}