commit 34e873ed1760d919313c35a8dfe92c4d4a8c738f Author: yaohunya <1763917516@qq.com> Date: Sat Aug 2 09:44:57 2025 +0800 1.0.0 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0807e96 --- /dev/null +++ b/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + com.yaohun.main + AuTntTag + 1.0-SNAPSHOT + + + 8 + 8 + UTF-8 + + + + + public-rpg + https://repo.aurora-pixels.com/repository/public-rpg/ + + + + + + org.spigotmc + spigot-api + 1.12.2 + + + me.Demon.DemonPlugin + DemonAPI + 2.2.9 + + + me.Demon.DemonWarps + DemonWarps + 2.0.3 + + + me.clip.placeholderapi + PlaceholderAPI + 2.9.2 + + + + \ No newline at end of file diff --git a/src/main/java/com/yaohun/tnttag/PapiExpansion.java b/src/main/java/com/yaohun/tnttag/PapiExpansion.java new file mode 100644 index 0000000..b958e20 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/PapiExpansion.java @@ -0,0 +1,90 @@ +package com.yaohun.tnttag; + +import com.yaohun.tnttag.manage.GameManager; +import com.yaohun.tnttag.manage.RoundManager; +import com.yaohun.tnttag.util.GameState; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +/** + * @Author: Baka + * @Date: 2019/12/23 13:20 + */ +public class PapiExpansion extends PlaceholderExpansion { + private Plugin plugin; + + public PapiExpansion(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public boolean persist() { + return true; + } + + @Override + public boolean canRegister() { + return true; + } + + @Override + public String getAuthor() { + return plugin.getDescription().getAuthors().toString(); + } + + @Override + public String getIdentifier() { + return "game"; + } + + @Override + public String getVersion() { + return plugin.getDescription().getVersion(); + } + + @Override + public String onPlaceholderRequest(Player player, String identifier) { + GameManager game = TagMain.getGame(); + if ("stats".equalsIgnoreCase(identifier)) { + if(game.gameState == GameState.LOBBY){ + return ""; + } + if(game.getAlivePlayers().isEmpty()){ + return ""; + } + RoundManager roundManager = game.getRoundManager(); + if(game.getAlivePlayers().contains(player)){ + if (roundManager.isTnt(player)) { + return "§c§l炸弹客"; + } else { + return "§a§l存活"; + } + } else { + return ""; + } + }else if ("tabstats".equalsIgnoreCase(identifier)) { + if(game.gameState == GameState.LOBBY){ + if(player.isOp()) { + return "§7[§c管理员§7]§4"; + } else { + return "§7[§2玩家§7]§r"; + } + } + if(game.getAlivePlayers().isEmpty()){ + return ""; + } + RoundManager roundManager = game.getRoundManager(); + if(game.getAlivePlayers().contains(player)){ + if (roundManager.isTnt(player)) { + return "§7[§d§l炸弹客§7]§5"; + } else { + return "§7[§a§l存活§7]§r"; + } + } else { + return "§7[§c§l阵亡§7]§7"; + } + } + return ""; + } +} \ No newline at end of file diff --git a/src/main/java/com/yaohun/tnttag/TagMain.java b/src/main/java/com/yaohun/tnttag/TagMain.java new file mode 100644 index 0000000..993f4d3 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/TagMain.java @@ -0,0 +1,74 @@ +package com.yaohun.tnttag; + +import com.yaohun.tnttag.config.Config; +import com.yaohun.tnttag.counter.LobbyCounter; +import com.yaohun.tnttag.listener.DoubleJumpListener; +import com.yaohun.tnttag.listener.GameListener; +import com.yaohun.tnttag.listener.PlayerListener; +import com.yaohun.tnttag.listener.ProtectListener; +import com.yaohun.tnttag.manage.GameManager; +import com.yaohun.tnttag.util.MessageUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; + +public class TagMain extends JavaPlugin { + + private static TagMain instance; + private static GameManager gameManager; + + + @Override + public void onEnable() { + instance = this; + saveDefaultConfig(); + Config.reloadConfig(this); + MessageUtil.init(this); + gameManager = new GameManager(this); + getServer().getPluginManager().registerEvents(new GameListener(),this); + getServer().getPluginManager().registerEvents(new PlayerListener(),this); + getServer().getPluginManager().registerEvents(new ProtectListener(),this); + getServer().getPluginManager().registerEvents(new DoubleJumpListener(gameManager),this); + + Bukkit.getConsoleSender().sendMessage("§b[斗魂帝国] §7趣味小游戏: §6烫手山芋(炸弹版)"); + Bukkit.getConsoleSender().sendMessage("§b[斗魂帝国] §7插件作者: 妖魂吖"); + if(getServer().getPluginManager().getPlugin("PlaceholderAPI") != null){ + new PapiExpansion(this).register(); + } + new BukkitRunnable() { + @Override + public void run() { + LobbyCounter.startWaiterMessage(); + } + }.runTaskLater(this,20 * 10); + } + + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if("forcestart".equalsIgnoreCase(label) && sender.isOp()){ + LobbyCounter.forceStartGame(); + return true; + } + if("game".equalsIgnoreCase(label) && sender.isOp()){ + if(args.length == 1 && "reload".equalsIgnoreCase(args[0])){ + MessageUtil.init(this); + Config.reloadConfig(this); + sender.sendMessage("[烫手山芋] 配置/语言文件已重载."); + } + return true; + } + return false; + } + + + public static TagMain inst() { + return instance; + } + + public static GameManager getGame() { + return gameManager; + } +} diff --git a/src/main/java/com/yaohun/tnttag/config/Config.java b/src/main/java/com/yaohun/tnttag/config/Config.java new file mode 100644 index 0000000..d19f8d8 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/config/Config.java @@ -0,0 +1,20 @@ +package com.yaohun.tnttag.config; + +import com.yaohun.tnttag.TagMain; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; + +public class Config { + + public static String backServer; + public static int requirementPlayer; + public static void reloadConfig(TagMain plugin){ + plugin.reloadConfig(); + plugin.saveConfig(); + FileConfiguration config = plugin.getConfig(); + requirementPlayer = config.getInt("requirementPlayer", 30); + Bukkit.getConsoleSender().sendMessage("[设置] 最低所需玩家: "+requirementPlayer); + backServer = config.getString("backServer","loginlobby01"); + Bukkit.getConsoleSender().sendMessage("[设置] BungeeCord大厅: "+backServer); + } +} diff --git a/src/main/java/com/yaohun/tnttag/counter/LobbyCounter.java b/src/main/java/com/yaohun/tnttag/counter/LobbyCounter.java new file mode 100644 index 0000000..5f84695 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/counter/LobbyCounter.java @@ -0,0 +1,108 @@ +package com.yaohun.tnttag.counter; + +import com.yaohun.tnttag.TagMain; +import com.yaohun.tnttag.config.Config; +import com.yaohun.tnttag.manage.GameManager; +import com.yaohun.tnttag.task.TntSmokeEffectTask; +import com.yaohun.tnttag.util.GameState; +import com.yaohun.tnttag.util.MessageUtil; +import com.yaohun.tnttag.util.SpeedEffectApplier; +import me.Demon.DemonPlugin.Util.RandomUtil; +import me.Demon.DemonWarps.WarpAPI; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; + +import static sun.audio.AudioPlayer.player; + +public class LobbyCounter { + + // 每多少秒提示一次还差多少人就可以开始游戏 + private static final int WAITER_TIME_DEFAULT = 60; + private static int waiterTime = 60; + private static int waiterTask; + + public static void startWaiterMessage(){ + startLobby(); + waiterTask = Bukkit.getScheduler().scheduleSyncRepeatingTask(TagMain.inst(), () -> { + waiterTime--; + if(waiterTime <= 0){ + waiterTime = WAITER_TIME_DEFAULT; + int online = Bukkit.getOnlinePlayers().size(); + int requirement = Config.requirementPlayer; + if(online < requirement){ + int value = requirement - online; + String message = MessageUtil.getMessage("insufficient_number_of_people").replace("{value}",String.valueOf(value)); + Bukkit.broadcastMessage(message); + MessageUtil.playSound(Sound.BLOCK_COMPARATOR_CLICK); + } + } + },0L,20L); + } + + private static final int LOBBY_TIME_DEFAULT = 181; + private static int lobbyTime = 181; + private static int lobbyTask; + private static void startLobby(){ + String message = MessageUtil.getMessage("start_countdown"); + lobbyTask = Bukkit.getScheduler().scheduleSyncRepeatingTask(TagMain.inst(), () -> { + lobbyTime--; + for (Player player : Bukkit.getOnlinePlayers()){ + player.setLevel(lobbyTime); + } + // 当玩家人数小于需求人数时,倒计时时间改为 LOBBY_TIME_DEFAULT 秒 + int online = Bukkit.getOnlinePlayers().size(); + if(online < Config.requirementPlayer){ + lobbyTime = LOBBY_TIME_DEFAULT; + } + switch (lobbyTime){ + case 60: + Bukkit.broadcastMessage(message.replace("%seconds%",String.valueOf(lobbyTime))); + break; + case 45: + case 30: + case 15: + case 10: + case 5: + case 4: + case 3: + case 2: + case 1: + Bukkit.broadcastMessage(message.replace("%seconds%",String.valueOf(lobbyTime))); + MessageUtil.playSound(Sound.BLOCK_COMPARATOR_CLICK); + break; + case 0: + forceStartGame(); + + } + },0L,20L); + } + + public static void forceStartGame(){ + // 关闭计时器 + Bukkit.getScheduler().cancelTask(waiterTask); + Bukkit.getScheduler().cancelTask(lobbyTask); + // 启动游戏状态 + GameManager manager = TagMain.getGame(); + manager.setGameState(GameState.INGAME); + // 执行玩家开始 + for (Player all : Bukkit.getOnlinePlayers()){ + all.setAllowFlight(false); + all.setFlying(false); + manager.addPlayer(all); + all.teleport(WarpAPI.getWarpLocation("复活点"+ RandomUtil.getRandomInt(1,5))); + all.getInventory().clear(); + MessageUtil.playSound(Sound.ENTITY_ENDERDRAGON_GROWL); + for (PotionEffect effect : all.getActivePotionEffects()) { + all.removePotionEffect(effect.getType()); + } + SpeedEffectApplier.applyInfiniteSpeed(all, 1); + } + TagMain.getGame().startGame(); + // 每 4 tick 检查一次(0.2秒) + new TntSmokeEffectTask(manager).runTaskTimer(TagMain.inst(), 0L, 4L); + } +} diff --git a/src/main/java/com/yaohun/tnttag/counter/RestartCounter.java b/src/main/java/com/yaohun/tnttag/counter/RestartCounter.java new file mode 100644 index 0000000..eb0dd3c --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/counter/RestartCounter.java @@ -0,0 +1,55 @@ +package com.yaohun.tnttag.counter; + +import com.yaohun.tnttag.TagMain; +import com.yaohun.tnttag.config.Config; +import com.yaohun.tnttag.manage.GameManager; +import com.yaohun.tnttag.util.GameState; +import com.yaohun.tnttag.util.MessageUtil; +import me.Demon.DemonPlugin.DemonAPI; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Random; + +public class RestartCounter { + + private static int restarTime = 30; + + public static void restart() { + GameManager gameManager = TagMain.getGame(); + gameManager.setGameState(GameState.RESTART); + Bukkit.getScheduler().cancelAllTasks(); + Bukkit.broadcastMessage("§f[§c系统§f] §a游戏即将结束,你将在 §6"+restarTime+"秒 §a后被传送到大厅!"); + Bukkit.getScheduler().scheduleSyncRepeatingTask(TagMain.inst(), () -> { + --restarTime; + switch (restarTime) { + case 0: + Bukkit.shutdown(); + break; + case 1: + Bukkit.broadcastMessage("§f[§c系统§f] §a游戏即将结束,你将在 §6"+restarTime+"秒 §a后被传送到大厅!"); + MessageUtil.playSound(Sound.BLOCK_COMPARATOR_CLICK); + String lobbyName = Config.backServer; + for (Player all : Bukkit.getOnlinePlayers()) { + DemonAPI.sendPlayerToBCServer(all, lobbyName); + } + return; + case 15: + case 10: + case 5: + case 4: + case 3: + case 2: + Bukkit.broadcastMessage("§f[§c系统§f] §a游戏即将结束,你将在 §6"+restarTime+"秒 §a后被传送到大厅!"); + MessageUtil.playSound(Sound.BLOCK_COMPARATOR_CLICK); + } + }, 0L, 20L); + } +} diff --git a/src/main/java/com/yaohun/tnttag/listener/DoubleJumpListener.java b/src/main/java/com/yaohun/tnttag/listener/DoubleJumpListener.java new file mode 100644 index 0000000..465dfac --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/listener/DoubleJumpListener.java @@ -0,0 +1,96 @@ +package com.yaohun.tnttag.listener; + +import com.yaohun.tnttag.TagMain; +import com.yaohun.tnttag.manage.GameManager; +import com.yaohun.tnttag.util.GameState; +import me.Demon.DemonPlugin.Util.CDTimeAPI; +import org.bukkit.Bukkit; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerToggleFlightEvent; +import org.bukkit.util.Vector; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +public class DoubleJumpListener implements Listener { + private final GameManager gameManager; + private final Set usedDoubleJump = new HashSet<>(); + + public DoubleJumpListener(GameManager gameManager) { + this.gameManager = gameManager; + } + + @EventHandler + public void onPlayerToggleFlight(PlayerToggleFlightEvent event) { + Player player = event.getPlayer(); + + // 仅允许在游戏中,并且是 TNT 玩家使用二段跳 + if (gameManager.gameState != GameState.INGAME) { + return; + } + if (!gameManager.getRoundManager().isTnt(player)) { + return; + } + // 防止重复使用 + if (usedDoubleJump.contains(player.getUniqueId())) { + return; + } + // 防止原版飞行 + event.setCancelled(true); + player.setAllowFlight(false); + player.setFlying(false); + + // 推动玩家向前斜上方跳跃 + Vector direction = player.getLocation().getDirection().multiply(1.6).setY(0.8); + player.setVelocity(direction); + + player.getWorld().playSound(player.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 1f, 1f); + player.getWorld().spawnParticle(Particle.CLOUD, player.getLocation(), 10); + + // 加入冷却队列 + usedDoubleJump.add(player.getUniqueId()); + + // 3秒后允许再次使用 + Bukkit.getScheduler().runTaskLater(TagMain.inst(), () -> { + if (gameManager.getRoundManager().isTnt(player)) { + player.setAllowFlight(true); + } + usedDoubleJump.remove(player.getUniqueId()); + }, 60L); + } + + /** + * 当玩家落地时,重新允许飞行(准备下次跳) + */ + @EventHandler + public void onMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + + if (gameManager.gameState != GameState.INGAME) { + return; + } + if (!gameManager.getRoundManager().isTnt(player)) { + return; + } + if (player.isOnGround() && !usedDoubleJump.contains(player.getUniqueId())) { + // 启用飞行作为二段跳触发器 + player.setAllowFlight(true); + } + } + + /** + * 玩家离开游戏时移除状态 + */ + @EventHandler + public void onQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + usedDoubleJump.remove(player.getUniqueId()); + } +} \ No newline at end of file diff --git a/src/main/java/com/yaohun/tnttag/listener/GameListener.java b/src/main/java/com/yaohun/tnttag/listener/GameListener.java new file mode 100644 index 0000000..01708f8 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/listener/GameListener.java @@ -0,0 +1,58 @@ +package com.yaohun.tnttag.listener; + +import com.yaohun.tnttag.TagMain; +import com.yaohun.tnttag.manage.GameManager; +import com.yaohun.tnttag.manage.RoundManager; +import com.yaohun.tnttag.util.GameState; +import me.Demon.DemonWarps.WarpAPI; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +public class GameListener implements Listener { + + @EventHandler + public void onTntHit(EntityDamageByEntityEvent e){ + if(e.getDamager() instanceof Player){ + if(e.getEntity() instanceof Player){ + GameManager gameManager = TagMain.getGame(); + if(gameManager.getGameState() != GameState.INGAME) { + return; + } + // 获取 RoundManager + RoundManager roundManager = gameManager.getRoundManager(); + Player attacker = (Player) e.getDamager(); + if(!gameManager.isAlive(attacker)){ + e.setCancelled(true); + attacker.teleport(WarpAPI.getWarpLocation("游戏场地")); + attacker.playSound(attacker.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,0.8f,1.2f); + return; + } + // 只有 TNT 持有者可以传递 + if (!roundManager.isTnt(attacker)) { + return; + } + Player victim = (Player) e.getEntity(); + if(!gameManager.isAlive(victim)){ + return; + } + // 不能把 TNT 传给另一个已经持有 TNT 的人 + if (roundManager.isTnt(victim)) { + return; + } + // 执行传递 + roundManager.passTnt(attacker, victim); + e.setDamage(0.0D); + + victim.sendTitle("§c你被传染了!", "§7快把 TNT 传出去!", 10, 40, 10); + attacker.sendTitle("§a传递成功", "", 10, 20, 10); + victim.getWorld().spawnParticle(Particle.EXPLOSION_NORMAL, victim.getLocation(), 10); + victim.getWorld().playSound(victim.getLocation(), Sound.ENTITY_TNT_PRIMED, 1F, 1F); + + } + } + } +} diff --git a/src/main/java/com/yaohun/tnttag/listener/PlayerListener.java b/src/main/java/com/yaohun/tnttag/listener/PlayerListener.java new file mode 100644 index 0000000..c12ab2d --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/listener/PlayerListener.java @@ -0,0 +1,195 @@ +package com.yaohun.tnttag.listener; + +import com.yaohun.tnttag.TagMain; +import com.yaohun.tnttag.config.Config; +import com.yaohun.tnttag.counter.LobbyCounter; +import com.yaohun.tnttag.manage.GameManager; +import com.yaohun.tnttag.util.GameState; +import com.yaohun.tnttag.util.MessageUtil; +import com.yaohun.tnttag.util.SideBar; +import com.yaohun.tnttag.util.StackUtil; +import me.Demon.DemonPlugin.DemonAPI; +import me.Demon.DemonWarps.WarpAPI; +import org.bukkit.*; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; +import org.omg.CORBA.INV_FLAG; + +public class PlayerListener implements Listener { + + @EventHandler + public void onFoodLevelChange(FoodLevelChangeEvent event){ + event.setCancelled(true); + } + + + @EventHandler + public void onJoin(PlayerJoinEvent e){ + Player player = e.getPlayer(); + String playerName = player.getName(); + e.setJoinMessage(null); + for (PotionEffect effetcs : player.getActivePotionEffects()) { + player.removePotionEffect(effetcs.getType()); + } + GameManager game = TagMain.getGame(); + if(game.gameState != GameState.LOBBY){ + return; + } + player.sendTitle("§6斗魂帝国","§3趣味小游戏 §f- §c烫手山芋§b(炸弹版)",10,60,20); + String message = MessageUtil.getMessage("join_message").replace("{online}",String.valueOf(Bukkit.getOnlinePlayers().size())); + message = message.replace("{name}",playerName); + e.setJoinMessage(message); + + Location lobbyLoc = WarpAPI.getWarpLocation("游戏大厅"); + if(player.hasPlayedBefore()){ + player.teleport(lobbyLoc); + } else { + Bukkit.getScheduler().scheduleSyncDelayedTask(TagMain.inst(), () -> { + player.teleport(lobbyLoc); + }, 10L); + } + player.setGameMode(GameMode.ADVENTURE); + player.setGlowing(false); + player.setExp(0.0F); + player.setLevel(0); + player.setHealth(20.0); + player.setFoodLevel(20); + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + player.setWalkSpeed(0.35F); + player.getInventory().setItem(0, StackUtil.observerOn()); + player.getInventory().setItem(8, StackUtil.quitStack()); + if(player.isOp()){ + player.getInventory().setItem(4, StackUtil.forciblyStack()); + } + new SideBar().updateScoreboard(); + } + + @EventHandler + public void onQuitLobby(PlayerQuitEvent e) { + e.setQuitMessage(null); + Player player = e.getPlayer(); + String playerName = player.getName(); + GameManager game = TagMain.getGame(); + if(game.gameState != GameState.LOBBY){ + return; + } + String message = MessageUtil.getMessage("quit_message").replace("{online}",String.valueOf(Bukkit.getOnlinePlayers().size())); + message = message.replace("{name}",playerName); + e.setQuitMessage(message); + new SideBar().updateScoreboard(); + } + + + @EventHandler + public void onChat(AsyncPlayerChatEvent e) { + Player p = e.getPlayer(); + if ((e.getMessage().contains("&k"))||(e.getMessage().contains("§k"))) { + e.getMessage().replace("&k", "").replace("§k", ""); + } + e.setMessage(ChatColor.translateAlternateColorCodes('&', e.getMessage())); + String prefix = "§7[§2§lPlayer§7]"; + if(p.isOp()){ + prefix = "§7[§c§lAdmin§7]"; + } + String format = prefix+"§f"+p.getName()+"§8§l > §r"+e.getMessage(); + e.setFormat(format); + } + + @EventHandler + public void onClick(InventoryClickEvent e){ + int slot = e.getSlot(); + Player player = (Player) e.getWhoClicked(); + e.setCancelled(true); + InventoryType inventoryType = e.getInventory().getType(); + if(inventoryType.equals(InventoryType.CRAFTING)){ + if(slot == 0 && player.isOp()){ + // 执行强制开始 + LobbyCounter.forceStartGame(); + } + if(slot == 8){ + player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,1); + new BukkitRunnable() { + @Override + public void run() { + DemonAPI.sendPlayerToBCServer(player, Config.backServer); + } + }.runTaskLater(TagMain.inst(), 5L); + } + } + } + @EventHandler + public void onUse(PlayerInteractEvent e){ + Player player = e.getPlayer(); + if(e.getHand() == EquipmentSlot.HAND) { + if(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) { + ItemStack item = player.getInventory().getItemInMainHand(); + if (!DemonAPI.itemIsNull(item)) { + Material material = item.getType(); + if (material.equals(Material.BED)) { + player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK, 1, 1); + new BukkitRunnable() { + @Override + public void run() { + DemonAPI.sendPlayerToBCServer(player, Config.backServer); + } + }.runTaskLater(TagMain.inst(), 5L); + } + if (material.equals(Material.DIAMOND)) { + GameManager game = TagMain.getGame(); + if (game.gameState != GameState.LOBBY) { + return; + } + if (!player.isOp()) { + return; + } + // 执行强制开始命令 + LobbyCounter.forceStartGame(); + } + if (material.equals(Material.SLIME_BALL)) { + player.getInventory().clear(); + player.setAllowFlight(true); + player.setFlying(true); + player.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 999999999, 1),true); + MessageUtil.sendMessage(player, "observer_on"); + player.playSound(player.getLocation(),Sound.BLOCK_COMPARATOR_CLICK,0.8f,1.2f); + player.getInventory().setItem(0, StackUtil.observerOff()); + } + if (material.equals(Material.MAGMA_CREAM)) { + player.getInventory().setItem(0, StackUtil.observerOn()); + player.getInventory().setItem(8, StackUtil.quitStack()); + player.setAllowFlight(false); + player.setFlying(false); + player.getActivePotionEffects().forEach((potionEffect) -> { + player.removePotionEffect(potionEffect.getType()); + }); + player.teleport(WarpAPI.getWarpLocation("游戏大厅")); + MessageUtil.sendMessage(player, "observer_off"); + GameManager gameManager = TagMain.getGame(); + if(gameManager.getGameState() == GameState.LOBBY){ + if(player.isOp()){ + player.getInventory().setItem(4, StackUtil.forciblyStack()); + } + } + player.playSound(player.getLocation(),Sound.BLOCK_COMPARATOR_CLICK,0.8f,1.2f); + } + } + } + } + } +} diff --git a/src/main/java/com/yaohun/tnttag/listener/ProtectListener.java b/src/main/java/com/yaohun/tnttag/listener/ProtectListener.java new file mode 100644 index 0000000..4a539d3 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/listener/ProtectListener.java @@ -0,0 +1,101 @@ +package com.yaohun.tnttag.listener; + +import com.yaohun.tnttag.util.MessageUtil; +import com.yaohun.tnttag.util.StackUtil; +import me.Demon.DemonWarps.WarpAPI; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.weather.WeatherChangeEvent; + +public class ProtectListener implements Listener { + + @EventHandler + public void onBreak(BlockBreakEvent e){ + e.setCancelled(true); + } + + @EventHandler + public void onPlace(BlockPlaceEvent e){ + e.setCancelled(true); + } + + @EventHandler + public void onCreateurs(CreatureSpawnEvent e){ + e.setCancelled(true); + } + + @EventHandler + public void onDamage(EntityDamageEvent e){ + if(e.getEntity() instanceof Player){ + e.setDamage(0.0); + } + } + + @EventHandler + public void onWeather(WeatherChangeEvent e){ + e.setCancelled(true); + } + + @EventHandler + public void onLeaves(LeavesDecayEvent e){ + e.setCancelled(true); + } + + @EventHandler + public void onDrop(PlayerDropItemEvent e){ + e.setCancelled(true); + } + + @EventHandler + public void onDamage(EntityDamageByEntityEvent e){ + if(e.getEntity() instanceof Player){ + if(e.getEntity().getLocation().getY() >= 130){ + e.setCancelled(true); + } + } + } + + // 位置1和位置2(你可以从配置文件中加载) + private final Location pos1 = new Location(Bukkit.getWorld("world"), 4, 9, 304); + private final Location pos2 = new Location(Bukkit.getWorld("world"), -303, 180, -3); + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + Location loc = player.getLocation(); + + // 获取当前坐标 + double x = loc.getX(); + double y = loc.getY(); + double z = loc.getZ(); + + // 计算区域边界(自动处理 pos1/pos2 顺序) + double minX = Math.min(pos1.getX(), pos2.getX()); + double maxX = Math.max(pos1.getX(), pos2.getX()); + double minY = Math.min(pos1.getY(), pos2.getY()); + double maxY = Math.max(pos1.getY(), pos2.getY()); + double minZ = Math.min(pos1.getZ(), pos2.getZ()); + double maxZ = Math.max(pos1.getZ(), pos2.getZ()); + + // 判断是否越界 + if (x < minX || x > maxX || y < minY || y > maxY || z < minZ || z > maxZ) { + player.teleport(WarpAPI.getWarpLocation("游戏场地")); + player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,0.8f,1.2f); + } + } + + + +} diff --git a/src/main/java/com/yaohun/tnttag/manage/GameManager.java b/src/main/java/com/yaohun/tnttag/manage/GameManager.java new file mode 100644 index 0000000..9c7de68 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/manage/GameManager.java @@ -0,0 +1,136 @@ +package com.yaohun.tnttag.manage; + +import com.yaohun.tnttag.TagMain; +import com.yaohun.tnttag.counter.RestartCounter; +import com.yaohun.tnttag.util.*; +import me.Demon.DemonPlugin.DemonAPI; +import me.Demon.DemonWarps.WarpAPI; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Sound; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +public class GameManager { + + private final TagMain plugin; + // 存活玩家集合(正在游戏中、未被淘汰) + private final Set alivePlayers = new HashSet<>(); + // 所有参与过该局的玩家(用于重置) + private final Set allPlayers = new HashSet<>(); + // RoundManager:每一轮的逻辑控制器 + private final RoundManager roundManager; + // 当前游戏状态(等待、开始中、进行中、结束) + public GameState gameState; + + public GameManager(TagMain plugin){ + this.plugin = plugin; + gameState = GameState.LOBBY; + this.roundManager = new RoundManager(this, plugin); + } + + public void setGameState(GameState gameState) { + this.gameState = gameState; + } + + /** + * 添加玩家到游戏中(只能在等待状态加入) + */ + public void addPlayer(Player player) { + alivePlayers.add(player); + allPlayers.add(player); + } + + /** + * 玩家离开游戏,若为最后一人则直接结束游戏 + */ + public void removePlayer(Player player) { + alivePlayers.remove(player); + allPlayers.remove(player); + + if (alivePlayers.size() <= 1 && gameState == GameState.INGAME) { + // 结束游戏 endGame(); + } + } + + public boolean isAlive(Player player) { + return alivePlayers.contains(player); + } + + /** + * 淘汰玩家(设为观察者模式并移出活跃列表) + */ + public void eliminatePlayer(Player player) { + alivePlayers.remove(player); + String playerName = player.getName(); + String message = "§f[§c系统§f] §a玩家 §6"+playerName+" §a因未在规定时间传递炸弹=v= §c§l已被炸死!"; + Bukkit.broadcastMessage(message); + player.teleport(WarpAPI.getWarpLocation("游戏大厅")); + player.getInventory().clear(); + String time = DemonAPI.getTime("HH:mm:ss"); + int aliveSize = alivePlayers.size(); + if(aliveSize == 2){ + String rankingRewards = MessageUtil.getMessage("ranking_rewards_3").replace("{time}", time); + Bukkit.broadcastMessage(rankingRewards.replace("{name}", playerName)); + }else if(aliveSize == 1){ + String rankingRewards = MessageUtil.getMessage("ranking_rewards_2").replace("{time}", time); + Bukkit.broadcastMessage(rankingRewards.replace("{name}", playerName)); + } + player.sendMessage("§f[§c系统§f] §b你被淘汰了,你可以选择留下继续观战~(●′ω`●)~"); + player.getInventory().setItem(0, StackUtil.observerOn()); + player.getInventory().setItem(8, StackUtil.quitStack()); + player.setAllowFlight(false); + player.setFlying(false); + player.setGlowing(false); + player.getActivePotionEffects().forEach((potionEffect) -> { + player.removePotionEffect(potionEffect.getType()); + }); + } + + /** + * 游戏结束逻辑,广播胜者、重置状态 + */ + public void endGame() { + gameState = GameState.RESTART; + roundManager.stopRound(); + + Player winner = alivePlayers.stream().findFirst().orElse(null); + if (winner != null) { + String playerName = winner.getName(); + String rankingRewards = MessageUtil.getMessage("ranking_rewards_1").replace("{time}", DemonAPI.getTime("HH:mm:ss")); + Bukkit.broadcastMessage(rankingRewards.replace("{name}", playerName)); + for (Player all : Bukkit.getOnlinePlayers()) { + all.sendTitle("§c§l游戏结束!", "§b" + playerName + " §6获得本场胜利!", 10, 80, 20); + } + } + RestartCounter.restart(); + } + + /** + * 正式开始游戏,传送玩家到战场并启动第一轮 + */ + public void startGame() { + new SideBar().updateScoreboard(); + roundManager.startNextRound(); // 启动第一轮 + for (Player player : getAlivePlayers()){ + roundManager.addBossBar(player); + } + } + + // ---------------------- Getter 方法 ---------------------- + + public Set getAlivePlayers() { + return alivePlayers; + } + + public GameState getGameState() { + return gameState; + } + + public RoundManager getRoundManager() { + return roundManager; + } +} diff --git a/src/main/java/com/yaohun/tnttag/manage/RoundManager.java b/src/main/java/com/yaohun/tnttag/manage/RoundManager.java new file mode 100644 index 0000000..1ddd57b --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/manage/RoundManager.java @@ -0,0 +1,231 @@ +package com.yaohun.tnttag.manage; + +import com.yaohun.tnttag.TagMain; +import com.yaohun.tnttag.counter.RestartCounter; +import com.yaohun.tnttag.util.MessageUtil; +import com.yaohun.tnttag.util.SideBar; +import com.yaohun.tnttag.util.SpeedEffectApplier; +import me.Demon.DemonPlugin.DemonAPI; +import me.Demon.DemonPlugin.Util.RandomUtil; +import me.Demon.DemonWarps.WarpAPI; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.*; + +public class RoundManager { + + private final GameManager gameManager; + private final TagMain plugin; + + private BossBar bossBar; + + private int roundNumber = 0; + private int countdownSeconds = 30; + private int taskId = -1; + + private final Set tntPlayers = new HashSet<>(); + + public RoundManager(GameManager gameManager, TagMain plugin) { + this.gameManager = gameManager; + this.plugin = plugin; + this.bossBar = Bukkit.createBossBar("倒计时", BarColor.RED, BarStyle.SEGMENTED_10); + } + + public void setBossBarProgress(double progress,int second) { + if(progress < 0){ + progress = 0; + } else if(progress > 1){ + progress = 1; + } + bossBar.setProgress(progress); + bossBar.setTitle("§a§l炸弹传递§c§l·§e§l即将在 §b§l"+second+"秒 §e§l后爆炸!"); + double chance = RandomUtil.getRandomDouble(0,100,1); + if(chance >= 75){ + bossBar.setColor(BarColor.PINK); + }else if(chance >= 50){ + bossBar.setColor(BarColor.BLUE); + }else if(chance >= 25){ + bossBar.setColor(BarColor.RED); + }else{ + bossBar.setColor(BarColor.YELLOW); + } + } + + public void addBossBar(Player player){ + if(!bossBar.getPlayers().contains(player)){ + bossBar.addPlayer(player); + } + } + + public int getRoundNumber() { + return roundNumber; + } + + public void startNextRound() { + roundNumber++; + if (roundNumber <= 3) { + countdownSeconds = 30; + } else if (roundNumber <= 6) { + countdownSeconds = 25; + } else if (roundNumber <= 9) { + countdownSeconds = 20; + } else { + countdownSeconds = 15; + } + // 刷新记分板 + new SideBar().updateScoreboard(); + int survivingPlayers = gameManager.getAlivePlayers().size(); + if(survivingPlayers < 5){ + for (Player all : gameManager.getAlivePlayers()) { + all.teleport(WarpAPI.getWarpLocation("游戏场地")); + MessageUtil.playSound(Sound.ENTITY_ENDERDRAGON_GROWL); + } + } + selectInitialTntPlayers(); + for (Player player : gameManager.getAlivePlayers()){ + if(isTnt(player)){ + MessageUtil.sendMessage(player,"§f[§c系统§f] §a糟糕你被抽中成为了本轮的§c§l炸弹客§a! §e(左键传递给其他人)", Sound.ENTITY_CAT_AMBIENT); + player.setGlowing(false); + } else { + MessageUtil.sendMessage(player,"§f[§c系统§f] §a快跑起来,远离头上炸弹的玩家,否则会被炸死!", Sound.ENTITY_CAT_AMBIENT); + player.setGlowing(true); + } + } + startCountdownTask(); + } + + public void stopRound() { + if (taskId != -1) { + Bukkit.getScheduler().cancelTask(taskId); + taskId = -1; + } + tntPlayers.clear(); + } + + public boolean isTnt(Player player) { + return tntPlayers.contains(player); + } + + public void passTnt(Player from, Player to) { + if (!tntPlayers.contains(from)) { + return; + } + + tntPlayers.remove(from); + tntPlayers.add(to); + + // 传递者TNT状态提示 + from.getInventory().clear(); + from.getInventory().setHelmet(null); + SpeedEffectApplier.applyInfiniteSpeed(from, 1); + from.setAllowFlight(false); + MessageUtil.sendMessage(from,"§f[§c系统§f] §b炸弹传递成功!尽快远离§6"+to.getName()+"§b他现在被定住了!",Sound.ENTITY_EXPERIENCE_ORB_PICKUP); + from.setGlowing(true); + + // 被传递者TNT状态提示 + for (int i = 0; i < 9;i++){ + to.getInventory().setItem(i, new ItemStack(Material.TNT)); + } + to.getInventory().setHelmet(new ItemStack(Material.TNT)); + to.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 70, 1, false, false)); + to.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 50, 5, false, false)); + SpeedEffectApplier.applyInfiniteSpeed(to, 3); + to.setAllowFlight(true); + MessageUtil.sendMessage(to,"§f[§c系统§f] §a谢特~§6"+from.getName()+"§a将炸弹传递给了你!",Sound.ENTITY_BLAZE_DEATH); + to.setGlowing(false); + } + + public Set getTntPlayers() { + return tntPlayers; + } + + private void startCountdownTask() { + taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() { + int seconds = countdownSeconds; + @Override + public void run() { + if (seconds <= 0) { + handleExplosions(); + stopRound(); + // 检查是否游戏结束 + if (gameManager.getAlivePlayers().size() <= 1) { + gameManager.endGame(); + } else { + startNextRound(); + } + return; + } + // 显示倒计时(可选:BossBar) + setBossBarProgress(seconds / (double) countdownSeconds,seconds); + seconds--; + } + }, 0L, 20L); // 每秒一次 + } + + private void handleExplosions() { + Set eliminated = new HashSet<>(tntPlayers); + for (Player player : eliminated) { + gameManager.eliminatePlayer(player); + // 不破坏方块 + player.getWorld().createExplosion(player.getLocation(), 0F); + } + } + private int calculateTntCount(int aliveCount, int roundNumber) { + // 决赛期直接限制为1个 + if (aliveCount <= 3) { + return 1; + } + // 基础分配比例,根据轮次略作调整(可调节) + double ratio; + if (roundNumber == 1) { + ratio = 0.12; // 开局温和一点 + } else if (roundNumber <= 4) { + ratio = 0.16; + } else if (roundNumber <= 7) { + ratio = 0.14; + } else { + ratio = 0.10; + } + + // 计算初步TNT数量 + int tntCount = (int) Math.floor(aliveCount * ratio); + + // 强制下限为1,上限为 aliveCount - 1 + tntCount = Math.max(1, tntCount); + tntCount = Math.min(tntCount, aliveCount - 1); + + return tntCount; + } + + + private void selectInitialTntPlayers() { + List alive = new ArrayList<>(gameManager.getAlivePlayers()); + int aliveCount = alive.size(); + int roundNumber = gameManager.getRoundManager().getRoundNumber(); + + int tntCount = calculateTntCount(aliveCount, roundNumber); + Collections.shuffle(alive); + + List stringList = new ArrayList<>(); + for (int i = 0; i < tntCount && i < alive.size(); i++) { + Player player = alive.get(i); + tntPlayers.add(player); + // TNT状态提示 + player.getInventory().setHelmet(new ItemStack(Material.TNT)); + SpeedEffectApplier.applyInfiniteSpeed(player, 3); + player.setAllowFlight(true); + stringList.add(player.getName()); + } + String bombsAnnounced = MessageUtil.getMessage("bombs_announced").replace("{listName}", String.join("§a, §e",stringList)); + Bukkit.broadcastMessage(bombsAnnounced); + } +} diff --git a/src/main/java/com/yaohun/tnttag/task/CountdownTask.java b/src/main/java/com/yaohun/tnttag/task/CountdownTask.java new file mode 100644 index 0000000..249c87b --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/task/CountdownTask.java @@ -0,0 +1,4 @@ +package com.yaohun.tnttag.task; + +public class CountdownTask { +} diff --git a/src/main/java/com/yaohun/tnttag/task/TntSmokeEffectTask.java b/src/main/java/com/yaohun/tnttag/task/TntSmokeEffectTask.java new file mode 100644 index 0000000..bd0cd1a --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/task/TntSmokeEffectTask.java @@ -0,0 +1,32 @@ +package com.yaohun.tnttag.task; + +import com.yaohun.tnttag.manage.GameManager; +import com.yaohun.tnttag.util.GameState; +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +public class TntSmokeEffectTask extends BukkitRunnable { + + private final GameManager gameManager; + + public TntSmokeEffectTask(GameManager gameManager) { + this.gameManager = gameManager; + } + + @Override + public void run() { + // 游戏未开始时跳过 + GameState gameState = gameManager.gameState; + if (gameState != GameState.INGAME) { + return; + } + // 遍历所有 TNT 玩家 + for (Player player : gameManager.getRoundManager().getTntPlayers()) { + // 播放烟雾粒子(1.12.2 推荐使用 Spigot API) + Location loc = player.getLocation().add(0, 0.5, 0); + player.getWorld().spigot().playEffect(loc, Effect.CLOUD, 0, 0, 0.15F, 0.15F, 0.15F, 0.15F, 5, 30); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/yaohun/tnttag/util/GameState.java b/src/main/java/com/yaohun/tnttag/util/GameState.java new file mode 100644 index 0000000..14e46a3 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/util/GameState.java @@ -0,0 +1,7 @@ +package com.yaohun.tnttag.util; + +public enum GameState { + LOBBY, // 等待玩家 + INGAME, // 游戏已开始 + RESTART // 游戏即将重启 +} diff --git a/src/main/java/com/yaohun/tnttag/util/MessageUtil.java b/src/main/java/com/yaohun/tnttag/util/MessageUtil.java new file mode 100644 index 0000000..9c4a396 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/util/MessageUtil.java @@ -0,0 +1,61 @@ +package com.yaohun.tnttag.util; + +import com.yaohun.tnttag.TagMain; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; +import java.util.HashMap; + +public class MessageUtil { + + private static HashMap messageMap = new HashMap<>(); + + public static void init(TagMain plugin) { + File file = new File(plugin.getDataFolder(), "message.yml"); + if (!file.exists()) { + plugin.saveResource("message.yml", false); + } + FileConfiguration config = YamlConfiguration.loadConfiguration(file); + for (String key : config.getKeys(false)){ + ConfigurationSection section = config.getConfigurationSection(key); + if(section == null){ + continue; + } + for (String key2 : section.getKeys(false)){ + String message = section.getString(key2).replace("&", "§"); + messageMap.put(key2, message); + } + } + } + + public static String getMessage(String key){ + if(messageMap.containsKey(key)){ + return messageMap.get(key); + } + return "§c缺少参数."+key; + } + + public static void sendMessage(CommandSender sender, String message, Sound sound){ + sender.sendMessage(message); + if(sender instanceof Player){ + Player player = (Player) sender; + player.playSound(player.getLocation(),sound,0.8f,1.2f); + } + } + + public static void sendMessage(CommandSender sender, String key){ + sender.sendMessage(getMessage(key)); + } + + public static void playSound(Sound sound){ + for (Player player : Bukkit.getOnlinePlayers()){ + player.playSound(player.getLocation(),sound,1.0f,1.0f); + } + } +} diff --git a/src/main/java/com/yaohun/tnttag/util/PlayerState.java b/src/main/java/com/yaohun/tnttag/util/PlayerState.java new file mode 100644 index 0000000..58fc28f --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/util/PlayerState.java @@ -0,0 +1,6 @@ +package com.yaohun.tnttag.util; + +public enum PlayerState { + SURVIVE, + DEATH +} diff --git a/src/main/java/com/yaohun/tnttag/util/SideBar.java b/src/main/java/com/yaohun/tnttag/util/SideBar.java new file mode 100644 index 0000000..6a99d55 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/util/SideBar.java @@ -0,0 +1,51 @@ +package com.yaohun.tnttag.util; + +import com.yaohun.tnttag.TagMain; +import com.yaohun.tnttag.manage.GameManager; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; + +public class SideBar { + + public void updateScoreboard() { + Scoreboard board = Bukkit.getScoreboardManager().getNewScoreboard(); + Objective objective = board.registerNewObjective("AAA", "BBB"); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + GameManager gameManager = TagMain.getGame(); + if (gameManager.gameState == GameState.LOBBY) { + objective.setDisplayName("§c====§6§lTNT-Tag§c===="); + objective.getScore("§A§r").setScore(7); + objective.getScore("§e地图: §a宗门领地").setScore(6); + int online = Bukkit.getOnlinePlayers().size(); + objective.getScore("§e地图: §a"+online+"/60").setScore(5); + objective.getScore("§A").setScore(4); + objective.getScore("§6等待中 ...").setScore(3); + objective.getScore("§f").setScore(2); + objective.getScore("§A§l咯吱窝:").setScore(1); + objective.getScore("§e§l mc.163.com").setScore(0); + for (Player all : Bukkit.getOnlinePlayers()) { + all.setScoreboard(board); + } + return; + } + if (gameManager.gameState == GameState.INGAME) { + objective.setDisplayName("§c====§6§lTNT-Tag§c===="); + objective.getScore("§A§r").setScore(6); + objective.getScore("§b§l存活: §6" + gameManager.getAlivePlayers().size()+"名").setScore(5); + int number = gameManager.getRoundManager().getRoundNumber(); + objective.getScore("§b§l回合: §6" + number).setScore(4); + int bombkeeper = gameManager.getRoundManager().getTntPlayers().size(); + objective.getScore("§b§l炸弹: §6" + bombkeeper+"颗").setScore(3); + objective.getScore("§f").setScore(2); + objective.getScore("§A§l咯吱窝:").setScore(1); + objective.getScore("§e§l mc.163.com").setScore(0); + for (Player all : Bukkit.getOnlinePlayers()) { + all.setScoreboard(board); + } + } + + } +} diff --git a/src/main/java/com/yaohun/tnttag/util/SpeedEffectApplier.java b/src/main/java/com/yaohun/tnttag/util/SpeedEffectApplier.java new file mode 100644 index 0000000..a36ff20 --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/util/SpeedEffectApplier.java @@ -0,0 +1,34 @@ +package com.yaohun.tnttag.util; + +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class SpeedEffectApplier { + + /** + * 给玩家添加无限持续时间的速度药水效果 + * + * @param player 玩家对象 + * @param amplifier 等级(0 = Speed I,1 = Speed II,依此类推) + */ + public static void applyInfiniteSpeed(Player player, int amplifier) { + if (player == null || !player.isOnline()) { + return; + } + player.removePotionEffect(PotionEffectType.SPEED); + + PotionEffect speed = new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, amplifier, false, false); + player.addPotionEffect(speed); + } + + /** + * 移除速度药水效果 + */ + public static void clearSpeed(Player player) { + if (player == null || !player.isOnline()) { + return; + } + player.removePotionEffect(PotionEffectType.SPEED); + } +} diff --git a/src/main/java/com/yaohun/tnttag/util/StackUtil.java b/src/main/java/com/yaohun/tnttag/util/StackUtil.java new file mode 100644 index 0000000..d80222d --- /dev/null +++ b/src/main/java/com/yaohun/tnttag/util/StackUtil.java @@ -0,0 +1,41 @@ +package com.yaohun.tnttag.util; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class StackUtil { + + public static ItemStack quitStack(){ + ItemStack stack = new ItemStack(Material.BED); + stack.setDurability((short) 14); + ItemMeta meta = stack.getItemMeta(); + meta.setDisplayName("§c§l退出游戏"); + stack.setItemMeta(meta); + return stack; + } + + public static ItemStack forciblyStack(){ + ItemStack stack = new ItemStack(Material.DIAMOND); + ItemMeta meta = stack.getItemMeta(); + meta.setDisplayName("§b§l强制开始"); + stack.setItemMeta(meta); + return stack; + } + + public static ItemStack observerOn(){ + ItemStack stack = new ItemStack(Material.SLIME_BALL); + ItemMeta meta = stack.getItemMeta(); + meta.setDisplayName("§a§l旁观§7(右键开启)"); + stack.setItemMeta(meta); + return stack; + } + + public static ItemStack observerOff(){ + ItemStack stack = new ItemStack(Material.MAGMA_CREAM); + ItemMeta meta = stack.getItemMeta(); + meta.setDisplayName("§c§l旁观§7(右键关闭)"); + stack.setItemMeta(meta); + return stack; + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..3b14185 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,2 @@ +requirementPlayer: 30 +backServer: loginlobby01 \ No newline at end of file diff --git a/src/main/resources/message.yml b/src/main/resources/message.yml new file mode 100644 index 0000000..f5b651e --- /dev/null +++ b/src/main/resources/message.yml @@ -0,0 +1,11 @@ +message: + insufficient_number_of_people: "§f[§c系统§f] §a还需要 §e{value}名 §a玩家加入,游戏才会开始。" + start_countdown: "§f[§c系统§f] §a游戏将在 §e%seconds%秒 §a后开始." + join_message: "§f[§c系统§f] §b欢迎玩家 §6{name} §b加入了烫手山芋 [§6{online} §b/ §660§b]" + quit_message: "§f[§c系统§f] §b玩家 §6{name} §b离开了烫手山芋 [§6{online} §b/ §660§b]" + observer_on: "§f[§c系统§f] §a☃ §b开启观察者模式!" + observer_off: "§f[§c系统§f] §c☃ §b关闭观察者模式!" + bombs_announced: "§f[§c系统§f] §a本轮炸弹客名单: §e{listName} §c(远离他们)" + ranking_rewards_3: "§7[§c§l公告§7] §6恭喜玩家§2{name}§6在 §d{time} §6炸弹传递获得第三名!奖励内容: §7[§d非献祭§7]§c十万年灵环抽奖箱" + ranking_rewards_2: "§7[§c§l公告§7] §6恭喜玩家§2{name}§6在 §d{time} §6炸弹传递获得第二名!奖励内容: §7[§d非献祭§7]§c十万年灵环抽奖箱" + ranking_rewards_1: "§7[§c§l公告§7] §6恭喜玩家§2{name}§6在 §d{time} §6炸弹传递获得游戏胜利!奖励内容: §7[§d献祭§7]§c十万年灵环抽奖箱" \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..9fca31e --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,9 @@ +name: AuTntTag +main: com.yaohun.tnttag.TagMain +version: 1.0.0 +author: yaohun +depend: + - DemonAPI +commands: + game: + forcestart: \ No newline at end of file