From 38993d28dabf0754132b2d2a36b250a050c8743a Mon Sep 17 00:00:00 2001 From: Bixilon Date: Sat, 27 Nov 2021 23:39:35 +0100 Subject: [PATCH] refactor audio system --- .../data/registries/blocks/BlockState.kt | 11 +- .../registries/blocks/types/CampfireBlock.kt | 5 +- .../data/registries/items/MusicDiscItem.kt | 7 +- .../data/registries/registries/Registries.kt | 5 +- .../registries/registry/Registry.kt | 1 + .../registry/ResourceLocationRegistry.kt | 81 +++++++++ .../data/registries/sounds/SoundEvent.kt | 35 ---- .../data/world/AbstractAudioPlayer.kt | 19 +++ .../de/bixilon/minosoft/data/world/World.kt | 23 +-- .../models/baked/WeightedBakedModel.kt | 4 +- .../gui/rendering/sound/AudioPlayer.kt | 156 +++++------------- .../gui/rendering/sound/SoundManager.kt | 55 ++++++ .../gui/rendering/sound/SoundSource.kt | 10 +- .../{sounds/SoundList.kt => SoundUtil.kt} | 27 +-- .../rendering/sound/sounds/OpenALBuffer.kt | 38 +++++ .../gui/rendering/sound/sounds/Sound.kt | 114 ++++++------- .../gui/rendering/sound/sounds/SoundData.kt | 80 +++++++++ .../gui/rendering/sound/sounds/SoundType.kt | 68 ++++++++ .../modding/event/events/PlaySoundEvent.kt | 4 +- .../packets/s2c/play/EntitySoundEventS2CP.kt | 5 +- .../packets/s2c/play/NamedSoundEventS2CP.kt | 4 +- .../packets/s2c/play/SoundEventS2CP.kt | 6 +- .../packets/s2c/play/StopSoundS2CP.kt | 9 +- 23 files changed, 487 insertions(+), 280 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/data/registries/registries/registry/ResourceLocationRegistry.kt delete mode 100644 src/main/java/de/bixilon/minosoft/data/registries/sounds/SoundEvent.kt create mode 100644 src/main/java/de/bixilon/minosoft/data/world/AbstractAudioPlayer.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundManager.kt rename src/main/java/de/bixilon/minosoft/gui/rendering/sound/{sounds/SoundList.kt => SoundUtil.kt} (64%) create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/OpenALBuffer.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundData.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundType.kt diff --git a/src/main/java/de/bixilon/minosoft/data/registries/blocks/BlockState.kt b/src/main/java/de/bixilon/minosoft/data/registries/blocks/BlockState.kt index b790db491..39ef5a233 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/blocks/BlockState.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/blocks/BlockState.kt @@ -18,7 +18,6 @@ import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties import de.bixilon.minosoft.data.registries.blocks.types.Block import de.bixilon.minosoft.data.registries.materials.Material import de.bixilon.minosoft.data.registries.registries.Registries -import de.bixilon.minosoft.data.registries.sounds.SoundEvent import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import de.bixilon.minosoft.util.KUtil.toBoolean import de.bixilon.minosoft.util.KUtil.toInt @@ -35,11 +34,11 @@ data class BlockState( val outlineShape: VoxelShape, val hardness: Float, val requiresTool: Boolean, - val breakSoundEvent: SoundEvent?, - val stepSoundEvent: SoundEvent?, - val placeSoundEvent: SoundEvent?, - val hitSoundEvent: SoundEvent?, - val fallSoundEvent: SoundEvent?, + val breakSoundEvent: ResourceLocation?, + val stepSoundEvent: ResourceLocation?, + val placeSoundEvent: ResourceLocation?, + val hitSoundEvent: ResourceLocation?, + val fallSoundEvent: ResourceLocation?, val soundEventVolume: Float = 1.0f, val soundEventPitch: Float = 1.0f, ) { diff --git a/src/main/java/de/bixilon/minosoft/data/registries/blocks/types/CampfireBlock.kt b/src/main/java/de/bixilon/minosoft/data/registries/blocks/types/CampfireBlock.kt index b163d6784..0c7db6aaa 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/blocks/types/CampfireBlock.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/blocks/types/CampfireBlock.kt @@ -40,7 +40,6 @@ import kotlin.random.Random open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map) : Block(resourceLocation, registries, data) { val lavaParticles = data["lava_particles"]?.toBoolean() ?: true - private val campfireCrackleSoundEvent = registries.soundEventRegistry[CAMPFIRE_CRACKLE_SOUND_RESOURCE_LOCATION]!! private val cosySmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.CosyFactory]!! private val signalSmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.SignalFactory]!! private val lavaParticle = registries.particleTypeRegistry[LavaParticle]!! @@ -82,7 +81,7 @@ open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registr return } if (random.chance(10)) { - connection.world.playSoundEvent(campfireCrackleSoundEvent, blockPosition + Vec3(0.5f), 0.5f + random.nextFloat(), 0.6f + random.nextFloat() * 0.7f) + connection.world.playSoundEvent(CAMPFIRE_CRACKLE_SOUND, blockPosition + Vec3(0.5f), 0.5f + random.nextFloat(), 0.6f + random.nextFloat() * 0.7f) } if (lavaParticles && random.chance(20)) { @@ -104,7 +103,7 @@ open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registr } companion object : BlockFactory { - private val CAMPFIRE_CRACKLE_SOUND_RESOURCE_LOCATION = "minecraft:block.campfire.crackle".toResourceLocation() + private val CAMPFIRE_CRACKLE_SOUND = "minecraft:block.campfire.crackle".toResourceLocation() override fun build(resourceLocation: ResourceLocation, registries: Registries, data: Map): CampfireBlock { return CampfireBlock(resourceLocation, registries, data) diff --git a/src/main/java/de/bixilon/minosoft/data/registries/items/MusicDiscItem.kt b/src/main/java/de/bixilon/minosoft/data/registries/items/MusicDiscItem.kt index 30519a136..1b151cb8f 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/items/MusicDiscItem.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/items/MusicDiscItem.kt @@ -15,7 +15,6 @@ package de.bixilon.minosoft.data.registries.items import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.registries.registries.Registries -import de.bixilon.minosoft.data.registries.sounds.SoundEvent import de.bixilon.minosoft.util.KUtil.nullCast open class MusicDiscItem( @@ -24,9 +23,5 @@ open class MusicDiscItem( data: Map, ) : Item(resourceLocation, registries, data) { val analogOutput = data["analog_output"].nullCast() ?: 0 - val sound: SoundEvent? = null - - init { - this::sound.inject(data["sound"]) - } + val sound: ResourceLocation? = registries.soundEventRegistry[data["sound"]] } diff --git a/src/main/java/de/bixilon/minosoft/data/registries/registries/Registries.kt b/src/main/java/de/bixilon/minosoft/data/registries/registries/Registries.kt index 7bc0742e6..e916e1049 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/registries/Registries.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/registries/Registries.kt @@ -40,7 +40,6 @@ import de.bixilon.minosoft.data.registries.other.containers.ContainerType import de.bixilon.minosoft.data.registries.other.game.event.GameEvent import de.bixilon.minosoft.data.registries.particle.ParticleType import de.bixilon.minosoft.data.registries.registries.registry.* -import de.bixilon.minosoft.data.registries.sounds.SoundEvent import de.bixilon.minosoft.data.registries.statistics.Statistic import de.bixilon.minosoft.data.registries.versions.Version import de.bixilon.minosoft.protocol.packets.c2s.play.EntityActionC2SP @@ -69,7 +68,7 @@ class Registries { val dimensionRegistry: Registry = Registry() val materialRegistry: Registry = Registry() val fluidRegistry: Registry = Registry() - val soundEventRegistry: Registry = Registry() + val soundEventRegistry: ResourceLocationRegistry = ResourceLocationRegistry() val villagerProfessionRegistry: Registry = Registry() @@ -159,7 +158,7 @@ class Registries { entityTypeRegistry.rawInitialize(pixlyzerData["entities"]?.compoundCast(), this, EntityType) motiveRegistry.rawInitialize(pixlyzerData["motives"]?.compoundCast(), this, Motive, version.isFlattened()) - soundEventRegistry.rawInitialize(pixlyzerData["sound_events"]?.compoundCast(), this, SoundEvent) + soundEventRegistry.rawInitialize(pixlyzerData["sound_events"]?.compoundCast()) particleTypeRegistry.rawInitialize(pixlyzerData["particles"]?.compoundCast(), this, ParticleType) materialRegistry.rawInitialize(pixlyzerData["materials"]?.compoundCast(), this, Material) enchantmentRegistry.rawInitialize(pixlyzerData["enchantments"]?.compoundCast(), this, Enchantment) diff --git a/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/Registry.kt b/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/Registry.kt index 8e6d00df3..17021990d 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/Registry.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/Registry.kt @@ -195,6 +195,7 @@ open class Registry( BITS_16, } + @Deprecated("TODO") override fun iterator(): Iterator { return resourceLocationMap.values.iterator() } diff --git a/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/ResourceLocationRegistry.kt b/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/ResourceLocationRegistry.kt new file mode 100644 index 000000000..f8c2d9f18 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/ResourceLocationRegistry.kt @@ -0,0 +1,81 @@ +package de.bixilon.minosoft.data.registries.registries.registry + +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.util.KUtil.toInt +import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap + +class ResourceLocationRegistry( + override var parent: AbstractRegistry? = null, +) : AbstractRegistry { + private var initialized = false + private val idValueMap: MutableMap = mutableMapOf() + private val valueIdMap: MutableMap = mutableMapOf() + + + override val size: Int + get() { + val value = idValueMap.size + parent?.let { + return value + it.size + } + return value + } + + override fun clear() { + idValueMap.clear() + valueIdMap.clear() + } + + override fun get(any: Any?): ResourceLocation? { + check(any is Int) { "Don't know how to get $any" } + return idValueMap[any] + } + + override fun get(id: Int): ResourceLocation? { + return idValueMap[id] + } + + override fun getId(value: ResourceLocation): Int { + return valueIdMap[value] ?: -1 + } + + fun initialize(data: Map?, alternative: ResourceLocationRegistry? = null): ResourceLocationRegistry { + check(!initialized) { "Already initialized" } + + if (data == null) { + if (alternative != null) { + parent = alternative + } + return this + } + + for ((resourceLocation, value) in data) { + val id: Int = when (value) { + is Number -> value.toInt() + is Map<*, *> -> value["id"].toInt() + else -> throw IllegalArgumentException("Don't know what $value is!") + } + idValueMap[id] = resourceLocation + valueIdMap[resourceLocation] = id + } + if (idValueMap.isEmpty()) { + parent = alternative + } + initialized = true + return this + } + + fun rawInitialize(data: Map?, alternative: ResourceLocationRegistry? = null): ResourceLocationRegistry { + return initialize(data?.toResourceLocationMap(), alternative) + } + + + override fun toString(): String { + return super.toString() + ": ${idValueMap.size}x" + } + + @Deprecated("TODO") + override fun iterator(): Iterator { + return idValueMap.values.iterator() + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/registries/sounds/SoundEvent.kt b/src/main/java/de/bixilon/minosoft/data/registries/sounds/SoundEvent.kt deleted file mode 100644 index baf4540b9..000000000 --- a/src/main/java/de/bixilon/minosoft/data/registries/sounds/SoundEvent.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2021 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ -package de.bixilon.minosoft.data.registries.sounds - -import de.bixilon.minosoft.data.registries.ResourceLocation -import de.bixilon.minosoft.data.registries.registries.Registries -import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem -import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationDeserializer - -data class SoundEvent( - override val resourceLocation: ResourceLocation, -) : RegistryItem() { - - override fun toString(): String { - return resourceLocation.toString() - } - - companion object : ResourceLocationDeserializer { - override fun deserialize(registries: Registries?, resourceLocation: ResourceLocation, data: Map): SoundEvent { - return SoundEvent( - resourceLocation = resourceLocation, - ) - } - } -} diff --git a/src/main/java/de/bixilon/minosoft/data/world/AbstractAudioPlayer.kt b/src/main/java/de/bixilon/minosoft/data/world/AbstractAudioPlayer.kt new file mode 100644 index 000000000..671a5fe0d --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/AbstractAudioPlayer.kt @@ -0,0 +1,19 @@ +package de.bixilon.minosoft.data.world + +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.gui.rendering.util.VecUtil.centerf +import glm_.vec3.Vec3 +import glm_.vec3.Vec3i + +interface AbstractAudioPlayer { + + fun playSoundEvent(sound: ResourceLocation, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { + playSoundEvent(sound, position?.centerf, volume, pitch) + } + + fun playSoundEvent(sound: ResourceLocation, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) + + fun stopSound(sound: ResourceLocation) + + // ToDo: Stop category +} 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 fa52871b9..0fb2b874c 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/World.kt @@ -20,12 +20,10 @@ import de.bixilon.minosoft.data.registries.biomes.Biome import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock import de.bixilon.minosoft.data.registries.dimension.DimensionProperties -import de.bixilon.minosoft.data.registries.sounds.SoundEvent import de.bixilon.minosoft.data.world.biome.accessor.BiomeAccessor import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer import de.bixilon.minosoft.gui.rendering.particle.types.Particle -import de.bixilon.minosoft.gui.rendering.sound.AudioPlayer 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 @@ -59,7 +57,7 @@ import kotlin.random.Random */ class World( val connection: PlayConnection, -) : BiomeAccessor { +) : BiomeAccessor, AbstractAudioPlayer { val lock = ReadWriteLock() var cacheBiomeAccessor: NoiseBiomeAccessor? = null val chunks: LockMap = lockMapOf() @@ -76,7 +74,7 @@ class World( var thunderGradient = 0.0f private val random = Random - var audioPlayer: AudioPlayer? = null + var audioPlayer: AbstractAudioPlayer? = null var particleRenderer: ParticleRenderer? = null operator fun get(blockPosition: Vec3i): BlockState? { @@ -188,20 +186,13 @@ class World( return ret.toMap() } - fun playSoundEvent(resourceLocation: ResourceLocation, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - audioPlayer?.playSoundEvent(resourceLocation, position, volume, pitch) + + override fun playSoundEvent(sound: ResourceLocation, position: Vec3?, volume: Float, pitch: Float) { + audioPlayer?.playSoundEvent(sound, position, volume, pitch) } - fun playSoundEvent(resourceLocation: ResourceLocation, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - audioPlayer?.playSoundEvent(resourceLocation, position, volume, pitch) - } - - fun playSoundEvent(soundEvent: SoundEvent, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - audioPlayer?.playSoundEvent(soundEvent, position, volume, pitch) - } - - fun playSoundEvent(soundEvent: SoundEvent, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - audioPlayer?.playSoundEvent(soundEvent, position, volume, pitch) + override fun stopSound(sound: ResourceLocation) { + audioPlayer?.stopSound(sound) } fun addParticle(particle: Particle) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt index 7b25d1eeb..650444a18 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt @@ -43,9 +43,7 @@ class WeightedBakedModel( } private fun getModel(random: Random): BakedBlockModel { - val totalWeight = abs(random.nextLong() % totalWeight) - - var weightLeft = totalWeight + var weightLeft = abs(random.nextLong() % totalWeight) for ((model, weight) in models) { weightLeft -= weight 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 d562b0db7..45662ae5f 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 @@ -13,35 +13,24 @@ package de.bixilon.minosoft.gui.rendering.sound -import com.google.gson.JsonArray import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.data.registries.ResourceLocation -import de.bixilon.minosoft.data.registries.sounds.SoundEvent +import de.bixilon.minosoft.data.world.AbstractAudioPlayer import de.bixilon.minosoft.gui.rendering.Rendering import de.bixilon.minosoft.gui.rendering.input.camera.Camera import de.bixilon.minosoft.gui.rendering.modding.events.CameraPositionChangeEvent 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.centerf import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection -import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.util.CountUpAndDownLatch -import de.bixilon.minosoft.util.KUtil.nullCast import de.bixilon.minosoft.util.KUtil.synchronizedListOf -import de.bixilon.minosoft.util.KUtil.toBoolean -import de.bixilon.minosoft.util.KUtil.toInt -import de.bixilon.minosoft.util.KUtil.toResourceLocation import de.bixilon.minosoft.util.KUtil.toSynchronizedList -import de.bixilon.minosoft.util.KUtil.unsafeCast import de.bixilon.minosoft.util.Queue import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogMessageType -import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast import glm_.vec3.Vec3 -import glm_.vec3.Vec3i import org.lwjgl.openal.AL import org.lwjgl.openal.ALC import org.lwjgl.openal.ALC10.* @@ -54,14 +43,13 @@ import java.nio.IntBuffer class AudioPlayer( val connection: PlayConnection, val rendering: Rendering, -) { - private val sounds: MutableMap = mutableMapOf() - +) : AbstractAudioPlayer { + private val soundManager = SoundManager(connection) var initialized = false private set - private var device = 0L - private var context = 0L + private var device = -1L + private var context = -1L private val queue = Queue() private lateinit var listener: SoundListener @@ -74,27 +62,12 @@ class AudioPlayer( get() = sources.size - private fun preloadSounds() { - Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Preloading sounds..." } - if (SoundConstants.DISABLE_PRELOADING) { - return - } - - for (soundList in sounds.values) { - for (sound in soundList.sounds) { - if (SoundConstants.PRELOAD_ALL_SOUNDS || sound.preload) { - sound.load(connection.assetsManager) - } - } - } - } - - fun init(latch: CountUpAndDownLatch) { Log.log(LogMessageType.AUDIO_LOADING, LogLevels.INFO) { "Loading OpenAL..." } - loadSounds() - preloadSounds() + soundManager.load() + Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Preloading sounds..." } + soundManager.preload() @@ -125,31 +98,33 @@ class AudioPlayer( Log.log(LogMessageType.AUDIO_LOADING, LogLevels.INFO) { "OpenAL loaded!" } - initialized = true connection.world.audioPlayer = this latch.dec() } - fun playSoundEvent(resourceLocation: ResourceLocation, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - 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) { - connection.registries.soundEventRegistry[resourceLocation]?.let { playSoundEvent(it, position, volume, pitch) } - } - - fun playSoundEvent(soundEvent: SoundEvent, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - playSoundEvent(soundEvent, position?.centerf, volume, pitch) - } - - fun playSoundEvent(soundEvent: SoundEvent, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { + override fun playSoundEvent(sound: ResourceLocation, position: Vec3?, volume: Float, pitch: Float) { if (!initialized) { return } - playSound(sounds[soundEvent]!!.getRandom(), position, volume, pitch) + playSound(soundManager[sound] ?: return, position, volume, pitch) } + override fun stopSound(sound: ResourceLocation) { + queue += { + for (source in sources) { + if (!source.isPlaying) { + continue + } + if (source.sound?.soundEvent != sound) { + continue + } + source.stop() + } + } + } + + @Synchronized private fun getAvailableSource(): SoundSource? { for (source in sources.toSynchronizedList()) { if (source.available) { @@ -169,11 +144,8 @@ class AudioPlayer( private fun playSound(sound: Sound, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { queue += add@{ sound.load(connection.assetsManager) - if (sound.loadFailed) { - return@add - } - val source = getAvailableSource() ?: let { - // ToDo: Queue sound for later (and check a certain delay to not make the game feel laggy) + val source = getAvailableSource() + if (source == null) { Log.log(LogMessageType.AUDIO_LOADING, LogLevels.WARN) { "Can not play sound: No source available: $sound" } return@add } @@ -191,20 +163,23 @@ class AudioPlayer( } } + private fun calculateAvailableSources() { + var availableSources = 0 + for (source in sources) { + if (source.available) { + availableSources++ + } + } + this.availableSources = availableSources + } + fun startLoop() { while (true) { if (connection.wasConnected || connection.error != null) { break } queue.work() - - var availableSources = 0 - for (source in sources) { - if (source.available) { - availableSources++ - } - } - this.availableSources = availableSources + calculateAvailableSources() Thread.sleep(1L) } @@ -214,11 +189,8 @@ class AudioPlayer( Log.log(LogMessageType.AUDIO_LOADING, LogLevels.INFO) { "Unloading OpenAL..." } Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Unloading sounds..." } - for (soundList in sounds.values) { - for (sound in soundList.sounds) { - sound.unload() - } - } + soundManager.unload() + Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Unloading sources..." } for (source in sources.toSynchronizedList()) { source.unload() @@ -229,53 +201,7 @@ class AudioPlayer( alcSetThreadContext(MemoryUtil.NULL) alcDestroyContext(context) alcCloseDevice(device) + Log.log(LogMessageType.AUDIO_LOADING, LogLevels.INFO) { "Unloaded OpenAL!" } } - - @Deprecated("Refactoring needed") - private fun loadSounds() { - Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Loading sounds.json" } - val data = connection.assetsManager.readJsonAsset(SOUNDS_INDEX_FILE) - - for ((soundEventResourceLocation, json) in data) { - check(json is Map<*, *>) - val soundEvent = connection.registries.soundEventRegistry[ResourceLocation(soundEventResourceLocation)]!! - - val sounds: MutableSet = mutableSetOf() - - fun String.getSoundLocation(): ResourceLocation { - return ResourceLocation(ProtocolDefinition.DEFAULT_NAMESPACE, "sounds/${this}".replace('.', '/') + ".ogg") // ToDo: Resource Location - } - - for (soundJson in json["sounds"]!!.listCast()!!) { - when (soundJson) { - is String -> { - sounds += Sound(soundJson.getSoundLocation()) - } - is Map<*, *> -> { - sounds += Sound( - path = soundJson["name"].unsafeCast().getSoundLocation(), - volume = soundJson["volume"]?.unsafeCast()?.toFloat() ?: 1.0f, - pitch = soundJson["pitch"]?.unsafeCast()?.toFloat() ?: 1.0f, - weight = soundJson["weight"]?.toInt() ?: 1, - stream = soundJson["stream"]?.toBoolean() ?: false, - attenuationDistance = soundJson["attenuation_distance"]?.toInt() ?: 16, - preload = soundJson["preload"]?.toBoolean() ?: false, - ) - } - is JsonArray -> TODO() - } - } - this.sounds[soundEvent] = SoundList( - soundEvent = soundEvent, - sounds = sounds.toSet(), - subTitle = json["subtitle"].nullCast()?.let { ResourceLocation(ProtocolDefinition.DEFAULT_NAMESPACE, it) }, - ) - } - } - - - companion object { - private val SOUNDS_INDEX_FILE = "minecraft:sounds.json".toResourceLocation() - } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundManager.kt new file mode 100644 index 000000000..d7540da7e --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundManager.kt @@ -0,0 +1,55 @@ +package de.bixilon.minosoft.gui.rendering.sound + +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.gui.rendering.sound.sounds.Sound +import de.bixilon.minosoft.gui.rendering.sound.sounds.SoundType +import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection +import de.bixilon.minosoft.util.KUtil.toResourceLocation +import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound +import java.util.* + +class SoundManager( + private val connection: PlayConnection, +) { + private val random = Random() + private val sounds: MutableMap = mutableMapOf() + + + fun load() { + val soundsIndex = connection.assetsManager.readJsonAsset(SOUNDS_INDEX_FILE) + + for ((name, data) in soundsIndex) { + val resourceLocation = name.toResourceLocation() + sounds[resourceLocation] = SoundType(resourceLocation, data.asCompound()) + } + } + + @Synchronized + fun unload() { + for (soundType in sounds.values) { + for (sound in soundType.sounds) { + sound.unload() + } + } + } + + @Synchronized + fun preload() { + for (soundType in sounds.values) { + for (sound in soundType.sounds) { + if (!sound.preload) { + continue + } + sound.load(connection.assetsManager) + } + } + } + + operator fun get(sound: ResourceLocation): Sound? { + return sounds[sound]?.getSound(random) + } + + companion object { + private val SOUNDS_INDEX_FILE = "minecraft:sounds.json".toResourceLocation() + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundSource.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundSource.kt index dde178fbb..34781635f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundSource.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundSource.kt @@ -61,11 +61,15 @@ class SoundSource { var sound: Sound? = null set(value) { stop() - if (value?.loaded != true || value.loadFailed) { + val buffer = value?.buffer + if (buffer == null) { field = null return } - alSourcei(source, AL_BUFFER, value.buffer) + if (buffer.unloaded) { + throw IllegalArgumentException("OpenAL buffer is not loaded: ${value.soundEvent}") + } + alSourcei(source, AL_BUFFER, buffer.buffer) field = value } @@ -73,7 +77,7 @@ class SoundSource { get() = alGetSourcei(source, AL_SOURCE_STATE) == AL_PLAYING val available: Boolean - get() = !isPlaying || System.currentTimeMillis() - playTime > (sound?.length ?: 0L) // ToDo: Allow pause + get() = !isPlaying || System.currentTimeMillis() - playTime > (sound?.data?.length ?: 0L) // ToDo: Allow pause fun play() { playTime = System.currentTimeMillis() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundList.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundUtil.kt similarity index 64% rename from src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundList.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundUtil.kt index f6148131e..9b33ffa53 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundList.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/SoundUtil.kt @@ -11,18 +11,25 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.gui.rendering.sound.sounds +package de.bixilon.minosoft.gui.rendering.sound import de.bixilon.minosoft.data.registries.ResourceLocation -import de.bixilon.minosoft.data.registries.sounds.SoundEvent +import de.bixilon.minosoft.util.KUtil.toResourceLocation -data class SoundList( - val soundEvent: SoundEvent, - val sounds: Set, - val subTitle: ResourceLocation?, -) { - fun getRandom(): Sound { - // ToDo: Support weight - return sounds.random() +object SoundUtil { + fun ResourceLocation.sound(): ResourceLocation { + var path = "" + + if (!this.path.startsWith("sounds/")) { + path += "sounds/" + } + path += this.path + + if (!path.contains(".")) { + // ending + path += ".ogg" + } + + return "$namespace:$path".toResourceLocation() } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/OpenALBuffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/OpenALBuffer.kt new file mode 100644 index 000000000..558a8779b --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/OpenALBuffer.kt @@ -0,0 +1,38 @@ +package de.bixilon.minosoft.gui.rendering.sound.sounds + +import org.lwjgl.openal.AL10.* +import org.lwjgl.system.MemoryUtil.memFree +import java.nio.ShortBuffer + +class OpenALBuffer( + val data: SoundData, +) { + val buffer: Int + private val pcm: ShortBuffer + var unloaded: Boolean = false + private set + + init { + val pcm = data.createPCM() + this.pcm = pcm + + this.buffer = alGenBuffers() + + alBufferData(buffer, data.format, pcm, data.sampleRate) + } + + @Synchronized + fun unload() { + if (unloaded) { + return + } + alDeleteBuffers(buffer) + memFree(pcm) + unloaded = true + } + + protected fun finalize() { + unload() + } + +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/Sound.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/Sound.kt index 3d56a580b..a4c3c6708 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/Sound.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/Sound.kt @@ -15,102 +15,80 @@ package de.bixilon.minosoft.gui.rendering.sound.sounds import de.bixilon.minosoft.data.assets.AssetsManager import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.gui.rendering.sound.SoundUtil.sound +import de.bixilon.minosoft.util.KUtil.toBoolean +import de.bixilon.minosoft.util.KUtil.toFloat +import de.bixilon.minosoft.util.KUtil.toInt +import de.bixilon.minosoft.util.KUtil.toResourceLocation import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogMessageType -import org.lwjgl.BufferUtils -import org.lwjgl.openal.AL10.* -import org.lwjgl.stb.STBVorbis.* -import org.lwjgl.stb.STBVorbisInfo -import org.lwjgl.system.MemoryUtil import java.io.FileNotFoundException -import java.nio.ByteBuffer data class Sound( + val soundEvent: ResourceLocation, val path: ResourceLocation, val volume: Float = 1.0f, val pitch: Float = 1.0f, val weight: Int = 1, - val stream: Boolean = false, // ToDo - val attenuationDistance: Int = 16, + val stream: Boolean = false, // ToDo: Implement + val attenuationDistance: Int = 16, // ToDo: Implement val preload: Boolean = false, - // ToDo: type ) { - var length: Long = -1L + var data: SoundData? = null private set - var loaded: Boolean = false + var buffer: OpenALBuffer? = null private set - var loadFailed: Boolean = false - private set - var channels: Int = -1 - private set - var sampleRate: Int = -1 - private set - var samplesLength: Int = -1 - private set - var sampleSeconds: Float = -1.0f - private set - var buffer = -1 - private set - - private var vorbisBuffer: ByteBuffer? = null @Synchronized fun load(assetsManager: AssetsManager) { - if (loaded || loadFailed) { + if (data != null) { return } Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Loading audio file: $path" } try { - val vorbisBuffer = assetsManager.readByteAsset(path) - this.vorbisBuffer = vorbisBuffer - - val error = BufferUtils.createIntBuffer(1) - val vorbis = stb_vorbis_open_memory(vorbisBuffer, error, null) - if (vorbis == MemoryUtil.NULL) { - throw IllegalStateException("Can not load vorbis: ${path}: ${error[0]}") - } - val info = stb_vorbis_get_info(vorbis, STBVorbisInfo.malloc()) - channels = info.channels() - val format = when (channels) { - 1 -> AL_FORMAT_MONO16 - 2 -> AL_FORMAT_STEREO16 - else -> error("Don't know vorbis channels: $channels") - } - sampleRate = info.sample_rate() - - samplesLength = stb_vorbis_stream_length_in_samples(vorbis) - sampleSeconds = stb_vorbis_stream_length_in_seconds(vorbis) - length = (sampleSeconds * 1000).toLong() - - - val pcm = BufferUtils.createShortBuffer(samplesLength) - - pcm.limit(stb_vorbis_get_samples_short_interleaved(vorbis, channels, pcm) * channels) - //ToDo: Somehow crashed?: MemoryUtil.memFree(vorbisBuffer) - - this.buffer = alGenBuffers() - - alBufferData(buffer, format, pcm, sampleRate) - loaded = true + val data = SoundData(assetsManager, this) + this.data = data + this.buffer = OpenALBuffer(data) } catch (exception: FileNotFoundException) { - loadFailed = true Log.log(LogMessageType.AUDIO_LOADING, LogLevels.WARN) { "Can not load sound: $path: $exception" } } } @Synchronized fun unload() { - if (!loaded) { - return + data?.unload() + buffer?.unload() + } + + protected fun finalize() { + unload() + } + + companion object { + + operator fun invoke(soundEvent: ResourceLocation, data: Any): Sound { + if (data is String) { + return Sound( + soundEvent = soundEvent, + path = data.toResourceLocation().sound(), + ) + } + + check(data is Map<*, *>) + + // ToDo: "type" attribute: event + + return Sound( + soundEvent = soundEvent, + path = data["name"].toResourceLocation(), + volume = data["volume"]?.toFloat() ?: 1.0f, + pitch = data["pitch"]?.toFloat() ?: 1.0f, + weight = data["weight"]?.toInt() ?: 1, + stream = data["stream"]?.toBoolean() ?: false, + attenuationDistance = data["attenuation_distance"]?.toInt() ?: 16, + preload = data["preload"]?.toBoolean() ?: false, + ) } - alDeleteBuffers(buffer) - vorbisBuffer?.let { MemoryUtil.memFree(it) } - buffer = -1 - channels = -1 - sampleRate = -1 - samplesLength = -1 - sampleSeconds = -1.0f - loaded = false } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundData.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundData.kt new file mode 100644 index 000000000..29bf67070 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundData.kt @@ -0,0 +1,80 @@ +package de.bixilon.minosoft.gui.rendering.sound.sounds + +import de.bixilon.minosoft.data.assets.AssetsManager +import org.lwjgl.BufferUtils +import org.lwjgl.openal.AL10.AL_FORMAT_MONO16 +import org.lwjgl.openal.AL10.AL_FORMAT_STEREO16 +import org.lwjgl.stb.STBVorbis.* +import org.lwjgl.stb.STBVorbisInfo +import org.lwjgl.system.MemoryUtil +import org.lwjgl.system.MemoryUtil.memFree +import java.nio.ByteBuffer +import java.nio.ShortBuffer + +class SoundData( + val vorbis: Long, + val format: Int, + val buffer: ByteBuffer, + val length: Long, + val channels: Int, + val sampleRate: Int, + val samplesLength: Int, + val sampleSeconds: Float, +) { + private var unloaded = false + + @Synchronized + fun unload() { + if (unloaded) { + return + } + memFree(buffer) + unloaded = true + } + + protected fun finalize() { + unload() + } + + fun createPCM(): ShortBuffer { + val pcm = BufferUtils.createShortBuffer(samplesLength) + pcm.limit(stb_vorbis_get_samples_short_interleaved(vorbis, channels, pcm) * channels) + return pcm + } + + companion object { + + operator fun invoke(assetsManager: AssetsManager, sound: Sound): SoundData { + val buffer = assetsManager.readByteAsset(sound.path) + + val error = BufferUtils.createIntBuffer(1) + val vorbis = stb_vorbis_open_memory(buffer, error, null) + if (vorbis == MemoryUtil.NULL) { + throw IllegalStateException("Can not load vorbis: ${sound.path}: ${error[0]}") + } + val info = stb_vorbis_get_info(vorbis, STBVorbisInfo.malloc()) + val channels = info.channels() + val format = when (channels) { + 1 -> AL_FORMAT_MONO16 + 2 -> AL_FORMAT_STEREO16 + else -> error("Don't know vorbis channels: $channels") + } + val sampleRate = info.sample_rate() + + val samplesLength = stb_vorbis_stream_length_in_samples(vorbis) + val sampleSeconds = stb_vorbis_stream_length_in_seconds(vorbis) + val length = (sampleSeconds * 1000).toLong() + + return SoundData( + vorbis = vorbis, + format = format, + buffer = buffer, + length = length, + channels = channels, + sampleRate = sampleRate, + samplesLength = samplesLength, + sampleSeconds = sampleSeconds + ) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundType.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundType.kt new file mode 100644 index 000000000..4eabc22ca --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/sounds/SoundType.kt @@ -0,0 +1,68 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.sound.sounds + +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.util.KUtil.asList +import de.bixilon.minosoft.util.KUtil.toResourceLocation +import java.util.* +import kotlin.math.abs + +data class SoundType( + val soundEvent: ResourceLocation, + val sounds: Set, + val subtitle: ResourceLocation?, +) { + val totalWeight: Int + + init { + var totalWeight = 0 + for (sound in sounds) { + totalWeight += sound.weight + } + + this.totalWeight = totalWeight + } + + fun getSound(random: Random): Sound { + var weightLeft = abs(random.nextLong() % totalWeight) + + for (sound in sounds) { + weightLeft -= sound.weight + if (weightLeft < 0) { + return sound + } + } + + throw IllegalStateException("Could not find sound: This should never happen!") + } + + companion object { + + operator fun invoke(soundEvent: ResourceLocation, data: Map): SoundType { + // ToDo: "replace" attribute + val subtitle = data["subtitle"]?.toResourceLocation() + val sounds: MutableSet = mutableSetOf() + + for (soundData in data["sounds"].asList()) { + sounds += Sound(soundEvent, soundData) + } + return SoundType( + soundEvent = soundEvent, + sounds = sounds, + subtitle = subtitle, + ) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/modding/event/events/PlaySoundEvent.kt b/src/main/java/de/bixilon/minosoft/modding/event/events/PlaySoundEvent.kt index b029026a1..ec9a268f3 100644 --- a/src/main/java/de/bixilon/minosoft/modding/event/events/PlaySoundEvent.kt +++ b/src/main/java/de/bixilon/minosoft/modding/event/events/PlaySoundEvent.kt @@ -14,7 +14,7 @@ package de.bixilon.minosoft.modding.event.events import de.bixilon.minosoft.data.SoundCategories -import de.bixilon.minosoft.data.registries.sounds.SoundEvent +import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.modding.event.EventInitiators import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection @@ -27,7 +27,7 @@ class PlaySoundEvent( initiator: EventInitiators, val category: SoundCategories?, position: Vec3, - val soundEvent: SoundEvent, + val soundEvent: ResourceLocation, val volume: Float, val pitch: Float, ) : PlayConnectionEvent(connection, initiator), CancelableEvent { diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/EntitySoundEventS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/EntitySoundEventS2CP.kt index be6f27e78..dc9440792 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/EntitySoundEventS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/EntitySoundEventS2CP.kt @@ -13,7 +13,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play import de.bixilon.minosoft.data.SoundCategories -import de.bixilon.minosoft.data.registries.sounds.SoundEvent +import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer import de.bixilon.minosoft.util.logging.Log @@ -21,7 +21,7 @@ import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogMessageType class EntitySoundEventS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { - val soundEvent: SoundEvent = buffer.connection.registries.soundEventRegistry[buffer.readVarInt()] + val soundEvent: ResourceLocation = buffer.connection.registries.soundEventRegistry[buffer.readVarInt()]!! val category: SoundCategories = SoundCategories[buffer.readVarInt()] val entityId: Int = buffer.readVarInt() val volume: Float = buffer.readFloat() @@ -30,5 +30,4 @@ class EntitySoundEventS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { override fun log() { Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Entity sound effect (soundEvent=$soundEvent, category=$category, entityId$entityId, volume=$volume, pitch=$pitch)" } } - } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/NamedSoundEventS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/NamedSoundEventS2CP.kt index fc5edefad..37dc2beb2 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/NamedSoundEventS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/NamedSoundEventS2CP.kt @@ -14,7 +14,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.data.SoundCategories -import de.bixilon.minosoft.data.registries.sounds.SoundEvent +import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.modding.event.events.PlaySoundEvent import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket @@ -27,7 +27,7 @@ import de.bixilon.minosoft.util.logging.LogMessageType import glm_.vec3.Vec3 class NamedSoundEventS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { - val soundEvent: SoundEvent? + val soundEvent: ResourceLocation? val volume: Float val pitch: Float lateinit var position: Vec3 diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/SoundEventS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/SoundEventS2CP.kt index 79f958468..9a4172bf9 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/SoundEventS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/SoundEventS2CP.kt @@ -14,7 +14,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.data.SoundCategories -import de.bixilon.minosoft.data.registries.sounds.SoundEvent +import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.modding.event.events.PlaySoundEvent import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket @@ -30,7 +30,7 @@ class SoundEventS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { var category: SoundCategories? = null private set val position: Vec3i - val soundEvent: SoundEvent + val soundEvent: ResourceLocation val volume: Float val pitch: Float @@ -39,7 +39,7 @@ class SoundEventS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { // category was moved to the top this.category = SoundCategories[buffer.readVarInt()] } - soundEvent = buffer.connection.registries.soundEventRegistry[buffer.readVarInt()] + soundEvent = buffer.connection.registries.soundEventRegistry[buffer.readVarInt()]!! if (buffer.versionId >= ProtocolVersions.V_17W15A && buffer.versionId < ProtocolVersions.V_17W18A) { buffer.readString() // parrot entity type } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/StopSoundS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/StopSoundS2CP.kt index 5903ccaf9..7bf289b2f 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/StopSoundS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/StopSoundS2CP.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play import de.bixilon.minosoft.data.SoundCategories import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer import de.bixilon.minosoft.protocol.protocol.ProtocolVersions @@ -21,7 +22,6 @@ import de.bixilon.minosoft.util.BitByte.isBitMask import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogMessageType -import java.util.* class StopSoundS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { val category: SoundCategories? @@ -31,7 +31,7 @@ class StopSoundS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { var category: SoundCategories? = null var sound: ResourceLocation? = null if (buffer.versionId < ProtocolVersions.V_17W45A) { // ToDo: these 2 values need to be switched in before 1.12.2 - category = SoundCategories.valueOf(buffer.readString().uppercase(Locale.getDefault())) + category = SoundCategories.valueOf(buffer.readString().uppercase()) sound = buffer.readResourceLocation() } else { val flags = buffer.readByte() @@ -46,6 +46,11 @@ class StopSoundS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { this.sound = sound } + override fun handle(connection: PlayConnection) { + sound?.let { connection.world.stopSound(it) } + // ToDo: Category + } + override fun log() { Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Stop sound (category=$category, sound=$sound)" } }