Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ allprojects {
maven("https://repo.auxilor.io/repository/maven-public/")
maven("https://mvn.lib.co.nz/public")
maven("https://mvn.lumine.io/repository/maven-public/")
maven("https://maven.playpro.com")
}

dependencies {
Expand Down
1 change: 1 addition & 0 deletions eco-core/core-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT")
compileOnly("io.github.arcaneplugins:levelledmobs-plugin:4.0.2")
compileOnly("me.libraryaddict.disguises:libsdisguises:11.0.14")
compileOnly("net.coreprotect:coreprotect:24.0")
implementation("com.willfp:ModelEngineBridge:1.4.0")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.willfp.eco.core.command.impl.PluginCommand
import com.willfp.eco.core.display.DisplayModule
import com.willfp.eco.core.entities.ai.EntityGoals
import com.willfp.eco.core.integrations.IntegrationLoader
import com.willfp.eco.core.items.Items
import com.willfp.eco.util.toSingletonList
import com.willfp.ecomobs.category.MobCategories
import com.willfp.ecomobs.category.spawning.spawnpoints.SpawnPointGenerator
Expand All @@ -19,8 +20,11 @@ import com.willfp.ecomobs.handler.MountHandler
import com.willfp.ecomobs.handler.SpawnEggHandler
import com.willfp.ecomobs.handler.SpawnTotemHandler
import com.willfp.ecomobs.handler.SpawnerHandler
import com.willfp.ecomobs.handler.SpawnerStackHandler
import com.willfp.ecomobs.handler.StackHandler
import com.willfp.ecomobs.handler.VanillaCompatibilityHandlers
import com.willfp.ecomobs.integrations.bettermodel.IntegrationBetterModel
import com.willfp.ecomobs.integrations.coreprotect.IntegrationCoreProtect
import com.willfp.ecomobs.integrations.levelledmobs.IntegrationLevelledMobs
import com.willfp.ecomobs.integrations.libsdisguises.IntegrationLibsDisguises
import com.willfp.ecomobs.integrations.modelengine.IntegrationModelEngine
Expand All @@ -30,8 +34,14 @@ import com.willfp.ecomobs.mob.impl.ecoMob
import com.willfp.ecomobs.spawner.PlacedSpawners
import com.willfp.ecomobs.spawner.SpawnerAnimations
import com.willfp.ecomobs.spawner.SpawnerDisplay
import com.willfp.ecomobs.spawner.SpawnerHolograms
import com.willfp.ecomobs.spawner.SpawnerItems
import com.willfp.ecomobs.spawner.SpawnerStackSettings
import com.willfp.ecomobs.spawner.SpawnerSettings
import com.willfp.ecomobs.spawner.SpawnerSpawnLoop
import com.willfp.ecomobs.stacking.MobStackTicker
import com.willfp.ecomobs.stacking.StackSettings
import com.willfp.ecomobs.trigger.EcoMobsTriggers
import com.willfp.ecomobs.spawner.particle.SpawnerParticleAnimations
import com.willfp.libreforge.EntityProvidedHolder
import com.willfp.libreforge.loader.LibreforgePlugin
Expand Down Expand Up @@ -61,6 +71,8 @@ class EcoMobsPlugin : LibreforgePlugin() {

override fun handleLoad() {
EntityGoals.register(EntityGoalRandomTeleport.Deserializer)
Items.registerItemProvider(SpawnerItems)
EcoMobsTriggers.registerAll()
}

override fun loadConfigCategories(): List<ConfigCategory> {
Expand All @@ -72,14 +84,23 @@ class EcoMobsPlugin : LibreforgePlugin() {

override fun handleReload() {
SpawnerAnimations.reload()
SpawnerStackSettings.reload()
SpawnerSettings.reload()
// Chunks loaded before the plugin enabled never fire a ChunkLoadEvent, and a
// config change can flip which spawners are tracked, so the index is rebuilt here.
SpawnerHandler.indexLoadedChunks()
SpawnerDisplay.start()
SpawnerSpawnLoop.start()
StackSettings.reload()
MobStackTicker.start()
SpawnerHolograms.reloadAll()
}

override fun handleDisable() {
SpawnerDisplay.stop()
SpawnerSpawnLoop.stop()
MobStackTicker.stop()
SpawnerHolograms.clear()
PlacedSpawners.clear()
}

Expand All @@ -94,6 +115,8 @@ class EcoMobsPlugin : LibreforgePlugin() {
SpawnTotemHandler,
topDamagerHandler,
SpawnerHandler,
SpawnerStackHandler,
StackHandler,
ChunkHandler
)
}
Expand All @@ -108,6 +131,7 @@ class EcoMobsPlugin : LibreforgePlugin() {
IntegrationLoader("ModelEngine") { this.eventManager.registerListener(IntegrationModelEngine) },
IntegrationLoader("BetterModel") { this.eventManager.registerListener(IntegrationBetterModel) },
IntegrationLoader("LibsDisguises") { this.eventManager.registerListener(IntegrationLibsDisguises) },
IntegrationLoader("CoreProtect") { this.eventManager.registerListener(IntegrationCoreProtect) },
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.willfp.ecomobs.category.spawning.SpawnMethod
import com.willfp.ecomobs.category.spawning.SpawnMethodFactory
import com.willfp.ecomobs.category.spawning.spawnpoints.SpawnPointType
import com.willfp.ecomobs.category.spawning.spawnpoints.spawnPoints
import com.willfp.ecomobs.folia.onEntity
import com.willfp.ecomobs.mob.SpawnReason
import com.willfp.ecomobs.plugin
import com.willfp.libreforge.EmptyProvidedHolder
Expand Down Expand Up @@ -59,9 +60,10 @@ object SpawnMethodFactoryCustom : SpawnMethodFactory("custom") {

private fun tick() {
for (player in Bukkit.getOnlinePlayers()) {
// The spawn points belong to the player's region, so the work is
// submitted to their context rather than run from the global one.
plugin.scheduler.on(player).run {
// Spawn points are found by scanning the blocks around the player, and
// the mobs then go into the world there, so the whole pass runs on the
// player's own region rather than the global one.
onEntity(player) {
tickPlayer(player)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package com.willfp.ecomobs.commands

import com.willfp.eco.core.command.impl.Subcommand
import com.willfp.ecomobs.folia.onEntity
import com.willfp.ecomobs.mob.EcoMobs
import com.willfp.ecomobs.mob.impl.mobKey
import com.willfp.ecomobs.plugin
import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.bukkit.entity.Mob
import org.bukkit.persistence.PersistentDataType
import org.bukkit.util.StringUtil

object CommandKillAll : Subcommand(
Expand Down Expand Up @@ -36,23 +33,18 @@ object CommandKillAll : Subcommand(

var killed = 0

for (world in Bukkit.getWorlds()) {
for (entity in world.entities.filterIsInstance<Mob>()) {
// Read the ID from the entity itself rather than from tracking, so that mobs
// spawned before a restart or reload are still killed.
val id = entity.persistentDataContainer.get(mobKey, PersistentDataType.STRING)
?: continue

if (filter != null && id != filter) {
continue
}

val livingMob = EcoMobs[id]?.getLivingMob(entity)
// Walked over what EcoMobs tracks rather than over world.entities: no thread
// owns every region, so there is no thread that can iterate a whole world.
// Mobs loaded before the plugin enabled are picked up by ChunkHandler, so a
// loaded mob of ours is a tracked mob of ours.
for (ecoMob in EcoMobs.values()) {
if (filter != null && ecoMob.id != filter) {
continue
}

if (livingMob != null) {
livingMob.despawn()
} else {
entity.remove()
for (living in ecoMob.livingMobs.toList()) {
onEntity(living.entity) {
living.despawn()
}

killed++
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.willfp.ecomobs.commands
import com.willfp.eco.core.command.impl.Subcommand
import com.willfp.eco.core.fast.fast
import com.willfp.ecomobs.plugin
import com.willfp.ecomobs.spawner.PlacedSpawner
import com.willfp.ecomobs.spawner.PlacedSpawners
import com.willfp.ecomobs.spawner.SpawnerAttributes
import com.willfp.ecomobs.spawner.applyVanillaSettings
Expand Down Expand Up @@ -80,7 +79,7 @@ object CommandSpawnerModify : Subcommand(
}
state.update()

PlacedSpawners.set(block.location, PlacedSpawner(block.location, state.spawner.particleAnim))
PlacedSpawners.sync(state)
}

sender.sendMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.willfp.eco.core.placeholder.context.placeholderContext
import com.willfp.eco.util.formatEco
import com.willfp.eco.util.titlecase
import com.willfp.ecomobs.plugin
import com.willfp.ecomobs.spawner.SpawnerStackSettings
import com.willfp.ecomobs.spawner.spawner
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
Expand All @@ -28,6 +29,9 @@ private fun FastItemStack.applySpawnerPlaceholders(text: String): String {
.replace("%pickup%", data.pickup)
.replace("%particle%", data.particleAnim ?: "none")
.replace("%explosion_proof%", data.explosionProof.toString())
.replace("%no_ai%", data.noAI.toString())
.replace("%size%", data.stackSize.toString())
.replace("%max_stack_size%", SpawnerStackSettings.maxSize.toString())
}

object SpawnerItemDisplay : DisplayModule(plugin, DisplayPriority.LOW) {
Expand All @@ -43,7 +47,14 @@ object SpawnerItemDisplay : DisplayModule(plugin, DisplayPriority.LOW) {
fis.setDisplayName(fis.applySpawnerPlaceholders(rawTitle).formatEco(context))
}

val lore = plugin.configYml.getStrings("spawner-display.lore")
val rawLore = plugin.configYml.getStrings("spawner-display.lore") +
if (fis.spawner.stackSize > 1) {
plugin.configYml.getStrings("spawner-display.stacked-lore")
} else {
emptyList()
}

val lore = rawLore
.map { Display.PREFIX + fis.applySpawnerPlaceholders(it).formatEco(context) }

fis.lore = lore + fis.lore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.willfp.ecomobs.event

import com.willfp.ecomobs.mob.LivingMob
import org.bukkit.entity.Player
import org.bukkit.event.Cancellable
import org.bukkit.event.Event
import org.bukkit.event.HandlerList
import org.bukkit.event.entity.EntityDamageEvent.DamageCause

/**
* Called when an EcoMob takes damage, after the mob's own damage modifiers have been
* applied and before its damage stages see the hit.
*
* Cancelling cancels the underlying [org.bukkit.event.entity.EntityDamageEvent].
*/
class EcoMobDamageEvent(
override val mob: LivingMob,
/**
* The player who dealt the damage, or null if it came from elsewhere.
*/
val player: Player?,
val cause: DamageCause,
/**
* The damage dealt. Writing to it writes back to the bukkit event.
*/
var damage: Double
) : Event(), MobEvent, Cancellable {
private var isCancelled: Boolean = false

override fun isCancelled(): Boolean {
return isCancelled
}

override fun setCancelled(cancelled: Boolean) {
isCancelled = cancelled
}

override fun getHandlers(): HandlerList {
return HANDLERS
}

companion object {
private val HANDLERS = HandlerList()

@JvmStatic
fun getHandlerList(): HandlerList {
return HANDLERS
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.willfp.ecomobs.event

import com.willfp.ecomobs.mob.EcoMob
import org.bukkit.Location
import org.bukkit.entity.Player
import org.bukkit.event.Cancellable
import org.bukkit.event.Event
import org.bukkit.event.HandlerList
import org.bukkit.inventory.ItemStack

/**
* Called once the mob's drop table has been rolled, before anything is given out.
* Cancelling drops nothing at all.
*
* Fired once per mob of a stack, as each one rolls the table separately.
*/
class EcoMobDropsEvent(
val ecoMob: EcoMob,
val location: Location,
/**
* The player the drops go to, or null if they fall on the ground.
*/
val player: Player?,
/**
* The items rolled, which can be edited in place.
*/
val drops: MutableList<ItemStack>,
var experience: Int
) : Event(), Cancellable {
private var isCancelled: Boolean = false

override fun isCancelled(): Boolean {
return isCancelled
}

override fun setCancelled(cancelled: Boolean) {
isCancelled = cancelled
}

override fun getHandlers(): HandlerList {
return HANDLERS
}

companion object {
private val HANDLERS = HandlerList()

@JvmStatic
fun getHandlerList(): HandlerList {
return HANDLERS
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.willfp.ecomobs.event

import com.willfp.ecomobs.mob.EcoMob
import org.bukkit.Location
import org.bukkit.entity.Player
import org.bukkit.event.Cancellable
import org.bukkit.event.Event
import org.bukkit.event.HandlerList

/**
* Called when a spawn egg is about to spawn its mob, before the egg's conditions are
* tested. Cancelling stops the spawn and leaves the egg in the inventory.
*/
class EcoMobEggUseEvent(
val mob: EcoMob,
val location: Location,
val player: Player?,
val source: Source
) : Event(), Cancellable {
private var isCancelled: Boolean = false

/**
* What used the egg.
*/
enum class Source {
/**
* A player right-clicked a block with the egg.
*/
PLAYER,

/**
* A dispenser or dropper fired the egg.
*/
DISPENSER
}

override fun isCancelled(): Boolean {
return isCancelled
}

override fun setCancelled(cancelled: Boolean) {
isCancelled = cancelled
}

override fun getHandlers(): HandlerList {
return HANDLERS
}

companion object {
private val HANDLERS = HandlerList()

@JvmStatic
fun getHandlerList(): HandlerList {
return HANDLERS
}
}
}
Loading
Loading