-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEventHandler.cs
More file actions
269 lines (236 loc) · 10.4 KB
/
Copy pathEventHandler.cs
File metadata and controls
269 lines (236 loc) · 10.4 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
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
using System;
using System.Linq;
using System.Threading.Tasks;
using Terraria;
using TerrariaApi.Server;
using TShockAPI;
using TShockAPI.Hooks;
using System.Collections.Generic;
using Terraria.ID;
namespace PlayerMail
{
public static class EventHandler
{
// 存储未绑定邮箱的玩家
private static readonly HashSet<string> UnboundPlayers = new HashSet<string>();
// 定时任务取消标记
private static readonly Dictionary<string, bool> CancelTokens = new Dictionary<string, bool>();
// 消息冷却时间记录
private static readonly Dictionary<string, DateTime> MessageCooldowns = new Dictionary<string, DateTime>();
public static void RegisterEvents(PlayerMailPlugin plugin)
{
PlayerHooks.PlayerPostLogin += OnPlayerPostLogin;
PlayerHooks.PlayerChat += OnPlayerChat;
GetDataHandlers.Teleport += OnTeleport;
ServerApi.Hooks.GameUpdate.Register(plugin, OnGameUpdate);
GeneralHooks.ReloadEvent += OnReload;
ServerApi.Hooks.ServerLeave.Register(plugin, OnServerLeave);
}
public static void UnregisterEvents(PlayerMailPlugin plugin)
{
PlayerHooks.PlayerPostLogin -= OnPlayerPostLogin;
PlayerHooks.PlayerChat -= OnPlayerChat;
GetDataHandlers.Teleport -= OnTeleport;
ServerApi.Hooks.GameUpdate.Deregister(plugin, OnGameUpdate);
GeneralHooks.ReloadEvent -= OnReload;
ServerApi.Hooks.ServerLeave.Deregister(plugin, OnServerLeave);
}
private static void OnPlayerPostLogin(PlayerPostLoginEventArgs e)
{
var player = e.Player;
if (player == null || !player.IsLoggedIn) return;
var plugin = PlayerMailPlugin.Instance;
if (!plugin.Config.进服前强制邮箱验证) return;
// 检查是否已绑定邮箱
var data = plugin.DataStore.GetPlayerData(player.Name);
if (data != null) return; // 已绑定,正常进入
// 未绑定,加入限制列表
UnboundPlayers.Add(player.Name);
CancelTokens[player.Name] = false;
player.SendErrorMessage("[PlayerMail] 你尚未绑定邮箱,已被限制行动!");
player.SendErrorMessage("[PlayerMail] 请使用 /ml b <邮箱> 绑定邮箱解除限制");
// 立即施加Debuff并传送回出生点
ApplyRestrictions(player);
TeleportToSpawn(player);
// 启动定时任务持续施加Debuff
Task.Run(async () =>
{
while (!CancelTokens[player.Name] && player.Active && player.IsLoggedIn)
{
await System.Threading.Tasks.Task.Delay(2000); // 每2秒检查一次
if (player.Active && player.IsLoggedIn && UnboundPlayers.Contains(player.Name))
{
ApplyRestrictions(player);
}
}
});
}
private static void ApplyRestrictions(TSPlayer player)
{
if (player == null || !player.Active) return;
// 石化 (Stoned) - 无法移动、跳跃、使用物品
player.SetBuff(BuffID.Stoned, 300); // 5秒
// 冰冻 (Frozen) - 无法移动
player.SetBuff(BuffID.Frozen, 300); // 5秒
// 蛛网 (Webbed) - 减速并限制移动
player.SetBuff(BuffID.Webbed, 300); // 5秒
}
private static void ClearRestrictions(TSPlayer player)
{
if (player == null || !player.Active) return;
// TSPlayer 没有 ClearBuff 方法,通过 TPlayer 操作
var tplayer = player.TPlayer;
if (tplayer == null) return;
// 遍历所有buff槽位,清除目标Debuff
for (int i = 0; i < tplayer.buffType.Length; i++)
{
if (tplayer.buffType[i] == BuffID.Stoned ||
tplayer.buffType[i] == BuffID.Frozen ||
tplayer.buffType[i] == BuffID.Webbed)
{
tplayer.buffType[i] = 0;
tplayer.buffTime[i] = 0;
}
}
// 发送网络包同步buff状态
NetMessage.SendData((int)PacketTypes.PlayerBuff, -1, -1, null, player.Index);
}
private static void TeleportToSpawn(TSPlayer player)
{
if (player == null || !player.Active) return;
// 传送到出生点
var spawnX = Main.spawnTileX * 16;
var spawnY = Main.spawnTileY * 16;
player.Teleport(spawnX, spawnY);
}
private static void OnTeleport(object sender, GetDataHandlers.TeleportEventArgs args)
{
var player = args.Player;
if (player == null) return;
var plugin = PlayerMailPlugin.Instance;
if (!plugin.Config.进服前强制邮箱验证) return;
// 如果玩家未绑定邮箱且尝试传送,阻止并传回出生点
if (UnboundPlayers.Contains(player.Name))
{
args.Handled = true;
SendCooldownMessage(player, "[PlayerMail] 未绑定邮箱禁止使用传送!");
TeleportToSpawn(player);
ApplyRestrictions(player);
}
}
private static void OnGameUpdate(EventArgs args)
{
var plugin = PlayerMailPlugin.Instance;
if (!plugin.Config.进服前强制邮箱验证) return;
// 每帧检查未绑定玩家,防止移动(放宽检测)
foreach (var player in TShock.Players)
{
if (player == null || !player.Active || !player.IsLoggedIn) continue;
if (!UnboundPlayers.Contains(player.Name)) continue;
// 如果玩家位置偏离出生点太远,强制传回(500像素约31格)
var spawnX = Main.spawnTileX * 16;
var spawnY = Main.spawnTileY * 16;
var dist = System.Math.Sqrt(
System.Math.Pow(player.X - spawnX, 2) +
System.Math.Pow(player.Y - spawnY, 2)
);
if (dist > 500) // 距离出生点超过500像素(约31格)才触发
{
TeleportToSpawn(player);
ApplyRestrictions(player);
SendCooldownMessage(player, "[PlayerMail] 未绑定邮箱禁止离开出生点!");
}
}
}
// 发送带冷却的消息,防止刷屏
private static void SendCooldownMessage(TSPlayer player, string message)
{
if (!MessageCooldowns.TryGetValue(player.Name, out var last) ||
(DateTime.Now - last).TotalSeconds >= 5)
{
MessageCooldowns[player.Name] = DateTime.Now;
player.SendErrorMessage(message);
}
}
private static void OnPlayerChat(PlayerChatEventArgs args)
{
if (args.Handled) return;
var player = args.Player;
if (player == null || !player.IsLoggedIn) return;
// 如果玩家处于未绑定状态,只允许绑定相关的命令
if (UnboundPlayers.Contains(player.Name))
{
var text = args.RawText.Trim();
// 允许 /ml b 和 /ml v 命令
if (text.StartsWith("/ml b") || text.StartsWith("/ml v") || text.StartsWith("/ml bind") || text.StartsWith("/ml verify"))
{
return; // 不拦截,让命令正常执行
}
// 拦截其他所有聊天和命令
if (!text.StartsWith("/ml"))
{
player.SendErrorMessage("[PlayerMail] 未绑定邮箱,只能使用 /ml b <邮箱> 和 /ml v <验证码> 命令!");
args.Handled = true;
}
}
}
// 供 CommandHandler 调用,绑定成功后解除限制
public static void ReleasePlayer(string playerName)
{
if (UnboundPlayers.Contains(playerName))
{
UnboundPlayers.Remove(playerName);
CancelTokens[playerName] = true;
MessageCooldowns.Remove(playerName);
var player = TShock.Players.FirstOrDefault(p => p != null && p.Active && p.Name == playerName);
if (player != null)
{
// 清除Debuff
ClearRestrictions(player);
player.SendSuccessMessage("[PlayerMail] 邮箱绑定成功,限制已解除!");
}
}
}
// 供 CommandHandler 调用,解绑后加入限制
public static void RestrictPlayer(string playerName)
{
var player = TShock.Players.FirstOrDefault(p => p != null && p.Active && p.Name == playerName);
if (player != null)
{
UnboundPlayers.Add(playerName);
CancelTokens[playerName] = false;
ApplyRestrictions(player);
TeleportToSpawn(player);
player.SendErrorMessage("[PlayerMail] 邮箱已解绑,你已被限制行动!");
player.SendErrorMessage("[PlayerMail] 请使用 /ml b <邮箱> 重新绑定解除限制");
// 启动定时任务
Task.Run(async () =>
{
while (!CancelTokens[playerName] && player.Active && player.IsLoggedIn)
{
await System.Threading.Tasks.Task.Delay(2000);
if (player.Active && player.IsLoggedIn && UnboundPlayers.Contains(playerName))
{
ApplyRestrictions(player);
}
}
});
}
}
private static void OnServerLeave(LeaveEventArgs args)
{
var player = TShock.Players[args.Who];
if (player != null)
{
UnboundPlayers.Remove(player.Name);
CancelTokens[player.Name] = true;
MessageCooldowns.Remove(player.Name);
}
}
private static void OnReload(ReloadEventArgs args)
{
ConfigLoader.Reload();
args.Player?.SendSuccessMessage("[PlayerMail] 配置与数据已重载");
}
}
}