1.0.0
This commit is contained in:
commit
34e873ed17
47
pom.xml
Normal file
47
pom.xml
Normal 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>
|
90
src/main/java/com/yaohun/tnttag/PapiExpansion.java
Normal file
90
src/main/java/com/yaohun/tnttag/PapiExpansion.java
Normal 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 "";
|
||||
}
|
||||
}
|
74
src/main/java/com/yaohun/tnttag/TagMain.java
Normal file
74
src/main/java/com/yaohun/tnttag/TagMain.java
Normal 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;
|
||||
}
|
||||
}
|
20
src/main/java/com/yaohun/tnttag/config/Config.java
Normal file
20
src/main/java/com/yaohun/tnttag/config/Config.java
Normal 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);
|
||||
}
|
||||
}
|
108
src/main/java/com/yaohun/tnttag/counter/LobbyCounter.java
Normal file
108
src/main/java/com/yaohun/tnttag/counter/LobbyCounter.java
Normal 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);
|
||||
}
|
||||
}
|
55
src/main/java/com/yaohun/tnttag/counter/RestartCounter.java
Normal file
55
src/main/java/com/yaohun/tnttag/counter/RestartCounter.java
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
58
src/main/java/com/yaohun/tnttag/listener/GameListener.java
Normal file
58
src/main/java/com/yaohun/tnttag/listener/GameListener.java
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
195
src/main/java/com/yaohun/tnttag/listener/PlayerListener.java
Normal file
195
src/main/java/com/yaohun/tnttag/listener/PlayerListener.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
src/main/java/com/yaohun/tnttag/listener/ProtectListener.java
Normal file
101
src/main/java/com/yaohun/tnttag/listener/ProtectListener.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
136
src/main/java/com/yaohun/tnttag/manage/GameManager.java
Normal file
136
src/main/java/com/yaohun/tnttag/manage/GameManager.java
Normal 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;
|
||||
}
|
||||
}
|
231
src/main/java/com/yaohun/tnttag/manage/RoundManager.java
Normal file
231
src/main/java/com/yaohun/tnttag/manage/RoundManager.java
Normal 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);
|
||||
}
|
||||
}
|
4
src/main/java/com/yaohun/tnttag/task/CountdownTask.java
Normal file
4
src/main/java/com/yaohun/tnttag/task/CountdownTask.java
Normal file
|
@ -0,0 +1,4 @@
|
|||
package com.yaohun.tnttag.task;
|
||||
|
||||
public class CountdownTask {
|
||||
}
|
32
src/main/java/com/yaohun/tnttag/task/TntSmokeEffectTask.java
Normal file
32
src/main/java/com/yaohun/tnttag/task/TntSmokeEffectTask.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
7
src/main/java/com/yaohun/tnttag/util/GameState.java
Normal file
7
src/main/java/com/yaohun/tnttag/util/GameState.java
Normal file
|
@ -0,0 +1,7 @@
|
|||
package com.yaohun.tnttag.util;
|
||||
|
||||
public enum GameState {
|
||||
LOBBY, // 等待玩家
|
||||
INGAME, // 游戏已开始
|
||||
RESTART // 游戏即将重启
|
||||
}
|
61
src/main/java/com/yaohun/tnttag/util/MessageUtil.java
Normal file
61
src/main/java/com/yaohun/tnttag/util/MessageUtil.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
6
src/main/java/com/yaohun/tnttag/util/PlayerState.java
Normal file
6
src/main/java/com/yaohun/tnttag/util/PlayerState.java
Normal file
|
@ -0,0 +1,6 @@
|
|||
package com.yaohun.tnttag.util;
|
||||
|
||||
public enum PlayerState {
|
||||
SURVIVE,
|
||||
DEATH
|
||||
}
|
51
src/main/java/com/yaohun/tnttag/util/SideBar.java
Normal file
51
src/main/java/com/yaohun/tnttag/util/SideBar.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
34
src/main/java/com/yaohun/tnttag/util/SpeedEffectApplier.java
Normal file
34
src/main/java/com/yaohun/tnttag/util/SpeedEffectApplier.java
Normal 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 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);
|
||||
}
|
||||
}
|
41
src/main/java/com/yaohun/tnttag/util/StackUtil.java
Normal file
41
src/main/java/com/yaohun/tnttag/util/StackUtil.java
Normal 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;
|
||||
}
|
||||
}
|
2
src/main/resources/config.yml
Normal file
2
src/main/resources/config.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
requirementPlayer: 30
|
||||
backServer: loginlobby01
|
11
src/main/resources/message.yml
Normal file
11
src/main/resources/message.yml
Normal 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十万年灵环抽奖箱"
|
9
src/main/resources/plugin.yml
Normal file
9
src/main/resources/plugin.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
name: AuTntTag
|
||||
main: com.yaohun.tnttag.TagMain
|
||||
version: 1.0.0
|
||||
author: yaohun
|
||||
depend:
|
||||
- DemonAPI
|
||||
commands:
|
||||
game:
|
||||
forcestart:
|
Loading…
Reference in New Issue
Block a user