add command and exp loot

This commit is contained in:
Xanadu13
2023-12-30 00:25:04 +08:00
parent 55bbc54335
commit 35ec0e6456
12 changed files with 335 additions and 43 deletions
@@ -9,40 +9,104 @@ import static pers.xanadu.enderdragon.EnderDragon.*;
public class FileUpdater {
public static void update() throws IOException {
FileConfiguration config_old = plugin.getConfig();
if("2.2.0".equals(config_old.getString("version"))){
Config.saveResource("config.yml","new/config.yml",true);
File config_new_F = new File(plugin.getDataFolder(),"new/config.yml");
FileConfiguration config_new = YamlConfiguration.loadConfiguration(config_new_F);
config_new.set("lang",config_old.getString("lang"));
config_new.set("damage_visible_mode",config_old.getString("damage_visible_mode"));
config_new.set("damage_statistics.limit",config_old.getInt("damage_statistics.limit"));
String judge_mode = config_old.getString("special_dragon_jude_mode");
if("edge".equals(judge_mode)) judge_mode = "weight";//"edge" is deprecated
config_new.set("special_dragon_jude_mode",judge_mode);
config_new.set("dragon_setting_file",config_old.getStringList("dragon_setting_file"));
// auto_respawn
config_new.set("auto_respawn",config_old.getConfigurationSection("auto_respawn"));
config_new.set("respawn_cd.enable",config_old.getBoolean("respawn_cd.enable"));
config_new.set("crystal_invulnerable",config_old.getBoolean("crystal_invulnerable"));
config_new.set("resist_player_respawn",config_old.getBoolean("resist_player_respawn"));
config_new.set("resist_dragon_breath_gather",config_old.getBoolean("resist_dragon_breath_gather"));
config_new.set("main_gui",config_old.getString("main_gui"));
config_new.set("blacklist_worlds",config_old.getStringList("blacklist_worlds"));
config_new.set("item_format.reward",config_old.getString("item_format.reward"));
config_new.set("hook_plugins.MythicLib",config_old.getBoolean("hook_plugins.MythicLib"));
config_new.set("expansion.groovy",config_old.getBoolean("expansion.groovy"));
config_new.set("debug",config_old.getBoolean("debug"));
config_new.set("advanced_setting.world_env_fix",config_old.getBoolean("advanced_setting.world_env_fix"));
config_new.set("advanced_setting.save_respawn_status",config_old.getBoolean("advanced_setting.save_respawn_status"));
config_new.set("save_bossbar",config_old.getBoolean("save_bossbar"));
config_new.set("backslash_split.reward",config_old.getBoolean("backslash_split.reward"));
config_new.save(config_new_F);
boolean chinese = "Chinese".equals(config_old.getString("lang"));
File folder = new File(plugin.getDataFolder(),"setting");
if(folder.exists()){
File[] files = folder.listFiles();
if(files != null){
for(File file : files){
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
String ver = config.getString("version");
if(!"2.2.0".equals(ver)) {
Lang.error("The version of setting/"+file.getName()+" is not supported!");
continue;
}
String name = file.getName();
Config.copyFile("setting/"+name,"new/setting/"+name,true);
}
File new_folder = new File(plugin.getDataFolder(),"new/setting/");
files = new_folder.listFiles();
if(files != null){
for(File file : files){
FileOutputStream out = new FileOutputStream(file,true);
if (chinese){
out.write(("\n\n" +
"# 一些特殊的战利品\n" +
"special_loot:\n" +
" # 你可以按格式添加更多条目,但是名称不能重复\n" +
" # 如果找不到执行目标(target),所在战利品条目会被忽略\n" +
" # 目前支持的type: exp(经验), command(执行指令,可解析伤害排名)\n" +
" loot1:\n" +
" # [true/false]\n" +
" enable: false\n" +
" type: command\n" +
" # %attacker% -> 所有参与屠龙的玩家\n" +
" target: \"%attacker%\"\n" +
" # %player% -> 目标, %damage% -> 该玩家造成的总伤害\n" +
" data:\n" +
" - 'give %player% stone 1'\n" +
" - 'ed action %player% tell: 你获得了保底奖励.'\n" +
" loot2:\n" +
" enable: false\n" +
" type: command\n" +
" # %attacker_top_<rank>% -> 在屠龙中取得此排名的玩家\n" +
" target: \"%attacker_top_1%\"\n" +
" data:\n" +
" - 'ed action %player% tell: 你的伤害占比是最高的!'\n" +
" - 'ed action %player% tell: 你造成的伤害: %damage%'\n" +
" loot_exp1:\n" +
" enable: false\n" +
" type: exp\n" +
" target: \"%attacker_top_2%\"\n" +
" data:\n" +
" # 给予排名第二的玩家20点经验\n" +
" amount: 20\n" +
"\n\n"
).getBytes());
}
else{
out.write(("\n\n" +
"special_loot:\n" +
" # You can add more entries with DIFFERENT name according to the format.\n" +
" # If such target not exists, this option will be ignored.\n" +
" # type: exp, command\n" +
" loot1:\n" +
" # [true/false]\n" +
" enable: false\n" +
" type: command\n" +
" # %attacker% -> all participants in dragon slaying\n" +
" target: \"%attacker%\"\n" +
" # %player% -> target, %damage% -> this player's damage to EnderDragon\n" +
" data:\n" +
" - 'give %player% stone 1'\n" +
" - 'ed action %player% tell: This is a guaranteed reward.'\n" +
" loot2:\n" +
" enable: false\n" +
" type: command\n" +
" # %attacker_top_<rank>% -> the player with exactly this rank\n" +
" target: \"%attacker_top_1%\"\n" +
" data:\n" +
" - 'ed action %player% tell: You are the one who causes the highest damage!'\n" +
" - 'ed action %player% tell: Your damage: %damage%'\n" +
" loot_exp1:\n" +
" enable: false\n" +
" type: exp\n" +
" target: \"%attacker_top_2%\"\n" +
" data:\n" +
" # add 20 exp for the rank_2 player\n" +
" amount: 20\n" +
"\n\n"
).getBytes());
}
out.close();
FileConfiguration fc = YamlConfiguration.loadConfiguration(file);
fc.set("version","2.4.0");
fc.save(file);
}
}
}
}
else Lang.error("The version of config.yml is not supported!");
Lang.info("New config files are generated in plugins/EnderDragon/new.");
Lang.warn("Attention: Please confirm the accuracy before using new config!");
}
@@ -20,11 +20,14 @@ import pers.xanadu.enderdragon.manager.DamageManager;
import pers.xanadu.enderdragon.manager.DragonManager;
import pers.xanadu.enderdragon.manager.TimerManager;
import pers.xanadu.enderdragon.metadata.MyDragon;
import pers.xanadu.enderdragon.reward.SpecialLoot;
import pers.xanadu.enderdragon.util.Pair;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import static pers.xanadu.enderdragon.EnderDragon.*;
@@ -80,6 +83,7 @@ public class DragonDeathListener implements Listener {
}
}
handleBroadcast(processed,myDragon,dragon);
handleSpecialLoot(myDragon,dragon);
}
DamageManager.data.remove(dragon.getUniqueId());
Lang.runCommands(myDragon.death_cmd,p);
@@ -90,6 +94,27 @@ public class DragonDeathListener implements Listener {
}
TimerManager.startTimer(dragon.getWorld().getName());
}
private static void handleSpecialLoot(final MyDragon myDragon, final EnderDragon dragon){
List<Pair<String,Double>> list = DamageManager.getDamageList(dragon.getUniqueId());
list.sort(DamageManager::sortByDamage);
Set<String> online_players = new HashSet<>();
Bukkit.getOnlinePlayers().forEach(player -> online_players.add(player.getName()));
List<SpecialLoot> participants = myDragon.lootMap.get(0);
boolean tag = participants != null;
int size = list.size();
for(int i=0;i<size;i++){
Pair<String,Double> pair = list.get(i);
String name = pair.first;
//玩家不在线
if(!online_players.contains(name)) continue;
String damage = String.format("%.2f",pair.second);
//所有参与者
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));
}
}
public static void handleBroadcast(final List<String> list,final MyDragon myDragon,final EnderDragon dragon){
boolean find = false;
for(String str : list){
@@ -1,5 +1,7 @@
package pers.xanadu.enderdragon.manager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import pers.xanadu.enderdragon.util.Pair;
import java.util.ArrayList;
@@ -22,4 +24,13 @@ public class DamageManager {
return -1;
}
public static void gc(){
for(UUID uuid : DamageManager.data.keySet()){
Entity entity = Bukkit.getEntity(uuid);
if(entity == null || entity.isDead()) DamageManager.data.remove(uuid);
}
}
}
@@ -6,6 +6,7 @@ import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.boss.DragonBattle;
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.*;
@@ -17,6 +18,7 @@ import pers.xanadu.enderdragon.config.Config;
import pers.xanadu.enderdragon.config.Lang;
import pers.xanadu.enderdragon.metadata.DragonInfo;
import pers.xanadu.enderdragon.reward.RewardDist;
import pers.xanadu.enderdragon.reward.SpecialLoot;
import pers.xanadu.enderdragon.util.ExtraPotionEffect;
import pers.xanadu.enderdragon.metadata.MyDragon;
import pers.xanadu.enderdragon.util.Version;
@@ -26,6 +28,8 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static pers.xanadu.enderdragon.EnderDragon.*;
@@ -44,6 +48,7 @@ public class DragonManager {
private static Method getX;
private static Method getY;
private static Method getZ;
private static final Pattern pattern_attacker_top = Pattern.compile("%attacker_top_(\\d+)%");
public static void reload(){
new BukkitRunnable(){
@@ -263,11 +268,67 @@ public class DragonManager {
}
myDragon.effect_cloud_potion = effectCloudPotions;
myDragon.reward_dist = RewardDist.parse(f.getConfigurationSection("reward_dist"));
ConfigurationSection loots = f.getConfigurationSection("special_loot");
Map<Integer, List<SpecialLoot>> loot_mp = new HashMap<>();
if(loots != null){
for (String key : loots.getKeys(false)) {
ConfigurationSection loot = loots.getConfigurationSection(key);
if(loot == null || !loot.getBoolean("enable")) continue;
String type = loot.getString("type");
SpecialLoot specialLoot;
if("command".equals(type)){
List<String> commands = loot.getStringList("data");
specialLoot = (player, damage) -> handleCommandLoot(commands,player,damage);
}
else if("exp".equals(type)){
int amount = loot.getInt("data"+f.options().pathSeparator()+"amount");
specialLoot = (player, __) -> {
Player p = Bukkit.getPlayer(player);
if(p != null) p.giveExp(amount);
};
}
else{
Lang.error("Unknown special_loot type: "+type);
continue;
}
String target = loot.getString("target");
if(target == null) continue;
if("%attacker%".equals(target)){
loot_mp.compute(0,(k,v)->{
if(v==null) return Collections.singletonList(specialLoot);
v.add(specialLoot);
return v;
});
}
else{
Matcher matcher = pattern_attacker_top.matcher(target);
if (matcher.find()) {
Integer rank = Integer.parseInt(matcher.group(1));
loot_mp.compute(rank,(k,v)->{
if(v==null) return Collections.singletonList(specialLoot);
v.add(specialLoot);
return v;
});
} else {
Lang.error("Wrong special_loot target: "+target);
continue;
}
}
}
}
myDragon.lootMap = loot_mp;
dragons.add(myDragon);
mp.put(myDragon.unique_name,myDragon);
dragon_names.add(myDragon.unique_name);
sum += edge;
}
private static void handleCommandLoot(List<String> list, String name, String damage){
if(list == null) return;
for (String cmd : list) {
if(cmd.equals("")) continue;
plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(),cmd.replaceAll("%player%",name).replaceAll("%damage%",damage));
}
}
public static void disable(){
dragons.clear();
mp.clear();
@@ -63,7 +63,6 @@ public class GroovyManager {
binding.setVariable("itemStack",player.getItemInHand());
binding.setVariable("world",player.getWorld());
GroovyShell shell = new GroovyShell(GroovyManager.class.getClassLoader(),binding,compilerConfig);
//Bukkit.broadcastMessage(lib);
return shell.evaluate(lib+expression);
}
@@ -4,10 +4,12 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import pers.xanadu.enderdragon.reward.Reward;
import pers.xanadu.enderdragon.reward.RewardDist;
import pers.xanadu.enderdragon.reward.SpecialLoot;
import pers.xanadu.enderdragon.util.ExtraPotionEffect;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class MyDragon implements Comparable<MyDragon>{
public ItemStack icon;
@@ -54,6 +56,7 @@ public class MyDragon implements Comparable<MyDragon>{
public List<PotionEffect> effect_cloud_potion;
public List<Reward> datum = new ArrayList<>();
public RewardDist reward_dist;
public Map<Integer, List<SpecialLoot>> lootMap;
@Override
public int compareTo(final MyDragon o) {
@@ -0,0 +1,8 @@
package pers.xanadu.enderdragon.reward;
import java.util.function.BiConsumer;
@FunctionalInterface
public interface SpecialLoot extends BiConsumer<String,String> {
}
@@ -9,7 +9,7 @@ import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager;
import static org.bukkit.Bukkit.getServer;
public class Version {
public static final String setting_dragon = "2.2.0";
public static final String setting_dragon = "2.4.0";
public static final String lang = "2.2.0";
public static final String config = "2.3.0";
public static final String data = "2.2.0";
+33 -2
View File
@@ -1,5 +1,5 @@
#文件版本,请勿修改
version: 2.2.0
version: 2.4.0
#用于插件内部识别,每一种末影龙的unique_name都需要设为不同值!
unique_name: 'default'
@@ -200,4 +200,35 @@ reward_dist:
max_num: 1
rank:
# 排名前几可获得奖励
max_num: 1
max_num: 1
# 一些特殊的战利品
special_loot:
# 你可以按格式添加更多条目,但是名称不能重复
# 如果找不到执行目标(target),所在战利品条目会被忽略
# 目前支持的type: exp(经验), command(执行指令,可解析伤害排名)
loot1:
# [true/false]
enable: false
type: command
# %attacker% -> 所有参与屠龙的玩家
target: "%attacker%"
# %player% -> 目标, %damage% -> 该玩家造成的总伤害
data:
- 'give %player% stone 1'
- 'ed action %player% tell: 你获得了保底奖励.'
loot2:
enable: false
type: command
# %attacker_top_<rank>% -> 在屠龙中取得此排名的玩家
target: "%attacker_top_1%"
data:
- 'ed action %player% tell: 你的伤害占比是最高的!'
- 'ed action %player% tell: 你造成的伤害: %damage%'
loot_exp1:
enable: false
type: exp
target: "%attacker_top_2%"
data:
# 给予排名第二的玩家20点经验
amount: 20
+32 -3
View File
@@ -1,4 +1,4 @@
version: 2.2.0
version: 2.4.0
#This is used for plugin internal identification.
#Please make sure the value is unique among all the types of dragons
@@ -154,7 +154,7 @@ effect_cloud:
#All the settings below can be disabled with a "[]".(Ex: spawn_cmd: [] )
#commands that server will run when this dragon spawn
#Attention: You shouldn't add “/” at the beginning of each command!
#Attention: Please DON'T add “/” at the beginning of each command!
spawn_cmd:
- ''
- ''
@@ -198,7 +198,7 @@ reward_dist:
# killer: Only give to the final killer.
# pack: Pack all items that trigger drop and distribute them to players weighted based on their damage percentage.
# rank: Strictly based on player damage ranking, give the top few players with the highest damage.
# termwise: Assign the items that trigger the drop ONE BY ONE to the player based on the weighted proportion of damage.
# termwise: Assign items that trigger the drop ONE BY ONE to the player based on the weighted proportion of damage.
type: killer
drop:
# Whether the dropped item glows.
@@ -211,3 +211,32 @@ reward_dist:
# Top few can receive rewards
max_num: 1
special_loot:
# You can add more entries with DIFFERENT name according to the format.
# If such target not exists, this option will be ignored.
# type: exp, command
loot1:
# [true/false]
enable: false
type: command
# %attacker% -> all participants in dragon slaying
target: "%attacker%"
# %player% -> target, %damage% -> this player's damage to EnderDragon
data:
- 'give %player% stone 1'
- 'ed action %player% tell: This is a guaranteed reward.'
loot2:
enable: false
type: command
# %attacker_top_<rank>% -> the player with exactly this rank
target: "%attacker_top_1%"
data:
- 'ed action %player% tell: You are the one who causes the highest damage!'
- 'ed action %player% tell: Your damage: %damage%'
loot_exp1:
enable: false
type: exp
target: "%attacker_top_2%"
data:
# add 20 exp for the rank_2 player
amount: 20
+33 -2
View File
@@ -1,5 +1,5 @@
#文件版本,请勿修改
version: 2.2.0
version: 2.4.0
#用于插件内部识别,每一种末影龙的unique_name都需要设为不同值!
unique_name: 'special001'
@@ -193,4 +193,35 @@ reward_dist:
max_num: 1
rank:
# 排名前几可获得奖励
max_num: 1
max_num: 1
# 一些特殊的战利品
special_loot:
# 你可以按格式添加更多条目,但是名称不能重复
# 如果找不到执行目标(target),所在战利品条目会被忽略
# 目前支持的type: exp(经验), command(执行指令,可解析伤害排名)
loot1:
# [true/false]
enable: false
type: command
# %attacker% -> 所有参与屠龙的玩家
target: "%attacker%"
# %player% -> 目标, %damage% -> 该玩家造成的总伤害
data:
- 'give %player% stone 1'
- 'ed action %player% tell: 你获得了保底奖励.'
loot2:
enable: false
type: command
# %attacker_top_<rank>% -> 在屠龙中取得此排名的玩家
target: "%attacker_top_1%"
data:
- 'ed action %player% tell: 你的伤害占比是最高的!'
- 'ed action %player% tell: 你造成的伤害: %damage%'
loot_exp1:
enable: false
type: exp
target: "%attacker_top_2%"
data:
# 给予排名第二的玩家20点经验
amount: 20
+32 -2
View File
@@ -1,7 +1,7 @@
## Special thanks to Phaxius for the translation
# File version, do not edit
version: 2.2.0
version: 2.4.0
# Unique ID used by plugin to identify each type of dragon
# unique_name needs to be different in each dragon settings file
@@ -229,4 +229,34 @@ reward_dist:
max_num: 1
rank:
# Top few can receive rewards
max_num: 1
max_num: 1
special_loot:
# You can add more entries with DIFFERENT name according to the format.
# If such target not exists, this option will be ignored.
# type: exp, command
loot1:
# [true/false]
enable: false
type: command
# %attacker% -> all participants in dragon slaying
target: "%attacker%"
# %player% -> target, %damage% -> this player's damage to EnderDragon
data:
- 'give %player% stone 1'
- 'ed action %player% tell: This is a guaranteed reward.'
loot2:
enable: false
type: command
# %attacker_top_<rank>% -> the player with exactly this rank
target: "%attacker_top_1%"
data:
- 'ed action %player% tell: You are the one who causes the highest damage!'
- 'ed action %player% tell: Your damage: %damage%'
loot_exp1:
enable: false
type: exp
target: "%attacker_top_2%"
data:
# add 20 exp for the rank_2 player
amount: 20