update to v2.2.0
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward;
|
||||||
|
|
||||||
|
|
||||||
|
public class Chance {
|
||||||
|
private double value;
|
||||||
|
private String str;
|
||||||
|
public Chance(Chance chance){
|
||||||
|
str = chance.str;
|
||||||
|
value = chance.value;
|
||||||
|
}
|
||||||
|
public Chance(double d0,String str){
|
||||||
|
this.str = str;
|
||||||
|
this.value = d0;
|
||||||
|
}
|
||||||
|
public double getValue(){
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
public String getStr(){
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
public enum DistType {
|
||||||
|
killer,
|
||||||
|
drop,//glow?
|
||||||
|
all,
|
||||||
|
rank,//num
|
||||||
|
pack,//num
|
||||||
|
termwise,
|
||||||
|
unknown;
|
||||||
|
|
||||||
|
private static final Map<String, DistType> mp = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
|
public static DistType getByName(String str){
|
||||||
|
//if(str == null) return drop;
|
||||||
|
return mp.getOrDefault(str,unknown);
|
||||||
|
}
|
||||||
|
static {
|
||||||
|
DistType[] values = DistType.values();
|
||||||
|
for (DistType type : values) {
|
||||||
|
String name = type.name();
|
||||||
|
mp.put(name, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import pers.xanadu.enderdragon.manager.ItemManager;
|
||||||
|
|
||||||
|
|
||||||
|
public class Reward extends ItemStack {
|
||||||
|
protected String name;
|
||||||
|
protected Chance chance;
|
||||||
|
private ItemStack item;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return ItemManager.write(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public int hashCode() {
|
||||||
|
// return this.name.hashCode();
|
||||||
|
// }
|
||||||
|
|
||||||
|
public ItemStack getItem() {
|
||||||
|
if(item == null) return new ItemStack(Material.AIR);
|
||||||
|
return item.clone();
|
||||||
|
}
|
||||||
|
public Chance getChance(){
|
||||||
|
return this.chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected Reward(ItemStack item,String chance) {
|
||||||
|
this.item = item;
|
||||||
|
|
||||||
|
}
|
||||||
|
public Reward(ItemStack item, Chance chance){
|
||||||
|
this.item = item;
|
||||||
|
this.chance = chance;
|
||||||
|
}
|
||||||
|
public Reward(ItemStack item){
|
||||||
|
this.item = item;
|
||||||
|
this.chance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.entity.EnderDragon;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.reward.dist.*;
|
||||||
|
import pers.xanadu.enderdragon.util.MyDragon;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public abstract class RewardDist {
|
||||||
|
public static RewardDist parse(ConfigurationSection section){
|
||||||
|
if(section == null) return new Dist_Drop();
|
||||||
|
String type_name = section.getString("type");
|
||||||
|
DistType type = DistType.getByName(type_name);
|
||||||
|
switch (type){
|
||||||
|
case all : {
|
||||||
|
return new Dist_All();
|
||||||
|
}
|
||||||
|
case drop : {
|
||||||
|
return new Dist_Drop(section.getConfigurationSection("drop"));
|
||||||
|
}
|
||||||
|
case killer : {
|
||||||
|
return new Dist_Killer();
|
||||||
|
}
|
||||||
|
case pack : {
|
||||||
|
return new Dist_Pack(section.getConfigurationSection("pack"));
|
||||||
|
}
|
||||||
|
case rank : {
|
||||||
|
return new Dist_Rank(section.getConfigurationSection("rank"));
|
||||||
|
}
|
||||||
|
case termwise : {
|
||||||
|
return new Dist_Termwise();
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
Lang.error("Unknown reward_dist type: "+type_name);
|
||||||
|
return new Dist_Drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<ItemStack> getDropReward(MyDragon myDragon){
|
||||||
|
List<ItemStack> list = new ArrayList<>();
|
||||||
|
for(Reward reward : myDragon.datum){
|
||||||
|
double chance = reward.getChance().getValue();
|
||||||
|
if(chance > ThreadLocalRandom.current().nextDouble(100)){
|
||||||
|
list.add(reward.getItem());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward.dist;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.EnderDragon;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.manager.DamageManager;
|
||||||
|
import pers.xanadu.enderdragon.reward.RewardDist;
|
||||||
|
import pers.xanadu.enderdragon.util.MyDragon;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class Dist_All extends RewardDist {
|
||||||
|
@Override
|
||||||
|
public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){
|
||||||
|
ConcurrentHashMap<String,Double> damage_data = DamageManager.data.get(dragon.getUniqueId());
|
||||||
|
if(damage_data == null) return;
|
||||||
|
List<ItemStack> items = getDropReward(myDragon);
|
||||||
|
if(items.isEmpty()) return;
|
||||||
|
Bukkit.getOnlinePlayers().forEach(p->{
|
||||||
|
if(damage_data.containsKey(p.getName())){
|
||||||
|
boolean full = false;
|
||||||
|
for(ItemStack item : items){
|
||||||
|
if(full || p.getInventory().firstEmpty() == -1){
|
||||||
|
p.getWorld().dropItem(p.getLocation(),item);
|
||||||
|
full = true;
|
||||||
|
}
|
||||||
|
else p.getInventory().addItem(item);
|
||||||
|
}
|
||||||
|
if(full) Lang.sendFeedback(p, Lang.dragon_player_inv_full);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward.dist;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.entity.EnderDragon;
|
||||||
|
import org.bukkit.entity.Item;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import pers.xanadu.enderdragon.manager.GlowManager;
|
||||||
|
import pers.xanadu.enderdragon.reward.RewardDist;
|
||||||
|
import pers.xanadu.enderdragon.util.MyDragon;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
import static pers.xanadu.enderdragon.manager.GlowManager.setGlowingColor;
|
||||||
|
|
||||||
|
public class Dist_Drop extends RewardDist {
|
||||||
|
private final GlowManager.GlowColor color;
|
||||||
|
public Dist_Drop(ConfigurationSection section){
|
||||||
|
if(section == null) color = GlowManager.GlowColor.NONE;
|
||||||
|
else {
|
||||||
|
String color = section.getString("glow","NONE").toUpperCase();
|
||||||
|
this.color = GlowManager.GlowColor.valueOf(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Dist_Drop(){
|
||||||
|
color = GlowManager.GlowColor.NONE;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void handle_dist(final MyDragon myDragon, final EnderDragon dragon, final Player killer){
|
||||||
|
List<ItemStack> items = getDropReward(myDragon);
|
||||||
|
if(items.isEmpty()) return;
|
||||||
|
World world = dragon.getWorld();
|
||||||
|
Location loc = dragon.getLocation();
|
||||||
|
items.forEach(item->{
|
||||||
|
Item entity_item = world.dropItemNaturally(loc,item);
|
||||||
|
ChatColor color = getGlowColor();
|
||||||
|
if(color!=null) setGlowingColor(entity_item,color);
|
||||||
|
double x = ThreadLocalRandom.current().nextDouble(0.25);
|
||||||
|
double y = ThreadLocalRandom.current().nextDouble(0.25);
|
||||||
|
double z = ThreadLocalRandom.current().nextDouble(0.25);
|
||||||
|
entity_item.setVelocity(new Vector(x,y,z));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatColor getGlowColor(){
|
||||||
|
return GlowManager.getGlowColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward.dist;
|
||||||
|
|
||||||
|
import org.bukkit.entity.EnderDragon;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.reward.RewardDist;
|
||||||
|
import pers.xanadu.enderdragon.util.MyDragon;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Dist_Killer extends RewardDist {
|
||||||
|
@Override
|
||||||
|
public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player p){
|
||||||
|
List<ItemStack> items = getDropReward(myDragon);
|
||||||
|
if(items.isEmpty()) return;
|
||||||
|
if(p != null){
|
||||||
|
boolean full = false;
|
||||||
|
for(ItemStack item : items){
|
||||||
|
if(full || p.getInventory().firstEmpty() == -1){
|
||||||
|
p.getWorld().dropItem(p.getLocation(),item);
|
||||||
|
full = true;
|
||||||
|
}
|
||||||
|
else p.getInventory().addItem(item);
|
||||||
|
}
|
||||||
|
if(full) Lang.sendFeedback(p, Lang.dragon_player_inv_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward.dist;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.entity.EnderDragon;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.manager.DamageManager;
|
||||||
|
import pers.xanadu.enderdragon.reward.RewardDist;
|
||||||
|
import pers.xanadu.enderdragon.util.AExpJ;
|
||||||
|
import pers.xanadu.enderdragon.util.MyDragon;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class Dist_Pack extends RewardDist {
|
||||||
|
private final int max_num;
|
||||||
|
public Dist_Pack(ConfigurationSection section){
|
||||||
|
if(section == null) max_num = 1;
|
||||||
|
else max_num = section.getInt("max_num",1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){
|
||||||
|
ConcurrentHashMap<String,Double> damage_data = DamageManager.data.get(dragon.getUniqueId());
|
||||||
|
if(damage_data == null) return;
|
||||||
|
List<ItemStack> items = getDropReward(myDragon);
|
||||||
|
if(items.isEmpty()) return;
|
||||||
|
int m = Math.min(max_num,damage_data.size());
|
||||||
|
if(m<=0) return;
|
||||||
|
List<String> receivers = AExpJ.sample(damage_data,m);
|
||||||
|
receivers.forEach(receiver->{
|
||||||
|
Player p = Bukkit.getPlayer(receiver);
|
||||||
|
if(p != null){
|
||||||
|
boolean full = false;
|
||||||
|
for(ItemStack item : items){
|
||||||
|
if(full || p.getInventory().firstEmpty() == -1){
|
||||||
|
p.getWorld().dropItem(p.getLocation(),item);
|
||||||
|
full = true;
|
||||||
|
}
|
||||||
|
else p.getInventory().addItem(item);
|
||||||
|
}
|
||||||
|
if(full) Lang.sendFeedback(p, Lang.dragon_player_inv_full);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMax_num(){
|
||||||
|
return max_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward.dist;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.entity.EnderDragon;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.manager.DamageManager;
|
||||||
|
import pers.xanadu.enderdragon.reward.RewardDist;
|
||||||
|
import pers.xanadu.enderdragon.util.MyDragon;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Dist_Rank extends RewardDist {
|
||||||
|
private final int max_num;
|
||||||
|
public Dist_Rank(ConfigurationSection section){
|
||||||
|
if(section == null) max_num = 1;
|
||||||
|
else max_num = section.getInt("max_num",1);
|
||||||
|
}
|
||||||
|
public int getMax_num(){
|
||||||
|
return max_num;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){
|
||||||
|
ConcurrentHashMap<String,Double> damage_data = DamageManager.data.get(dragon.getUniqueId());
|
||||||
|
if(damage_data == null) return;
|
||||||
|
List<ItemStack> items = getDropReward(myDragon);
|
||||||
|
if(items.isEmpty()) return;
|
||||||
|
int m = Math.min(max_num,damage_data.size());
|
||||||
|
if(m<=0) return;
|
||||||
|
List<Map.Entry<String, Double>> list = damage_data.entrySet().stream().sorted(Dist_Rank::sortByDamage).collect(Collectors.toList());
|
||||||
|
for(int i=0;i<m;i++){
|
||||||
|
String name = list.get(i).getKey();
|
||||||
|
Player p = Bukkit.getPlayer(name);
|
||||||
|
if(p != null){
|
||||||
|
boolean full = false;
|
||||||
|
for(ItemStack item : items){
|
||||||
|
if(full || p.getInventory().firstEmpty() == -1){
|
||||||
|
p.getWorld().dropItem(p.getLocation(),item);
|
||||||
|
full = true;
|
||||||
|
}
|
||||||
|
else p.getInventory().addItem(item);
|
||||||
|
}
|
||||||
|
if(full) Lang.sendFeedback(p, Lang.dragon_player_inv_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static <T> int sortByDamage(Map.Entry<T, Double> e1,Map.Entry<T, Double> e2){
|
||||||
|
if(e2.getValue()>e1.getValue()) return 1;
|
||||||
|
if(e2.getValue().equals(e1.getValue())) return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package pers.xanadu.enderdragon.reward.dist;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.EnderDragon;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.manager.DamageManager;
|
||||||
|
import pers.xanadu.enderdragon.reward.RewardDist;
|
||||||
|
import pers.xanadu.enderdragon.util.AliasSample;
|
||||||
|
import pers.xanadu.enderdragon.util.MyDragon;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class Dist_Termwise extends RewardDist {
|
||||||
|
@Override
|
||||||
|
public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){
|
||||||
|
ConcurrentHashMap<String,Double> damage_data = DamageManager.data.get(dragon.getUniqueId());
|
||||||
|
if(damage_data == null) return;
|
||||||
|
List<ItemStack> items = getDropReward(myDragon);
|
||||||
|
if(items.isEmpty()) return;
|
||||||
|
AliasSample alias = new AliasSample(new ArrayList<>(damage_data.values()));
|
||||||
|
List<String> list = new ArrayList<>(damage_data.keySet());
|
||||||
|
items.forEach(item->{
|
||||||
|
int idx = alias.next();
|
||||||
|
String receiver = list.get(idx);
|
||||||
|
Player p = Bukkit.getPlayer(receiver);
|
||||||
|
if(p != null){
|
||||||
|
if(p.getInventory().firstEmpty() == -1){
|
||||||
|
p.getWorld().dropItem(p.getLocation(),item);
|
||||||
|
Lang.sendFeedback(p, Lang.dragon_player_inv_full);
|
||||||
|
}
|
||||||
|
else p.getInventory().addItem(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package pers.xanadu.enderdragon.script;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.plugin.EventExecutor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import pers.xanadu.enderdragon.manager.GroovyManager;
|
||||||
|
|
||||||
|
import static pers.xanadu.enderdragon.EnderDragon.plugin;
|
||||||
|
|
||||||
|
public class Events<T extends Event> implements Listener, EventExecutor {
|
||||||
|
private final Consumer<T> consumer;
|
||||||
|
private final Class<T> clazz;
|
||||||
|
private boolean disabled;
|
||||||
|
private final AtomicLong expireTime;
|
||||||
|
public Events(Class<T> clazz, Consumer<T> consumer) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
this.consumer = consumer;
|
||||||
|
this.expireTime = new AtomicLong(-1L);
|
||||||
|
this.disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregister() {
|
||||||
|
if (!this.disabled) {
|
||||||
|
try {
|
||||||
|
Method method = this.clazz.getMethod("getHandlerList");
|
||||||
|
HandlerList handlerList = (HandlerList) method.invoke(null);
|
||||||
|
if (Bukkit.isPrimaryThread()) {
|
||||||
|
handlerList.unregister(this);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, () -> handlerList.unregister(this));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
this.disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static <T extends Event> Events<T> registerPersistently(Class<T> clazz, Consumer<T> consumer) {
|
||||||
|
return Events.registerPersistently(clazz, EventPriority.NORMAL, false, consumer);
|
||||||
|
}
|
||||||
|
public static <T extends Event> Events<T> registerPersistently(Class<T> clazz, EventPriority priority, boolean ignoreCancelled, Consumer<T> consumer) {
|
||||||
|
Events<T> tmp = new Events<>(clazz, consumer);
|
||||||
|
if (Bukkit.isPrimaryThread()) {
|
||||||
|
Bukkit.getPluginManager().registerEvent(clazz,tmp,priority,tmp,plugin,ignoreCancelled);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.getPluginManager().registerEvent(clazz,tmp,priority,tmp,plugin,ignoreCancelled));
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
public static <T extends Event> Events<T> register(Class<T> clazz, Consumer<T> consumer) {
|
||||||
|
return Events.register(clazz, EventPriority.NORMAL, false, consumer);
|
||||||
|
}
|
||||||
|
public static <T extends Event> Events<T> register(Class<T> clazz, EventPriority priority, boolean ignoreCancelled, Consumer<T> consumer) {
|
||||||
|
Events<T> tmp = new Events<>(clazz, consumer);
|
||||||
|
if (Bukkit.isPrimaryThread()) {
|
||||||
|
Bukkit.getPluginManager().registerEvent(clazz,tmp,priority,tmp,plugin,ignoreCancelled);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.getPluginManager().registerEvent(clazz,tmp,priority,tmp,plugin,ignoreCancelled));
|
||||||
|
}
|
||||||
|
GroovyManager.event_set.add(tmp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
// private static <T extends Event> void register(Class<T> clazz, Events<T> event, EventPriority priority, boolean ignoreCancelled) {
|
||||||
|
// Bukkit.getPluginManager().registerEvent(clazz,event,priority,event,plugin,ignoreCancelled);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(@NotNull Listener listener, @NotNull Event event) {
|
||||||
|
if (this.expireTime.get() > 0L && System.currentTimeMillis() > this.expireTime.get()) {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, this::unregister);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.clazz.isInstance(event)) {
|
||||||
|
this.consumer.accept((T) event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Events<T> withTime(long time) {
|
||||||
|
this.expireTime.set(time);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean cancelIfExpired() {
|
||||||
|
if (this.expireTime.get() > 0L && System.currentTimeMillis() > this.expireTime.get()) {
|
||||||
|
this.unregister();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package pers.xanadu.enderdragon.task;
|
||||||
|
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.EnderDragon;
|
||||||
|
|
||||||
|
import static pers.xanadu.enderdragon.EnderDragon.*;
|
||||||
|
|
||||||
|
public class DragonRespawnRunnable extends BukkitRunnable {
|
||||||
|
private final Task task;
|
||||||
|
public DragonRespawnRunnable(Task task){
|
||||||
|
this.task = task;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void run(){
|
||||||
|
if(task == null) {
|
||||||
|
this.cancel();
|
||||||
|
Lang.error("The config of auto-respawn errors!Task has been disabled...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(task.isTimeUp()){
|
||||||
|
new BukkitRunnable(){
|
||||||
|
@Override
|
||||||
|
public void run(){
|
||||||
|
EnderDragon.getInstance().getDragonManager().initiateRespawn(task.world_name);
|
||||||
|
task.updateTime();
|
||||||
|
task.saveFile();
|
||||||
|
}
|
||||||
|
}.runTask(plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void start(){
|
||||||
|
this.runTaskTimerAsynchronously(plugin,0,200L);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package pers.xanadu.enderdragon.task;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import pers.xanadu.enderdragon.EnderDragon;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.util.MathUtil;
|
||||||
|
|
||||||
|
import static pers.xanadu.enderdragon.EnderDragon.plugin;
|
||||||
|
|
||||||
|
public class DragonRespawnTimer {
|
||||||
|
private final String world_name;
|
||||||
|
private final int delay;
|
||||||
|
private BukkitRunnable runnable;
|
||||||
|
private int remainSecond;
|
||||||
|
private boolean isRunning;
|
||||||
|
public DragonRespawnTimer(String WorldName,int second){
|
||||||
|
this(WorldName,second,second);
|
||||||
|
}
|
||||||
|
public DragonRespawnTimer(String WorldName,int second,int rest_second){
|
||||||
|
this.world_name = WorldName;
|
||||||
|
this.delay = second;
|
||||||
|
this.remainSecond = rest_second;
|
||||||
|
this.isRunning = false;
|
||||||
|
resetRunnable();
|
||||||
|
}
|
||||||
|
public void run(){
|
||||||
|
if(!isRunning) runnable.runTaskTimerAsynchronously(plugin,0L,20L);
|
||||||
|
isRunning = true;
|
||||||
|
}
|
||||||
|
public void update(){
|
||||||
|
remainSecond = delay;
|
||||||
|
runnable.cancel();
|
||||||
|
isRunning = false;
|
||||||
|
resetRunnable();
|
||||||
|
}
|
||||||
|
public void del(){
|
||||||
|
if(isRunning) runnable.cancel();
|
||||||
|
}
|
||||||
|
public String getWorld_name(){
|
||||||
|
return this.world_name;
|
||||||
|
}
|
||||||
|
public int getSetTime(){
|
||||||
|
return this.delay;
|
||||||
|
}
|
||||||
|
public int getRestTime(){
|
||||||
|
return this.remainSecond;
|
||||||
|
}
|
||||||
|
public boolean isRunning(){
|
||||||
|
return isRunning;
|
||||||
|
}
|
||||||
|
public double getProgress(){
|
||||||
|
return 1d*remainSecond/delay;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "(" + world_name + ") " +
|
||||||
|
"remain:" + MathUtil.formatDuration(remainSecond) +
|
||||||
|
", set:" + MathUtil.formatDuration(delay);
|
||||||
|
}
|
||||||
|
private void resetRunnable(){
|
||||||
|
this.runnable = new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
remainSecond--;
|
||||||
|
if(remainSecond <= 0){
|
||||||
|
Bukkit.getScheduler().runTask(plugin,() -> {
|
||||||
|
if(EnderDragon.getInstance().getDragonManager().canRespawn(world_name)){
|
||||||
|
EnderDragon.getInstance().getDragonManager().initiateRespawn(world_name);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
remainSecond = delay;
|
||||||
|
Lang.error(Lang.command_respawn_cd_retry);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package pers.xanadu.enderdragon.task;
|
||||||
|
|
||||||
|
import pers.xanadu.enderdragon.EnderDragon;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.manager.TaskManager;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
|
import static pers.xanadu.enderdragon.EnderDragon.data;
|
||||||
|
import static pers.xanadu.enderdragon.EnderDragon.dataF;
|
||||||
|
import static pers.xanadu.enderdragon.manager.TaskManager.getRoundTimeStr;
|
||||||
|
|
||||||
|
public abstract class Task {
|
||||||
|
protected int period;
|
||||||
|
protected int day;
|
||||||
|
private final TaskType type;
|
||||||
|
protected abstract LocalDateTime initNextTime(LocalDateTime cur);
|
||||||
|
public abstract void updateTime();
|
||||||
|
protected LocalDateTime nextTime;
|
||||||
|
protected final String world_name;
|
||||||
|
protected final String unique_name;
|
||||||
|
protected Task(TaskType type, String unique_name,String world_name,String str){
|
||||||
|
this.type = type;
|
||||||
|
this.unique_name = unique_name;
|
||||||
|
this.world_name = world_name;
|
||||||
|
switch (type){
|
||||||
|
case minute :
|
||||||
|
case hour : {
|
||||||
|
this.period = Integer.parseInt(str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case day : {
|
||||||
|
this.period = Integer.parseInt(str.split(",")[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case week :
|
||||||
|
case month :
|
||||||
|
case year : {
|
||||||
|
this.day = Integer.parseInt(str.split(",")[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char split = data.options().pathSeparator();
|
||||||
|
String next_time = EnderDragon.data.getString("auto_respawn"+split+unique_name+split+"next_respawn_time");
|
||||||
|
if(next_time == null){
|
||||||
|
switch (type){
|
||||||
|
case minute :
|
||||||
|
case hour : {
|
||||||
|
this.nextTime = this.initNextTime(LocalDateTime.now().withSecond(0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case day :
|
||||||
|
case week :
|
||||||
|
case month :
|
||||||
|
case year : {
|
||||||
|
calcNextTime(str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.saveFile();
|
||||||
|
}
|
||||||
|
else this.nextTime = TaskManager.getLocalDateTime(next_time);
|
||||||
|
}
|
||||||
|
private void calcNextTime(String str){
|
||||||
|
LocalTime time = TaskManager.getRoundTime(str.split(",")[1]);
|
||||||
|
if(time != null) this.nextTime = this.initNextTime(LocalDateTime.now().withSecond(0).with(time));
|
||||||
|
else this.nextTime = this.initNextTime(LocalDateTime.now().withSecond(0));
|
||||||
|
}
|
||||||
|
public boolean isTimeUp(){
|
||||||
|
LocalDateTime now = LocalDateTime.now().plusSeconds(1);
|
||||||
|
if(now.isAfter(nextTime)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public void saveFile(){
|
||||||
|
char split = data.options().pathSeparator();
|
||||||
|
String path = "auto_respawn"+split+unique_name+split;
|
||||||
|
data.set(path+"world_name",world_name);
|
||||||
|
data.set(path+"next_respawn_time",getRoundTimeStr(nextTime));
|
||||||
|
try{
|
||||||
|
data.save(dataF);
|
||||||
|
}catch (IOException ex){
|
||||||
|
Lang.error(Lang.plugin_file_save_error.replaceAll("\\{file_name}",dataF.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskType getType(){
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package pers.xanadu.enderdragon.task;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
public enum TaskType {
|
||||||
|
minute,
|
||||||
|
hour,
|
||||||
|
day,
|
||||||
|
week,
|
||||||
|
month,
|
||||||
|
year,
|
||||||
|
unknown;
|
||||||
|
private static final Map<String,TaskType> mp = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
public static TaskType getByName(String str){
|
||||||
|
if(str == null) return unknown;
|
||||||
|
return mp.getOrDefault(str,unknown);
|
||||||
|
}
|
||||||
|
static{
|
||||||
|
TaskType[] values = values();
|
||||||
|
for (TaskType taskType : values) {
|
||||||
|
String name = taskType.name();
|
||||||
|
mp.put(name, taskType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package pers.xanadu.enderdragon.task.type;
|
||||||
|
|
||||||
|
import pers.xanadu.enderdragon.task.Task;
|
||||||
|
import pers.xanadu.enderdragon.task.TaskType;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class Day extends Task {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime initNextTime(LocalDateTime cur) {
|
||||||
|
return cur.plusDays(period);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateTime(){
|
||||||
|
this.nextTime = LocalDateTime.now().withSecond(0).plusDays(period);
|
||||||
|
}
|
||||||
|
public Day(TaskType type, String unique_name,String world_name,String str){
|
||||||
|
super(type,unique_name,world_name,str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package pers.xanadu.enderdragon.task.type;
|
||||||
|
|
||||||
|
import pers.xanadu.enderdragon.task.Task;
|
||||||
|
import pers.xanadu.enderdragon.task.TaskType;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class Hour extends Task {
|
||||||
|
@Override
|
||||||
|
public LocalDateTime initNextTime(LocalDateTime cur) {
|
||||||
|
return cur.plusHours(period);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateTime(){
|
||||||
|
this.nextTime = LocalDateTime.now().withSecond(0).plusHours(period);
|
||||||
|
}
|
||||||
|
public Hour(TaskType type, String unique_name,String world_name,String str){
|
||||||
|
super(type,unique_name,world_name,str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package pers.xanadu.enderdragon.task.type;
|
||||||
|
|
||||||
|
import pers.xanadu.enderdragon.task.Task;
|
||||||
|
import pers.xanadu.enderdragon.task.TaskType;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class Minute extends Task {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime initNextTime(LocalDateTime cur) {
|
||||||
|
return cur.plusMinutes(period);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateTime(){
|
||||||
|
this.nextTime = LocalDateTime.now().withSecond(0).plusMinutes(period);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Minute(TaskType type, String unique_name,String world_name,String str){
|
||||||
|
super(type,unique_name,world_name,str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package pers.xanadu.enderdragon.task.type;
|
||||||
|
|
||||||
|
import pers.xanadu.enderdragon.task.Task;
|
||||||
|
import pers.xanadu.enderdragon.task.TaskType;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class Month extends Task {
|
||||||
|
@Override
|
||||||
|
public LocalDateTime initNextTime(LocalDateTime cur) {
|
||||||
|
return cur.plusMonths(1).withDayOfMonth(day);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateTime(){
|
||||||
|
this.nextTime = LocalDateTime.now().withSecond(0).plusMonths(1).withDayOfMonth(day);
|
||||||
|
}
|
||||||
|
public Month(TaskType type, String unique_name,String world_name,String str){
|
||||||
|
super(type,unique_name,world_name,str);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package pers.xanadu.enderdragon.task.type;
|
||||||
|
|
||||||
|
import pers.xanadu.enderdragon.task.Task;
|
||||||
|
import pers.xanadu.enderdragon.task.TaskType;
|
||||||
|
|
||||||
|
import java.time.DayOfWeek;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class Week extends Task {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime initNextTime(LocalDateTime cur) {
|
||||||
|
return cur.with(DayOfWeek.of(day)).plusDays(7);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateTime(){
|
||||||
|
this.nextTime = LocalDateTime.now().withSecond(0).plusDays(7);
|
||||||
|
}
|
||||||
|
public Week(TaskType type, String unique_name,String world_name,String str){
|
||||||
|
super(type,unique_name,world_name,str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package pers.xanadu.enderdragon.task.type;
|
||||||
|
|
||||||
|
import pers.xanadu.enderdragon.task.Task;
|
||||||
|
import pers.xanadu.enderdragon.task.TaskType;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class Year extends Task {
|
||||||
|
@Override
|
||||||
|
public LocalDateTime initNextTime(LocalDateTime cur) {
|
||||||
|
return cur.plusYears(1).withDayOfMonth(day);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateTime(){
|
||||||
|
this.nextTime = LocalDateTime.now().withSecond(0).plusYears(1);
|
||||||
|
}
|
||||||
|
public Year(TaskType type, String unique_name,String world_name,String str){
|
||||||
|
super(type,unique_name,world_name,str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public final class AExpJ {
|
||||||
|
public static <T> List<T> sample(final ConcurrentHashMap<T,Double> mp,int m){
|
||||||
|
List<Pair<T,Double>> list = new ArrayList<>();
|
||||||
|
mp.forEach((k,v)->list.add(new Pair<>(k,v)));
|
||||||
|
return sample(list,m);
|
||||||
|
}
|
||||||
|
public static <T> List<T> sample(final List<Pair<T,Double>> samples, int m) {
|
||||||
|
PriorityQueue<Pair<T,Double>> heap = new PriorityQueue<>(Comparator.comparingDouble(p -> p.second));
|
||||||
|
double Xw = 0.0;
|
||||||
|
double Tw = 0.0;
|
||||||
|
double w_acc = 0.0;
|
||||||
|
for (Pair<T,Double> sample : samples) {
|
||||||
|
if (heap.size() < m) {
|
||||||
|
double wi = sample.second;
|
||||||
|
double ui = ThreadLocalRandom.current().nextDouble();
|
||||||
|
double ki = Math.pow(ui, 1 / wi);
|
||||||
|
heap.offer(new Pair<>(sample.first, ki));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (w_acc == 0) {
|
||||||
|
if (heap.isEmpty()) break;
|
||||||
|
Tw = heap.peek().second;
|
||||||
|
double r = ThreadLocalRandom.current().nextDouble();
|
||||||
|
Xw = Math.log(r) / Math.log(Tw);
|
||||||
|
}
|
||||||
|
double wi = sample.second;
|
||||||
|
if (w_acc + wi < Xw) {
|
||||||
|
w_acc += wi;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else w_acc = 0;
|
||||||
|
double tw = Math.pow(Tw, wi);
|
||||||
|
double r2 = ThreadLocalRandom.current().nextDouble() * (1 - tw) + tw;
|
||||||
|
double ki = Math.pow(r2, 1 / wi);
|
||||||
|
heap.poll();
|
||||||
|
heap.offer(new Pair<>(sample.first, ki));
|
||||||
|
}
|
||||||
|
List<T> res = new ArrayList<>();
|
||||||
|
for (Pair<T,Double> pair : heap) {
|
||||||
|
res.add(pair.first);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// List<Pair<String,Double>> samples = new ArrayList<>();
|
||||||
|
// samples.add(new Pair<>("item1", 0.8));
|
||||||
|
// samples.add(new Pair<>("item2", 0.4));
|
||||||
|
// samples.add(new Pair<>("item3", 0.2));
|
||||||
|
// Map<String,Integer> mp = new HashMap<>();
|
||||||
|
// for(int i=0;i<1e5;i++){
|
||||||
|
// List<String> result = sample(samples, 1);
|
||||||
|
// mp.compute(result.get(0), (k, v)->v==null?1:v+1);
|
||||||
|
// }
|
||||||
|
// System.out.println(mp);
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public final class AliasSample {
|
||||||
|
private final int[] alias;
|
||||||
|
private final double[] probability;
|
||||||
|
public AliasSample(List<Double> probabilities) {
|
||||||
|
if (probabilities == null) throw new NullPointerException();
|
||||||
|
if (probabilities.size() == 0)
|
||||||
|
throw new IllegalArgumentException("Probability vector can't be empty.");
|
||||||
|
this.probability = new double[probabilities.size()];
|
||||||
|
this.alias = new int[probabilities.size()];
|
||||||
|
final double average = 1.0 / probabilities.size();
|
||||||
|
probabilities = new ArrayList<>(probabilities);//make a copy of list, avoid modifying the param
|
||||||
|
Deque<Integer> small = new ArrayDeque<>();
|
||||||
|
Deque<Integer> large = new ArrayDeque<>();
|
||||||
|
for (int i = 0; i < probabilities.size(); ++i) {
|
||||||
|
if (probabilities.get(i) >= average) large.add(i);
|
||||||
|
else small.add(i);
|
||||||
|
}
|
||||||
|
while (!small.isEmpty() && !large.isEmpty()) {
|
||||||
|
int less = small.removeLast();
|
||||||
|
int more = large.removeLast();
|
||||||
|
probability[less] = probabilities.get(less) * probabilities.size();
|
||||||
|
alias[less] = more;
|
||||||
|
probabilities.set(more, (probabilities.get(more) + probabilities.get(less)) - average);
|
||||||
|
if (probabilities.get(more) >= 1.0 / probabilities.size()) large.add(more);
|
||||||
|
else small.add(more);
|
||||||
|
}
|
||||||
|
while (!small.isEmpty()) probability[small.removeLast()] = 1.0;
|
||||||
|
while (!large.isEmpty()) probability[large.removeLast()] = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int next() {
|
||||||
|
int column = ThreadLocalRandom.current().nextInt(probability.length);
|
||||||
|
boolean coinToss = ThreadLocalRandom.current().nextDouble() < probability[column];
|
||||||
|
return coinToss ? column : alias[column];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static pers.xanadu.enderdragon.util.Version.mcMainVersion;
|
||||||
|
|
||||||
|
public class ColorUtil {
|
||||||
|
|
||||||
|
public static Pattern hex_code = Pattern.compile("&#([0-9A-Fa-f]{6})");
|
||||||
|
public static Pattern gradient = Pattern.compile("&\\[#([0-9a-fA-F]{6})-#([0-9a-fA-F]{6})(.+)]");
|
||||||
|
public static String parse(String str){
|
||||||
|
if(mcMainVersion >= 16){
|
||||||
|
return org.bukkit.ChatColor.translateAlternateColorCodes('&',transGradient(str));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return org.bukkit.ChatColor.translateAlternateColorCodes('&',str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static String translateHexCodes(String str) {
|
||||||
|
Matcher matcher = hex_code.matcher(str);
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
while(matcher.find()) {
|
||||||
|
matcher.appendReplacement(buffer, ChatColor.of("#" + matcher.group(1)).toString());
|
||||||
|
}
|
||||||
|
return ChatColor.translateAlternateColorCodes('&', matcher.appendTail(buffer).toString());
|
||||||
|
}
|
||||||
|
private static String transGradient(String str) {
|
||||||
|
if (str.contains("&[#")&&str.contains("]")) {
|
||||||
|
Matcher matcher = gradient.matcher(str);
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
while (matcher.find()) {
|
||||||
|
String text = matcher.group(3);
|
||||||
|
int[] colors = gradient(matcher.group(1),matcher.group(2),text.length());
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (int i = 0; i < text.length(); i++) {
|
||||||
|
Color c = new Color(colors[i]);
|
||||||
|
builder.append(ChatColor.of(c)).append(text.charAt(i));
|
||||||
|
}
|
||||||
|
matcher.appendReplacement(buffer, builder.toString());
|
||||||
|
}
|
||||||
|
matcher.appendTail(buffer);
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
return translateHexCodes(str);
|
||||||
|
}
|
||||||
|
private static int[] gradient(String start,String end,int length){
|
||||||
|
int[] color = new int[length];
|
||||||
|
int[] rgb1 = MathUtil.hexToInt(start);
|
||||||
|
int[] rgb2 = MathUtil.hexToInt(end);
|
||||||
|
if(length==0){return color;}
|
||||||
|
if(length==1){
|
||||||
|
for(int j=0;j<3;j++){
|
||||||
|
color[0] = color[0]*256+rgb1[j];
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
for(int i=0;i<length;i++){
|
||||||
|
for(int j=0;j<3;j++){
|
||||||
|
color[i] = color[i]*256+rgb1[j]+(rgb2[j]-rgb1[j])*i/(length-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class ExtraPotionEffect {
|
||||||
|
private final ExtraPotionEffectType type;
|
||||||
|
private final int tick;
|
||||||
|
|
||||||
|
public void apply(final Player player){
|
||||||
|
switch (type){
|
||||||
|
case fire: {
|
||||||
|
player.setFireTicks(player.getFireTicks()+tick);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case freeze: {
|
||||||
|
player.setFreezeTicks(player.getFreezeTicks()+tick);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ExtraPotionEffect(final String effect,int second){
|
||||||
|
this(ExtraPotionEffectType.valueOf(effect.toLowerCase()),second);
|
||||||
|
}
|
||||||
|
public ExtraPotionEffect(final ExtraPotionEffectType type,int second){
|
||||||
|
this.type = type;
|
||||||
|
this.tick = second*20;
|
||||||
|
}
|
||||||
|
public enum ExtraPotionEffectType{
|
||||||
|
fire,
|
||||||
|
freeze
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
public class MathUtil {
|
||||||
|
public static int floor(double d) {
|
||||||
|
int i = (int)d;
|
||||||
|
return d < (double)i ? i - 1 : i;
|
||||||
|
}
|
||||||
|
public static double c(final Entity entity, double x, double y, double z) {
|
||||||
|
Location loc = entity.getLocation();
|
||||||
|
double d0 = loc.getX() - x;
|
||||||
|
double d1 = loc.getY() - y;
|
||||||
|
double d2 = loc.getZ() - z;
|
||||||
|
return d0 * d0 + d1 * d1 + d2 * d2;
|
||||||
|
}
|
||||||
|
public static double div(double d1,double d2,int len){
|
||||||
|
BigDecimal b1 = new BigDecimal(d1);
|
||||||
|
BigDecimal b2 = new BigDecimal(d2);
|
||||||
|
return b1.divide(b2,len, RoundingMode.HALF_UP).doubleValue();
|
||||||
|
}
|
||||||
|
public static int[] hexToInt(final String hex){
|
||||||
|
int[] result = new int[3];
|
||||||
|
String s1 = hex.substring(0,2);
|
||||||
|
String s2 = hex.substring(2,4);
|
||||||
|
String s3 = hex.substring(4,6);
|
||||||
|
result[0] = Integer.parseInt(s1,16);
|
||||||
|
result[1] = Integer.parseInt(s2,16);
|
||||||
|
result[2] = Integer.parseInt(s3,16);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public static String locationToString(final Location loc){
|
||||||
|
if (loc.getWorld() == null) return "";
|
||||||
|
return loc.getWorld().getName()+";"+loc.getX()+";"+loc.getY()+";"+loc.getZ();
|
||||||
|
}
|
||||||
|
public static Location stringToLocation(final String str){
|
||||||
|
final String[] parts = str.split(";");
|
||||||
|
if(parts.length != 4) return null;
|
||||||
|
final World world = Bukkit.getWorld(parts[0]);
|
||||||
|
final double x = Double.parseDouble(parts[1]);
|
||||||
|
final double y = Double.parseDouble(parts[2]);
|
||||||
|
final double z = Double.parseDouble(parts[3]);
|
||||||
|
return new Location(world,x,y,z);
|
||||||
|
}
|
||||||
|
public static String formatDuration(int seconds) {
|
||||||
|
if (seconds < 0) throw new IllegalArgumentException("Duration must be a positive number.");
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
int hours = (seconds % (24 * 3600)) / 3600;
|
||||||
|
int minutes = ((seconds % (24 * 3600)) % 3600) / 60;
|
||||||
|
int remainingSeconds = ((seconds % (24 * 3600)) % 3600) % 60;
|
||||||
|
StringBuilder duration = new StringBuilder();
|
||||||
|
boolean f = false;
|
||||||
|
if(days>0){
|
||||||
|
duration.append(days).append("d");
|
||||||
|
f = true;
|
||||||
|
}
|
||||||
|
if(f||hours>0){
|
||||||
|
duration.append(hours).append("h");
|
||||||
|
f = true;
|
||||||
|
}
|
||||||
|
if(f||minutes>0){
|
||||||
|
duration.append(minutes).append("m");
|
||||||
|
}
|
||||||
|
duration.append(remainingSeconds).append("s");
|
||||||
|
return duration.toString();
|
||||||
|
}
|
||||||
|
public static int[] getDate(int seconds){
|
||||||
|
if (seconds < 0) throw new IllegalArgumentException("Duration must be a positive number.");
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
int hours = (seconds % (24 * 3600)) / 3600;
|
||||||
|
int minutes = ((seconds % (24 * 3600)) % 3600) / 60;
|
||||||
|
int remainingSeconds = ((seconds % (24 * 3600)) % 3600) % 60;
|
||||||
|
return new int[]{days,hours,minutes,remainingSeconds};
|
||||||
|
}
|
||||||
|
@Deprecated
|
||||||
|
public static <K> K getByWeight(final ConcurrentHashMap<K,Double> mp){
|
||||||
|
double sum = mp.values().stream().mapToDouble(Double::doubleValue).sum();
|
||||||
|
double rand = ThreadLocalRandom.current().nextDouble(sum);
|
||||||
|
final AtomicReference<Double> cur = new AtomicReference<>(0d);
|
||||||
|
final AtomicReference<K> res = new AtomicReference<>();
|
||||||
|
mp.forEach((k,v)->{
|
||||||
|
Double value = cur.get();
|
||||||
|
if(value<=rand && value+v>rand) {
|
||||||
|
res.set(k);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur.updateAndGet(v1 -> v1 + v);
|
||||||
|
});
|
||||||
|
return res.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import pers.xanadu.enderdragon.reward.Reward;
|
||||||
|
import pers.xanadu.enderdragon.reward.RewardDist;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MyDragon implements Comparable<MyDragon>{
|
||||||
|
public ItemStack icon;
|
||||||
|
public String unique_name;
|
||||||
|
public String display_name;
|
||||||
|
public String drop_gui;
|
||||||
|
public int edge;
|
||||||
|
public int priority;
|
||||||
|
public double spawn_chance;
|
||||||
|
public int max_health;
|
||||||
|
public int spawn_health;
|
||||||
|
public int no_damage_tick;
|
||||||
|
public int exp_drop;
|
||||||
|
public int dragon_egg_spawn_delay;
|
||||||
|
public int dragon_egg_spawn_x;
|
||||||
|
public int dragon_egg_spawn_y;
|
||||||
|
public int dragon_egg_spawn_z;
|
||||||
|
public double dragon_egg_spawn_chance;
|
||||||
|
public double attack_damage_modify;
|
||||||
|
//public double move_speed_modify;
|
||||||
|
public double armor_modify;
|
||||||
|
public double armor_toughness_modify;
|
||||||
|
public double crystal_heal_speed;
|
||||||
|
public boolean suck_blood_enable;
|
||||||
|
public double suck_blood_rate;
|
||||||
|
public double suck_blood_base_amount;
|
||||||
|
public boolean suck_blood_only_player;
|
||||||
|
public List<PotionEffect> attack_potion_effect;
|
||||||
|
public List<ExtraPotionEffect> attack_extra_effect;
|
||||||
|
public List<String> spawn_cmd;
|
||||||
|
public List<String> death_cmd;
|
||||||
|
public List<String> spawn_broadcast_msg;
|
||||||
|
public List<String> death_broadcast_msg;
|
||||||
|
public List<String> msg_to_killer;
|
||||||
|
public String glow_color;
|
||||||
|
public String bossbar_color;
|
||||||
|
public String bossbar_style;
|
||||||
|
public double effect_cloud_original_radius;
|
||||||
|
public double effect_cloud_expand_speed;
|
||||||
|
public int effect_cloud_duration;
|
||||||
|
public int effect_cloud_color_R;
|
||||||
|
public int effect_cloud_color_G;
|
||||||
|
public int effect_cloud_color_B;
|
||||||
|
public List<PotionEffect> effect_cloud_potion;
|
||||||
|
public List<Reward> datum = new ArrayList<>();
|
||||||
|
public RewardDist reward_dist;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(final MyDragon o) {
|
||||||
|
return o.priority - this.priority;//降序
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,453 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
import pers.xanadu.enderdragon.EnderDragon;
|
||||||
|
import pers.xanadu.enderdragon.config.Config;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static pers.xanadu.enderdragon.EnderDragon.getInstance;
|
||||||
|
|
||||||
|
public class NMSUtil {
|
||||||
|
private String getEDB_base;
|
||||||
|
private Method getNMSWord;
|
||||||
|
private Method asNMSCopy;
|
||||||
|
private Method copyNMSStack;
|
||||||
|
private Method asBukkitCopy;
|
||||||
|
private Method asCraftMirror;
|
||||||
|
private Method asCraftCopy;
|
||||||
|
private Method NMSItemStack_save;
|
||||||
|
private Method NMSItemStack_setTag;
|
||||||
|
private Method cpdToEi;
|
||||||
|
private Method stringToCPD;
|
||||||
|
private Method stringToNBTBase;
|
||||||
|
private Method serializeNBTBase;
|
||||||
|
private Method deserializeObject;
|
||||||
|
private Method PDCtoCPD;
|
||||||
|
private Method PersistentDataContainer_putAll;
|
||||||
|
private Method NBTTagCompound_set;
|
||||||
|
private Field unhandledTags;
|
||||||
|
private Field internalTag;
|
||||||
|
private Field MOJANGSON_PARSER;
|
||||||
|
private Field world_c_environment;
|
||||||
|
private Field NBTTagCompound_map;
|
||||||
|
private Class<?> WorldClass;
|
||||||
|
private Class<?> CraftWorldClass;
|
||||||
|
private Class<?> WorldProviderClass;
|
||||||
|
private Class<?> WorldProviderTheEndClass;
|
||||||
|
private Class<?> CraftItemStackClass;
|
||||||
|
private Class<?> CraftMetaItemClass;
|
||||||
|
private Class<?> NMSItemStackClass;
|
||||||
|
private Class<?> CraftEntityClass;
|
||||||
|
private Class<?> NBTTagCompoundClass;
|
||||||
|
private Class<?> NBTBaseClass;
|
||||||
|
private Class<?> MojangsonParserClass;
|
||||||
|
private Class<?> CraftNBTTagConfigSerializerClass;
|
||||||
|
private Class<?> CraftPersistentDataContainerClass;
|
||||||
|
|
||||||
|
public void init(){
|
||||||
|
String version = Version.getVersion();
|
||||||
|
try{
|
||||||
|
this.CraftWorldClass = Class.forName("org.bukkit.craftbukkit." + version + ".CraftWorld");
|
||||||
|
this.getNMSWord = CraftWorldClass.getDeclaredMethod("getHandle");
|
||||||
|
this.WorldClass = this.getNMSWord.getReturnType().getSuperclass();
|
||||||
|
this.world_c_environment = CraftWorldClass.getDeclaredField("environment");
|
||||||
|
this.world_c_environment.setAccessible(true);
|
||||||
|
if(Version.mcMainVersion>=12 && Version.mcMainVersion<16){
|
||||||
|
this.WorldProviderClass = Class.forName("net.minecraft.server."+version+".WorldProvider");
|
||||||
|
this.WorldProviderTheEndClass = Class.forName("net.minecraft.server."+version+".WorldProviderTheEnd");
|
||||||
|
}
|
||||||
|
this.CraftItemStackClass = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack");
|
||||||
|
this.CraftMetaItemClass = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftMetaItem");
|
||||||
|
this.unhandledTags = CraftMetaItemClass.getDeclaredField("unhandledTags");
|
||||||
|
unhandledTags.setAccessible(true);
|
||||||
|
this.internalTag = CraftMetaItemClass.getDeclaredField("internalTag");
|
||||||
|
internalTag.setAccessible(true);
|
||||||
|
this.NMSItemStackClass = CraftItemStackClass.getDeclaredField("handle").getType();
|
||||||
|
this.CraftEntityClass = Class.forName("org.bukkit.craftbukkit."+version+".entity.CraftEntity");
|
||||||
|
init_NBTTagCompoundClass();
|
||||||
|
init_NBTBaseClass();
|
||||||
|
init_NBTTagCompound_map();
|
||||||
|
this.NBTTagCompound_set = NBTTagCompoundClass.getMethod(getMethodName(ReflectiveMethod.NBTTagCompound_set),String.class,NBTBaseClass);
|
||||||
|
this.asNMSCopy = CraftItemStackClass.getMethod("asNMSCopy",ItemStack.class);
|
||||||
|
this.copyNMSStack = CraftItemStackClass.getMethod("copyNMSStack",NMSItemStackClass,int.class);
|
||||||
|
this.asBukkitCopy = CraftItemStackClass.getMethod("asBukkitCopy",NMSItemStackClass);
|
||||||
|
this.asCraftMirror = CraftItemStackClass.getMethod("asCraftMirror",NMSItemStackClass);
|
||||||
|
this.asCraftCopy = CraftItemStackClass.getMethod("asCraftCopy",ItemStack.class);
|
||||||
|
this.NMSItemStack_save = NMSItemStackClass.getMethod(getMethodName(ReflectiveMethod.NMSItemStack_save),NBTTagCompoundClass);
|
||||||
|
this.NMSItemStack_setTag = NMSItemStackClass.getMethod(getMethodName(ReflectiveMethod.NMSItemStack_setTag),NBTTagCompoundClass);
|
||||||
|
if(Version.mcMainVersion>=13) this.cpdToEi = NMSItemStackClass.getMethod("a",NBTTagCompoundClass);
|
||||||
|
|
||||||
|
if(Version.mcMainVersion<=16) this.MojangsonParserClass = Class.forName("net.minecraft.server."+version+".MojangsonParser");
|
||||||
|
else this.MojangsonParserClass = Class.forName("net.minecraft.nbt.MojangsonParser");
|
||||||
|
this.stringToCPD = MojangsonParserClass.getMethod(getMethodName(ReflectiveMethod.MojangsonParser_parse),String.class);
|
||||||
|
this.stringToNBTBase = MojangsonParserClass.getDeclaredMethod(getMethodName(ReflectiveMethod.MojangsonParser_parseLiteral),String.class);
|
||||||
|
stringToNBTBase.setAccessible(true);
|
||||||
|
|
||||||
|
if(Version.mcMainVersion>13 || "v1_13_R2".equals(Version.getVersion())){
|
||||||
|
this.CraftNBTTagConfigSerializerClass = Class.forName("org.bukkit.craftbukkit." + version + ".util.CraftNBTTagConfigSerializer");
|
||||||
|
this.serializeNBTBase = CraftNBTTagConfigSerializerClass.getMethods()[0];
|
||||||
|
this.deserializeObject = CraftNBTTagConfigSerializerClass.getMethod("deserialize",Object.class);
|
||||||
|
this.MOJANGSON_PARSER = CraftNBTTagConfigSerializerClass.getDeclaredField("MOJANGSON_PARSER");
|
||||||
|
MOJANGSON_PARSER.setAccessible(true);
|
||||||
|
}
|
||||||
|
if(Version.mcMainVersion>=14){
|
||||||
|
this.CraftPersistentDataContainerClass = Class.forName("org.bukkit.craftbukkit." + version + ".persistence.CraftPersistentDataContainer");
|
||||||
|
this.PDCtoCPD = CraftPersistentDataContainerClass.getDeclaredMethod("toTagCompound");
|
||||||
|
this.PersistentDataContainer_putAll = CraftPersistentDataContainerClass.getDeclaredMethod("putAll",NBTTagCompoundClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}catch(ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
switch (version) {
|
||||||
|
case "v1_12_R1" : {
|
||||||
|
getEDB_base = "t";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "v1_13_R1" :
|
||||||
|
case "v1_13_R2" : {
|
||||||
|
getEDB_base = "r";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "v1_14_R1" : {
|
||||||
|
getEDB_base = "q";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "v1_15_R1" : {
|
||||||
|
getEDB_base = "o";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : getEDB_base = null;
|
||||||
|
}
|
||||||
|
if(Config.debug) check();
|
||||||
|
}
|
||||||
|
public void check(){
|
||||||
|
try{
|
||||||
|
Field[] fields = NMSUtil.class.getDeclaredFields();
|
||||||
|
for(Field field : fields){
|
||||||
|
Bukkit.getLogger().info(field.getName()+"->"+field.get(this));
|
||||||
|
}
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// public Object getMetaCPD(ItemMeta meta){
|
||||||
|
// try{
|
||||||
|
// Object craft_meta = CraftMetaItemClass.cast(meta);
|
||||||
|
// Object internalTag = this.internalTag.get(craft_meta);
|
||||||
|
// return internalTag;
|
||||||
|
// }catch (ReflectiveOperationException e){
|
||||||
|
// e.printStackTrace();
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 只保留物品type和amount
|
||||||
|
* nbt深合并需要遍历每一层
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public ItemStack mergeItemCPD(final ItemStack item,final Object cpd){
|
||||||
|
Map<String,Object> self = cpdToMap(getCPD(item));
|
||||||
|
Map<String,Object> rhs = cpdToMap(cpd);
|
||||||
|
self.putAll(rhs);
|
||||||
|
Object new_cpd = getNBTTagCompound(self);
|
||||||
|
return EnderDragon.getInstance().getNMSItemManager().cpdToItem(new_cpd);
|
||||||
|
}
|
||||||
|
public Map<String,Object> cpdToMap(final Object cpd){
|
||||||
|
try{
|
||||||
|
return (Map<String, Object>) NBTTagCompound_map.get(cpd);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Object getNBTTagCompound(final Map<String,Object> mp){
|
||||||
|
try{
|
||||||
|
Object cpd = NBTTagCompoundClass.newInstance();
|
||||||
|
mp.forEach((key,value)->{
|
||||||
|
Object res;
|
||||||
|
if(value instanceof Map){
|
||||||
|
res = getNBTTagCompound((Map<String, Object>) value);
|
||||||
|
}
|
||||||
|
else res = value;
|
||||||
|
try{
|
||||||
|
NBTTagCompound_set.invoke(cpd,key,res);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
throw new RuntimeException("Reflective error!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return cpd;
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Object StringParseLiteral(final String str){
|
||||||
|
try{
|
||||||
|
return stringToNBTBase.invoke(MOJANGSON_PARSER.get(null),str);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void setPersistentDataContainer(final PersistentDataContainer dataContainer,final Object cpd){
|
||||||
|
try{
|
||||||
|
Object PDC = CraftPersistentDataContainerClass.cast(dataContainer);
|
||||||
|
PersistentDataContainer_putAll.invoke(PDC,cpd);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public String PDCtoString(final PersistentDataContainer dataContainer){
|
||||||
|
try{
|
||||||
|
Object PDC = CraftPersistentDataContainerClass.cast(dataContainer);
|
||||||
|
return PDCtoCPD.invoke(PDC).toString();
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object deserializeObject(final Object object){
|
||||||
|
try{
|
||||||
|
return deserializeObject.invoke(null,object);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Object serializeNBTBase(final Object nbt_base){
|
||||||
|
try{
|
||||||
|
return serializeNBTBase.invoke(null, nbt_base);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void setUnhandledTags(final ItemMeta meta, Map<String,?> unhandledTags){
|
||||||
|
try{
|
||||||
|
Object craft_meta = CraftMetaItemClass.cast(meta);
|
||||||
|
this.unhandledTags.set(craft_meta, unhandledTags);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Map<String,Object> getUnhandledTags(final ItemMeta meta){
|
||||||
|
try{
|
||||||
|
Object craft_meta = CraftMetaItemClass.cast(meta);
|
||||||
|
Object unhandledTags = this.unhandledTags.get(craft_meta);
|
||||||
|
return (Map<String, Object>) unhandledTags;
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ItemStack applyItemTag(final ItemStack item,final Object cpd){
|
||||||
|
try{
|
||||||
|
Object ei = asNMSCopy.invoke(null,item);
|
||||||
|
NMSItemStack_setTag.invoke(ei,cpd);
|
||||||
|
return (ItemStack) asBukkitCopy.invoke(null,ei);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return new ItemStack(Material.AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public String getNBT(final ItemStack item){
|
||||||
|
try{
|
||||||
|
Object ci = CraftItemStackClass.isInstance(item)?CraftItemStackClass.cast(item):asCraftCopy.invoke(null,item);
|
||||||
|
Object ei = asNMSCopy.invoke(null, ci);
|
||||||
|
Object cpd = NMSItemStack_save.invoke(ei, NBTTagCompoundClass.newInstance());
|
||||||
|
return cpd.toString();
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return "{id:\"minecraft:air\"}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Object getCPD(final ItemStack item){
|
||||||
|
try{
|
||||||
|
Object ci = CraftItemStackClass.isInstance(item)?CraftItemStackClass.cast(item):asCraftCopy.invoke(null,item);
|
||||||
|
Object ei = asNMSCopy.invoke(null, ci);
|
||||||
|
return NMSItemStack_save.invoke(ei, NBTTagCompoundClass.newInstance());
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Object getCPD(final String nbt){
|
||||||
|
try{
|
||||||
|
return stringToCPD.invoke(null,nbt);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 仅1.13+可用
|
||||||
|
*/
|
||||||
|
public ItemStack getItemStack(final Object cpd){
|
||||||
|
try{
|
||||||
|
Object ei = cpdToEi.invoke(null,cpd);
|
||||||
|
Object ci = asBukkitCopy.invoke(null,ei);
|
||||||
|
return (ItemStack) ci;
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 仅1.13+可用
|
||||||
|
*/
|
||||||
|
public ItemStack getItemStack(final String nbt){
|
||||||
|
try{
|
||||||
|
Object cpd = stringToCPD.invoke(null,nbt);
|
||||||
|
Object ei = cpdToEi.invoke(null,cpd);
|
||||||
|
Object ci = asBukkitCopy.invoke(null,ei);
|
||||||
|
return (ItemStack) ci;
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void setEnvironment(final World world,final World.Environment env){
|
||||||
|
Object world_c = getCraftWorld(world);
|
||||||
|
try{
|
||||||
|
//Object old_env = world_c_environment.get(world_c);
|
||||||
|
world_c_environment.set(world_c,env);
|
||||||
|
}catch (ReflectiveOperationException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Object getEnderDragonBattle(final World world){
|
||||||
|
String version = Version.getVersion();
|
||||||
|
if (Version.mcMainVersion>=12 && Version.mcMainVersion<16) {
|
||||||
|
try {
|
||||||
|
Object worldServer = getInstance().getNMSManager().getWorldServer(world);
|
||||||
|
assert worldServer != null;
|
||||||
|
Field field = worldServer.getClass().getField("worldProvider");
|
||||||
|
Object worldProvider = field.get(worldServer);
|
||||||
|
Object WorldProviderTheEnd = WorldProviderTheEndClass.cast(worldProvider);
|
||||||
|
String method_name = getInstance().getNMSManager().getEDB_base;
|
||||||
|
if(method_name == null) return null;
|
||||||
|
Method method = WorldProviderTheEnd.getClass().getDeclaredMethod(method_name);
|
||||||
|
return method.invoke(WorldProviderTheEnd);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
Lang.warn("Your server version (" + version + ") is not supported!");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Lang.warn("Your server version (" + version + ") is not supported!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public Object getWorldServer(final World ThisWorld) {
|
||||||
|
try {
|
||||||
|
Object castClass = getCraftWorld(ThisWorld);
|
||||||
|
return this.CraftWorldClass.getDeclaredMethod("getHandle").invoke(castClass);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public Object getCraftWorld(final World ThisWorld) {
|
||||||
|
if (this.CraftWorldClass.isInstance(ThisWorld)) return this.CraftWorldClass.cast(ThisWorld);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public Object getWorld_e(final World world){
|
||||||
|
try {
|
||||||
|
Object world_c = getCraftWorld(world);
|
||||||
|
return this.getNMSWord.invoke(world_c);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public Class<?> getNBTBaseClass(){
|
||||||
|
return this.NBTBaseClass;
|
||||||
|
}
|
||||||
|
public Class<?> getNBTTagCompoundClass(){
|
||||||
|
return this.NBTTagCompoundClass;
|
||||||
|
}
|
||||||
|
public Class<?> getWorldClass(){
|
||||||
|
return this.WorldClass;
|
||||||
|
}
|
||||||
|
public Class<?> getWorldProviderClass(){
|
||||||
|
return this.WorldProviderClass;
|
||||||
|
}
|
||||||
|
private String getMethodName(final ReflectiveMethod method){
|
||||||
|
switch (method){
|
||||||
|
case NMSItemStack_save: {
|
||||||
|
if(Version.mcMainVersion<=17) return "save";
|
||||||
|
return "b";
|
||||||
|
}
|
||||||
|
case NMSItemStack_setTag: {
|
||||||
|
if(Version.mcMainVersion<=17) return "setTag";
|
||||||
|
return "c";
|
||||||
|
}
|
||||||
|
case MojangsonParser_parse: {
|
||||||
|
if(Version.mcMainVersion<=17) return "parse";
|
||||||
|
return "a";
|
||||||
|
}
|
||||||
|
case MojangsonParser_parseLiteral: {
|
||||||
|
if(Version.mcMainVersion==12) return "c";
|
||||||
|
else if("v1_13_R1".equals(Version.getVersion())) return "b";
|
||||||
|
else if(Version.mcMainVersion<=17) return "parseLiteral";
|
||||||
|
else return "b";
|
||||||
|
}
|
||||||
|
case NBTTagCompound_set: {
|
||||||
|
if(Version.mcMainVersion<=17) return "set";
|
||||||
|
return "a";
|
||||||
|
}
|
||||||
|
default: return "unreachable";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void init_NBTTagCompoundClass(){
|
||||||
|
try{
|
||||||
|
Class<?> CraftMetaBlockStateClass = Class.forName("org.bukkit.craftbukkit."+Version.getVersion()+".inventory.CraftMetaBlockState");
|
||||||
|
Field field = CraftMetaBlockStateClass.getDeclaredField("blockEntityTag");
|
||||||
|
this.NBTTagCompoundClass = field.getType();
|
||||||
|
return;
|
||||||
|
}catch (ReflectiveOperationException ignored){}
|
||||||
|
|
||||||
|
Method[] methods = CraftEntityClass.getDeclaredMethods();
|
||||||
|
for (Method method : methods) {
|
||||||
|
if ("save".equals(method.getName())) this.NBTTagCompoundClass = method.getReturnType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void init_NBTTagCompound_map(){
|
||||||
|
Field[] fields = NBTTagCompoundClass.getDeclaredFields();
|
||||||
|
for(Field field : fields){
|
||||||
|
if(field.getType() == this.unhandledTags.getType()){
|
||||||
|
this.NBTTagCompound_map = field;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.NBTTagCompound_map.setAccessible(true);
|
||||||
|
}
|
||||||
|
private void init_NBTBaseClass(){
|
||||||
|
try{
|
||||||
|
//在mohist端使用getPackage()喜提null
|
||||||
|
this.NBTBaseClass = Class.forName(this.NBTTagCompoundClass.getName().replace(".NBTTagCompound",".NBTBase"));
|
||||||
|
}catch (ClassNotFoundException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static enum ReflectiveMethod {
|
||||||
|
NMSItemStack_save,
|
||||||
|
NMSItemStack_setTag,
|
||||||
|
MojangsonParser_parse,
|
||||||
|
MojangsonParser_parseLiteral,
|
||||||
|
NBTTagCompound_set
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
public class Pair<P1,P2> {
|
||||||
|
public P1 first;
|
||||||
|
public P2 second;
|
||||||
|
public Pair(P1 first, P2 second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import pers.xanadu.enderdragon.EnderDragon;
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.script.Events;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
public class UpdateChecker {
|
||||||
|
public static void checkUpdate(){
|
||||||
|
Lang.info(Lang.plugin_checking_update);
|
||||||
|
new BukkitRunnable(){
|
||||||
|
@Override
|
||||||
|
public void run(){
|
||||||
|
try {
|
||||||
|
URLConnection conn = new URL("https://api.github.com/repos/iXanadu13/EnderDragon/releases/latest").openConnection();
|
||||||
|
conn.setConnectTimeout(20000);
|
||||||
|
conn.setReadTimeout(60000);
|
||||||
|
InputStream is = conn.getInputStream();
|
||||||
|
String line = new BufferedReader(new InputStreamReader(is)).readLine();
|
||||||
|
is.close();
|
||||||
|
String newVer = line.substring(line.indexOf("\"tag_name\"") + 13, line.indexOf("\"target_commitish\"") - 2);
|
||||||
|
String localVer = EnderDragon.plugin.getDescription().getVersion();
|
||||||
|
if (!localVer.equals(newVer)) {
|
||||||
|
Lang.warn(Lang.plugin_out_of_date.replace("{0}",localVer).replace("{1}",newVer));
|
||||||
|
Events.registerPersistently(PlayerJoinEvent.class,e->{
|
||||||
|
if(e.getPlayer().hasPermission("ed.update.notify")) {
|
||||||
|
e.getPlayer().sendMessage("§3An update for §bEnderDragon §r(v" + newVer + ")§3 is available at", "§7§nhttps://www.spigotmc.org/resources/enderdragon.101583/");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Lang.info(Lang.plugin_up_to_date.replace("{1}",newVer));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Lang.warn(Lang.plugin_check_update_fail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.runTaskAsynchronously(EnderDragon.plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package pers.xanadu.enderdragon.util;
|
||||||
|
|
||||||
|
import pers.xanadu.enderdragon.config.Lang;
|
||||||
|
import pers.xanadu.enderdragon.nms.BossBar.I_BossBarManager;
|
||||||
|
import pers.xanadu.enderdragon.nms.NMSItem.I_NMSItemManager;
|
||||||
|
import pers.xanadu.enderdragon.nms.RespawnAnchor.I_RespawnAnchorManager;
|
||||||
|
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 lang = "2.2.0";
|
||||||
|
public static final String config = "2.2.0";
|
||||||
|
public static final String data = "2.2.0";
|
||||||
|
public static int mcMainVersion;
|
||||||
|
public static int mcPatchVersion;
|
||||||
|
private static String version = "no version found";
|
||||||
|
private static boolean isMohist = false;
|
||||||
|
public static void init(){
|
||||||
|
try {
|
||||||
|
version = getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||||
|
String[] mc_version = getServer().getBukkitVersion().split("-")[0].split("\\.");
|
||||||
|
mcMainVersion = Integer.parseInt(mc_version[1]);
|
||||||
|
if(mc_version.length<=2) mcPatchVersion = 0;
|
||||||
|
else mcPatchVersion = Integer.parseInt(mc_version[2]);
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
throwable.printStackTrace();
|
||||||
|
Lang.warn("Failed to get nms-version!");
|
||||||
|
}
|
||||||
|
Lang.info("Found version: " + version);
|
||||||
|
try{
|
||||||
|
Class.forName("net.minecraftforge.server.ServerMain");
|
||||||
|
isMohist = true;
|
||||||
|
}catch(ReflectiveOperationException ignored){}
|
||||||
|
|
||||||
|
}
|
||||||
|
public static I_NMSItemManager getNMSItemManager(){
|
||||||
|
switch (version){
|
||||||
|
case "v1_12_R1" : return new pers.xanadu.enderdragon.nms.NMSItem.v1_12_R1.NMSItemManager();
|
||||||
|
case "v1_13_R1" : return new pers.xanadu.enderdragon.nms.NMSItem.v1_13_R1.NMSItemManager();
|
||||||
|
default: return new pers.xanadu.enderdragon.nms.NMSItem.v1_13_R2_above.NMSItemManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static I_BossBarManager getBossBarManager(){
|
||||||
|
switch(version){
|
||||||
|
case "v1_12_R1" : return new pers.xanadu.enderdragon.nms.BossBar.v1_12_R1.BossBarManager();
|
||||||
|
case "v1_13_R1" : return new pers.xanadu.enderdragon.nms.BossBar.v1_13_R1.BossBarManager();
|
||||||
|
case "v1_13_R2" : return new pers.xanadu.enderdragon.nms.BossBar.v1_13_R2.BossBarManager();
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static I_WorldDataManager getWorldDataManager(){
|
||||||
|
switch (version){
|
||||||
|
case "v1_12_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_12_R1.WorldDataManager();
|
||||||
|
case "v1_13_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_13_R1.WorldDataManager();
|
||||||
|
case "v1_13_R2" : return new pers.xanadu.enderdragon.nms.WorldData.v1_13_R2.WorldDataManager();
|
||||||
|
case "v1_14_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_14_R1.WorldDataManager();
|
||||||
|
case "v1_15_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_15_R1.WorldDataManager();
|
||||||
|
case "v1_16_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_16_R1.WorldDataManager();
|
||||||
|
case "v1_16_R2" : return new pers.xanadu.enderdragon.nms.WorldData.v1_16_R2.WorldDataManager();
|
||||||
|
case "v1_16_R3" : return new pers.xanadu.enderdragon.nms.WorldData.v1_16_R3.WorldDataManager();
|
||||||
|
default : return new pers.xanadu.enderdragon.nms.WorldData.v1_17_above.WorldDataManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static I_RespawnAnchorManager getRespawnAnchorManager(){
|
||||||
|
switch (version){
|
||||||
|
case "v1_12_R1" :
|
||||||
|
case "v1_13_R1" :
|
||||||
|
case "v1_14_R1" :
|
||||||
|
case "v1_13_R2" :
|
||||||
|
case "v1_15_R1" : return null;
|
||||||
|
case "v1_16_R1" : return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R1.RespawnAnchorManager();
|
||||||
|
case "v1_16_R2" : return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R2.RespawnAnchorManager();
|
||||||
|
case "v1_16_R3" : return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R3.RespawnAnchorManager();
|
||||||
|
case "v1_17_R1" : return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_17_R1.RespawnAnchorManager();
|
||||||
|
default: return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_18_above.RespawnAnchorManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
public static boolean isMohist(){
|
||||||
|
return isMohist;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user