Skip to content

Commit e93b212

Browse files
Merge pull request #18 from 1242509682/master
添加了:数据包拦截插件
2 parents c2146d9 + 8c2cca9 commit e93b212

File tree

5 files changed

+368
-37
lines changed

5 files changed

+368
-37
lines changed

PacketsStop/Configuration.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using Newtonsoft.Json;
2+
using TShockAPI;
3+
4+
namespace PacketsStop
5+
{
6+
public class Configuration
7+
{
8+
[JsonProperty("数据包名可查看")]
9+
public string README = "https://github.com/Pryaxis/TSAPI/blob/general-devel/TerrariaServerAPI/TerrariaApi.Server/PacketTypes.cs";
10+
11+
[JsonProperty("插件指令与权限名")]
12+
public string README2 = "拦截";
13+
14+
[JsonProperty("第一次使用输这个")]
15+
public string README3 = "/group addperm default 免拦截";
16+
17+
[JsonProperty("拦截的数据包名")]
18+
public HashSet<string> Packets { get; set; } = new HashSet<string>();
19+
20+
public static readonly string FilePath = Path.Combine(TShock.SavePath, "数据包拦截.json");
21+
22+
23+
public Configuration()
24+
{
25+
Packets = new HashSet<string>
26+
{
27+
"ConnectRequest",
28+
"Disconnect",
29+
"ContinueConnecting",
30+
"ContinueConnecting2",
31+
"PlayerInfo",
32+
"PlayerSlot",
33+
"TileGetSection",
34+
"PlayerSpawn",
35+
"ProjectileNew",
36+
"ProjectileDestroy",
37+
"SyncProjectileTrackers",
38+
};
39+
}
40+
41+
public void Write(string path)
42+
{
43+
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write))
44+
{
45+
var str = JsonConvert.SerializeObject(this, Formatting.Indented);
46+
using (var sw = new StreamWriter(fs))
47+
{
48+
sw.Write(str);
49+
}
50+
}
51+
}
52+
53+
public static Configuration Read(string path)
54+
{
55+
if (!File.Exists(path))
56+
{
57+
var defaultConfig = new Configuration();
58+
defaultConfig.Write(path);
59+
return defaultConfig;
60+
}
61+
else
62+
{
63+
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
64+
using (var sr = new StreamReader(fs))
65+
{
66+
var json = sr.ReadToEnd();
67+
var cf = JsonConvert.DeserializeObject<Configuration>(json);
68+
return cf;
69+
}
70+
}
71+
}
72+
}
73+
}

PacketsStop/PacketsStop.cs

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
using Terraria;
2+
using TerrariaApi.Server;
3+
using TShockAPI;
4+
using TShockAPI.Hooks;
5+
6+
namespace PacketsStop
7+
{
8+
[ApiVersion(2, 1)]
9+
public class PacketsStop : TerrariaPlugin
10+
{
11+
12+
public override string Name => "数据包拦截 PacketsStop";
13+
public override Version Version => new Version(1, 0, 0);
14+
public override string Author => "羽学 感谢少司命";
15+
public override string Description => "拦截没有指定权限的用户组数据包";
16+
17+
#region 配置方法的工具
18+
private readonly Dictionary<string, Dictionary<PacketTypes, DateTime>> countDictionary = new Dictionary<string, Dictionary<PacketTypes, DateTime>>();
19+
private const double PacketInterval = 1000.0;
20+
private bool _Enabled = false;
21+
internal static Configuration Config;
22+
private HashSet<PacketTypes> Packets;
23+
#endregion
24+
25+
public PacketsStop(Main game) : base(game)
26+
{
27+
Config = new Configuration();
28+
}
29+
30+
public override void Initialize()
31+
{
32+
LoadConfig();
33+
Packets = GetPackets();
34+
ServerApi.Hooks.NetGetData.Register(this, OnGetData, int.MaxValue);
35+
Commands.ChatCommands.Add(new Command("拦截", Command, "拦截"));
36+
GeneralHooks.ReloadEvent += LoadConfig;
37+
}
38+
39+
protected override void Dispose(bool disposing)
40+
{
41+
if (disposing)
42+
{
43+
ServerApi.Hooks.NetGetData.Deregister(this, OnGetData);
44+
}
45+
base.Dispose(disposing);
46+
}
47+
48+
#region 配置文件创建与重读加载方法
49+
private static void LoadConfig(ReloadEventArgs args = null)
50+
{
51+
if (!File.Exists(Configuration.FilePath))
52+
{
53+
var defaultConfig = new Configuration();
54+
defaultConfig.Write(Configuration.FilePath);
55+
}
56+
else
57+
{
58+
Config = Configuration.Read(Configuration.FilePath);
59+
}
60+
61+
if (args != null && args.Player != null)
62+
{
63+
args.Player.SendSuccessMessage("[数据包拦截]重新加载配置完毕。");
64+
}
65+
}
66+
#endregion
67+
68+
#region 指令
69+
70+
71+
private void Command(CommandArgs args)
72+
{
73+
if (args.Player != null && !args.Player.HasPermission("拦截"))
74+
{
75+
args.Player.SendErrorMessage("你没有使用数据包拦截的权限");
76+
return;
77+
}
78+
else
79+
{
80+
_Enabled = !_Enabled;
81+
TSPlayer.All.SendInfoMessage($"[数据包拦截]已{(_Enabled ? "启用" : "禁用")}");
82+
}
83+
84+
85+
if (args.Parameters.Count != 2)
86+
{
87+
args.Player.SendInfoMessage("/拦截 add 玩家名 - 将玩家添加到LJ组(不存在自动创建)。\n/拦截 del 玩家名 - 将玩家从LJ组移除并设为default组。");
88+
return;
89+
}
90+
91+
string Action = args.Parameters[0];
92+
string Name = args.Parameters[1];
93+
var Account = TShock.UserAccounts.GetUserAccountByName(Name);
94+
95+
if (Account == null)
96+
{
97+
args.Player.SendInfoMessage($"无法找到名为'{Name}'的在线玩家。");
98+
return;
99+
}
100+
101+
switch (Action.ToLower())
102+
{
103+
case "add":
104+
if (!TShock.Groups.GroupExists("LJ"))
105+
{
106+
TShock.Groups.AddGroup("LJ", "", "tshock.canchat,tshock,tshock.partychat,tshock.sendemoji", "045,235,203");
107+
args.Player.SendSuccessMessage("LJ组已创建。");
108+
}
109+
110+
try
111+
{
112+
TShock.UserAccounts.SetUserGroup(Account, "LJ");
113+
args.Player.SendSuccessMessage($"{Name}已被设为LJ组成员。");
114+
}
115+
catch (Exception ex)
116+
{
117+
args.Player.SendErrorMessage($"无法将{Name}设为LJ组成员。错误信息: \n{ex.Message}");
118+
}
119+
break;
120+
case "del":
121+
try
122+
{
123+
TShock.UserAccounts.SetUserGroup(Account, "default");
124+
args.Player.SendSuccessMessage($"{Name}已从LJ组移除,并被设为default组。");
125+
}
126+
catch (Exception ex)
127+
{
128+
args.Player.SendErrorMessage($"无法将{Name}从LJ组移除或设为default组。错误信息: \n{ex.Message}");
129+
}
130+
break;
131+
default:
132+
args.Player.SendInfoMessage("无效的子命令。使用 'add' 或 'del'。");
133+
break;
134+
}
135+
}
136+
#endregion
137+
138+
#region 获取数据包方法
139+
private void OnGetData(GetDataEventArgs args)
140+
{
141+
TSPlayer player = TShock.Players[args.Msg.whoAmI];
142+
143+
if (!_Enabled ||! Packets.Contains(args.MsgID))
144+
{
145+
return;
146+
}
147+
148+
if (!player.HasPermission("免拦截"))
149+
{
150+
151+
HandlePacket(player, args.MsgID);
152+
}
153+
}
154+
155+
private HashSet<PacketTypes> GetPackets()
156+
{
157+
HashSet<PacketTypes> Packets = new HashSet<PacketTypes>();
158+
foreach (string packetName in Config.Packets)
159+
{
160+
if (Enum.TryParse(packetName, out PacketTypes packetType))
161+
{
162+
Packets.Add(packetType);
163+
}
164+
else
165+
{
166+
TShock.Log.Error($"无法识别的数据包类型名称: {packetName}");
167+
}
168+
}
169+
return Packets;
170+
}
171+
#endregion
172+
173+
#region 处理数据包方法
174+
private void HandlePacket(TSPlayer args, PacketTypes packetType)
175+
{
176+
if (_Enabled)
177+
{
178+
DateTime now = DateTime.Now;
179+
if (args.Name != null)
180+
{
181+
if (!countDictionary.TryGetValue(args.Name, out var packetDictionary))
182+
{
183+
packetDictionary = new Dictionary<PacketTypes, DateTime>();
184+
countDictionary[args.Name] = packetDictionary;
185+
}
186+
if (packetDictionary.TryGetValue(packetType, out DateTime lastPacketTime))
187+
{
188+
if ((now - lastPacketTime).TotalMilliseconds >= PacketInterval)
189+
{
190+
packetDictionary[packetType] = now;
191+
}
192+
}
193+
else
194+
{
195+
packetDictionary[packetType] = now;
196+
}
197+
}
198+
}
199+
}
200+
#endregion
201+
}
202+
}

PacketsStop/PacketsStop.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<Import Project="..\template.targets"/>
3+
</Project>

PacketsStop/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# PacketsStop 数据包拦截
2+
3+
- 作者: 羽学
4+
- 出处: [github](https://github.com/1242509682/PacketsStop/)
5+
- 插件源码来于少司命的游客限制插件,将其处理数据包方法做成了一个独立的功能插件
6+
- 这是一个Tshock服务器插件主要用于:
7+
- 使用指令开启拦截玩家数据包
8+
- 使用前必须先给default组一个权限【免拦截】
9+
- 接着通过修改配置文件添加数据包名使用/reload重载
10+
- 输入【/拦截 add 名字】将玩家分配到一个新建的【LJ组】
11+
- 封锁了大部分可用权限并对其数据包拦截。
12+
## 更新日志
13+
14+
```
15+
- 2.0
16+
- 修复数据包拦截插件的GetPacket逻辑:原对配置文件内的数据包名以外的全部拦截问题已修复
17+
- 1.0
18+
- 将少司命的游客限制插件处理数据包方法,做成了一个独立的功能插件。
19+
```
20+
## 指令
21+
22+
| 语法 | 权限 | 说明 |
23+
| -------------- | :-----------------: | :------: |
24+
| /拦截 | 拦截 | 开启功能 |
25+
| /拦截 add 玩家名 | 拦截 |添加拦截指定玩家并分配到一个自动创建的LJ组|
26+
| /拦截 del 玩家名 | 拦截 |移除拦截指定玩家并分配回default组|
27+
|| 免拦截 | 不受插件数据包拦截影响 |
28+
29+
## 配置
30+
31+
```json
32+
{
33+
"数据包名可查看": "https://github.com/Pryaxis/TSAPI/blob/general-devel/TerrariaServerAPI/TerrariaApi.Server/PacketTypes.cs",
34+
"插件指令与权限名": "拦截",
35+
"第一次使用输这个": "/group addperm default 免拦截",
36+
"拦截的数据包名": [
37+
"ConnectRequest",
38+
"Disconnect",
39+
"ContinueConnecting",
40+
"ContinueConnecting2",
41+
"PlayerInfo",
42+
"PlayerSlot",
43+
"TileGetSection",
44+
"PlayerSpawn",
45+
"ProjectileNew",
46+
"ProjectileDestroy",
47+
"SyncProjectileTrackers"
48+
]
49+
}
50+
```
51+
## 反馈
52+
- 共同维护的插件库:https://github.com/THEXN/TShockPlugin/
53+
- 国内社区trhub.cn 或 TShock官方群等

0 commit comments

Comments
 (0)