9
0
mirror of https://github.com/Auxilor/EcoMobs.git synced 2025-12-22 16:39:25 +00:00

Continued rewrite

This commit is contained in:
Auxilor
2022-02-05 18:57:56 +00:00
parent 03efa137f4
commit baa2b6718e
12 changed files with 327 additions and 212 deletions

View File

@@ -1,64 +0,0 @@
package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.eco.util.PlayerUtils;
import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.tick.BossTicker;
import net.kyori.adventure.bossbar.BossBar;
import org.bukkit.Bukkit;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.name(StringUtils.toComponent(entity.getCustomName()));
bossBar.progress((float) (entity.getHealth() / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()));
if (tick % 40 == 0) {
for (Player player : Bukkit.getOnlinePlayers()) {
PlayerUtils.getAudience(player).hideBossBar(bossBar);
}
entity.getNearbyEntities(radius, radius, radius).forEach(entity1 -> {
if (entity1 instanceof Player) {
PlayerUtils.getAudience((Player) entity1).showBossBar(bossBar);
}
});
}
}
@Override
public void onDeath(@NotNull final EcoBoss boss,
@Nullable final LivingEntity entity,
final long tick) {
for (Player player : Bukkit.getOnlinePlayers()) {
PlayerUtils.getAudience(player).hideBossBar(bossBar);
}
}
}

View File

@@ -1,35 +0,0 @@
package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
import com.willfp.ecobosses.tick.BossTicker;
import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
public class DeathTimeTicker implements BossTicker {
@Override
public void tick(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
final long tick) {
if (boss.getTimeToLive() < 0) {
return;
}
int timeLeft;
timeLeft = (int) (entity.getMetadata("death-time").get(0).asLong() - System.currentTimeMillis());
timeLeft = (int) Math.ceil(timeLeft / 1000D);
if (timeLeft <= 0) {
entity.remove();
boss.removeLivingBoss(entity);
for (String despawnMessage : boss.getDespawnMessages()) {
Bukkit.broadcastMessage(despawnMessage);
}
for (OptionedSound sound : boss.getDespawnSounds()) {
entity.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
}
}
}
}

View File

@@ -1,30 +0,0 @@
package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.tick.BossTicker;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
public class NamePlaceholderTicker implements BossTicker {
@Override
public void tick(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
final long tick) {
int timeLeft = -1;
if (boss.getTimeToLive() > 0) {
timeLeft = (int) (entity.getMetadata("death-time").get(0).asLong() - System.currentTimeMillis());
timeLeft = (int) Math.ceil(timeLeft / 1000D);
}
String time = "";
if (timeLeft > 0) {
time = String.format("%d:%02d", timeLeft/60, timeLeft%60);
}
entity.setCustomName(
boss.getDisplayName()
.replace("%health%", StringUtils.internalToString(entity.getHealth()))
.replace("%time%", time)
);
}
}

View File

@@ -1,57 +0,0 @@
package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.tick.BossTicker;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class TargetTicker implements BossTicker {
/**
* The targeting mode.
*/
private final TargetMode mode;
/**
* The maximum range.
*/
private final double range;
/**
* Create new target ticker.
*
* @param mode The targeting mode.
* @param range The range.
*/
public TargetTicker(@NotNull final TargetMode mode,
final double range) {
this.mode = mode;
this.range = range;
}
@Override
public void tick(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
final long tick) {
Mob mob = (Mob) entity;
if (tick % 10 == 0) {
List<Player> nearbyPlayers = new ArrayList<>();
for (Entity nearbyEntity : entity.getNearbyEntities(range, range, range)) {
if (nearbyEntity instanceof Player) {
nearbyPlayers.add((Player) nearbyEntity);
}
}
if (nearbyPlayers.isEmpty()) {
return;
}
mob.setTarget(mode.getTarget(nearbyPlayers, entity));
}
}
}

View File

@@ -1,8 +0,0 @@
package com.willfp.ecobosses.bosses.util.obj;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public record ArgumentedEffectName(@NotNull String name, @NotNull List<String> args) {
}

View File

@@ -3,6 +3,6 @@ package com.willfp.ecobosses.bosses
enum class BossLifecycle {
SPAWN,
KILL,
DESPAWN
DESPAWN,
INJURE
}

View File

@@ -4,16 +4,23 @@ import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.entities.Entities
import com.willfp.eco.core.entities.TestableEntity
import com.willfp.eco.core.items.Items
import com.willfp.eco.util.toComponent
import com.willfp.ecobosses.tick.BossBarTicker
import com.willfp.ecobosses.tick.BossTicker
import com.willfp.ecobosses.tick.DisplayNameTicker
import com.willfp.ecobosses.tick.LifespanTicker
import com.willfp.ecobosses.tick.TargetTicker
import com.willfp.ecobosses.util.BossDrop
import com.willfp.ecobosses.util.CommandReward
import com.willfp.ecobosses.util.ConfiguredSound
import com.willfp.ecobosses.util.LocalBroadcast
import com.willfp.ecobosses.util.PlayableSound
import com.willfp.ecobosses.util.XpReward
import com.willfp.libreforge.Holder
import com.willfp.libreforge.conditions.ConfiguredCondition
import com.willfp.libreforge.effects.ConfiguredEffect
import com.willfp.libreforge.effects.Effects
import net.kyori.adventure.bossbar.BossBar
import org.bukkit.Location
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
@@ -36,6 +43,14 @@ class EcoBoss(
val targetMode = TargetMode.getByID(config.getString("target.mode"))!!
val isBossBarEnabled = config.getBool("bossBar.enabled")
val bossBarRadius = config.getDouble("bossBar.radius")
private val bossBarColor = BossBar.Color.valueOf(config.getString("bossBar.color").uppercase())
private val bossBarStyle = BossBar.Overlay.valueOf(config.getString("bossBar.style").uppercase())
private val sounds: Map<BossLifecycle, PlayableSound> = run {
val map = mutableMapOf<BossLifecycle, PlayableSound>()
@@ -48,6 +63,79 @@ class EcoBoss(
map
}
private val messages: Map<BossLifecycle, Iterable<LocalBroadcast>> = run {
val map = mutableMapOf<BossLifecycle, Iterable<LocalBroadcast>>()
for (value in BossLifecycle.values()) {
map[value] = config.getSubsections("messages.${value.name.lowercase()}").map {
LocalBroadcast.fromConfig(it)
}
}
map
}
private val commandRewards: Map<Int, Iterable<CommandReward>> = run {
val map = mutableMapOf<Int, Iterable<CommandReward>>()
for (rank in config.getSubsection("rewards.topDamagerCommands").getKeys(false)) {
val rankRewards = mutableListOf<CommandReward>()
for (config in config.getSubsections("rewards.topDamagerCommands.$rank")) {
rankRewards.add(
CommandReward(
config.getDouble("chance"),
config.getStrings("commands")
)
)
}
map[rank.toInt()] = rankRewards
}
map
}
private val nearbyCommandRewardRadius = config.getDouble("rewards.nearbyPlayerCommands.radius")
private val nearbyCommands: Iterable<CommandReward> = run {
val list = mutableListOf<CommandReward>()
for (config in config.getSubsections("rewards.nearbyPlayerCommands.commands")) {
list.add(
CommandReward(
config.getDouble("chance"),
config.getStrings("commands")
)
)
}
list
}
private val xp = XpReward(
config.getInt("rewards.xp.minimum"),
config.getInt("rewards.xp.maximum")
)
private val drops: Iterable<BossDrop> = run {
val list = mutableListOf<BossDrop>()
for (config in config.getSubsections("rewards.drops")) {
list.add(
BossDrop(
config.getDouble("chance"),
config.getStrings("items")
.map { Items.lookup(it) }
.map { it.item }
)
)
}
list
}
private val mob: TestableEntity = Entities.lookup(config.getString("mob"))
private val currentlyAlive = mutableMapOf<UUID, LivingEcoBoss>()
@@ -85,15 +173,39 @@ class EcoBoss(
}
private fun createTickersFor(entity: LivingEntity): Set<BossTicker> {
return setOf(
val tickers = mutableSetOf(
LifespanTicker(),
DisplayNameTicker(),
TargetTicker()
)
if (isBossBarEnabled) {
tickers.add(
BossBarTicker(
BossBar.bossBar(
this.displayName.toComponent(),
1.0f,
bossBarColor,
bossBarStyle
)
)
)
}
return tickers
}
fun handleLifecycle(player: Player, lifecycle: BossLifecycle) {
sounds[lifecycle]?.play(player)
fun handleLifecycle(lifecycle: BossLifecycle, location: Location) {
sounds[lifecycle]?.play(location)
messages[lifecycle]?.forEach { it.broadcast(location) }
}
fun processRewards(player: Player, location: Location) {
for (drop in drops) {
drop.drop(location, player)
}
xp.drop(location, player)
}
override fun equals(other: Any?): Boolean {
@@ -114,8 +226,3 @@ class EcoBoss(
+ "}")
}
}
class SimpleHolder(
override val conditions: Set<ConfiguredCondition>,
override val effects: Set<ConfiguredEffect>
) : Holder

View File

@@ -0,0 +1,45 @@
package com.willfp.ecobosses.tick
import com.willfp.eco.util.asAudience
import com.willfp.eco.util.toComponent
import com.willfp.ecobosses.bosses.LivingEcoBoss
import net.kyori.adventure.bossbar.BossBar
import org.bukkit.Bukkit
import org.bukkit.attribute.Attribute
import org.bukkit.entity.Player
class BossBarTicker(
private val bar: BossBar
) : BossTicker {
override fun tick(boss: LivingEcoBoss, tick: Int) {
val entity = boss.entity ?: return
bar.name(entity.customName!!.toComponent())
bar.progress((entity.health / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH)!!.value).toFloat())
if (tick % 40 == 0) {
for (player in Bukkit.getOnlinePlayers()) {
player.asAudience().hideBossBar(bar)
}
entity.getNearbyEntities(
boss.boss.bossBarRadius,
boss.boss.bossBarRadius,
boss.boss.bossBarRadius
).filterIsInstance<Player>()
.map { it.asAudience() }
.forEach { it.showBossBar(bar) }
}
if (tick % 10 != 0) {
return
}
entity.target = boss.boss.targetMode.getTarget(boss) ?: return
}
override fun onDeath(boss: LivingEcoBoss, tick: Int) {
for (player in Bukkit.getOnlinePlayers()) {
player.asAudience().hideBossBar(bar)
}
}
}

View File

@@ -0,0 +1,33 @@
package com.willfp.ecobosses.util
import com.willfp.eco.core.config.interfaces.Config
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.entity.Player
data class LocalBroadcast(
val messages: Iterable<String>,
val radius: Double
) {
fun broadcast(location: Location) {
if (radius < 0) {
for (message in messages) {
Bukkit.broadcastMessage(message)
}
} else {
val world = location.world ?: return
world.getNearbyEntities(location, radius, radius, radius)
.filterIsInstance<Player>()
.forEach { player -> messages.forEach { player.sendMessage(it) } }
}
}
companion object {
fun fromConfig(config: Config): LocalBroadcast {
return LocalBroadcast(
config.getFormattedStrings("message"),
config.getDouble("radius")
)
}
}
}

View File

@@ -1,16 +1,16 @@
package com.willfp.ecobosses.util
import com.willfp.eco.core.config.interfaces.Config
import org.bukkit.Location
import org.bukkit.Sound
import org.bukkit.entity.Player
data class ConfiguredSound(
private val sound: Sound,
private val pitch: Double,
private val volume: Double
) {
fun play(player: Player) {
player.playSound(player.location, sound, volume.toFloat(), pitch.toFloat())
fun play(location: Location) {
location.world?.playSound(location, sound, volume.toFloat(), pitch.toFloat())
}
companion object {
@@ -27,9 +27,9 @@ data class ConfiguredSound(
data class PlayableSound(
val sounds: Iterable<ConfiguredSound>
) {
fun play(player: Player) {
fun play(location: Location) {
for (sound in sounds) {
sound.play(player)
sound.play(location)
}
}
}
}

View File

@@ -0,0 +1,50 @@
package com.willfp.ecobosses.util
import com.willfp.eco.core.drops.DropQueue
import com.willfp.eco.util.NumberUtils
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
data class BossDrop(
val chance: Double,
val drops: Collection<ItemStack>
) {
fun drop(location: Location, player: Player) {
if (NumberUtils.randFloat(0.0, 100.0) < chance) {
DropQueue(player)
.setLocation(location)
.addItems(drops)
.push()
}
}
}
data class CommandReward(
val chance: Double,
val commands: Collection<String>
) {
fun reward(player: Player) {
if (NumberUtils.randFloat(0.0, 100.0) < chance) {
for (command in commands) {
Bukkit.getServer().dispatchCommand(
Bukkit.getConsoleSender(),
command.replace("%player%", player.name)
)
}
}
}
}
data class XpReward(
val minimum: Int,
val maximum: Int
) {
fun drop(location: Location, player: Player) {
DropQueue(player)
.setLocation(location)
.addXP(NumberUtils.randInt(minimum, maximum))
.push()
}
}

View File

@@ -22,4 +22,78 @@ bosses:
- id: steel_golem
mob: iron_golem
displayName: "&8Steel Golem &7| &c%health%♥ &7| &e%time%"
effects: [ ]
effects: [ ]
rewards:
xp:
minimum: 30000
maximum: 60000
topDamagerCommands:
1: []
2: []
3: []
nearbyPlayerCommands:
radius: 10
commands: []
drops: []
target:
mode: highest_health
range: 40
bossBar:
enabled: true
color: white
style: solid
radius: 120
messages:
spawn:
- message:
- ""
- "&fA &8&lSteel Golem&r&f has been spawned!"
- "&fCome fight it at &8%x%&f, &8%y%&f, &8%z%&f!"
- ""
radius: -1
kill:
- message:
- ""
- "&fThe &8&lSteel Golem&r&f has been killed!"
- "&fMost Damage:"
- "&f - &8%damage_1_player%&f (%damage_1% Damage)"
- "&f - &8%damage_2_player%&f (%damage_2% Damage)"
- "&f - &8%damage_3_player%&f (%damage_3% Damage)"
- ""
radius: -1
despawn:
- message:
- ""
- "&fYou ran out of time to kill the &8&lSteel Golem&r&f!"
- ""
radius: -1
injure: [ ]
sounds:
spawn:
- sound: entity_iron_golem_death
pitch: 0.8
volume: 100
- sound: entity_iron_golem_hurt
pitch: 0.5
volume: 100
- sound: entity_ender_dragon_growl
pitch: 0.5
volume: 100
kill:
- sound: entity_ender_dragon_death
pitch: 1.8
volume: 100
- sound: entity_wither_death
pitch: 1.2
volume: 100
despawn:
- sound: entity_ender_dragon_ambient
pitch: 0.5
volume: 50
- sound: entity_enderman_death
pitch: 0.5
volume: 50
injure:
- sound: entity_iron_golem_damage
pitch: 0.7
volume: 10