From a43741b4f5c38eccb815c257891d69172937e212 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Fri, 28 May 2021 21:26:16 +0200 Subject: [PATCH] random ticks, campfire sounds --- .../data/mappings/blocks/types/Block.kt | 6 +++- .../mappings/blocks/types/CampfireBlock.kt | 32 +++++++++++++++---- .../de/bixilon/minosoft/data/world/World.kt | 22 +++++++++++++ .../gui/rendering/sound/AudioPlayer.kt | 6 ++-- .../gui/rendering/sound/SoundListener.kt | 5 ++- .../minosoft/gui/rendering/util/VecUtil.kt | 16 ++++++++++ .../network/connection/PlayConnection.kt | 32 +++++++++++-------- .../java/de/bixilon/minosoft/util/KUtil.kt | 4 +++ 8 files changed, 100 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/types/Block.kt b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/types/Block.kt index 0588fe99e..6b057b796 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/types/Block.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/types/Block.kt @@ -30,12 +30,14 @@ import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.gui.rendering.TintColorCalculator import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.BlockLikeRenderer import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit +import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer import de.bixilon.minosoft.protocol.network.connection.PlayConnection import glm_.vec3.Vec3i +import kotlin.random.Random open class Block( final override val resourceLocation: ResourceLocation, - mappings: Registries, + registries: Registries, data: JsonObject, ) : RegistryItem { open val explosionResistance: Float = data["explosion_resistance"]?.asFloat ?: 0.0f @@ -96,6 +98,8 @@ open class Block( return this.defaultState.withProperties(properties) } + open fun randomTick(connection: PlayConnection, particleRenderer: ParticleRenderer?, blockState: BlockState, blockPosition: Vec3i, random: Random) {} + companion object : ResourceLocationDeserializer { override fun deserialize(mappings: Registries?, resourceLocation: ResourceLocation, data: JsonObject): Block { check(mappings != null) { "Registries is null!" } diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/types/CampfireBlock.kt b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/types/CampfireBlock.kt index 9ffe561e5..69590a8b7 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/types/CampfireBlock.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/types/CampfireBlock.kt @@ -26,11 +26,16 @@ import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.CampfireSmokeParticle import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import de.bixilon.minosoft.util.KUtil.asResourceLocation +import de.bixilon.minosoft.util.KUtil.chance import glm_.vec3.Vec3 import glm_.vec3.Vec3i import kotlin.random.Random -open class CampfireBlock(resourceLocation: ResourceLocation, mappings: Registries, data: JsonObject) : Block(resourceLocation, mappings, data) { +open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registries, data: JsonObject) : Block(resourceLocation, registries, data) { + private val campfireCrackleSoundEvent = registries.soundEventRegistry[CAMPFIRE_CRACKLE_SOUND_RESOURCE_LOCATION]!! + private val cosySmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.CosySmokeParticleFactory]!! + private val signalSmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.SignalSmokeParticleFactory]!! private fun extinguish(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i) { val particleRenderer = connection.rendering?.renderWindow?.get(ParticleRenderer) ?: return @@ -48,19 +53,30 @@ open class CampfireBlock(resourceLocation: ResourceLocation, mappings: Registrie ) val isSignal = blockState.properties[BlockProperties.CAMPFIRE_SIGNAL_FIRE] == true - val data = connection.registries.particleTypeRegistry[if (isSignal) { - CampfireSmokeParticle.SignalSmokeParticleFactory + val particleType = if (isSignal) { + signalSmokeParticle } else { - CampfireSmokeParticle.CosySmokeParticleFactory - }]!! + cosySmokeParticle + } - particleRenderer.add(CampfireSmokeParticle(connection, particleRenderer, position, Vec3(0.0f, 0.07f, 0.0f), data.simple(), isSignal)) + particleRenderer.add(CampfireSmokeParticle(connection, particleRenderer, position, Vec3(0.0f, 0.07f, 0.0f), particleType.simple(), isSignal)) if (extinguished) { // ToDo: Spawn smoke particles } } + override fun randomTick(connection: PlayConnection, particleRenderer: ParticleRenderer?, blockState: BlockState, blockPosition: Vec3i, random: Random) { + particleRenderer ?: return + if (blockState.properties[BlockProperties.LIT] != true) { + return + } + if (random.chance(10)) { + connection.rendering?.audioPlayer?.playSoundEvent(campfireCrackleSoundEvent, blockPosition + Vec3(0.5f), 0.5f + random.nextFloat(), 0.6f + random.nextFloat() * 0.7f) + } + // ToDo: Spawn Lava particles + } + override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages { if (itemStack?.item !is ShovelItem || blockState.properties[BlockProperties.LIT] != true) { return super.onUse(connection, blockState, blockPosition, raycastHit, hands, itemStack) @@ -69,4 +85,8 @@ open class CampfireBlock(resourceLocation: ResourceLocation, mappings: Registrie extinguish(connection, blockState, blockPosition) return BlockUsages.SUCCESS } + + companion object { + private val CAMPFIRE_CRACKLE_SOUND_RESOURCE_LOCATION = "minecraft:block.campfire.crackle".asResourceLocation() + } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/World.kt b/src/main/java/de/bixilon/minosoft/data/world/World.kt index d45d2a2dd..9b0693624 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/World.kt @@ -21,9 +21,13 @@ import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker import de.bixilon.minosoft.data.world.biome.accessor.BiomeAccessor import de.bixilon.minosoft.data.world.biome.accessor.NullBiomeAccessor import de.bixilon.minosoft.data.world.light.WorldLightAccessor +import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer +import de.bixilon.minosoft.gui.rendering.util.VecUtil.blockPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition +import de.bixilon.minosoft.gui.rendering.util.VecUtil.minus +import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight import de.bixilon.minosoft.modding.event.EventInitiators import de.bixilon.minosoft.modding.event.events.BlockSetEvent @@ -33,6 +37,7 @@ import de.bixilon.minosoft.util.KUtil.synchronizedMapOf import de.bixilon.minosoft.util.KUtil.toSynchronizedMap import glm_.vec2.Vec2i import glm_.vec3.Vec3i +import kotlin.random.Random /** * Collection of chunks and more @@ -51,6 +56,7 @@ class World( var biomeAccessor: BiomeAccessor = NullBiomeAccessor var time = 0L var age = 0L + private val random = Random operator fun get(blockPosition: Vec3i): BlockState? { return chunks[blockPosition.chunkPosition]?.get(blockPosition.inChunkPosition) @@ -162,6 +168,22 @@ class World( } } + fun randomTick() { + val particleRenderer = connection.rendering?.renderWindow?.get(ParticleRenderer) + for (i in 0 until 667) { + randomTick(16, particleRenderer) + randomTick(32, particleRenderer) + } + } + + private fun randomTick(radius: Int, particleRenderer: ParticleRenderer?) { + val blockPosition = connection.player.entity.position.blockPosition + { random.nextInt(radius) } - { random.nextInt(radius) } + + val blockState = this[blockPosition] ?: return + + blockState.block.randomTick(connection, particleRenderer, blockState, blockPosition, random) + } + fun getBlocks(start: Vec3i, end: Vec3i): Map { val blocks: MutableMap = mutableMapOf() 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 8e9ba4af1..85e0165d2 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 @@ -104,6 +104,8 @@ class AudioPlayer( listener = SoundListener() + listener.masterVolume = Minosoft.config.config.game.sound.masterVolume + connection.registerEvent(CallbackEventInvoker.of { queue += { listener.position = it.newPosition @@ -176,13 +178,13 @@ class AudioPlayer( } source.sound = sound source.pitch = pitch * sound.pitch - source.gain = volume * sound.volume * Minosoft.config.config.game.sound.masterVolume + source.gain = volume * sound.volume source.play() } } fun startLoop() { - while (connection.connectionState != ConnectionStates.DISCONNECTING) { + while (connection.connectionState != ConnectionStates.DISCONNECTING) { // ToDo: Also kill when disconnected queue.work() Thread.sleep(1L) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundListener.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundListener.kt index 2fae1866b..b83b52baa 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundListener.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundListener.kt @@ -18,7 +18,6 @@ import glm_.vec3.Vec3 import org.lwjgl.openal.AL10.* class SoundListener(position: Vec3 = Vec3.EMPTY) { - var position: Vec3 = position set(value) { alListener3f(AL_POSITION, value.x, value.y, value.z) @@ -31,6 +30,10 @@ class SoundListener(position: Vec3 = Vec3.EMPTY) { field = value } + var masterVolume: Float + get() = alGetListenerf(AL_MAX_GAIN) + set(value) = alListenerf(AL_MAX_GAIN, value) + fun setOrientation(look: Vec3, up: Vec3) { alListenerfv(AL_ORIENTATION, floatArrayOf(look.x, look.y, look.z, up.x, up.y, up.z)) } 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 cbe25717d..68c8892e5 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 @@ -93,6 +93,22 @@ object VecUtil { ) } + infix operator fun Vec3i.plus(lambda: () -> Int): Vec3i { + return Vec3i( + x = x + lambda(), + y = y + lambda(), + z = z + lambda(), + ) + } + + infix operator fun Vec3i.minus(lambda: () -> Int): Vec3i { + return Vec3i( + x = x - lambda(), + y = y - lambda(), + z = z - lambda(), + ) + } + infix operator fun Vec3.plusAssign(lambda: () -> Float) { this assign this + lambda } diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/PlayConnection.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/PlayConnection.kt index 23819560f..3192ecae4 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/PlayConnection.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/PlayConnection.kt @@ -78,9 +78,9 @@ class PlayConnection( lateinit var player: Player private set - lateinit var velocityHandlerTask: TimeWorkerTask - private var velocityHandlerLastExecutionTime: Long = 0L - lateinit var worldTickTask: TimeWorkerTask + private lateinit var entityTickTask: TimeWorkerTask + private lateinit var blockEntityTickTask: TimeWorkerTask + private lateinit var randomTickTask: TimeWorkerTask val collisionDetector = CollisionDetector(this) override var connectionState: ConnectionStates = ConnectionStates.DISCONNECTED @@ -124,8 +124,8 @@ class PlayConnection( if (CLI.getCurrentConnection() == null) { CLI.setCurrentConnection(this) } - velocityHandlerLastExecutionTime = System.currentTimeMillis() - velocityHandlerTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME / 5) { + var velocityHandlerLastExecutionTime = System.currentTimeMillis() + entityTickTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME / 5) { val currentTime = System.currentTimeMillis() val deltaTime = currentTime - velocityHandlerLastExecutionTime if (deltaTime > 0L) { @@ -136,12 +136,15 @@ class PlayConnection( } velocityHandlerLastExecutionTime = currentTime } - TimeWorker.addTask(velocityHandlerTask) + TimeWorker.addTask(entityTickTask) - worldTickTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) { + TimeWorker.addTask(TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) { world.realTick() - } - TimeWorker.addTask(worldTickTask) + }) + + TimeWorker.addTask(TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) { + world.randomTick() + }) registerEvent(CallbackEventInvoker.of { val additionalPrefix = when (it.position) { @@ -160,11 +163,14 @@ class PlayConnection( CLI.setCurrentConnection(null) Command.print("Disconnected from current connection!") } - if (this::velocityHandlerTask.isInitialized) { - TimeWorker.removeTask(velocityHandlerTask) + if (this::entityTickTask.isInitialized) { + TimeWorker.removeTask(entityTickTask) } - if (this::worldTickTask.isInitialized) { - TimeWorker.removeTask(worldTickTask) + if (this::blockEntityTickTask.isInitialized) { + TimeWorker.removeTask(blockEntityTickTask) + } + if (this::randomTickTask.isInitialized) { + TimeWorker.removeTask(randomTickTask) } } else -> { diff --git a/src/main/java/de/bixilon/minosoft/util/KUtil.kt b/src/main/java/de/bixilon/minosoft/util/KUtil.kt index 2017e8532..ddab143a9 100644 --- a/src/main/java/de/bixilon/minosoft/util/KUtil.kt +++ b/src/main/java/de/bixilon/minosoft/util/KUtil.kt @@ -126,4 +126,8 @@ object KUtil { */ val Number.millis: Int get() = this.toInt() * ProtocolDefinition.TICK_TIME + + fun Random.chance(intPercent: Int): Boolean { + return this.nextInt(100) < intPercent + } }