This commit is contained in:
yaohunya 2025-08-07 17:13:13 +08:00
commit 779420568e
12 changed files with 655 additions and 0 deletions

42
pom.xml Normal file
View File

@ -0,0 +1,42 @@
<?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>org.example</groupId>
<artifactId>DemonPvpProtect</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>com.io.yaohun.worldbosshurt</groupId>
<artifactId>WorldBossHurt</artifactId>
<version>1.4.8</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,93 @@
package com.yaohun.pvpprotect;
import com.yaohun.pvpprotect.config.Config;
import com.yaohun.pvpprotect.data.PlayerData;
import com.yaohun.pvpprotect.gui.OperateGui;
import com.yaohun.pvpprotect.listener.PlayerListener;
import com.yaohun.pvpprotect.manage.PlayerManager;
import me.Demon.DemonPlugin.Util.DataRefreshUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
public class PvpMain extends JavaPlugin {
private static PvpMain instance;
private static PlayerManager playerManager;
@Override
public void onEnable() {
instance = this;
Config.reloadConfig(this);
playerManager = new PlayerManager(this);
getServer().getPluginManager().registerEvents(new OperateGui(), this);
getServer().getPluginManager().registerEvents(new PlayerListener(), this);
Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
getPlayerManager().carryOutCheckTime();
},100L,20L * 60);
DataRefreshUtil.createRefreshDataRecord("PvpProtectDaily");
}
@Override
public void onDisable() {
getPlayerManager().saveAllPlayerData();
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if("pvp".equalsIgnoreCase(label)){
if (!sender.isOp()) {
Player p = (Player) sender;
OperateGui.openGui(p);
return true;
}
if (args.length == 0) {
sender.sendMessage("");
sender.sendMessage("§e------- ======= §6竞技保护 §e======= -------");
sender.sendMessage("§2/" + label + " open §f- §2打开界面");
sender.sendMessage("§2/" + label + " reload §f- §2重载配置");
sender.sendMessage("§2/" + label + " reset §e[玩家/ALL] §f- §2重置保护世界");
sender.sendMessage("§e------- ======= §6竞技保护 §e======= -------");
return true;
}
if(args.length == 1 && "open".equalsIgnoreCase(args[0])){
Player p = (Player) sender;
OperateGui.openGui(p);
return true;
}
if(args.length == 1 && "reload".equalsIgnoreCase(args[0])){
Config.reloadConfig(this);
sender.sendMessage("[竞技保护] 配置文件已重载完成.");
return true;
}
if(args.length >= 1 && "reset".equalsIgnoreCase(args[0])){
String name = "all";
if(args.length >= 2){
name = args[1];
}
if("all".equalsIgnoreCase(name)) {
getPlayerManager().resetAllPlayerData();
sender.sendMessage("[竞技保护] 所有玩家的竞技保护时间已重置.");
return true;
}
PlayerData playerData = getPlayerManager().getPlayerData(name);
playerData.resetTimeLeft();
sender.sendMessage("[竞技保护] 玩家 "+name+" 竞技保护时间已重置.");
}
}
return false;
}
public static PvpMain inst() {
return instance;
}
public static PlayerManager getPlayerManager() {
return playerManager;
}
}

View File

@ -0,0 +1,43 @@
package com.yaohun.pvpprotect.config;
import com.yaohun.pvpprotect.PvpMain;
import me.Demon.DemonPlugin.DemonAPI;
import me.Demon.DemonPlugin.data.GuiItemData;
import me.Demon.DemonPlugin.data.LangData;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
public class Config {
public static int default_hour = 12;
public static LangData langData;
private static HashMap<String, GuiItemData> guiItemDataMap = new HashMap<>();
public static void reloadConfig(PvpMain plugin){
guiItemDataMap.clear();
langData = DemonAPI.getLangData("DemonPvpProtect");
plugin.reloadConfig();
plugin.saveConfig();
FileConfiguration config = plugin.getConfig();
default_hour = config.getInt("DefaultHour",12);
loadGuiItemData(config);
}
private static void loadGuiItemData(FileConfiguration configuration){
ConfigurationSection section = configuration.getConfigurationSection("GuiItemData");
if(section == null){return;}
for (String itemKey : section.getKeys(false)){
guiItemDataMap.put(itemKey,new GuiItemData(itemKey,section));
}
}
public static ItemStack getItemStack(String itemKey) {
if(guiItemDataMap.containsKey(itemKey)){
return guiItemDataMap.get(itemKey).getItemStack().clone();
}
return DemonAPI.getErrItems();
}
}

View File

@ -0,0 +1,62 @@
package com.yaohun.pvpprotect.data;
import com.yaohun.pvpprotect.PvpMain;
import com.yaohun.pvpprotect.config.Config;
import com.yaohun.pvpprotect.util.MessageUtil;
import org.bukkit.Bukkit;
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;
public class PlayerData {
private String playerName;
private long timeLeft;
private long startTime;
public PlayerData(String name, FileConfiguration config){
this.playerName = name;
this.timeLeft = config.getLong(name);
if(this.timeLeft == 0){
this.resetTimeLeft();
}
this.startTime = System.currentTimeMillis();
}
public void saveData(){
File file = new File(PvpMain.inst().getDataFolder(), "data.yml");
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
config.set(playerName, timeLeft);
}
public String getPlayerName() {
return playerName;
}
public long getTimeLeft() {
return timeLeft;
}
public void setTimeLeft(long timeLeft) {
this.timeLeft = timeLeft;
}
public void resetTimeLeft(){
this.timeLeft = Config.default_hour * 60 * 60 * 1000L;
}
public void resetStartTime(){
this.startTime = System.currentTimeMillis();
}
public void timeSpentThisTimeEvent() {
long deductionTime = System.currentTimeMillis() - startTime;
this.startTime = System.currentTimeMillis();
setTimeLeft(getTimeLeft() - deductionTime);
if(this.timeLeft <= 0){
this.timeLeft = -1000 * 60;
}
}
}

View File

@ -0,0 +1,85 @@
package com.yaohun.pvpprotect.gui;
import com.yaohun.pvpprotect.PvpMain;
import com.yaohun.pvpprotect.config.Config;
import com.yaohun.pvpprotect.data.PlayerData;
import com.yaohun.pvpprotect.manage.PlayerManager;
import com.yaohun.pvpprotect.util.MessageUtil;
import com.yaohun.pvpprotect.util.StackUtil;
import me.Demon.DemonPlugin.Util.CDTimeAPI;
import me.Demon.DemonPlugin.Util.DataRefreshUtil;
import me.Demon.DemonPlugin.settings.RefreshData;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import java.util.UUID;
public class OperateGui implements Listener {
private static String invTitle = Config.langData.getMessage("invTitle");
public static void openGui(Player player){
PlayerManager playerManager = PvpMain.getPlayerManager();
RefreshData refreshData = DataRefreshUtil.getSetting("PvpProtectDaily");
if(refreshData != null && !refreshData.isSameDayAsRecord()){
refreshData.setRecordTime(System.currentTimeMillis());
DataRefreshUtil.SaveRefreshDataRecord(refreshData);
playerManager.resetAllPlayerData();
}
String playerName = player.getName();
PlayerData playerData = playerManager.getPlayerData(playerName);
if(playerData.getTimeLeft() < 1000L){
String message = Config.langData.getMessage("insufficientTime");
MessageUtil.sendMessage(player,message, Sound.ENTITY_VILLAGER_NO);
return;
}
Inventory inv = Bukkit.createInventory(null,9,invTitle);
inv.setItem(1,Config.getItemStack("ProtectInfo"));
inv.setItem(4, StackUtil.startSwitch(player.getName()));
inv.setItem(7,StackUtil.timeDisplay(playerData));
player.openInventory(inv);
}
@EventHandler
public void onclick(InventoryClickEvent e) {
int rawSlot = e.getRawSlot();
Player p = (Player) e.getWhoClicked();
UUID uuid = p.getUniqueId();
String playerName = p.getName();
if (e.getView().getTitle().equalsIgnoreCase(invTitle)) {
e.setCancelled(true);
if(e.getRawSlot() == 4) {
p.closeInventory();
String cdKey = "switchModePvp";
if(CDTimeAPI.isCD(uuid,cdKey)){
double second = (double) CDTimeAPI.getCD(uuid, cdKey) / 1000L;
String message = Config.langData.getMessage("switchCoolDown").replace("{time}",String.format("%.1f",second));
MessageUtil.sendMessage(p,message, Sound.ENTITY_VILLAGER_NO);
return;
}
CDTimeAPI.setPlayerCD(uuid,cdKey,1000L * 10L);
PlayerManager playerManager = PvpMain.getPlayerManager();
if (playerManager.isPlayerOpened(playerName)) {
playerManager.setProtectStats(playerName,false);
String message = Config.langData.getMessage("switchModeOff");
MessageUtil.sendMessage(p,message, Sound.ENTITY_VILLAGER_NO);
} else {
PlayerData playerData = playerManager.getPlayerData(playerName);
if(playerData.getTimeLeft() < 1000L){
String message = Config.langData.getMessage("insufficientTime");
MessageUtil.sendMessage(p,message, Sound.ENTITY_VILLAGER_NO);
return;
}
playerManager.setProtectStats(playerName,true);
String message = Config.langData.getMessage("switchModeOn");
MessageUtil.sendMessage(p,message, Sound.BLOCK_COMPARATOR_CLICK);
}
}
}
}
}

View File

@ -0,0 +1,85 @@
package com.yaohun.pvpprotect.listener;
import com.io.yaohun.worldbosshurt.api.BossHurtAPI;
import com.yaohun.pvpprotect.PvpMain;
import com.yaohun.pvpprotect.config.Config;
import com.yaohun.pvpprotect.manage.PlayerManager;
import com.yaohun.pvpprotect.util.MessageUtil;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
public class PlayerListener implements Listener {
@EventHandler
public void onDamageBy(EntityDamageByEntityEvent e) {
if (!(e.getEntity() instanceof Player)) {
return;
}
Player damaged = (Player) e.getEntity();
Player damager = null;
// 判断攻击者类型
if (e.getDamager() instanceof Player) {
damager = (Player) e.getDamager();
} else if (e.getDamager() instanceof Projectile) {
Projectile projectile = (Projectile) e.getDamager();
if (projectile.getShooter() instanceof Player) {
damager = (Player) projectile.getShooter();
}
}
if (damager == null) {
return;
}
World world = damager.getWorld();
if ("hsjjc".equalsIgnoreCase(world.getName())) {
return;
}
PlayerManager playerManager = PvpMain.getPlayerManager();
String damagerName = damager.getName();
String damagedName = damaged.getName();
if (playerManager.isPlayerOpened(damagerName)) {
e.setCancelled(true);
damaged.sendMessage(Config.langData.getMessage("damagerPVP"));
return;
}
if (playerManager.isPlayerOpened(damagedName)) {
e.setCancelled(true);
damager.sendMessage(Config.langData.getMessage("entityPVP"));
}
}
@EventHandler
public void onBossDiscover(EntityDamageByEntityEvent e) {
if (!(e.getDamager() instanceof Player)) {
return;
}
if (e.getEntity() instanceof Player) {
return;
}
Player player = (Player) e.getDamager();
String playerName = player.getName();
PlayerManager playerManager = PvpMain.getPlayerManager();
// 判断玩家是否已开启Pvp保护
if(playerManager.isPlayerOpened(playerName)){
// 判断玩家攻击目标是否是BOSS
Entity entity = e.getEntity();
String customName = entity.getCustomName();
if (customName != null && BossHurtAPI.isBossExist(customName)) {
String message = Config.langData.getMessage("attackBossClose");
MessageUtil.sendMessage(player,message, Sound.ENTITY_VILLAGER_YES);
playerManager.setProtectStats(playerName,false);
}
}
}
}

View File

@ -0,0 +1,131 @@
package com.yaohun.pvpprotect.manage;
import com.yaohun.pvpprotect.PvpMain;
import com.yaohun.pvpprotect.config.Config;
import com.yaohun.pvpprotect.data.PlayerData;
import com.yaohun.pvpprotect.util.MessageUtil;
import org.bukkit.Bukkit;
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.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class PlayerManager {
private final File file;
private final FileConfiguration config;
// 当玩家开启了竞技保护就会例如这里
private final HashMap<String,Boolean> protectStatsMap = new HashMap<>();
private final HashMap<String, PlayerData> playerDataMap = new HashMap<>();
public PlayerManager(PvpMain plugin) {
this.file = new File(plugin.getDataFolder(),"data.yml");
this.config = YamlConfiguration.loadConfiguration(this.file);
}
public PlayerData getPlayerData(String playerName) {
if(!playerDataMap.containsKey(playerName)) {
PlayerData playerData = new PlayerData(playerName,this.config);
playerDataMap.put(playerName,playerData);
return playerData;
}
return playerDataMap.get(playerName);
}
public void saveAllPlayerData() {
for (PlayerData playerData : playerDataMap.values()) {
playerData.saveData();
}
try {
config.save(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void setAllPlayerData(long time) {
for (PlayerData playerData : playerDataMap.values()){
playerData.setTimeLeft(time);
}
}
// 将所有玩家的竞技保护时间重置
public void resetAllPlayerData() {
saveAllPlayerData();
playerDataMap.clear();
long defaultTime = Config.default_hour * 1000L * 60 * 60;
for (String playerName : config.getKeys(false)) {
config.set(playerName, defaultTime);
}
try {
config.save(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 判断玩家是否已开启竞技保护
public boolean isPlayerOpened(String playerName) {
if(this.protectStatsMap.containsKey(playerName)){
return this.protectStatsMap.get(playerName);
}
return false;
}
// 设置玩家是否开启竞技保护
public void setProtectStats(String playerName, boolean isOpened){
this.protectStatsMap.put(playerName,isOpened);
// 若是开启竞技保护 将重置玩家数据中的 startTime
if(isOpened){
PlayerData playerData = getPlayerData(playerName);
playerData.resetStartTime();
}
}
public List<String> getOpenedList(){
List<String> stringList = new ArrayList<>();
for (String playerName : protectStatsMap.keySet()) {
if(protectStatsMap.get(playerName)){
stringList.add(playerName);
}
}
return stringList;
}
public void carryOutCheckTime() {
// 获取已开启竞技保护的玩家列表
List<String> stringList = getOpenedList();
if(stringList.isEmpty()){
return;
}
for (String playerName : stringList) {
PlayerData playerData = getPlayerData(playerName);
if (playerData == null) {
continue;
}
playerData.timeSpentThisTimeEvent();
long timeLeft = playerData.getTimeLeft();
if (timeLeft < 0) {
// 回到主线程再操作 Bukkit API
Bukkit.getScheduler().runTask(PvpMain.inst(), () -> {
Player player = Bukkit.getPlayer(playerName);
if (player != null) {
MessageUtil.sendMessage(player, Config.langData.getMessage("insufficientTime"));
}
setProtectStats(playerName, false);
});
}
}
int onSize = stringList.size();
if (onSize >= 1) {
Bukkit.getConsoleSender().sendMessage("[日志 - 竞技保护] 当前开启保护玩家: " + onSize + "");
}
}
}

View File

@ -0,0 +1,26 @@
package com.yaohun.pvpprotect.util;
import org.bukkit.Sound;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class MessageUtil {
public static void sendMessage(CommandSender sender, String message) {
if(sender instanceof Player){
Player player = (Player) sender;
player.sendMessage(message);
} else {
sender.sendMessage(message);
}
}
public static void sendMessage(CommandSender sender, String message, Sound sound) {
if(sender instanceof Player){
Player player = (Player) sender;
player.sendMessage(message);
player.playSound(player.getLocation(), sound, 0.8f, 1.2f);
} else {
sender.sendMessage(message);
}
}
}

View File

@ -0,0 +1,47 @@
package com.yaohun.pvpprotect.util;
import com.yaohun.pvpprotect.PvpMain;
import com.yaohun.pvpprotect.config.Config;
import com.yaohun.pvpprotect.data.PlayerData;
import com.yaohun.pvpprotect.manage.PlayerManager;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.List;
public class StackUtil {
public static ItemStack startSwitch(String playName){
PlayerManager playerManager = PvpMain.getPlayerManager();
ItemStack stack = Config.getItemStack("SwitchButt");
ItemMeta meta = stack.getItemMeta();
String stats = Config.langData.getMessage("statsOn");
if(!playerManager.isPlayerOpened(playName)){
stats = Config.langData.getMessage("statsOff");
}
String itemName = meta.getDisplayName().replace("{stats}",stats);
meta.setDisplayName(itemName);
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
stack.setItemMeta(meta);
return stack;
}
public static ItemStack timeDisplay(PlayerData playerData){
ItemStack stack = Config.getItemStack("TimeShow");
ItemMeta meta = stack.getItemMeta();
List<String> lore = meta.getLore();
for (int i = 0; i < lore.size(); i++) {
String string = lore.get(i);
if(string.contains("{time}")){
int second = (int) (playerData.getTimeLeft() / 1000L);
string = string.replace("{time}",String.valueOf(second));
lore.set(i, string);
}
}
meta.setLore(lore);
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
stack.setItemMeta(meta);
return stack;
}
}

View File

@ -0,0 +1,11 @@
Message:
statsOn: §a開啓
statsOff: §c關閉
invTitle: §8§l競技保護系統
damagerPVP: §7[§6競技保護§7] §f你開啓了競技保護,無法攻擊其他人.
entityPVP: §7[§6競技保護§7] §f目標開啓了競技保護,無法對他造成傷害.
switchModeOn: '§7[§6競技保護§7] §f模式切換成功: §a開啓'
switchModeOff: '§7[§6競技保護§7] §f模式切換成功: §c關閉'
switchCoolDown: §7[§6競技保護§7] §f你還需要等待§e[{time}秒]§f才能切換模式.
insufficientTime: §7[§6競技保護§7] §c今日的有效時長已用光,無法開啓.
attackBossClose: §7[§6競技保護§7] §b因為對世界BOSS造成了傷害,競技保護已自動關閉.

View File

@ -0,0 +1,24 @@
DefaultHour: 12
GuiItemData:
ProtectInfo:
Material: SIGN
DisplayName: §7竞技保护系统介绍
Lore:
- §a§l★§7为§a保护所有玩家§7可进入更高级别猎魂区
- §a§l★§7进行猎杀灵兽夺取灵环、材料等内容
- §a§l★§7玩家可开启竞技保护开启后将不会受到
- §a§l★§7来自§c其他玩家§7的伤害但同时也§c无法对其他§7玩家造成伤害。
- §a§l★§7每日都会赠送器师§b720分钟§7免费保护时长
- §c当你对世界BOSS造成伤害时会自动关闭保护
- ' '
- §c§l★§7系统处于测试阶段,发现任何Bug请务必联系管理反馈
SwitchButt:
Material: DIAMOND_SWORD
DisplayName: §6当前状态 §7[{stats}§7]
Lore:
- §a§l★§7点击切换状态
TimeShow:
Material: GOLD_HELMET
DisplayName: §6竞技保护状态查询
Lore:
- '§a§l★§7剩余时长: §b{time}秒'

View File

@ -0,0 +1,6 @@
name: DemonPvpProtect
main: com.yaohun.pvpprotect.PvpMain
version: 2.0.0
author: yaohun
commands:
pvp: