Minecraft反脏话插件开发:如何检测聊天内容中包含的敏感词子串
问题根因
你现在的逻辑是将聊天内容按空格拆分为单词后,和敏感词列表做全匹配,只有玩家输入的单词和敏感词完全一致才会触发拦截,自然识别不了testtt这类包含敏感词的衍生内容。
修复方案
调整检测逻辑为遍历所有敏感词,只要聊天内容中包含任意敏感词就触发拦截即可,同时还可以做一些基础性能和防绕过优化,修改后的代码参考如下:
public class EventsClass implements Listener { AntiSwear plugin = AntiSwear.getPlugin(AntiSwear.class); // 提前将敏感词加载到内存,避免每次聊天都读取配置文件,提升性能 private List<String> swearWords; // 类初始化时加载一次敏感词即可,如果你的插件支持配置热重载,可以在重载配置的方法中重新为该变量赋值 public EventsClass() { swearWords = plugin.getConfig().getStringList("swears").stream() .map(String::toLowerCase) // 敏感词统一转小写,实现大小写不敏感检测,避免玩家用TeSt这类大小写混合的方式绕过 .toList(); } // 玩家加入服务器提示 @EventHandler public void onPlayerJoinEvent(PlayerJoinEvent event) { Player player = event.getPlayer(); player.sendMessage(ChatColor.GOLD + "本服务器正在运行AntiSwear v1.0反脏话插件"); } // 聊天检测与处罚逻辑 @EventHandler public void chatevent(AsyncPlayerChatEvent event) { // 将玩家输入的聊天内容也转小写,和预处理后的敏感词格式对齐 String message = event.getMessage().toLowerCase(); // 遍历所有敏感词,只要消息内容包含任意一个敏感词就触发处罚 for (String swear : swearWords) { if (message.contains(swear)) { event.setCancelled(true); event.getPlayer().sendMessage(ChatColor.RED + "§l本服务器不允许使用脏话!"); // 处罚执行逻辑 Bukkit.getScheduler().runTask(plugin, () -> { event.getPlayer().damage(10); Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "smite " + event.getPlayer().getName()); Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "eco take " + event.getPlayer().getName() + " 100"); Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "burn " + event.getPlayer().getName() + " 5"); plugin.getServer().broadcastMessage(ChatColor.GOLD + "§l玩家 " + event.getPlayer().getName() + " §l因使用脏话已被处罚!"); }); break; // 匹配到敏感词后直接跳出循环,不需要再检测剩余敏感词 } } } }
额外防绕过优化建议
- 可以增加特殊字符预处理逻辑,先把玩家输入内容里的空格、特殊符号、形近字符(比如把
@替换为a、0替换为o)清理掉再做检测,避免玩家用t e s t、t@st这类方式绕过 - 如果需要更高的检测准确率,还可以用正则匹配逻辑,适配敏感词中间插入无关字符、前后重复加字符等更多变形场景。
内容的提问来源于stack exchange,提问作者BeamCRASH
相关产品推荐
相关产品推荐

