This commit is contained in:
yaohunya 2025-08-02 09:44:57 +08:00
commit 34e873ed17
23 changed files with 1469 additions and 0 deletions

47
pom.xml Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yaohun.main</groupId>
<artifactId>AuTntTag</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>public-rpg</id>
<url>https://repo.aurora-pixels.com/repository/public-rpg/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2</version>
</dependency>
<dependency>
<groupId>me.Demon.DemonPlugin</groupId>
<artifactId>DemonAPI</artifactId>
<version>2.2.9</version>
</dependency>
<dependency>
<groupId>me.Demon.DemonWarps</groupId>
<artifactId>DemonWarps</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>me.clip.placeholderapi</groupId>
<artifactId>PlaceholderAPI</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
</project>

View File

@ -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 "";
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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<UUID> 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());
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<Player> alivePlayers = new HashSet<>();
// 所有参与过该局的玩家用于重置
private final Set<Player> 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<Player> getAlivePlayers() {
return alivePlayers;
}
public GameState getGameState() {
return gameState;
}
public RoundManager getRoundManager() {
return roundManager;
}
}

View File

@ -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<Player> 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<Player> 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<Player> 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<Player> alive = new ArrayList<>(gameManager.getAlivePlayers());
int aliveCount = alive.size();
int roundNumber = gameManager.getRoundManager().getRoundNumber();
int tntCount = calculateTntCount(aliveCount, roundNumber);
Collections.shuffle(alive);
List<String> 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);
}
}

View File

@ -0,0 +1,4 @@
package com.yaohun.tnttag.task;
public class CountdownTask {
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,7 @@
package com.yaohun.tnttag.util;
public enum GameState {
LOBBY, // 等待玩家
INGAME, // 游戏已开始
RESTART // 游戏即将重启
}

View File

@ -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<String,String> 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);
}
}
}

View File

@ -0,0 +1,6 @@
package com.yaohun.tnttag.util;
public enum PlayerState {
SURVIVE,
DEATH
}

View File

@ -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);
}
}
}
}

View File

@ -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 I1 = 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);
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,2 @@
requirementPlayer: 30
backServer: loginlobby01

View File

@ -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十万年灵环抽奖箱"

View File

@ -0,0 +1,9 @@
name: AuTntTag
main: com.yaohun.tnttag.TagMain
version: 1.0.0
author: yaohun
depend:
- DemonAPI
commands:
game:
forcestart: