From 69c9e0ceb9456643fa71135d07acfd1f7c75f655 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Tue, 23 Jun 2026 17:57:24 +0800 Subject: [PATCH] =?UTF-8?q?@=20=E9=A2=86=E5=9C=B0=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E5=A4=A7=E4=BF=AE=EF=BC=9A=E6=96=B0=E5=A2=9E10=E4=B8=AA?= =?UTF-8?q?=E6=9D=83=E9=99=90=E4=BA=8B=E4=BB=B6=E5=A4=84=E7=90=86=E5=99=A8?= =?UTF-8?q?=20+=20GUI=E6=9D=83=E9=99=90=E8=A1=A5=E5=85=A8=20+=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=BA=8C=E6=AC=A1=E7=A1=AE=E8=AE=A4=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增事件处理器: - ProjectileLaunchEvent: 投掷物检测(三叉戟/雪球/风蛋) - PlayerInteractEvent: 门禁交互(按钮/门/压力板/绊线钩) - NotePlayEvent: 音符盒交互 - JukeboxPlay(InteractEvent): 唱片机交互 - PlayerInteractEvent: 红石交互(中继器/比较器) - PlayerInteractEntityEvent: 拴绳使用 - BlockGrowEvent: 农作物收获 - PlayerShearEntityEvent: 剪切羊毛/生物 - EntityBreedEvent: 投喂动物 - RaidTriggerEvent: 袭击侦测 - 周期性扫描: 玩家发光检测 修复: - GUI权限列表: "PVP"→"玩家对战", "Raid"→"袭击侦测", 补全全部29项权限 - 删除二次确认: 防止绕过1分钟延迟 - 移除重复import, 修复InventoryHolder缺失 @ --- src/main/java/Sdf1_login/AreaGUIManager.java | 42 +++++-- src/main/java/Sdf1_login/AreaProtection.java | 121 ++++++++++++++++++- src/main/java/Sdf1_login/Main.java | 5 +- 3 files changed, 155 insertions(+), 13 deletions(-) diff --git a/src/main/java/Sdf1_login/AreaGUIManager.java b/src/main/java/Sdf1_login/AreaGUIManager.java index 90bf6af..63cd67e 100644 --- a/src/main/java/Sdf1_login/AreaGUIManager.java +++ b/src/main/java/Sdf1_login/AreaGUIManager.java @@ -326,19 +326,32 @@ public class AreaGUIManager implements Listener { perms.add(new PermEntry("移动", !land.denyMove)); perms.add(new PermEntry("放置方块", !land.denyBlockPlace)); perms.add(new PermEntry("破坏方块", !land.denyBlockBreak)); - perms.add(new PermEntry("PVP", !land.denyPVP)); + perms.add(new PermEntry("玩家对战", !land.denyPVP)); perms.add(new PermEntry("骑乘坐具", !land.denyMount)); perms.add(new PermEntry("投掷末影珍珠", !land.denyEnderPearl)); - perms.add(new PermEntry("Raid", !land.denyRaid)); + perms.add(new PermEntry("投掷物(三叉戟/雪球/风蛋)", !land.denyThrownProjectiles)); + perms.add(new PermEntry("袭击侦测", !land.denyRaid)); + perms.add(new PermEntry("弓箭射击", !land.denyBow)); + perms.add(new PermEntry("药水效果", !land.denyPotion)); perms.add(new PermEntry("点燃", !land.denyFire)); + perms.add(new PermEntry("火焰蔓延", !land.denyFireSpread)); perms.add(new PermEntry("拾取物品", !land.denyPickup)); perms.add(new PermEntry("丢弃物品", !land.denyDrop)); - perms.add(new PermEntry("弓箭", !land.denyBow)); - perms.add(new PermEntry("药水", !land.denyPotion)); perms.add(new PermEntry("爆炸", !land.denyExplosion)); perms.add(new PermEntry("摔落伤害", !land.denyFallDamage)); perms.add(new PermEntry("饥饿", !land.denyHunger)); perms.add(new PermEntry("所有伤害", !land.denyAllDamage)); + perms.add(new PermEntry("所有效果", !land.denyAllEffects)); + perms.add(new PermEntry("展示框交互", !land.denyItemFrame)); + perms.add(new PermEntry("红石电路(中继器/比较器)", !land.denyRedstoneInteraction)); + perms.add(new PermEntry("门禁(门/按钮/压力板)", !land.denyDoorInteraction)); + perms.add(new PermEntry("音频(音符盒/唱片机)", !land.denyNoteblockJukebox)); + perms.add(new PermEntry("拴绳使用", !land.denyLead)); + perms.add(new PermEntry("农作物收获", !land.denyCropHarvest)); + perms.add(new PermEntry("剪切羊毛/生物", !land.denyWoolShear)); + perms.add(new PermEntry("投喂动物", !land.denyAnimalFeeding)); + perms.add(new PermEntry("玩家发光", !land.denyGlowing)); + perms.add(new PermEntry("和平模式", !land.peaceMode)); return perms; } @@ -363,19 +376,32 @@ public class AreaGUIManager implements Listener { case "移动": land.denyMove = !land.denyMove; break; case "放置方块": land.denyBlockPlace = !land.denyBlockPlace; break; case "破坏方块": land.denyBlockBreak = !land.denyBlockBreak; break; - case "PVP": land.denyPVP = !land.denyPVP; break; + case "玩家对战": land.denyPVP = !land.denyPVP; break; case "骑乘坐具": land.denyMount = !land.denyMount; break; case "投掷末影珍珠": land.denyEnderPearl = !land.denyEnderPearl; break; - case "Raid": land.denyRaid = !land.denyRaid; break; + case "投掷物(三叉戟/雪球/风蛋)": land.denyThrownProjectiles = !land.denyThrownProjectiles; break; + case "袭击侦测": land.denyRaid = !land.denyRaid; break; + case "弓箭射击": land.denyBow = !land.denyBow; break; + case "药水效果": land.denyPotion = !land.denyPotion; break; case "点燃": land.denyFire = !land.denyFire; break; + case "火焰蔓延": land.denyFireSpread = !land.denyFireSpread; break; case "拾取物品": land.denyPickup = !land.denyPickup; break; case "丢弃物品": land.denyDrop = !land.denyDrop; break; - case "弓箭": land.denyBow = !land.denyBow; break; - case "药水": land.denyPotion = !land.denyPotion; break; case "爆炸": land.denyExplosion = !land.denyExplosion; break; case "摔落伤害": land.denyFallDamage = !land.denyFallDamage; break; case "饥饿": land.denyHunger = !land.denyHunger; break; case "所有伤害": land.denyAllDamage = !land.denyAllDamage; break; + case "所有效果": land.denyAllEffects = !land.denyAllEffects; break; + case "展示框交互": land.denyItemFrame = !land.denyItemFrame; break; + case "红石电路(中继器/比较器)": land.denyRedstoneInteraction = !land.denyRedstoneInteraction; break; + case "门禁(门/按钮/压力板)": land.denyDoorInteraction = !land.denyDoorInteraction; break; + case "音频(音符盒/唱片机)": land.denyNoteblockJukebox = !land.denyNoteblockJukebox; break; + case "拴绳使用": land.denyLead = !land.denyLead; break; + case "农作物收获": land.denyCropHarvest = !land.denyCropHarvest; break; + case "剪切羊毛/生物": land.denyWoolShear = !land.denyWoolShear; break; + case "投喂动物": land.denyAnimalFeeding = !land.denyAnimalFeeding; break; + case "玩家发光": land.denyGlowing = !land.denyGlowing; break; + case "和平模式": land.peaceMode = !land.peaceMode; break; } areaProtect.saveAreaToDb(land); } diff --git a/src/main/java/Sdf1_login/AreaProtection.java b/src/main/java/Sdf1_login/AreaProtection.java index 6c88503..1cdbdca 100644 --- a/src/main/java/Sdf1_login/AreaProtection.java +++ b/src/main/java/Sdf1_login/AreaProtection.java @@ -9,6 +9,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.NotePlayEvent; import org.bukkit.event.entity.*; import org.bukkit.event.player.*; import org.bukkit.inventory.ItemStack; @@ -21,13 +22,12 @@ import org.bukkit.event.block.BlockSpreadEvent; import org.bukkit.event.block.BlockGrowEvent; import org.bukkit.entity.Entity; import org.bukkit.entity.Animals; +import org.bukkit.entity.EnderPearl; import org.bukkit.event.player.PlayerInteractAtEntityEvent; import org.bukkit.inventory.InventoryHolder; import org.bukkit.block.BlockState; import org.bukkit.block.Container; import java.sql.*; -import org.bukkit.event.entity.*; -import org.bukkit.event.player.*; import org.bukkit.GameMode; import org.bukkit.event.EventPriority; @@ -5147,10 +5147,38 @@ public class AreaProtection implements Listener { } // ★ 验证是发起者本人确认(或管理员) PendingDelete pd = pendingDeletes.get(areaName); - if (pd != null && !pd.playerName.equals(p.getName()) && !isAreaAdmin(sender)) { + if (pd == null) { + // 没有待删除记录,先创建一个(防止绕过延迟) + sender.sendMessage("§e⚠ 此操作不可逆!请在60秒内输入: §c/protect 删除 " + areaName + " " + areaName); + PendingDelete old = pendingDeletes.remove(areaName); + if (old != null) old.task.cancel(); + UUID uid = p.getUniqueId(); + String finalAreaName = areaName; + long start = System.currentTimeMillis(); + BukkitTask task = new BukkitRunnable() { + @Override + public void run() { + pendingDeletes.remove(finalAreaName); + Player online = Bukkit.getPlayer(uid); + if (online != null && online.isOnline()) { + online.sendMessage("§c§l[防护] §f领地 §e" + finalAreaName + " §f的删除请求已超时失效"); + } + } + }.runTaskLater(plugin, 1200L); + pendingDeletes.put(areaName, new PendingDelete(areaName, p.getName(), start, task)); + return true; + } + if (!pd.playerName.equals(p.getName()) && !isAreaAdmin(sender)) { sender.sendMessage("§c只有发起删除的玩家才能确认"); return true; } + // ★ 检查是否已超时(1分钟) + if (System.currentTimeMillis() - pd.startTime > 60_000) { + pendingDeletes.remove(areaName); + pd.task.cancel(); + sender.sendMessage("§c删除请求已超时,请重新发起"); + return true; + } // ★ 冻结期间如果玩家操作了领地,则自动取消 pendingDeletes.remove(areaName); if (pd != null) pd.task.cancel(); @@ -6662,6 +6690,93 @@ public class AreaProtection implements Listener { e.setCancelled(true); } + // ===== ★ 拴绳使用(给生物拴绳或拉拽)===== + @EventHandler + public void onLeash(PlayerInteractEntityEvent e) { + if (!(e.getPlayer() instanceof Player)) return; + Player p = e.getPlayer(); + Entity entity = e.getRightClicked(); + // 检查玩家所在位置或实体位置 + AreaConfig ac = getArea( + p.getWorld().getName(), + p.getLocation().getBlockX(), + p.getLocation().getBlockY(), + p.getLocation().getBlockZ()); + if (ac == null) { + ac = getArea( + entity.getWorld().getName(), + entity.getLocation().getBlockX(), + entity.getLocation().getBlockY(), + entity.getLocation().getBlockZ()); + } + if (ac == null || !ac.denyLead) return; + if (hasPermission(p, ac, PermissionLevel.OWNER)) return; + // 只拦截拴绳操作(主手持拴绳) + ItemStack hand = p.getInventory().getItemInMainHand(); + if (hand != null && hand.getType() == Material.LEAD) { + e.setCancelled(true); + p.sendMessage("§c§l[区域防护] §f禁止在此区域使用拴绳"); + } + } + + // ===== ★ 投喂动物 ===== + @EventHandler + public void onPlayerFeedAnimal(EntityBreedEvent e) { + if (!(e.getBreeder() instanceof Player)) return; + Player p = (Player) e.getBreeder(); + Entity entity = e.getEntity(); + AreaConfig ac = getArea( + p.getWorld().getName(), + p.getLocation().getBlockX(), + p.getLocation().getBlockY(), + p.getLocation().getBlockZ()); + if (ac == null) { + ac = getArea( + entity.getWorld().getName(), + entity.getLocation().getBlockX(), + entity.getLocation().getBlockY(), + entity.getLocation().getBlockZ()); + } + if (ac == null || !ac.denyAnimalFeeding) return; + if (hasPermission(p, ac, PermissionLevel.OWNER)) return; + e.setCancelled(true); + p.sendMessage("§c§l[区域防护] §f禁止在此区域繁殖动物"); + } + + // ===== ★ 袭击侦听(玩家触发袭击时检测)===== + @EventHandler + public void onRaidTrigger(org.bukkit.event.raid.RaidTriggerEvent e) { + Player p = e.getPlayer(); + AreaConfig ac = getArea( + p.getWorld().getName(), + p.getLocation().getBlockX(), + p.getLocation().getBlockY(), + p.getLocation().getBlockZ()); + if (ac == null || !ac.denyRaid) return; + if (hasPermission(p, ac, PermissionLevel.OWNER)) return; + e.setCancelled(true); + p.sendMessage("§c§l[区域防护] §f此区域禁止触发袭击事件"); + } + + // ===== ★ 玩家发光检测(通过定期扫描清除区域内发光效果)===== + // 在onEnable中注册repeating task,此处提供public方法供Main调用 + public void checkGlowingPlayers() { + for (Player p : Bukkit.getOnlinePlayers()) { + AreaConfig ac = getArea( + p.getWorld().getName(), + p.getLocation().getBlockX(), + p.getLocation().getBlockY(), + p.getLocation().getBlockZ()); + if (ac != null && ac.denyGlowing) { + if (hasPermission(p, ac, PermissionLevel.OWNER)) continue; + if (p.hasPotionEffect(PotionEffectType.GLOWING)) { + p.removePotionEffect(PotionEffectType.GLOWING); + p.sendMessage("§c§l[区域防护] §f此区域禁止使用发光效果"); + } + } + } + } + private void savePeaceWhitelist(AreaConfig ac) { File file = new File(rootDir, ac.name + ".txt"); diff --git a/src/main/java/Sdf1_login/Main.java b/src/main/java/Sdf1_login/Main.java index 41f636c..cc5a01d 100644 --- a/src/main/java/Sdf1_login/Main.java +++ b/src/main/java/Sdf1_login/Main.java @@ -513,11 +513,12 @@ public class Main extends JavaPlugin getServer().getPluginManager() .registerEvents(areaGUIManager, this); -// 效果清除定时器(只留一个) +// 发光效果检测(每2秒扫描一次) getServer().getScheduler().runTaskTimer(this, () -> { if (areaProtection != null) { + areaProtection.checkGlowingPlayers(); } - }, 20L, 20L); + }, 20L, 40L); // 和平模式独立检测 getServer().getScheduler().runTaskTimer(this, () -> {