Skip to content

Commit 8d0528c

Browse files
authored
fix(CaiBotLite): block unexpected netmodule packets (#1174)
* fix(CaiBotLite): block unexpected netmodule packet * feat(CaiBotLite): 在主线程新增登录队列,以缓解背包还原失败 * 更改 * fix review issues
1 parent a4e9c1d commit 8d0528c

4 files changed

Lines changed: 62 additions & 10 deletions

File tree

src/CaiBotLite/CaiBotLite.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace CaiBotLite;
1313
// ReSharper disable once ClassNeverInstantiated.Global
1414
public class CaiBotLite(Main game) : TerrariaPlugin(game)
1515
{
16-
public static readonly Version VersionNum = new (2026, 06, 21, 0);
16+
public static readonly Version VersionNum = new (2026, 07, 7, 0);
1717
internal static int InitCode = -1;
1818
internal static bool DebugMode = Program.LaunchParameters.ContainsKey("-caidebug");
1919
private const string CharacterInfoKey = "CaiBotLite.CharacterInfo";
@@ -45,6 +45,7 @@ public override void Initialize()
4545
ProgressControlSupport.Init();
4646
WebsocketManager.Init();
4747
Commands.ChatCommands.Add(new Command("caibotlite.admin", CaiBotCommand, "caibotlite", "cbl"));
48+
ClearCharacterInfoForActivePlayers();
4849
}
4950

5051
protected override void Dispose(bool disposing)
@@ -64,6 +65,7 @@ protected override void Dispose(bool disposing)
6465
PlayerHooks.PlayerPostLogin -= PlayerHooksOnPlayerPostLogin;
6566
GetDataHandlers.KillMe.UnRegister(KillMe);
6667
WebsocketManager.StopWebsocket();
68+
ClearCharacterInfoForActivePlayers();
6769
}
6870

6971
base.Dispose(disposing);
@@ -85,6 +87,7 @@ private static void OnGameUpdate(EventArgs args)
8587
}
8688

8789
_timer++;
90+
LoginHelper.ProcessLoginQueue();
8891
}
8992

9093
private static void KillMe(object? sender, GetDataHandlers.KillMeEventArgs e)
@@ -300,6 +303,14 @@ public static void GenBindCode(EventArgs? args)
300303
InitCode = new Random().Next(10000000, 99999999);
301304
TShock.Log.ConsoleError($"[CaiBotLite]您的服务器绑定码为: {InitCode}");
302305
}
306+
307+
private static void ClearCharacterInfoForActivePlayers()
308+
{
309+
foreach (var player in TShock.Players.Where(x => x is { Active: true }))
310+
{
311+
player.RemoveData(CharacterInfoKey);
312+
}
313+
}
303314

304315

305316
#region 加载前置
@@ -320,4 +331,4 @@ public static void GenBindCode(EventArgs? args)
320331
}
321332

322333
#endregion
323-
}
334+
}

src/CaiBotLite/Common/CaiBotApi.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ internal static void HandleMessage(string receivedData)
8888

8989
if (LoginHelper.CheckWhitelist(player, whitelistResult))
9090
{
91-
LoginHelper.HandleLogin(player);
91+
LoginHelper.PostLoginQueue(player);
9292
}
9393

9494
break;

src/CaiBotLite/Common/LoginHelper.cs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CaiBotLite.Enums;
2+
using System.Collections.Concurrent;
23
using Terraria;
34
using TerrariaApi.Server;
45
using TShockAPI;
@@ -9,6 +10,26 @@ namespace CaiBotLite.Common;
910

1011
internal static class LoginHelper
1112
{
13+
private static readonly ConcurrentQueue<TSPlayer> LoginQueue = new ();
14+
15+
internal static void PostLoginQueue(TSPlayer player)
16+
{
17+
LoginQueue.Enqueue(player);
18+
}
19+
20+
// 在主线程调用
21+
internal static void ProcessLoginQueue()
22+
{
23+
while (LoginQueue.TryDequeue(out var player))
24+
{
25+
if (!player.ConnectionAlive)
26+
{
27+
continue;
28+
}
29+
HandleLogin(player);
30+
}
31+
}
32+
1233
internal static void On_MessageBufferOnGetData(On.Terraria.MessageBuffer.orig_GetData orig, MessageBuffer self,
1334
int start, int length, out int messageType)
1435
{
@@ -83,6 +104,17 @@ internal static void OnGetData(GetDataEventArgs args)
83104
return;
84105
}
85106

107+
if (type == PacketTypes.LoadNetModule)
108+
{
109+
var moduleId = (GetDataHandlers.NetModuleType)args.Msg.reader.ReadUInt16();
110+
// 客户端疑似异常发送 CreativePowers
111+
if (moduleId != GetDataHandlers.NetModuleType.CreativePowers)
112+
{
113+
args.Handled = true;
114+
return;
115+
}
116+
}
117+
86118
if (type != PacketTypes.ContinueConnecting2)
87119
{
88120
return;
@@ -119,9 +151,7 @@ private static void Login(TSPlayer player, UserAccount account)
119151
player.PlayerData.CopyCharacter(player);
120152
TShock.CharacterDB.InsertPlayerData(player);
121153
}
122-
123-
// 调用两次以确保SSC角色数据稳定还原
124-
player.PlayerData.RestoreCharacter(player);
154+
125155
player.PlayerData.RestoreCharacter(player);
126156
}
127157

@@ -153,7 +183,7 @@ private static UserAccount Register(TSPlayer player)
153183
return account;
154184
}
155185

156-
internal static void HandleLogin(TSPlayer player)
186+
private static void HandleLogin(TSPlayer player)
157187
{
158188
if (player.Name == TSServerPlayer.AccountName)
159189
{

src/CaiBotLite/README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,29 @@ https://docs.terraria.ink/zh/caibot/CaiBotLite.html
2525
2626
```json5
2727
{
28-
"白名单开关": true, //Cai白名单的开关
29-
"密钥": "1145141919810", //由系统自动配置
30-
"白名单拦截提示的群号": 991556763 //为0时不显示群号
28+
"白名单开关": true,
29+
//Cai白名单的开关
30+
"密钥": "1145141919810",
31+
//由系统自动配置
32+
"白名单拦截提示的群号": 991556763
33+
//为0时不显示群号
3134
}
3235
```
3336

3437
## 更新日志
3538

39+
### v2026.7.7
40+
41+
- 新增登录队列,在主线程处理登录
42+
- 拦截非预期的NetModule包
43+
- 修复热重载导致CaiCharacterInfo报错
44+
3645
### v2026.3.11
46+
3747
- 将SSC登录还原改为重复两次以提升稳定性
3848

3949
### v2026.3.8
50+
4051
- 支持动态识别配置路径
4152

4253
### v2026.02.25.1

0 commit comments

Comments
 (0)