This commit is contained in:
Xanadu13
2026-05-03 16:32:16 +09:00
parent 88bc3867d5
commit 9613e0333c
4 changed files with 253 additions and 201 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>pers.xanadu</groupId> <groupId>pers.xanadu</groupId>
<artifactId>EnderDragon</artifactId> <artifactId>EnderDragon</artifactId>
<version>2.5.7</version> <version>2.5.8</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>EnderDragon</name> <name>EnderDragon</name>
@@ -1,186 +1,187 @@
package pers.xanadu.enderdragon.listener; package pers.xanadu.enderdragon.listener;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder; import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.EnderDragon; import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import pers.xanadu.enderdragon.config.Config; import pers.xanadu.enderdragon.config.Config;
import pers.xanadu.enderdragon.config.Lang; import pers.xanadu.enderdragon.config.Lang;
import pers.xanadu.enderdragon.manager.DamageManager; import pers.xanadu.enderdragon.manager.DamageManager;
import pers.xanadu.enderdragon.manager.DragonManager; import pers.xanadu.enderdragon.manager.DragonManager;
import pers.xanadu.enderdragon.manager.TimerManager; import pers.xanadu.enderdragon.manager.TimerManager;
import pers.xanadu.enderdragon.manager.WorldManager; import pers.xanadu.enderdragon.manager.WorldManager;
import pers.xanadu.enderdragon.metadata.MyDragon; import pers.xanadu.enderdragon.metadata.MyDragon;
import pers.xanadu.enderdragon.reward.SpecialLoot; import pers.xanadu.enderdragon.reward.SpecialLoot;
import pers.xanadu.enderdragon.util.Pair; import pers.xanadu.enderdragon.util.Pair;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import static pers.xanadu.enderdragon.EnderDragon.*; import static pers.xanadu.enderdragon.EnderDragon.*;
public class DragonDeathListener implements Listener { public class DragonDeathListener implements Listener {
@EventHandler @EventHandler
public void OnDragonDeath(final EntityDeathEvent e){ public void OnDragonDeath(final EntityDeathEvent e){
if(!(e.getEntity() instanceof EnderDragon)) return; if(!(e.getEntity() instanceof EnderDragon)) return;
EnderDragon dragon = (EnderDragon) e.getEntity(); EnderDragon dragon = (EnderDragon) e.getEntity();
if(!WorldManager.enable_worlds.contains(dragon.getWorld().getName())) return; if(!WorldManager.enable_worlds.contains(dragon.getWorld().getName())) return;
String unique_name = DragonManager.getSpecialKey(dragon); String unique_name = DragonManager.getSpecialKey(dragon);
if(unique_name == null) return; if(unique_name == null) return;
MyDragon myDragon = DragonManager.get_dragon_config(unique_name); MyDragon myDragon = DragonManager.get_dragon_config(unique_name);
if(myDragon == null) return; if(myDragon == null) return;
int times = data.getInt("times"); int times = data.getInt("times");
data.set("times",times+1); data.set("times",times+1);
try{ try{
data.save(dataF); data.save(dataF);
}catch (IOException ex){ }catch (IOException ex){
Lang.error(Lang.plugin_file_save_error.replaceAll("\\{file_name}",dataF.getName())); Lang.error(Lang.plugin_file_save_error.replaceAll("\\{file_name}",dataF.getName()));
} }
e.setDroppedExp(myDragon.exp_drop); e.setDroppedExp(myDragon.exp_drop);
if(myDragon.dragon_egg_spawn_chance > ThreadLocalRandom.current().nextDouble(100)){ if(myDragon.dragon_egg_spawn_chance > ThreadLocalRandom.current().nextDouble(100)){
new BukkitRunnable() { new BukkitRunnable() {
@Override @Override
public void run() { public void run() {
Block block = e.getEntity().getWorld().getBlockAt(myDragon.dragon_egg_spawn_x, myDragon.dragon_egg_spawn_y, myDragon.dragon_egg_spawn_z); Block block = e.getEntity().getWorld().getBlockAt(myDragon.dragon_egg_spawn_x, myDragon.dragon_egg_spawn_y, myDragon.dragon_egg_spawn_z);
block.setType(Material.DRAGON_EGG); block.setType(Material.DRAGON_EGG);
} }
}.runTaskLater(plugin, myDragon.dragon_egg_spawn_delay); }.runTaskLater(plugin, myDragon.dragon_egg_spawn_delay);
} }
Player p = e.getEntity().getKiller(); Player p = e.getEntity().getKiller();
myDragon.reward_dist.handle_dist(myDragon,dragon,p); myDragon.reward_dist.handle_dist(myDragon,dragon,p);
{ {
List<String> processed = new ArrayList<>(); List<String> processed = new ArrayList<>();
if(p != null){ if(p != null){
for(String str : myDragon.death_broadcast_msg){ for(String str : myDragon.death_broadcast_msg){
processed.add(str.replaceAll("%times%",String.valueOf(times)).replaceAll("%player%",p.getDisplayName())); processed.add(str.replaceAll("%times%",String.valueOf(times)).replaceAll("%player%",p.getDisplayName()));
} }
} }
else{ else{
StringBuilder names = new StringBuilder(); StringBuilder names = new StringBuilder();
List<Entity> entities = dragon.getNearbyEntities(5,5,5); List<Entity> entities = dragon.getNearbyEntities(5,5,5);
for (Entity entity : entities) { for (Entity entity : entities) {
if (entity instanceof Player) { if (entity instanceof Player) {
names.append(((Player) entity).getDisplayName()).append(","); names.append(((Player) entity).getDisplayName()).append(",");
} }
} }
String name = names.toString(); String name = names.toString();
if(name.equals("")) name = Lang.dragon_no_killer; if(name.equals("")) name = Lang.dragon_no_killer;
if(name.endsWith(",")) name = name.substring(0,name.length()-1); if(name.endsWith(",")) name = name.substring(0,name.length()-1);
for(String str : myDragon.death_broadcast_msg){ for(String str : myDragon.death_broadcast_msg){
processed.add(str.replaceAll("%times%",String.valueOf(times)).replaceAll("%player%", name)); processed.add(str.replaceAll("%times%",String.valueOf(times)).replaceAll("%player%", name));
} }
} }
handleBroadcast(processed,myDragon,dragon); handleBroadcast(processed,myDragon,dragon);
handleSpecialLoot(myDragon,dragon); handleSpecialLoot(myDragon,dragon);
} }
DamageManager.data.remove(dragon.getUniqueId()); DamageManager.data.remove(dragon.getUniqueId());
Lang.runCommands(myDragon.death_cmd,p); Lang.runCommands(myDragon.death_cmd,p);
if(p != null){ if(p != null){
for(String str : myDragon.msg_to_killer){ for(String str : myDragon.msg_to_killer){
Lang.sendFeedback(p,str.replaceAll("%times%",String.valueOf(times))); Lang.sendFeedback(p,str.replaceAll("%times%",String.valueOf(times)));
} }
} }
TimerManager.startTimer(dragon.getWorld().getName()); TimerManager.startTimer(dragon.getWorld().getName());
} }
private static void handleSpecialLoot(final MyDragon myDragon, final EnderDragon dragon){ private static void handleSpecialLoot(final MyDragon myDragon, final EnderDragon dragon){
List<Pair<String,Double>> list = DamageManager.getDamageList(dragon.getUniqueId()); List<Pair<String,Double>> list = DamageManager.getDamageList(dragon.getUniqueId());
list.sort(DamageManager::sortByDamage); list.sort(DamageManager::sortByDamage);
List<SpecialLoot> participants = myDragon.lootMap.get(0); List<SpecialLoot> participants = myDragon.lootMap.get(0);
boolean tag = participants != null; // 是否给所有参与者发奖励
int size = list.size(); boolean tag = participants != null;
for(int i=0;i<size;i++){ int size = list.size();
Pair<String,Double> pair = list.get(i); for(int i=0;i<size;i++){
String name = pair.first; Pair<String,Double> pair = list.get(i);
String damage = String.format("%.2f",pair.second); String name = pair.first;
//所有参与者 String damage = String.format("%.2f",pair.second);
if(tag) participants.forEach(loot -> loot.accept(name,damage)); //所有参与者
//针对特殊名次 if(tag) participants.forEach(loot -> loot.accept(name,damage));
List<SpecialLoot> loots = myDragon.lootMap.get(i+1); //针对特殊名次
if(loots!=null) loots.forEach(loot -> loot.accept(name,damage)); List<SpecialLoot> loots = myDragon.lootMap.get(i+1);
} if(loots!=null) loots.forEach(loot -> loot.accept(name,damage));
} }
public static void handleBroadcast(final List<String> list,final MyDragon myDragon,final EnderDragon dragon){ }
boolean find = false; public static void handleBroadcast(final List<String> list,final MyDragon myDragon,final EnderDragon dragon){
for(String str : list){ boolean find = false;
if(str.contains("{damage_statistics}")){ for(String str : list){
find = true; if(str.contains("{damage_statistics}")){
break; find = true;
} break;
} }
if(!find) Lang.broadcastMSG(list); }
else{ if(!find) Lang.broadcastMSG(list);
final TextComponent hover = getHover(myDragon,dragon); else{
for(String str : list){ final TextComponent hover = getHover(myDragon,dragon);
final String[] splits = str.split("\\{damage_statistics}"); for(String str : list){
final ComponentBuilder builder = new ComponentBuilder(Lang.plugin_prefix); final String[] splits = str.split("\\{damage_statistics}");
int size = splits.length; final ComponentBuilder builder = new ComponentBuilder(Lang.plugin_prefix);
for(int i=0;i<size-1;i++){ int size = splits.length;
builder.append(splits[i]).append(hover); for(int i=0;i<size-1;i++){
} builder.append(splits[i]).append(hover);
builder.append(splits[size-1]); }
if(str.endsWith("{damage_statistics}")) builder.append(hover); builder.append(splits[size-1]);
Bukkit.getOnlinePlayers().forEach(p->p.spigot().sendMessage(builder.create())); if(str.endsWith("{damage_statistics}")) builder.append(hover);
} Bukkit.getOnlinePlayers().forEach(p->p.spigot().sendMessage(builder.create()));
} }
} }
public static TextComponent getHover(final MyDragon myDragon,final EnderDragon dragon) { }
final TextComponent text = new TextComponent(Lang.dragon_damage_statistics_text); public static TextComponent getHover(final MyDragon myDragon,final EnderDragon dragon) {
List<Pair<String,Double>> list = DamageManager.getDamageList(dragon.getUniqueId()); final TextComponent text = new TextComponent(Lang.dragon_damage_statistics_text);
list.sort(DamageManager::sortByDamage); List<Pair<String,Double>> list = DamageManager.getDamageList(dragon.getUniqueId());
double sum = 0d; list.sort(DamageManager::sortByDamage);
for(Pair<String,Double> pair : list){ double sum = 0d;
sum += pair.second; for(Pair<String,Double> pair : list){
} sum += pair.second;
StringBuilder builder = new StringBuilder(); }
for(String raw : Lang.dragon_damage_statistics_hover_prefix){ StringBuilder builder = new StringBuilder();
builder.append(raw for(String raw : Lang.dragon_damage_statistics_hover_prefix){
.replaceAll("%dragon_display_name%",myDragon.display_name) builder.append(raw
.replaceAll("%damage_sum%",String.format("%.2f",sum)) .replaceAll("%dragon_display_name%",myDragon.display_name)
).append("\n"); .replaceAll("%damage_sum%",String.format("%.2f",sum))
} ).append("\n");
int i = 0; }
for(Pair<String,Double> pair : list){ int i = 0;
String raw = Lang.dragon_damage_statistics_hover_mt; for(Pair<String,Double> pair : list){
if(i < Config.damage_statistics_limit){ String raw = Lang.dragon_damage_statistics_hover_mt;
double damage = pair.second; if(i < Config.damage_statistics_limit){
double percent = damage/sum*100; double damage = pair.second;
builder.append(raw double percent = damage/sum*100;
.replaceAll("%rank%", String.valueOf(++i)) builder.append(raw
.replaceAll("%player%", pair.first) .replaceAll("%rank%", String.valueOf(++i))
.replaceAll("%damage%",String.format("%.2f",damage)) .replaceAll("%player%", pair.first)
.replaceAll("%percent%",String.format("%.2f%%",percent)) .replaceAll("%damage%",String.format("%.2f",damage))
).append("\n"); .replaceAll("%percent%",String.format("%.2f%%",percent))
} ).append("\n");
} }
if(list.size()-i>0){ }
String raw = Lang.dragon_damage_statistics_hover_exceeds_limit; if(list.size()-i>0){
builder.append(raw String raw = Lang.dragon_damage_statistics_hover_exceeds_limit;
.replaceAll("%exceeds_number%", String.valueOf(list.size()-i)) builder.append(raw
).append("\n"); .replaceAll("%exceeds_number%", String.valueOf(list.size()-i))
} ).append("\n");
for(String raw : Lang.dragon_damage_statistics_hover_suffix){ }
builder.append(raw for(String raw : Lang.dragon_damage_statistics_hover_suffix){
.replaceAll("%dragon_display_name%",myDragon.display_name) builder.append(raw
.replaceAll("%damage_sum%",String.format("%.2f",sum)) .replaceAll("%dragon_display_name%",myDragon.display_name)
); .replaceAll("%damage_sum%",String.format("%.2f",sum))
} );
BaseComponent[] cmp = new ComponentBuilder(builder.toString()).create(); }
text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,cmp)); BaseComponent[] cmp = new ComponentBuilder(builder.toString()).create();
return text; text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,cmp));
} return text;
}
}
}
@@ -51,7 +51,7 @@ public class NMSUtil {
public void init(){ public void init(){
String version = Version.getVersion(); String version = Version.getVersion();
try{ try{
this.CraftWorldClass = Class.forName("org.bukkit.craftbukkit." + version + ".CraftWorld"); this.CraftWorldClass = ClassResolver.obc("CraftWorld");
this.getNMSWord = CraftWorldClass.getDeclaredMethod("getHandle"); this.getNMSWord = CraftWorldClass.getDeclaredMethod("getHandle");
this.WorldClass = this.getNMSWord.getReturnType().getSuperclass(); this.WorldClass = this.getNMSWord.getReturnType().getSuperclass();
this.world_c_environment = CraftWorldClass.getDeclaredField("environment"); this.world_c_environment = CraftWorldClass.getDeclaredField("environment");
@@ -60,12 +60,12 @@ public class NMSUtil {
this.WorldProviderClass = Class.forName("net.minecraft.server."+version+".WorldProvider"); this.WorldProviderClass = Class.forName("net.minecraft.server."+version+".WorldProvider");
//this.WorldProviderTheEndClass = Class.forName("net.minecraft.server."+version+".WorldProviderTheEnd"); //this.WorldProviderTheEndClass = Class.forName("net.minecraft.server."+version+".WorldProviderTheEnd");
} }
this.CraftItemStackClass = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); this.CraftItemStackClass = ClassResolver.obc("inventory.CraftItemStack");
this.CraftMetaItemClass = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftMetaItem"); this.CraftMetaItemClass = ClassResolver.obc("inventory.CraftMetaItem");
this.unhandledTags = CraftMetaItemClass.getDeclaredField("unhandledTags"); this.unhandledTags = CraftMetaItemClass.getDeclaredField("unhandledTags");
unhandledTags.setAccessible(true); unhandledTags.setAccessible(true);
this.NMSItemStackClass = CraftItemStackClass.getDeclaredField("handle").getType(); this.NMSItemStackClass = CraftItemStackClass.getDeclaredField("handle").getType();
this.CraftEntityClass = Class.forName("org.bukkit.craftbukkit."+version+".entity.CraftEntity"); this.CraftEntityClass = ClassResolver.obc("entity.CraftEntity");
init_NBTTagCompoundClass(); init_NBTTagCompoundClass();
init_NBTBaseClass(); init_NBTBaseClass();
if (!Version.isNBT_UPDATE()){ if (!Version.isNBT_UPDATE()){
@@ -83,11 +83,17 @@ public class NMSUtil {
if(Version.mcMainVersion<=16) this.MojangsonParserClass = Class.forName("net.minecraft.server."+version+".MojangsonParser"); if(Version.mcMainVersion<=16) this.MojangsonParserClass = Class.forName("net.minecraft.server."+version+".MojangsonParser");
else this.MojangsonParserClass = Class.forName("net.minecraft.nbt.MojangsonParser"); else if (Version.mcMainVersion < 26) this.MojangsonParserClass = Class.forName("net.minecraft.nbt.MojangsonParser");
this.stringToCPD = MojangsonParserClass.getMethod(getMethodName(ReflectiveMethod.MojangsonParser_parse),String.class); else {
// TODO: 2026/5/3 16:21
this.MojangsonParserClass = null;
}
if (this.MojangsonParserClass != null) {
this.stringToCPD = MojangsonParserClass.getMethod(getMethodName(ReflectiveMethod.MojangsonParser_parse),String.class);
}
if(Version.mcMainVersion>=14){ if(Version.mcMainVersion>=14){
this.CraftPersistentDataContainerClass = Class.forName("org.bukkit.craftbukkit." + version + ".persistence.CraftPersistentDataContainer"); this.CraftPersistentDataContainerClass = ClassResolver.obc("persistence.CraftPersistentDataContainer");
this.PDCtoCPD = CraftPersistentDataContainerClass.getDeclaredMethod("toTagCompound"); this.PDCtoCPD = CraftPersistentDataContainerClass.getDeclaredMethod("toTagCompound");
if (!Version.isNBT_UPDATE()){ if (!Version.isNBT_UPDATE()){
this.PersistentDataContainer_putAll = CraftPersistentDataContainerClass.getDeclaredMethod("putAll",NBTTagCompoundClass); this.PersistentDataContainer_putAll = CraftPersistentDataContainerClass.getDeclaredMethod("putAll",NBTTagCompoundClass);
@@ -101,6 +107,44 @@ public class NMSUtil {
} }
if(Config.debug) check(); if(Config.debug) check();
} }
public static final class ClassResolver {
private static final String OBC_BASE = "org.bukkit.craftbukkit";
private static final String NMS_LEGACY_BASE = "net.minecraft.server";
private static final String NMS_MODERN_BASE = "net.minecraft";
private static final String VERSION = Version.getVersion();
private static boolean isModern() {
return Version.mcMainVersion >= 26;
}
public static Class<?> obc(String path) throws ClassNotFoundException {
String fullName;
if (isModern()) {
fullName = OBC_BASE + "." + path;
} else {
fullName = OBC_BASE + "." + VERSION + "." + path;
}
return Class.forName(fullName);
}
public static Class<?> nms(String path) throws ClassNotFoundException {
String fullName;
if (isModern()) {
fullName = NMS_MODERN_BASE + "." + path;
} else {
fullName = NMS_LEGACY_BASE + "." + VERSION + "." + path;
}
return Class.forName(fullName);
}
}
public void check(){ public void check(){
try{ try{
Field[] fields = NMSUtil.class.getDeclaredFields(); Field[] fields = NMSUtil.class.getDeclaredFields();
@@ -303,7 +347,7 @@ public class NMSUtil {
} }
private void init_NBTTagCompoundClass(){ private void init_NBTTagCompoundClass(){
try{ try{
Class<?> CraftMetaBlockStateClass = Class.forName("org.bukkit.craftbukkit."+Version.getVersion()+".inventory.CraftMetaBlockState"); Class<?> CraftMetaBlockStateClass = ClassResolver.obc("inventory.CraftMetaBlockState");
Field field = CraftMetaBlockStateClass.getDeclaredField("blockEntityTag"); Field field = CraftMetaBlockStateClass.getDeclaredField("blockEntityTag");
this.NBTTagCompoundClass = field.getType(); this.NBTTagCompoundClass = field.getType();
return; return;
@@ -35,15 +35,22 @@ public class Version {
Field LEGACY_CB_VERSION = clazz.getField("LEGACY_CB_VERSION"); Field LEGACY_CB_VERSION = clazz.getField("LEGACY_CB_VERSION");
version = (String) LEGACY_CB_VERSION.get(null); version = (String) LEGACY_CB_VERSION.get(null);
}catch (ReflectiveOperationException e){ }catch (ReflectiveOperationException e){
throwable.printStackTrace(); version = Bukkit.getVersion().split("-")[0];
Lang.warn("Failed to get nms-version!");
Bukkit.getServer().getPluginManager().disablePlugin(EnderDragon.plugin);
} }
} }
String[] mc_version = getServer().getBukkitVersion().split("-")[0].split("\\."); String[] mc_version = getServer().getBukkitVersion().split("-")[0].split("\\.");
mcMainVersion = Integer.parseInt(mc_version[1]);
if(mc_version.length<=2) mcPatchVersion = 0; int first = Integer.parseInt(mc_version[0]);
else mcPatchVersion = Integer.parseInt(mc_version[2]); // e.g. 26.1.2.build.53
if (first >= 26) {
mcMainVersion = first;
mcPatchVersion = Integer.parseInt(mc_version[1]);
} else {
mcMainVersion = Integer.parseInt(mc_version[1]);
if(mc_version.length<=2) mcPatchVersion = 0;
else mcPatchVersion = Integer.parseInt(mc_version[2]);
}
Lang.info("Found version: " + version); Lang.info("Found version: " + version);
try{ try{
Class.forName("net.minecraftforge.server.ServerMain"); Class.forName("net.minecraftforge.server.ServerMain");