diff --git a/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/DespawnSystems.kt b/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/DespawnSystems.kt new file mode 100644 index 00000000..beff6f4a --- /dev/null +++ b/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/DespawnSystems.kt @@ -0,0 +1,33 @@ +package com.mineinabyss.mobzy.features.despawning + +import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.papermc.tracking.entities.toGeary +import com.mineinabyss.geary.systems.builders.system +import com.mineinabyss.geary.systems.query.Query +import com.mineinabyss.idofront.typealiases.BukkitEntity +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.world.EntitiesUnloadEvent +import kotlin.time.Duration.Companion.seconds + +class DespawnSystems : Listener { + //TODO this event fires when chunk unloaded but at ChunkUnloadEvent there are no entities in the chunk??? + @EventHandler + fun EntitiesUnloadEvent.removeCustomOnChunkUnload() { + if (!chunk.isLoaded) return + + for (entity in chunk.entities) { + val removeOnUnload = entity.toGeary().get() ?: continue + if (!(removeOnUnload.keepIfRenamed && entity.customName() != null)) + entity.remove() + } + } +} + +fun GearyModule.removeWhenFarAway() = system(object : Query() { + val bukkit by get() + val remove by get() +}).every(3.seconds).exec { + if (bukkit.customName == null && bukkit.world.getNearbyPlayers(bukkit.location, remove.distance).isEmpty()) + bukkit.remove() +} diff --git a/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveOnChunkUnload.kt b/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveOnChunkUnload.kt index 01983326..1a051b11 100644 --- a/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveOnChunkUnload.kt +++ b/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveOnChunkUnload.kt @@ -9,7 +9,7 @@ import kotlinx.serialization.Serializable * Specifies this entity should be completely removed when the chunk it is in unloads. */ @Serializable -@SerialName("mobzy:remove_on_chunk_unload") +@SerialName("mobzy:despawn.on_chunk_unload") data class RemoveOnChunkUnload( val keepIfRenamed: Boolean = true ) diff --git a/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveOnChunkUnloadSystem.kt b/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveOnChunkUnloadSystem.kt deleted file mode 100644 index 5b2cfe1e..00000000 --- a/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveOnChunkUnloadSystem.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.mineinabyss.mobzy.features.despawning - -import com.mineinabyss.geary.papermc.tracking.entities.toGeary -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.world.ChunkUnloadEvent - -class RemoveOnChunkUnloadSystem : Listener { - @EventHandler - fun ChunkUnloadEvent.removeCustomOnChunkUnload() { - for (entity in chunk.entities) { - val removeOnUnload = entity.toGeary().get() ?: continue - if (!(removeOnUnload.keepIfRenamed && entity.customName() != null)) - entity.remove() - } - } -} diff --git a/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveWhenFarAway.kt b/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveWhenFarAway.kt new file mode 100644 index 00000000..901c5f14 --- /dev/null +++ b/mobzy-features/src/main/kotlin/com/mineinabyss/mobzy/features/despawning/RemoveWhenFarAway.kt @@ -0,0 +1,14 @@ +package com.mineinabyss.mobzy.features.despawning + +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("mobzy:despawn.when_far_away") +data class RemoveWhenFarAway( + @EncodeDefault(EncodeDefault.Mode.NEVER) + val keepIfRenamed: Boolean = true, + @EncodeDefault(EncodeDefault.Mode.NEVER) + val distance: Double = 128.0, +) diff --git a/mobzy-spawning/src/main/kotlin/com/mineinabyss/mobzy/spawning/SpawnDefinition.kt b/mobzy-spawning/src/main/kotlin/com/mineinabyss/mobzy/spawning/SpawnDefinition.kt index bf521694..e49ce276 100644 --- a/mobzy-spawning/src/main/kotlin/com/mineinabyss/mobzy/spawning/SpawnDefinition.kt +++ b/mobzy-spawning/src/main/kotlin/com/mineinabyss/mobzy/spawning/SpawnDefinition.kt @@ -144,13 +144,7 @@ fun GearyModule.spawnRequestListener() = listener(object : ListenerQuery() { val prefab = type.prefab.toEntity() val boundingBox = prefab.get() - // Original location always gets a spawn, we assume all conditions, including no suffocation are met there. - if (spawns > 0) { - location.spawnFromPrefab(prefab).onSuccess { spawnCount++ } - } - - // Other locations only need to meet the suffocation condition - repeat(spawns - 1) { + repeat(spawns) { val chosenLoc = if (spawnPos != SpawnPosition.AIR) getSpawnInRadius(location, radius) ?: location @@ -166,7 +160,7 @@ fun GearyModule.spawnRequestListener() = listener(object : ListenerQuery() { event.entity.set( Spawned( spawnCount, - prefab.collectPrefabs().intersect(mobzySpawning.spawnRegistry.spawnCategories.keys) + prefab.collectPrefabs() ) ) } @@ -185,7 +179,6 @@ fun ensureSuitableLocationOrNull( bb: BoundingBox, extraAttemptsUp: Int = mobzySpawning.config.retriesUpWhenInsideBlock ): Location? { - return chosenLoc val bb = bb.clone() // We shrink the box by a bit since overlap checks are strict inequalities val bbShrunk = bb.clone().apply { diff --git a/mobzy-spawning/src/main/kotlin/com/mineinabyss/mobzy/spawning/SpawnableChunks.kt b/mobzy-spawning/src/main/kotlin/com/mineinabyss/mobzy/spawning/SpawnableChunks.kt index 59cc498d..895fad40 100644 --- a/mobzy-spawning/src/main/kotlin/com/mineinabyss/mobzy/spawning/SpawnableChunks.kt +++ b/mobzy-spawning/src/main/kotlin/com/mineinabyss/mobzy/spawning/SpawnableChunks.kt @@ -18,6 +18,7 @@ object SpawnableChunks { } } return positions + .filter { (x, z) -> world.isChunkLoaded(x, z) } .map { (x, z) -> world.getChunkAt(x, z) } } } diff --git a/src/main/kotlin/com/mineinabyss/mobzy/MobzyPlugin.kt b/src/main/kotlin/com/mineinabyss/mobzy/MobzyPlugin.kt index d2556b78..e3cec23d 100644 --- a/src/main/kotlin/com/mineinabyss/mobzy/MobzyPlugin.kt +++ b/src/main/kotlin/com/mineinabyss/mobzy/MobzyPlugin.kt @@ -14,7 +14,8 @@ import com.mineinabyss.idofront.messaging.observeLogger import com.mineinabyss.idofront.plugin.Plugins import com.mineinabyss.idofront.plugin.actions import com.mineinabyss.idofront.plugin.listeners -import com.mineinabyss.mobzy.features.despawning.RemoveOnChunkUnloadSystem +import com.mineinabyss.mobzy.features.despawning.DespawnSystems +import com.mineinabyss.mobzy.features.despawning.removeWhenFarAway import com.mineinabyss.mobzy.features.displayname.ShowDisplayNameOnKillerSystem import com.mineinabyss.mobzy.features.prevent.breeding.PreventBreedingSystem import com.mineinabyss.mobzy.features.prevent.interaction.PreventInteractionSystem @@ -58,7 +59,7 @@ class MobzyPlugin : JavaPlugin() { listeners( PreventBreedingSystem(), - RemoveOnChunkUnloadSystem(), + DespawnSystems(), ShowDisplayNameOnKillerSystem(), TamingBukkitListener(), PreventRidingSystem(), @@ -67,6 +68,10 @@ class MobzyPlugin : JavaPlugin() { OverrideMobSoundsBukkitListener(), ) + geary.apply { + removeWhenFarAway() + } + geary { if (Plugins.isEnabled("ModelEngine")) { install(ModelEngineSupport)