mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 19:35:00 -04:00
refactor audio system
This commit is contained in:
parent
8f010c6b84
commit
38993d28da
@ -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,
|
||||
) {
|
||||
|
@ -40,7 +40,6 @@ import kotlin.random.Random
|
||||
open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>) : 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<CampfireBlock> {
|
||||
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<String, Any>): CampfireBlock {
|
||||
return CampfireBlock(resourceLocation, registries, data)
|
||||
|
@ -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<String, Any>,
|
||||
) : Item(resourceLocation, registries, data) {
|
||||
val analogOutput = data["analog_output"].nullCast<Item>() ?: 0
|
||||
val sound: SoundEvent? = null
|
||||
|
||||
init {
|
||||
this::sound.inject(data["sound"])
|
||||
}
|
||||
val sound: ResourceLocation? = registries.soundEventRegistry[data["sound"]]
|
||||
}
|
||||
|
@ -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<Dimension> = Registry()
|
||||
val materialRegistry: Registry<Material> = Registry()
|
||||
val fluidRegistry: Registry<Fluid> = Registry()
|
||||
val soundEventRegistry: Registry<SoundEvent> = Registry()
|
||||
val soundEventRegistry: ResourceLocationRegistry = ResourceLocationRegistry()
|
||||
|
||||
val villagerProfessionRegistry: Registry<VillagerProfession> = 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)
|
||||
|
@ -195,6 +195,7 @@ open class Registry<T : RegistryItem>(
|
||||
BITS_16,
|
||||
}
|
||||
|
||||
@Deprecated("TODO")
|
||||
override fun iterator(): Iterator<T> {
|
||||
return resourceLocationMap.values.iterator()
|
||||
}
|
||||
|
@ -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<ResourceLocation>? = null,
|
||||
) : AbstractRegistry<ResourceLocation> {
|
||||
private var initialized = false
|
||||
private val idValueMap: MutableMap<Int, ResourceLocation> = mutableMapOf()
|
||||
private val valueIdMap: MutableMap<ResourceLocation, Int> = 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<ResourceLocation, Any>?, 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<String, Any>?, 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<ResourceLocation> {
|
||||
return idValueMap.values.iterator()
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<SoundEvent> {
|
||||
override fun deserialize(registries: Registries?, resourceLocation: ResourceLocation, data: Map<String, Any>): SoundEvent {
|
||||
return SoundEvent(
|
||||
resourceLocation = resourceLocation,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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<Vec2i, Chunk> = 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) {
|
||||
|
@ -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
|
||||
|
@ -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<SoundEvent, SoundList> = 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<Sound> = mutableSetOf()
|
||||
|
||||
fun String.getSoundLocation(): ResourceLocation {
|
||||
return ResourceLocation(ProtocolDefinition.DEFAULT_NAMESPACE, "sounds/${this}".replace('.', '/') + ".ogg") // ToDo: Resource Location
|
||||
}
|
||||
|
||||
for (soundJson in json["sounds"]!!.listCast<Any>()!!) {
|
||||
when (soundJson) {
|
||||
is String -> {
|
||||
sounds += Sound(soundJson.getSoundLocation())
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
sounds += Sound(
|
||||
path = soundJson["name"].unsafeCast<String>().getSoundLocation(),
|
||||
volume = soundJson["volume"]?.unsafeCast<Double>()?.toFloat() ?: 1.0f,
|
||||
pitch = soundJson["pitch"]?.unsafeCast<Double>()?.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<String>()?.let { ResourceLocation(ProtocolDefinition.DEFAULT_NAMESPACE, it) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private val SOUNDS_INDEX_FILE = "minecraft:sounds.json".toResourceLocation()
|
||||
}
|
||||
}
|
||||
|
@ -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<ResourceLocation, SoundType> = 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()
|
||||
}
|
||||
}
|
@ -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()
|
||||
|
@ -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<Sound>,
|
||||
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()
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<Sound>,
|
||||
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<String, Any>): SoundType {
|
||||
// ToDo: "replace" attribute
|
||||
val subtitle = data["subtitle"]?.toResourceLocation()
|
||||
val sounds: MutableSet<Sound> = mutableSetOf()
|
||||
|
||||
for (soundData in data["sounds"].asList()) {
|
||||
sounds += Sound(soundEvent, soundData)
|
||||
}
|
||||
return SoundType(
|
||||
soundEvent = soundEvent,
|
||||
sounds = sounds,
|
||||
subtitle = subtitle,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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)" }
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)" }
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user