mirror of
https://github.com/Auxilor/EcoMobs.git
synced 2025-12-23 08:59:31 +00:00
Added boss tick system
This commit is contained in:
@@ -8,49 +8,26 @@ import com.willfp.eco.util.plugin.AbstractEcoPlugin;
|
|||||||
import com.willfp.eco.util.tuples.Pair;
|
import com.willfp.eco.util.tuples.Pair;
|
||||||
import com.willfp.ecobosses.bosses.util.bosstype.BossEntityUtils;
|
import com.willfp.ecobosses.bosses.util.bosstype.BossEntityUtils;
|
||||||
import com.willfp.ecobosses.bosses.util.bosstype.BossType;
|
import com.willfp.ecobosses.bosses.util.bosstype.BossType;
|
||||||
import com.willfp.ecobosses.bosses.util.obj.BossbarProperties;
|
import com.willfp.ecobosses.bosses.util.obj.*;
|
||||||
import com.willfp.ecobosses.bosses.util.obj.ExperienceOptions;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.ImmunityOptions;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.SpawnTotem;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.TeleportOptions;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.attacks.EffectOption;
|
import com.willfp.ecobosses.bosses.util.obj.attacks.EffectOption;
|
||||||
import com.willfp.ecobosses.bosses.util.obj.attacks.SummonsOption;
|
import com.willfp.ecobosses.bosses.util.obj.attacks.SummonsOption;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.attribute.Attribute;
|
|
||||||
import org.bukkit.attribute.AttributeInstance;
|
|
||||||
import org.bukkit.boss.BarColor;
|
import org.bukkit.boss.BarColor;
|
||||||
import org.bukkit.boss.BarFlag;
|
|
||||||
import org.bukkit.boss.BarStyle;
|
import org.bukkit.boss.BarStyle;
|
||||||
import org.bukkit.boss.BossBar;
|
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Mob;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.entity.EntityDamageEvent;
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
import org.bukkit.potion.PotionEffect;
|
import org.bukkit.potion.PotionEffect;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class EcoBoss extends PluginDependent {
|
public class EcoBoss extends PluginDependent {
|
||||||
@@ -239,6 +216,11 @@ public class EcoBoss extends PluginDependent {
|
|||||||
@Getter
|
@Getter
|
||||||
private final Map<EntityDamageEvent.DamageCause, Double> incomingMultipliers;
|
private final Map<EntityDamageEvent.DamageCause, Double> incomingMultipliers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently living bosses of this type.
|
||||||
|
*/
|
||||||
|
private final Map<UUID, LivingEcoBoss> livingBosses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Boss.
|
* Create a new Boss.
|
||||||
*
|
*
|
||||||
@@ -252,6 +234,7 @@ public class EcoBoss extends PluginDependent {
|
|||||||
super(plugin);
|
super(plugin);
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.livingBosses = new HashMap<>();
|
||||||
|
|
||||||
this.displayName = this.getConfig().getString("name");
|
this.displayName = this.getConfig().getString("name");
|
||||||
|
|
||||||
@@ -469,89 +452,21 @@ public class EcoBoss extends PluginDependent {
|
|||||||
*/
|
*/
|
||||||
public void spawn(@NotNull final Location location) {
|
public void spawn(@NotNull final Location location) {
|
||||||
LivingEntity entity = bossType.spawnBossEntity(location);
|
LivingEntity entity = bossType.spawnBossEntity(location);
|
||||||
entity.getPersistentDataContainer().set(this.getPlugin().getNamespacedKeyFactory().create("boss"), PersistentDataType.STRING, name);
|
this.livingBosses.put(entity.getUniqueId(), new LivingEcoBoss(
|
||||||
entity.setPersistent(true);
|
this.getPlugin(),
|
||||||
|
entity,
|
||||||
entity.setCustomName(this.getDisplayName());
|
this
|
||||||
entity.setCustomNameVisible(true);
|
)
|
||||||
|
);
|
||||||
AttributeInstance movementSpeed = entity.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
|
|
||||||
assert movementSpeed != null;
|
|
||||||
movementSpeed.setBaseValue(this.getMovementSpeed());
|
|
||||||
|
|
||||||
AttributeInstance maxHealth = entity.getAttribute(Attribute.GENERIC_MAX_HEALTH);
|
|
||||||
assert maxHealth != null;
|
|
||||||
maxHealth.setBaseValue(this.getMaxHealth());
|
|
||||||
|
|
||||||
entity.setHealth(maxHealth.getValue());
|
|
||||||
|
|
||||||
AttributeInstance attackDamage = entity.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE);
|
|
||||||
assert attackDamage != null;
|
|
||||||
attackDamage.setBaseValue(this.getAttackDamage());
|
|
||||||
|
|
||||||
for (OptionedSound sound : this.getSpawnSounds()) {
|
|
||||||
location.getWorld().playSound(location, sound.getSound(), sound.getVolume(), sound.getPitch());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String spawnMessage : this.getSpawnMessages()) {
|
|
||||||
Bukkit.broadcastMessage(spawnMessage
|
|
||||||
.replace("%x%", StringUtils.internalToString(location.getBlockX()))
|
|
||||||
.replace("%y%", StringUtils.internalToString(location.getBlockY()))
|
|
||||||
.replace("%z%", StringUtils.internalToString(location.getBlockZ()))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getPlugin().getRunnableFactory().create(runnable -> {
|
|
||||||
entity.setCustomName(this.getDisplayName().replace("%health%", StringUtils.internalToString(entity.getHealth())));
|
|
||||||
if (entity.isDead()) {
|
|
||||||
runnable.cancel();
|
|
||||||
}
|
|
||||||
}).runTaskTimer(0, 1);
|
|
||||||
|
|
||||||
for (Entity nearbyEntity : entity.getNearbyEntities(15, 15, 15)) {
|
|
||||||
if (nearbyEntity instanceof Player && entity instanceof Mob) {
|
|
||||||
((Mob) entity).setTarget((LivingEntity) nearbyEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isBossbarEnabled()) {
|
|
||||||
createBossBar(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBossBar(@NotNull final LivingEntity entity) {
|
/**
|
||||||
BossBar bossBar = Bukkit.getServer().createBossBar(
|
* Remove living boss.
|
||||||
entity.getCustomName(),
|
*
|
||||||
this.getBossbarProperties().getColor(),
|
* @param uuid The entity UUID.
|
||||||
this.getBossbarProperties().getStyle(),
|
*/
|
||||||
(BarFlag) null
|
public void removeLivingBoss(@NotNull final UUID uuid) {
|
||||||
);
|
this.livingBosses.remove(uuid);
|
||||||
|
|
||||||
int radius = this.getPlugin().getConfigYml().getInt("bossbar-radius");
|
|
||||||
|
|
||||||
this.getPlugin().getRunnableFactory().create(runnable -> {
|
|
||||||
if (!entity.isDead()) {
|
|
||||||
bossBar.getPlayers().forEach(bossBar::removePlayer);
|
|
||||||
entity.getNearbyEntities(radius, radius, radius).forEach(entity1 -> {
|
|
||||||
if (entity1 instanceof Player) {
|
|
||||||
bossBar.addPlayer((Player) entity1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
runnable.cancel();
|
|
||||||
}
|
|
||||||
}).runTaskTimer(0, 40);
|
|
||||||
|
|
||||||
this.getPlugin().getRunnableFactory().create(runnable -> {
|
|
||||||
if (!entity.isDead()) {
|
|
||||||
bossBar.setTitle(entity.getCustomName());
|
|
||||||
bossBar.setProgress(entity.getHealth() / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
|
||||||
} else {
|
|
||||||
bossBar.getPlayers().forEach(bossBar::removePlayer);
|
|
||||||
bossBar.setVisible(false);
|
|
||||||
runnable.cancel();
|
|
||||||
}
|
|
||||||
}).runTaskTimer(0, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package com.willfp.ecobosses.bosses;
|
||||||
|
|
||||||
|
import com.willfp.eco.util.StringUtils;
|
||||||
|
import com.willfp.eco.util.bukkit.scheduling.EcoBukkitRunnable;
|
||||||
|
import com.willfp.eco.util.internal.PluginDependent;
|
||||||
|
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
|
||||||
|
import com.willfp.ecobosses.bosses.tick.BossTicker;
|
||||||
|
import com.willfp.ecobosses.bosses.tick.tickers.BossBarTicker;
|
||||||
|
import com.willfp.ecobosses.bosses.tick.tickers.HealthPlaceholderTicker;
|
||||||
|
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.attribute.AttributeInstance;
|
||||||
|
import org.bukkit.boss.BarFlag;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Mob;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class LivingEcoBoss extends PluginDependent {
|
||||||
|
/**
|
||||||
|
* The entity.
|
||||||
|
*/
|
||||||
|
private final LivingEntity entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The boss.
|
||||||
|
*/
|
||||||
|
private final EcoBoss boss;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The boss tickers.
|
||||||
|
*/
|
||||||
|
private final Set<BossTicker> tickers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new living EcoBoss.
|
||||||
|
*
|
||||||
|
* @param plugin Instance of EcoBosses.
|
||||||
|
* @param entity The entity.
|
||||||
|
* @param boss The boss.
|
||||||
|
*/
|
||||||
|
public LivingEcoBoss(@NotNull final AbstractEcoPlugin plugin,
|
||||||
|
@NotNull final LivingEntity entity,
|
||||||
|
@NotNull final EcoBoss boss) {
|
||||||
|
super(plugin);
|
||||||
|
this.entity = entity;
|
||||||
|
this.boss = boss;
|
||||||
|
|
||||||
|
this.onSpawn();
|
||||||
|
|
||||||
|
|
||||||
|
// Tickers
|
||||||
|
this.tickers = new HashSet<>();
|
||||||
|
this.tickers.add(new HealthPlaceholderTicker());
|
||||||
|
if (boss.isBossbarEnabled()) {
|
||||||
|
this.tickers.add(
|
||||||
|
new BossBarTicker(
|
||||||
|
Bukkit.getServer().createBossBar(
|
||||||
|
entity.getCustomName(),
|
||||||
|
boss.getBossbarProperties().getColor(),
|
||||||
|
boss.getBossbarProperties().getStyle(),
|
||||||
|
(BarFlag) null
|
||||||
|
),
|
||||||
|
this.getPlugin().getConfigYml().getInt("bossbar-radius")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AtomicLong currentTick = new AtomicLong(0);
|
||||||
|
this.getPlugin().getRunnableFactory().create(runnable -> {
|
||||||
|
this.tick(currentTick.getAndAdd(1), runnable);
|
||||||
|
}).runTaskTimer(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSpawn() {
|
||||||
|
entity.getPersistentDataContainer().set(this.getPlugin().getNamespacedKeyFactory().create("boss"), PersistentDataType.STRING, boss.getName());
|
||||||
|
entity.setPersistent(true);
|
||||||
|
|
||||||
|
entity.setCustomName(boss.getDisplayName());
|
||||||
|
entity.setCustomNameVisible(true);
|
||||||
|
|
||||||
|
AttributeInstance movementSpeed = entity.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
|
||||||
|
assert movementSpeed != null;
|
||||||
|
movementSpeed.setBaseValue(boss.getMovementSpeed());
|
||||||
|
|
||||||
|
AttributeInstance maxHealth = entity.getAttribute(Attribute.GENERIC_MAX_HEALTH);
|
||||||
|
assert maxHealth != null;
|
||||||
|
maxHealth.setBaseValue(boss.getMaxHealth());
|
||||||
|
|
||||||
|
entity.setHealth(maxHealth.getValue());
|
||||||
|
|
||||||
|
AttributeInstance attackDamage = entity.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE);
|
||||||
|
assert attackDamage != null;
|
||||||
|
attackDamage.setBaseValue(boss.getAttackDamage());
|
||||||
|
|
||||||
|
for (OptionedSound sound : boss.getSpawnSounds()) {
|
||||||
|
entity.getWorld().playSound(entity.getLocation(), sound.getSound(), sound.getVolume(), sound.getPitch());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String spawnMessage : boss.getSpawnMessages()) {
|
||||||
|
Bukkit.broadcastMessage(spawnMessage
|
||||||
|
.replace("%x%", StringUtils.internalToString(entity.getLocation().getBlockX()))
|
||||||
|
.replace("%y%", StringUtils.internalToString(entity.getLocation().getBlockY()))
|
||||||
|
.replace("%z%", StringUtils.internalToString(entity.getLocation().getBlockZ()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entity nearbyEntity : entity.getNearbyEntities(15, 15, 15)) {
|
||||||
|
if (nearbyEntity instanceof Player && entity instanceof Mob) {
|
||||||
|
((Mob) entity).setTarget((LivingEntity) nearbyEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tick(final long tick,
|
||||||
|
@NotNull final EcoBukkitRunnable runnable) {
|
||||||
|
for (BossTicker ticker : tickers) {
|
||||||
|
ticker.tick(boss, entity, tick);
|
||||||
|
}
|
||||||
|
if (entity.isDead()) {
|
||||||
|
for (BossTicker ticker : tickers) {
|
||||||
|
ticker.onDeath(boss, entity, tick);
|
||||||
|
}
|
||||||
|
runnable.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.willfp.ecobosses.bosses.tick;
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.EcoBoss;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public interface BossTicker {
|
||||||
|
/**
|
||||||
|
* Run on boss tick.
|
||||||
|
*
|
||||||
|
* @param boss The boss.
|
||||||
|
* @param entity The boss entity.
|
||||||
|
* @param tick The current tick: counts up from zero.
|
||||||
|
*/
|
||||||
|
void tick(@NotNull EcoBoss boss,
|
||||||
|
@NotNull LivingEntity entity,
|
||||||
|
long tick);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run on boss death.
|
||||||
|
*
|
||||||
|
* @param boss The boss.
|
||||||
|
* @param entity The boss entity.
|
||||||
|
* @param tick The current tick: counts up from zero.
|
||||||
|
*/
|
||||||
|
default void onDeath(@NotNull EcoBoss boss,
|
||||||
|
@NotNull LivingEntity entity,
|
||||||
|
long tick) {
|
||||||
|
// Can be overridden when needed.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.willfp.ecobosses.bosses.tick.tickers;
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.EcoBoss;
|
||||||
|
import com.willfp.ecobosses.bosses.tick.BossTicker;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.boss.BossBar;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class BossBarTicker implements BossTicker {
|
||||||
|
/**
|
||||||
|
* The boss bar.
|
||||||
|
*/
|
||||||
|
private final BossBar bossBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The radius that the boss bar should be visible in.
|
||||||
|
*/
|
||||||
|
private final double radius;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new boss bar ticker.
|
||||||
|
* @param bossBar The boss bar.
|
||||||
|
* @param radius The radius.
|
||||||
|
*/
|
||||||
|
public BossBarTicker(@NotNull final BossBar bossBar,
|
||||||
|
final double radius) {
|
||||||
|
this.bossBar = bossBar;
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(@NotNull final EcoBoss boss,
|
||||||
|
@NotNull final LivingEntity entity,
|
||||||
|
final long tick) {
|
||||||
|
bossBar.setTitle(entity.getCustomName());
|
||||||
|
bossBar.setProgress(entity.getHealth() / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
||||||
|
|
||||||
|
if (tick % 40 == 0) {
|
||||||
|
bossBar.getPlayers().forEach(bossBar::removePlayer);
|
||||||
|
entity.getNearbyEntities(radius, radius, radius).forEach(entity1 -> {
|
||||||
|
if (entity1 instanceof Player) {
|
||||||
|
bossBar.addPlayer((Player) entity1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeath(@NotNull final EcoBoss boss,
|
||||||
|
@NotNull final LivingEntity entity,
|
||||||
|
final long tick) {
|
||||||
|
bossBar.getPlayers().forEach(bossBar::removePlayer);
|
||||||
|
bossBar.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.willfp.ecobosses.bosses.tick.tickers;
|
||||||
|
|
||||||
|
import com.willfp.eco.util.StringUtils;
|
||||||
|
import com.willfp.ecobosses.bosses.EcoBoss;
|
||||||
|
import com.willfp.ecobosses.bosses.tick.BossTicker;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class HealthPlaceholderTicker implements BossTicker {
|
||||||
|
@Override
|
||||||
|
public void tick(@NotNull final EcoBoss boss,
|
||||||
|
@NotNull final LivingEntity entity,
|
||||||
|
final long tick) {
|
||||||
|
entity.setCustomName(boss.getDisplayName().replace("%health%", StringUtils.internalToString(entity.getHealth())));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user