Skip to content

Commit 695b425

Browse files
committed
v2.3.0 支持将玩家消息转换为系统消息
1 parent 7d972ec commit 695b425

8 files changed

Lines changed: 175 additions & 31 deletions

File tree

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,13 @@ dev:
3131
# 是否对输入的 JSON 进行序列化, 修改它可能影响现有的配置
3232
# CreatePacket = 使用 protocolLib 创建新数据包再解析, 这没有意义
3333
# ComponentSerializer = 这会使 JSON 内部的顺序发生变化, 并可能丢失部分原版消息
34-
# NONE = 不进行序列化
34+
# NONE = 不进行序列化
3535
serializedInput: NONE
36+
# 将玩家消息转换为系统消息
37+
# Convert = 转换消息并进行替换
38+
# ConvertBypass = 转换消息并绕过替换
39+
# NONE = 禁用此功能
40+
convertPlayerMessages: NONE
3641

3742
list: # 替换列表
3843

@@ -64,13 +69,13 @@ list: # 替换列表
6469
# [可选] 仅对拥有该权限的玩家处理这条消息, 默认所有玩家
6570
- permission: 'minecraft.command'
6671
# [必选] 检查消息长度是否在此区间内
67-
# [50, 64] = 大于等于50且小于等于64
72+
# [50, 64] = 大于等于 50 且小于等于 64
6873
# [64] = 等于 64
6974
inspectLength: [50, 64]
7075
# [必选] 使用正则表达式匹配
7176
get: '^\{"text":"","extra":\["Missing required argument (\d+)"\]\}$'
7277
# [必选] 将消息替换为
73-
# _$1_ = 正则匹配到的变量 1, 也可以是 `_$2_` (第 2 个变量)...
78+
# _$1_ = 正则匹配到的变量 1, 也可以是 _$2_ (第 2 个变量)...
7479
# _$1:ItemType_ = 将 _$1_ 用于获取物品类型, 提供给 JSON hoverEvent 使用的物品类型 show_entity, show_item(block)
7580
# _$1:TranslatedName_ = 将 _$1_ 用于名称翻译, 返回与语言路径对应的 KEY, 例如 `entity.minecraft.allay`
7681
# _$1:Words:组名_ = 将 _$1_ 用于词替换, 需要配置 words.yml
@@ -91,8 +96,8 @@ list: # 替换列表
9196
displayObject: ''
9297
# [可选] 继承和其他配置. 将多个配置合并为组, 同时处理来提高性能
9398
# LINK = 与下一条配置合并为组, 将此配置处理完毕的内容传递给下一条配置, 请确保存在下一条配置
94-
# LINK_SER = 使 GROUP 传递序列化后的 JSON 文本
95-
# CLOSE = 如果匹配, 则立即退出匹配检查循环, 不再处理任何数据
99+
# LINK_SER = 使 LINK 传递序列化后的 JSON 文本, 需要开启序列化功能
100+
# CLOSE = 如果匹配, 则停止处理这条消息, 可用于排除一些被高频发送的消息
96101
inherit: ''
97102

98103
```

README_MCBBS.txt

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ https://github.com/ApliNi/useTranslatedNames
1313

1414
---
1515

16+
## useTranslatedNames
17+
内置获取翻译名功能的JSON字符串替换插件, 可用于消息替换和翻译 CoreProtect 等插件的消息
18+
19+
![](https://github.com/ApliNi/useTranslatedNames/blob/main/_img/%E6%95%88%E6%9E%9C%E5%9B%BE.png)
20+
21+
下载: https://modrinth.com/plugin/usetranslatednames
22+
23+
---
24+
1625
## 功能和指令
1726
- `/utn` 显示插件信息和统计数据
1827
- `/utn json <JSON>` - 测试 JSON 字符串
@@ -37,8 +46,13 @@ dev:
3746
# 是否对输入的 JSON 进行序列化, 修改它可能影响现有的配置
3847
# CreatePacket = 使用 protocolLib 创建新数据包再解析, 这没有意义
3948
# ComponentSerializer = 这会使 JSON 内部的顺序发生变化, 并可能丢失部分原版消息
40-
# NONE = 不进行序列化
49+
# NONE = 不进行序列化
4150
serializedInput: NONE
51+
# 将玩家消息转换为系统消息
52+
# Convert = 转换消息并进行替换
53+
# ConvertBypass = 转换消息并绕过替换
54+
# NONE = 禁用此功能
55+
convertPlayerMessages: NONE
4256

4357
list: # 替换列表
4458

@@ -70,13 +84,13 @@ list: # 替换列表
7084
# [可选] 仅对拥有该权限的玩家处理这条消息, 默认所有玩家
7185
- permission: 'minecraft.command'
7286
# [必选] 检查消息长度是否在此区间内
73-
# [50, 64] = 大于等于50且小于等于64
87+
# [50, 64] = 大于等于 50 且小于等于 64
7488
# [64] = 等于 64
7589
inspectLength: [50, 64]
7690
# [必选] 使用正则表达式匹配
7791
get: '^\{"text":"","extra":\["Missing required argument (\d+)"\]\}$'
7892
# [必选] 将消息替换为
79-
# _$1_ = 正则匹配到的变量 1, 也可以是 `_$2_` (第 2 个变量)...
93+
# _$1_ = 正则匹配到的变量 1, 也可以是 _$2_ (第 2 个变量)...
8094
# _$1:ItemType_ = 将 _$1_ 用于获取物品类型, 提供给 JSON hoverEvent 使用的物品类型 show_entity, show_item(block)
8195
# _$1:TranslatedName_ = 将 _$1_ 用于名称翻译, 返回与语言路径对应的 KEY, 例如 `entity.minecraft.allay`
8296
# _$1:Words:组名_ = 将 _$1_ 用于词替换, 需要配置 words.yml
@@ -97,8 +111,8 @@ list: # 替换列表
97111
displayObject: ''
98112
# [可选] 继承和其他配置. 将多个配置合并为组, 同时处理来提高性能
99113
# LINK = 与下一条配置合并为组, 将此配置处理完毕的内容传递给下一条配置, 请确保存在下一条配置
100-
# LINK_SER = 使 GROUP 传递序列化后的 JSON 文本
101-
# CLOSE = 如果匹配, 则立即退出匹配检查循环, 不再处理任何数据
114+
# LINK_SER = 使 LINK 传递序列化后的 JSON 文本, 需要开启序列化功能
115+
# CLOSE = 如果匹配, 则停止处理这条消息, 可用于排除一些被高频发送的消息
102116
inherit: ''
103117

104118
```

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>io.github.aplini</groupId>
88
<artifactId>useTranslatedNames</artifactId>
9-
<version>2.2.0</version>
9+
<version>2.3.0</version>
1010

1111
<name>useTranslatedNames</name>
1212

src/main/java/aplini/usetranslatednames/Enum/Key.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@ public enum Key {
1717
GetStrings,
1818
CreatePacket,
1919
ComponentSerializer,
20+
Convert,
21+
ConvertBypass,
22+
NONE,
2023
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package aplini.usetranslatednames.Enum;
22

33
public class Status {
4-
public long Messages = 0;
5-
public long Matches = 0;
4+
// 消息总数
5+
public long MsgCount = 0;
6+
// 成功匹配次数
7+
public long MatchesCount = 0;
8+
// 总计耗时
69
public double TotalTime = 0;
710
}

src/main/java/aplini/usetranslatednames/UseTranslatedNames.java

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
import org.bukkit.command.TabExecutor;
2222
import org.bukkit.configuration.file.YamlConfiguration;
2323
import org.bukkit.entity.Player;
24+
import org.bukkit.event.EventHandler;
25+
import org.bukkit.event.HandlerList;
2426
import org.bukkit.event.Listener;
27+
import org.bukkit.event.player.AsyncPlayerChatEvent;
2528
import org.bukkit.plugin.java.JavaPlugin;
2629

2730
import java.io.File;
@@ -34,6 +37,8 @@
3437

3538
public final class UseTranslatedNames extends JavaPlugin implements CommandExecutor, TabExecutor, Listener {
3639

40+
public static UseTranslatedNames plugin;
41+
3742
// 用户配置版本
3843
public static int _configVersion;
3944
// 解析器模式
@@ -48,31 +53,48 @@ public final class UseTranslatedNames extends JavaPlugin implements CommandExecu
4853
int listSize = 0;
4954

5055
// 调试模式
51-
private int _debug = 0;
56+
public static int _debug = 0;
5257

5358
// 记录统计信息
54-
Status status = new Status();
59+
static Status status = new Status();
5560

5661
// 用于静默发送聊天消息, 绕过消息监听器
57-
private ProtocolManager protocolManager;
62+
public static ProtocolManager protocolManager;
5863

5964

6065
@Override
6166
public void onEnable() {
67+
plugin = this;
6268
loadConfig();
6369
Util.load(this);
6470

6571
// bStats
66-
if(getConfig().getBoolean("bStats", true)){
67-
new Metrics(this, 20766);
68-
}
72+
// 收集一些性能数据和消息总数
73+
Metrics metrics = new Metrics(this, 20766);
74+
// 平均消息延迟
75+
metrics.addCustomChart(new Metrics.SimplePie("AverageTime", () -> {
76+
double TotalTime = status.TotalTime / 1_000_000.0;
77+
double AverageTime = TotalTime / status.MsgCount;
78+
return String.format("%.2f", AverageTime) +"ms";
79+
}));
80+
// 其他统计信息
81+
// metrics.addCustomChart(new Metrics.MultiLineChart("Status", () -> {
82+
// Map<String, Integer> map = new HashMap<>();
83+
// map.put("NumberOfMessages", Math.toIntExact(status.MsgCount));
84+
// map.put("NumberOfMatches", Math.toIntExact(status.MatchesCount));
85+
// map.put("NumberOfTotalTime", Math.toIntExact(Math.round(status.TotalTime / 1e9)));
86+
// return map;
87+
// }));
88+
metrics.addCustomChart(new Metrics.SingleLineChart("MsgCount", () -> Math.toIntExact(status.MsgCount)));
89+
metrics.addCustomChart(new Metrics.SingleLineChart("MatchesCount", () -> Math.toIntExact(status.MatchesCount)));
90+
metrics.addCustomChart(new Metrics.SingleLineChart("TotalTime", () -> Math.toIntExact(Math.round(status.TotalTime / 1e9))));
6991

7092
// 注册指令
7193
Objects.requireNonNull(getCommand("utn")).setExecutor(this);
7294

95+
// 用于静默发送聊天消息, 绕过消息监听器
7396
protocolManager = ProtocolLibrary.getProtocolManager();
7497

75-
7698
// 添加一个数据包监听器
7799
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(this,
78100
ListenerPriority.LOW, // 监听器优先级
@@ -114,7 +136,7 @@ public void onPacketSending(PacketEvent event){
114136
}
115137

116138
// 记录运行时间
117-
status.Messages ++;
139+
status.MsgCount++;
118140
status.TotalTime += System.nanoTime() - _startTime;
119141
}
120142
});
@@ -169,7 +191,7 @@ public boolean runJsonTestReplaceConfig(PacketEvent event, Player player, String
169191
Matcher matcher = cli.regExp.matcher(jsonTest);
170192
while(matcher.find()){
171193

172-
status.Matches ++;
194+
status.MatchesCount++;
173195

174196
if(_debug >= 4){
175197
getLogger().info(" - [HIT]");
@@ -418,10 +440,42 @@ public long loadConfig(){
418440
}
419441
listSize = list.size();
420442

443+
// 配置玩家消息监听器
444+
onPlayerChat.mode = switch(getConfig().getString("dev.convertPlayerMessages", "NONE")){
445+
case "Convert" -> Key.Convert;
446+
case "ConvertBypass" -> Key.ConvertBypass;
447+
default -> Key.NONE;
448+
};
449+
// 注册和注销监听器
450+
if(onPlayerChat.mode == Key.NONE){
451+
if(onPlayerChat.func != null){
452+
HandlerList.unregisterAll(onPlayerChat.func);
453+
onPlayerChat.func = null;
454+
}
455+
}else{
456+
if(onPlayerChat.func == null){
457+
onPlayerChat.func = new onPlayerChat();
458+
getServer().getPluginManager().registerEvents(onPlayerChat.func, this);
459+
}
460+
}
461+
421462
return Math.round((System.nanoTime() - _startTime) / 1_000_000.0);
422463
}
423464

424465

466+
@EventHandler
467+
public void onPlayerChat(AsyncPlayerChatEvent event){
468+
String message = event.getMessage();
469+
470+
// 在这里处理玩家发送的消息
471+
// 你可以根据需要进行逻辑处理或条件检查
472+
473+
// 示例:将玩家发送的消息改为大写
474+
String upperCaseMessage = message.toUpperCase();
475+
event.setMessage(upperCaseMessage);
476+
}
477+
478+
425479
@Override // 指令补全
426480
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
427481
if(args.length == 1){
@@ -443,10 +497,10 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
443497
return null;
444498
}
445499
@Override // 执行指令
446-
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
500+
public boolean onCommand(CommandSender sender, Command command, String label, String[] args){
447501

448502
double TotalTime = status.TotalTime / 1_000_000.0;
449-
double AverageTime = TotalTime / status.Messages;
503+
double AverageTime = TotalTime / status.MsgCount;
450504

451505
// 默认输出插件信息
452506
if(args.length == 0){
@@ -458,8 +512,8 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
458512
" - /utn reload - 重载配置\n"+
459513
" - /utn debug [Level] - 调试模式\n"+
460514
" 统计信息:\n"+
461-
" - 监听消息: "+ status.Messages +"\n"+
462-
" - 成功匹配: "+ status.Matches +"\n"+
515+
" - 监听消息: "+ status.MsgCount +"\n"+
516+
" - 成功匹配: "+ status.MatchesCount +"\n"+
463517
" - 平均延迟: "+ String.format("%.2f", AverageTime) +" ms [累计: "+ String.format("%.2f", TotalTime) +" ms]\n"
464518
);
465519
return true;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package aplini.usetranslatednames;
2+
3+
import aplini.usetranslatednames.Enum.Key;
4+
import com.comphenix.protocol.PacketType;
5+
import com.comphenix.protocol.events.PacketContainer;
6+
import com.comphenix.protocol.wrappers.WrappedChatComponent;
7+
import net.md_5.bungee.api.chat.TextComponent;
8+
import org.bukkit.Bukkit;
9+
import org.bukkit.entity.Player;
10+
import org.bukkit.event.EventHandler;
11+
import org.bukkit.event.EventPriority;
12+
import org.bukkit.event.Listener;
13+
import org.bukkit.event.player.AsyncPlayerChatEvent;
14+
15+
import java.util.concurrent.CompletableFuture;
16+
17+
import static aplini.usetranslatednames.UseTranslatedNames.*;
18+
19+
public class onPlayerChat implements Listener {
20+
21+
static onPlayerChat func = null;
22+
static Key mode;
23+
24+
@EventHandler(priority = EventPriority.HIGHEST)
25+
public void onAsyncPlayerChatEvent(AsyncPlayerChatEvent event){
26+
// 取消发送消息
27+
event.setCancelled(true);
28+
29+
CompletableFuture.runAsync(() -> {
30+
31+
Player player = event.getPlayer();
32+
// 获取已格式化的消息
33+
String msg = String.format(event.getFormat(), player.getName(), event.getMessage());
34+
35+
if(_debug >= 1){
36+
plugin.getLogger().info("");
37+
plugin.getLogger().info("");
38+
plugin.getLogger().info("[DEBUG] [PlayerChat] [Player: "+ event.getPlayer().getName() +
39+
", Lang: "+ player.getLocale() +"] [Length: "+ msg.length() +"], [MODE: "+ mode.toString() +"]");
40+
if(_debug >= 2){
41+
plugin.getLogger().info(" - [FORMAT]: "+ event.getFormat());
42+
plugin.getLogger().info(" - [MSG]: "+ event.getMessage());
43+
plugin.getLogger().info(" - [GET]: "+ msg);
44+
}
45+
}
46+
Bukkit.getConsoleSender().sendMessage(msg);
47+
switch(mode){
48+
case Convert -> Bukkit.spigot().broadcast(new TextComponent(msg));
49+
case ConvertBypass -> {
50+
// 静默发送消息给每个玩家
51+
PacketContainer chatPacket = protocolManager.createPacket(PacketType.Play.Server.SYSTEM_CHAT);
52+
chatPacket.getChatComponents().write(0, WrappedChatComponent.fromText(msg));
53+
for(Player li : Bukkit.getOnlinePlayers()){
54+
protocolManager.sendServerPacket(li, chatPacket, false);
55+
}
56+
}
57+
}
58+
});
59+
}
60+
}

src/main/resources/config.yml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ dev:
1111
# 是否对输入的 JSON 进行序列化, 修改它可能影响现有的配置
1212
# CreatePacket = 使用 protocolLib 创建新数据包再解析, 这没有意义
1313
# ComponentSerializer = 这会使 JSON 内部的顺序发生变化, 并可能丢失部分原版消息
14-
# NONE = 不进行序列化
14+
# NONE = 不进行序列化
1515
serializedInput: NONE
16+
# 将玩家消息转换为系统消息
17+
# Convert = 转换消息并进行替换
18+
# ConvertBypass = 转换消息并绕过替换
19+
# NONE = 禁用此功能
20+
convertPlayerMessages: NONE
1621

1722
list: # 替换列表
1823

@@ -44,13 +49,13 @@ list: # 替换列表
4449
# [可选] 仅对拥有该权限的玩家处理这条消息, 默认所有玩家
4550
- permission: 'minecraft.command'
4651
# [必选] 检查消息长度是否在此区间内
47-
# [50, 64] = 大于等于50且小于等于64
52+
# [50, 64] = 大于等于 50 且小于等于 64
4853
# [64] = 等于 64
4954
inspectLength: [50, 64]
5055
# [必选] 使用正则表达式匹配
5156
get: '^\{"text":"","extra":\["Missing required argument (\d+)"\]\}$'
5257
# [必选] 将消息替换为
53-
# _$1_ = 正则匹配到的变量 1, 也可以是 `_$2_` (第 2 个变量)...
58+
# _$1_ = 正则匹配到的变量 1, 也可以是 _$2_ (第 2 个变量)...
5459
# _$1:ItemType_ = 将 _$1_ 用于获取物品类型, 提供给 JSON hoverEvent 使用的物品类型 show_entity, show_item(block)
5560
# _$1:TranslatedName_ = 将 _$1_ 用于名称翻译, 返回与语言路径对应的 KEY, 例如 `entity.minecraft.allay`
5661
# _$1:Words:组名_ = 将 _$1_ 用于词替换, 需要配置 words.yml
@@ -71,6 +76,6 @@ list: # 替换列表
7176
displayObject: ''
7277
# [可选] 继承和其他配置. 将多个配置合并为组, 同时处理来提高性能
7378
# LINK = 与下一条配置合并为组, 将此配置处理完毕的内容传递给下一条配置, 请确保存在下一条配置
74-
# LINK_SER = 使 GROUP 传递序列化后的 JSON 文本
75-
# CLOSE = 如果匹配, 则立即退出匹配检查循环, 不再处理任何数据
79+
# LINK_SER = 使 LINK 传递序列化后的 JSON 文本, 需要开启序列化功能
80+
# CLOSE = 如果匹配, 则停止处理这条消息, 可用于排除一些被高频发送的消息
7681
inherit: ''

0 commit comments

Comments
 (0)