random ticks, campfire sounds

This commit is contained in:
Bixilon 2021-05-28 21:26:16 +02:00 committed by Lukas
parent 50168dfbe2
commit a43741b4f5
8 changed files with 100 additions and 23 deletions

View File

@ -30,12 +30,14 @@ import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.TintColorCalculator
import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.BlockLikeRenderer
import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import glm_.vec3.Vec3i
import kotlin.random.Random
open class Block(
final override val resourceLocation: ResourceLocation,
mappings: Registries,
registries: Registries,
data: JsonObject,
) : RegistryItem {
open val explosionResistance: Float = data["explosion_resistance"]?.asFloat ?: 0.0f
@ -96,6 +98,8 @@ open class Block(
return this.defaultState.withProperties(properties)
}
open fun randomTick(connection: PlayConnection, particleRenderer: ParticleRenderer?, blockState: BlockState, blockPosition: Vec3i, random: Random) {}
companion object : ResourceLocationDeserializer<Block> {
override fun deserialize(mappings: Registries?, resourceLocation: ResourceLocation, data: JsonObject): Block {
check(mappings != null) { "Registries is null!" }

View File

@ -26,11 +26,16 @@ import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.CampfireSmokeParticle
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.KUtil.asResourceLocation
import de.bixilon.minosoft.util.KUtil.chance
import glm_.vec3.Vec3
import glm_.vec3.Vec3i
import kotlin.random.Random
open class CampfireBlock(resourceLocation: ResourceLocation, mappings: Registries, data: JsonObject) : Block(resourceLocation, mappings, data) {
open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registries, data: JsonObject) : Block(resourceLocation, registries, data) {
private val campfireCrackleSoundEvent = registries.soundEventRegistry[CAMPFIRE_CRACKLE_SOUND_RESOURCE_LOCATION]!!
private val cosySmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.CosySmokeParticleFactory]!!
private val signalSmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.SignalSmokeParticleFactory]!!
private fun extinguish(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i) {
val particleRenderer = connection.rendering?.renderWindow?.get(ParticleRenderer) ?: return
@ -48,19 +53,30 @@ open class CampfireBlock(resourceLocation: ResourceLocation, mappings: Registrie
)
val isSignal = blockState.properties[BlockProperties.CAMPFIRE_SIGNAL_FIRE] == true
val data = connection.registries.particleTypeRegistry[if (isSignal) {
CampfireSmokeParticle.SignalSmokeParticleFactory
val particleType = if (isSignal) {
signalSmokeParticle
} else {
CampfireSmokeParticle.CosySmokeParticleFactory
}]!!
cosySmokeParticle
}
particleRenderer.add(CampfireSmokeParticle(connection, particleRenderer, position, Vec3(0.0f, 0.07f, 0.0f), data.simple(), isSignal))
particleRenderer.add(CampfireSmokeParticle(connection, particleRenderer, position, Vec3(0.0f, 0.07f, 0.0f), particleType.simple(), isSignal))
if (extinguished) {
// ToDo: Spawn smoke particles
}
}
override fun randomTick(connection: PlayConnection, particleRenderer: ParticleRenderer?, blockState: BlockState, blockPosition: Vec3i, random: Random) {
particleRenderer ?: return
if (blockState.properties[BlockProperties.LIT] != true) {
return
}
if (random.chance(10)) {
connection.rendering?.audioPlayer?.playSoundEvent(campfireCrackleSoundEvent, blockPosition + Vec3(0.5f), 0.5f + random.nextFloat(), 0.6f + random.nextFloat() * 0.7f)
}
// ToDo: Spawn Lava particles
}
override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {
if (itemStack?.item !is ShovelItem || blockState.properties[BlockProperties.LIT] != true) {
return super.onUse(connection, blockState, blockPosition, raycastHit, hands, itemStack)
@ -69,4 +85,8 @@ open class CampfireBlock(resourceLocation: ResourceLocation, mappings: Registrie
extinguish(connection, blockState, blockPosition)
return BlockUsages.SUCCESS
}
companion object {
private val CAMPFIRE_CRACKLE_SOUND_RESOURCE_LOCATION = "minecraft:block.campfire.crackle".asResourceLocation()
}
}

View File

@ -21,9 +21,13 @@ import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker
import de.bixilon.minosoft.data.world.biome.accessor.BiomeAccessor
import de.bixilon.minosoft.data.world.biome.accessor.NullBiomeAccessor
import de.bixilon.minosoft.data.world.light.WorldLightAccessor
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.util.VecUtil.blockPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.minus
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
import de.bixilon.minosoft.modding.event.EventInitiators
import de.bixilon.minosoft.modding.event.events.BlockSetEvent
@ -33,6 +37,7 @@ import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
import glm_.vec2.Vec2i
import glm_.vec3.Vec3i
import kotlin.random.Random
/**
* Collection of chunks and more
@ -51,6 +56,7 @@ class World(
var biomeAccessor: BiomeAccessor = NullBiomeAccessor
var time = 0L
var age = 0L
private val random = Random
operator fun get(blockPosition: Vec3i): BlockState? {
return chunks[blockPosition.chunkPosition]?.get(blockPosition.inChunkPosition)
@ -162,6 +168,22 @@ class World(
}
}
fun randomTick() {
val particleRenderer = connection.rendering?.renderWindow?.get(ParticleRenderer)
for (i in 0 until 667) {
randomTick(16, particleRenderer)
randomTick(32, particleRenderer)
}
}
private fun randomTick(radius: Int, particleRenderer: ParticleRenderer?) {
val blockPosition = connection.player.entity.position.blockPosition + { random.nextInt(radius) } - { random.nextInt(radius) }
val blockState = this[blockPosition] ?: return
blockState.block.randomTick(connection, particleRenderer, blockState, blockPosition, random)
}
fun getBlocks(start: Vec3i, end: Vec3i): Map<Vec3i, BlockState> {
val blocks: MutableMap<Vec3i, BlockState> = mutableMapOf()

View File

@ -104,6 +104,8 @@ class AudioPlayer(
listener = SoundListener()
listener.masterVolume = Minosoft.config.config.game.sound.masterVolume
connection.registerEvent(CallbackEventInvoker.of<CameraPositionChangeEvent> {
queue += {
listener.position = it.newPosition
@ -176,13 +178,13 @@ class AudioPlayer(
}
source.sound = sound
source.pitch = pitch * sound.pitch
source.gain = volume * sound.volume * Minosoft.config.config.game.sound.masterVolume
source.gain = volume * sound.volume
source.play()
}
}
fun startLoop() {
while (connection.connectionState != ConnectionStates.DISCONNECTING) {
while (connection.connectionState != ConnectionStates.DISCONNECTING) { // ToDo: Also kill when disconnected
queue.work()
Thread.sleep(1L)
}

View File

@ -18,7 +18,6 @@ import glm_.vec3.Vec3
import org.lwjgl.openal.AL10.*
class SoundListener(position: Vec3 = Vec3.EMPTY) {
var position: Vec3 = position
set(value) {
alListener3f(AL_POSITION, value.x, value.y, value.z)
@ -31,6 +30,10 @@ class SoundListener(position: Vec3 = Vec3.EMPTY) {
field = value
}
var masterVolume: Float
get() = alGetListenerf(AL_MAX_GAIN)
set(value) = alListenerf(AL_MAX_GAIN, value)
fun setOrientation(look: Vec3, up: Vec3) {
alListenerfv(AL_ORIENTATION, floatArrayOf(look.x, look.y, look.z, up.x, up.y, up.z))
}

View File

@ -93,6 +93,22 @@ object VecUtil {
)
}
infix operator fun Vec3i.plus(lambda: () -> Int): Vec3i {
return Vec3i(
x = x + lambda(),
y = y + lambda(),
z = z + lambda(),
)
}
infix operator fun Vec3i.minus(lambda: () -> Int): Vec3i {
return Vec3i(
x = x - lambda(),
y = y - lambda(),
z = z - lambda(),
)
}
infix operator fun Vec3.plusAssign(lambda: () -> Float) {
this assign this + lambda
}

View File

@ -78,9 +78,9 @@ class PlayConnection(
lateinit var player: Player
private set
lateinit var velocityHandlerTask: TimeWorkerTask
private var velocityHandlerLastExecutionTime: Long = 0L
lateinit var worldTickTask: TimeWorkerTask
private lateinit var entityTickTask: TimeWorkerTask
private lateinit var blockEntityTickTask: TimeWorkerTask
private lateinit var randomTickTask: TimeWorkerTask
val collisionDetector = CollisionDetector(this)
override var connectionState: ConnectionStates = ConnectionStates.DISCONNECTED
@ -124,8 +124,8 @@ class PlayConnection(
if (CLI.getCurrentConnection() == null) {
CLI.setCurrentConnection(this)
}
velocityHandlerLastExecutionTime = System.currentTimeMillis()
velocityHandlerTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME / 5) {
var velocityHandlerLastExecutionTime = System.currentTimeMillis()
entityTickTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME / 5) {
val currentTime = System.currentTimeMillis()
val deltaTime = currentTime - velocityHandlerLastExecutionTime
if (deltaTime > 0L) {
@ -136,12 +136,15 @@ class PlayConnection(
}
velocityHandlerLastExecutionTime = currentTime
}
TimeWorker.addTask(velocityHandlerTask)
TimeWorker.addTask(entityTickTask)
worldTickTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) {
TimeWorker.addTask(TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) {
world.realTick()
}
TimeWorker.addTask(worldTickTask)
})
TimeWorker.addTask(TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) {
world.randomTick()
})
registerEvent(CallbackEventInvoker.of<ChatMessageReceiveEvent> {
val additionalPrefix = when (it.position) {
@ -160,11 +163,14 @@ class PlayConnection(
CLI.setCurrentConnection(null)
Command.print("Disconnected from current connection!")
}
if (this::velocityHandlerTask.isInitialized) {
TimeWorker.removeTask(velocityHandlerTask)
if (this::entityTickTask.isInitialized) {
TimeWorker.removeTask(entityTickTask)
}
if (this::worldTickTask.isInitialized) {
TimeWorker.removeTask(worldTickTask)
if (this::blockEntityTickTask.isInitialized) {
TimeWorker.removeTask(blockEntityTickTask)
}
if (this::randomTickTask.isInitialized) {
TimeWorker.removeTask(randomTickTask)
}
}
else -> {

View File

@ -126,4 +126,8 @@ object KUtil {
*/
val Number.millis: Int
get() = this.toInt() * ProtocolDefinition.TICK_TIME
fun Random.chance(intPercent: Int): Boolean {
return this.nextInt(100) < intPercent
}
}