diff --git a/src/main/java/de/bixilon/minosoft/data/entities/block/MobSpawnerBlockEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/block/MobSpawnerBlockEntity.kt index 909fc30c2..0e5a18333 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/block/MobSpawnerBlockEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/block/MobSpawnerBlockEntity.kt @@ -14,19 +14,54 @@ package de.bixilon.minosoft.data.entities.block import de.bixilon.minosoft.data.mappings.ResourceLocation +import de.bixilon.minosoft.data.mappings.blocks.BlockState +import de.bixilon.minosoft.data.world.WorldEntities +import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.fire.SmokeParticle +import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.slowing.FlameParticle +import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY +import de.bixilon.minosoft.gui.rendering.util.VecUtil.center +import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus +import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3d import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import de.bixilon.minosoft.util.KUtil.nullCast +import glm_.vec3.Vec3d +import glm_.vec3.Vec3i +import kotlin.random.Random class MobSpawnerBlockEntity(connection: PlayConnection) : BlockEntity(connection), BlockActionEntity { + private val smokeParticleType = connection.registries.particleTypeRegistry[SmokeParticle] + private val flameParticleType = connection.registries.particleTypeRegistry[FlameParticle] + private var requiredPlayerRange = 16 + private fun isPlayerInRange(blockPosition: Vec3i): Boolean { + return connection.world.entities.getInRadius(blockPosition.center, requiredPlayerRange.toDouble(), WorldEntities.CHECK_CLOSEST_PLAYER).isNotEmpty() + } + + private fun spawnParticles(blockPosition: Vec3i) { + if (!isPlayerInRange(blockPosition)) { + return + } + val particlePosition = blockPosition.toVec3d + { Random.nextDouble() } + smokeParticleType?.let { connection.world += SmokeParticle(connection, Vec3d(particlePosition), Vec3d.EMPTY, it.default()) } + flameParticleType?.let { connection.world += FlameParticle(connection, Vec3d(particlePosition), Vec3d.EMPTY, it.default()) } + } + override fun setBlockActionData(data1: Byte, data2: Byte) { // ToDo } override fun updateNBT(nbt: Map) { + nbt["MaxNearbyEntities"]?.let { + requiredPlayerRange = nbt["MaxNearbyEntities"]?.nullCast()?.toInt() ?: 16 + } // ToDo: {MaxNearbyEntities: 6s, RequiredPlayerRange: 16s, SpawnCount: 4s, x: -80, y: 4, SpawnData: {id: "minecraft:zombie"}, z: 212, id: "minecraft:mob_spawner", MaxSpawnDelay: 800s, SpawnRange: 4s, Delay: 0s, MinSpawnDelay: 200s} } + override fun realTick(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i) { + spawnParticles(blockPosition) + } + companion object : BlockEntityFactory { override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minecraft:mob_spawner") diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/AudioPlayer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/AudioPlayer.kt index 9ec95ae1a..50274bebf 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/AudioPlayer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/AudioPlayer.kt @@ -25,7 +25,7 @@ import de.bixilon.minosoft.gui.rendering.modding.events.CameraPositionChangeEven import de.bixilon.minosoft.gui.rendering.sound.sounds.Sound import de.bixilon.minosoft.gui.rendering.sound.sounds.SoundList import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY -import de.bixilon.minosoft.gui.rendering.util.VecUtil.center +import de.bixilon.minosoft.gui.rendering.util.VecUtil.centerf import de.bixilon.minosoft.modding.event.CallbackEventInvoker import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition @@ -123,7 +123,7 @@ class AudioPlayer( } fun playSoundEvent(resourceLocation: ResourceLocation, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - connection.registries.soundEventRegistry[resourceLocation]?.let { playSoundEvent(it, position?.center, volume, pitch) } + connection.registries.soundEventRegistry[resourceLocation]?.let { playSoundEvent(it, position?.centerf, volume, pitch) } } fun playSoundEvent(resourceLocation: ResourceLocation, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { @@ -131,7 +131,7 @@ class AudioPlayer( } fun playSoundEvent(soundEvent: SoundEvent, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - playSoundEvent(soundEvent, position?.center, volume, pitch) + playSoundEvent(soundEvent, position?.centerf, volume, pitch) } fun playSoundEvent(soundEvent: SoundEvent, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt index 7bd7b74ac..06d90f955 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt @@ -117,6 +117,14 @@ object VecUtil { ) } + infix fun Vec3i.plusDouble(double: () -> Double): Vec3d { + return Vec3d( + x = x + double(), + y = y + double(), + z = z + double(), + ) + } + infix operator fun Vec3i.minus(lambda: () -> Int): Vec3i { return Vec3i( x = x - lambda(), @@ -236,9 +244,12 @@ object VecUtil { val Vec3d.blockPosition: Vec3i get() = this.floor - val Vec3i.center: Vec3 + val Vec3i.centerf: Vec3 get() = Vec3(x + 0.5f, y + 0.5f, z + 0.5f) + val Vec3i.center: Vec3d + get() = Vec3d(x + 0.5, y + 0.5, z + 0.5) + fun Vec3i.Companion.of(chunkPosition: Vec2i, sectionHeight: Int, inChunkSectionPosition: Vec3i): Vec3i { return Vec3i( chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X + inChunkSectionPosition.x, diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/Connection.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/Connection.kt index afbbea816..19c471495 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/Connection.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/Connection.kt @@ -24,11 +24,12 @@ import de.bixilon.minosoft.protocol.packets.s2c.S2CPacket import de.bixilon.minosoft.protocol.protocol.ConnectionStates import de.bixilon.minosoft.protocol.protocol.PacketTypes.C2S import de.bixilon.minosoft.protocol.protocol.PacketTypes.S2C -import java.util.* +import de.bixilon.minosoft.util.KUtil.synchronizedListOf +import de.bixilon.minosoft.util.KUtil.toSynchronizedList abstract class Connection { val network = Network.getNetworkInstance(this) - protected val eventListeners = LinkedList() + protected val eventListeners: MutableList = synchronizedListOf() val connectionId = lastConnectionId++ abstract var connectionState: ConnectionStates var error: Throwable? = null @@ -56,7 +57,7 @@ abstract class Connection { } } - for (eventInvoker in eventListeners) { + for (eventInvoker in eventListeners.toSynchronizedList()) { if (!eventInvoker.eventType.isAssignableFrom(connectionEvent::class.java)) { continue }