Merge branch 'work/async-ticking'

This commit is contained in:
Bixilon 2022-05-01 16:02:34 +02:00
commit 9b1df43018
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
16 changed files with 242 additions and 86 deletions

View File

@ -474,7 +474,7 @@
<dependency>
<groupId>de.bixilon</groupId>
<artifactId>kutil</artifactId>
<version>1.10.2</version>
<version>1.10.4</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>

View File

@ -57,7 +57,7 @@ object BlockDestroyedHandler : WorldEventHandler {
for (z in 0 until max.z) {
val center = (Vec3d(x, y, z) + 0.5) / max
val particlePosition = center * delta + aabb.min
particleRenderer.add(BlockDustParticle(connection, particlePosition + position, particlePosition - 0.5, particleData))
particleRenderer += BlockDustParticle(connection, particlePosition + position, particlePosition - 0.5, particleData)
}
}
}

View File

@ -13,28 +13,30 @@
package de.bixilon.minosoft.data.world
import de.bixilon.kotlinglm.vec2.Vec2i
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.kotlinglm.vec3.Vec3i
import de.bixilon.kutil.collections.CollectionUtil.lockMapOf
import de.bixilon.kutil.collections.map.LockMap
import de.bixilon.kutil.concurrent.lock.simple.SimpleLock
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
import de.bixilon.kutil.latch.CountUpAndDownLatch
import de.bixilon.kutil.watcher.DataWatcher.Companion.watched
import de.bixilon.minosoft.data.Difficulties
import de.bixilon.minosoft.data.entities.block.BlockEntity
import de.bixilon.minosoft.data.registries.AABB
import de.bixilon.minosoft.data.registries.ResourceLocation
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.world.audio.AbstractAudioPlayer
import de.bixilon.minosoft.data.world.audio.WorldAudioPlayer
import de.bixilon.minosoft.data.world.biome.accessor.BiomeAccessor
import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor
import de.bixilon.minosoft.data.world.border.WorldBorder
import de.bixilon.minosoft.data.world.particle.AbstractParticleRenderer
import de.bixilon.minosoft.data.world.particle.WorldParticleRenderer
import de.bixilon.minosoft.data.world.time.WorldTime
import de.bixilon.minosoft.data.world.view.WorldView
import de.bixilon.minosoft.data.world.weather.WorldWeather
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.particle.types.Particle
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
@ -56,7 +58,7 @@ import kotlin.random.Random
*/
class World(
val connection: PlayConnection,
) : BiomeAccessor, AbstractAudioPlayer {
) : BiomeAccessor, WorldAudioPlayer, WorldParticleRenderer {
val lock = SimpleLock()
var cacheBiomeAccessor: NoiseBiomeAccessor? = null
val chunks: LockMap<Vec2i, Chunk> = lockMapOf()
@ -72,8 +74,8 @@ class World(
val border = WorldBorder()
private val random = Random
var audioPlayer: AbstractAudioPlayer? = null
var particleRenderer: ParticleRenderer? = null
override var audioPlayer: AbstractAudioPlayer? = null
override var particleRenderer: AbstractParticleRenderer? = null
operator fun get(blockPosition: Vec3i): BlockState? {
return chunks[blockPosition.chunkPosition]?.get(blockPosition.inChunkPosition)
@ -176,15 +178,18 @@ class World(
val simulationDistance = view.simulationDistance
val cameraPosition = connection.player.positionInfo.chunkPosition
chunks.lock.acquire()
val latch = CountUpAndDownLatch(chunks.size)
for ((chunkPosition, chunk) in chunks) {
// ToDo: Cache (improve performance)
if (!chunkPosition.isInViewDistance(simulationDistance, cameraPosition)) {
latch.dec()
continue
}
chunk.tick(connection, chunkPosition)
DefaultThreadPool += { chunk.tick(connection, chunkPosition); latch.dec() }
}
chunks.lock.release()
border.tick()
latch.await()
}
fun randomTick() {
@ -210,23 +215,6 @@ class World(
return ret.toMap()
}
override fun playSoundEvent(sound: ResourceLocation, position: Vec3?, volume: Float, pitch: Float) {
audioPlayer?.playSoundEvent(sound, position, volume, pitch)
}
override fun stopSound(sound: ResourceLocation) {
audioPlayer?.stopSound(sound)
}
fun addParticle(particle: Particle) {
particleRenderer?.add(particle)
}
operator fun plusAssign(particle: Particle?) {
addParticle(particle ?: return)
}
fun isSpaceEmpty(aabb: AABB, checkFluids: Boolean = false): Boolean {
for (position in aabb.blockPositions) {
val blockState = this[position] ?: continue

View File

@ -15,6 +15,8 @@ package de.bixilon.minosoft.data.world
import de.bixilon.kotlinglm.vec3.Vec3d
import de.bixilon.kutil.concurrent.lock.simple.SimpleLock
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
import de.bixilon.kutil.latch.CountUpAndDownLatch
import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.entities.entities.Entity
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
@ -179,6 +181,16 @@ class WorldEntities : Iterable<Entity> {
return false
}
fun tick() {
lock.acquire()
val latch = CountUpAndDownLatch(entities.size)
for (entity in entities) {
DefaultThreadPool += { entity.tick(); latch.dec() }
}
lock.release()
latch.await()
}
companion object {
val CHECK_CLOSEST_PLAYER: (Entity) -> Boolean = check@{
if (it !is PlayerEntity) {

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.world
package de.bixilon.minosoft.data.world.audio
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.kotlinglm.vec3.Vec3i
@ -21,16 +21,17 @@ import de.bixilon.minosoft.gui.rendering.util.VecUtil.centerf
interface AbstractAudioPlayer {
fun playSoundEvent(sound: ResourceLocation, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) {
playSoundEvent(sound, position?.centerf, volume, pitch)
playSound(sound, position?.centerf, volume, pitch)
}
fun playSoundEvent(sound: ResourceLocation, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f)
fun playSound(sound: ResourceLocation, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f)
fun play2DSound(sound: ResourceLocation, volume: Float = 1.0f, pitch: Float = 1.0f) {
playSoundEvent(sound, null as Vec3?, volume, pitch)
playSound(sound, null as Vec3?, volume, pitch)
}
fun stopSound(sound: ResourceLocation)
fun stopAllSounds()
// ToDo: Stop category
fun stopSound(sound: ResourceLocation)
}

View File

@ -0,0 +1,33 @@
/*
* Minosoft
* Copyright (C) 2020-2022 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.world.audio
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.minosoft.data.registries.ResourceLocation
interface WorldAudioPlayer : AbstractAudioPlayer {
val audioPlayer: AbstractAudioPlayer?
override fun playSound(sound: ResourceLocation, position: Vec3?, volume: Float, pitch: Float) {
audioPlayer?.playSound(sound, position, volume, pitch)
}
override fun stopAllSounds() {
audioPlayer?.stopAllSounds()
}
override fun stopSound(sound: ResourceLocation) {
audioPlayer?.stopSound(sound)
}
}

View File

@ -0,0 +1,27 @@
/*
* Minosoft
* Copyright (C) 2020-2022 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.world.particle
import de.bixilon.minosoft.gui.rendering.particle.types.Particle
interface AbstractParticleRenderer {
fun addParticle(particle: Particle)
operator fun plusAssign(particle: Particle?) {
addParticle(particle ?: return)
}
fun removeAllParticles()
}

View File

@ -0,0 +1,28 @@
/*
* Minosoft
* Copyright (C) 2020-2022 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.world.particle
import de.bixilon.minosoft.gui.rendering.particle.types.Particle
interface WorldParticleRenderer : AbstractParticleRenderer {
val particleRenderer: AbstractParticleRenderer?
override fun addParticle(particle: Particle) {
particleRenderer?.addParticle(particle)
}
override fun removeAllParticles() {
particleRenderer?.removeAllParticles()
}
}

View File

@ -23,6 +23,7 @@ import de.bixilon.kutil.time.TimeUtil
import de.bixilon.kutil.watcher.DataWatcher.Companion.observe
import de.bixilon.minosoft.config.profile.delegate.watcher.SimpleProfileDelegateWatcher.Companion.profileWatch
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.world.particle.AbstractParticleRenderer
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.RenderingStates
@ -37,6 +38,7 @@ import de.bixilon.minosoft.gui.rendering.system.base.phases.TransparentDrawable
import de.bixilon.minosoft.gui.rendering.system.base.shader.Shader
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnectionStates
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnectionStates.Companion.disconnected
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.chunk.ChunkUtil.isInViewDistance
@ -46,7 +48,7 @@ import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
class ParticleRenderer(
private val connection: PlayConnection,
override val renderWindow: RenderWindow,
) : Renderer, TransparentDrawable, TranslucentDrawable, SkipAll {
) : Renderer, TransparentDrawable, TranslucentDrawable, SkipAll, AbstractParticleRenderer {
override val renderSystem: RenderSystem = renderWindow.renderSystem
private val profile = connection.profiles.particle
private val transparentShader: Shader = renderSystem.createShader(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "particle"))
@ -146,7 +148,7 @@ class ParticleRenderer(
connection.world.particleRenderer = this
particleTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) {
if (renderWindow.renderingState == RenderingStates.PAUSED || renderWindow.renderingState == RenderingStates.STOPPED || !enabled) {
if (renderWindow.renderingState == RenderingStates.PAUSED || renderWindow.renderingState == RenderingStates.STOPPED || !enabled || connection.state != PlayConnectionStates.PLAYING) {
return@TimeWorkerTask
}
val cameraPosition = connection.player.positionInfo.chunkPosition
@ -191,7 +193,7 @@ class ParticleRenderer(
}
}
fun add(particle: Particle) {
override fun addParticle(particle: Particle) {
if (renderWindow.renderingState == RenderingStates.PAUSED || renderWindow.renderingState == RenderingStates.STOPPED || !enabled) {
return
}
@ -211,8 +213,6 @@ class ParticleRenderer(
particleQueueLock.unlock()
}
operator fun plusAssign(particle: Particle) = add(particle)
override fun prepareDraw() {
transparentMesh.unload()
translucentMesh.unload()
@ -258,6 +258,15 @@ class ParticleRenderer(
translucentMesh.draw()
}
override fun removeAllParticles() {
particlesLock.lock()
particles.clear()
particlesLock.unlock()
particleQueueLock.lock()
particleQueue.clear()
particleQueueLock.unlock()
}
companion object : RendererBuilder<ParticleRenderer> {
override val RESOURCE_LOCATION = ResourceLocation("minosoft:particle")

View File

@ -21,7 +21,7 @@ import de.bixilon.kutil.concurrent.queue.Queue
import de.bixilon.kutil.latch.CountUpAndDownLatch
import de.bixilon.minosoft.config.profile.delegate.watcher.SimpleProfileDelegateWatcher.Companion.profileWatch
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.world.AbstractAudioPlayer
import de.bixilon.minosoft.data.world.audio.AbstractAudioPlayer
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.camera.MatrixHandler
import de.bixilon.minosoft.gui.rendering.modding.events.CameraPositionChangeEvent
@ -122,7 +122,7 @@ class AudioPlayer(
latch.dec()
}
override fun playSoundEvent(sound: ResourceLocation, position: Vec3?, volume: Float, pitch: Float) {
override fun playSound(sound: ResourceLocation, position: Vec3?, volume: Float, pitch: Float) {
if (!initialized) {
return
}
@ -153,6 +153,17 @@ class AudioPlayer(
}
}
override fun stopAllSounds() {
queue += {
for (source in sources) {
if (!source.isPlaying) {
continue
}
source.stop()
}
}
}
@Synchronized
private fun getAvailableSource(): SoundSource? {
for (source in sources.toSynchronizedList()) {

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
* Copyright (C) 2020-2022 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.
*
@ -26,8 +26,8 @@ object DefaultAudioBehavior {
fun register(connection: PlayConnection) {
val world = connection.world
val invokers = listOf(
CallbackEventInvoker.of<PlaySoundEvent> { world.playSoundEvent(it.soundEvent, it.position, it.volume, it.pitch) },
CallbackEventInvoker.of<ExplosionEvent> { world.playSoundEvent(ENTITY_GENERIC_EXPLODE, it.position, 4.0f, (1.0f + (Random.nextFloat() - Random.nextFloat()) * 0.2f) * 0.7f) },
CallbackEventInvoker.of<PlaySoundEvent> { world.playSound(it.soundEvent, it.position, it.volume, it.pitch) },
CallbackEventInvoker.of<ExplosionEvent> { world.playSound(ENTITY_GENERIC_EXPLODE, it.position, 4.0f, (1.0f + (Random.nextFloat() - Random.nextFloat()) * 0.2f) * 0.7f) },
)
connection.registerEvents(*invokers.toTypedArray())

View File

@ -13,10 +13,12 @@
package de.bixilon.minosoft.protocol.network.connection.play
import de.bixilon.kotlinglm.vec3.Vec3d
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY
import de.bixilon.minosoft.modding.event.events.ChatMessageSendEvent
import de.bixilon.minosoft.modding.event.events.InternalMessageReceiveEvent
import de.bixilon.minosoft.protocol.packets.c2s.play.chat.ChatMessageC2SP
@ -52,4 +54,11 @@ class ConnectionUtil(
Log.log(LogMessageType.CHAT_OUT) { toSend }
connection.sendPacket(ChatMessageC2SP(toSend))
}
fun prepareSpawn() {
connection.world.chunks.clear()
connection.player.velocity = Vec3d.EMPTY
connection.world.audioPlayer?.stopAllSounds()
connection.world.particleRenderer?.removeAllParticles()
}
}

View File

@ -15,8 +15,6 @@ package de.bixilon.minosoft.protocol.network.connection.play
import de.bixilon.kutil.collections.CollectionUtil.synchronizedMapOf
import de.bixilon.kutil.collections.CollectionUtil.synchronizedSetOf
import de.bixilon.kutil.concurrent.time.TimeWorker
import de.bixilon.kutil.concurrent.time.TimeWorkerTask
import de.bixilon.kutil.latch.CountUpAndDownLatch
import de.bixilon.kutil.watcher.DataWatcher.Companion.observe
import de.bixilon.kutil.watcher.DataWatcher.Companion.watched
@ -48,9 +46,9 @@ import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.protocol.network.connection.Connection
import de.bixilon.minosoft.protocol.network.connection.play.clientsettings.ClientSettingsManager
import de.bixilon.minosoft.protocol.network.connection.play.tick.ConnectionTicker
import de.bixilon.minosoft.protocol.packets.c2s.handshaking.HandshakeC2SP
import de.bixilon.minosoft.protocol.packets.c2s.login.StartC2SP
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.protocol.protocol.ProtocolStates
import de.bixilon.minosoft.terminal.CLI
import de.bixilon.minosoft.terminal.RunConfiguration
@ -74,6 +72,7 @@ class PlayConnection(
val scoreboardManager = ScoreboardManager(this)
val bossbarManager = BossbarManager()
val util = ConnectionUtil(this)
val ticker = ConnectionTicker(this)
val serverInfo = ServerInfo()
lateinit var assetsManager: AssetsManager
@ -89,9 +88,6 @@ class PlayConnection(
lateinit var player: LocalPlayerEntity
private set
private lateinit var entityTickTask: TimeWorkerTask
private lateinit var worldTickTask: TimeWorkerTask
private lateinit var randomTickTask: TimeWorkerTask
val collisionDetector = CollisionDetector(this)
var retry = true
@ -136,15 +132,6 @@ class PlayConnection(
CLI.setCurrentConnection(null)
Command.print("Disconnected from current connection!")
}
if (this::entityTickTask.isInitialized) {
TimeWorker.removeTask(entityTickTask)
}
if (this::worldTickTask.isInitialized) {
TimeWorker.removeTask(worldTickTask)
}
if (this::randomTickTask.isInitialized) {
TimeWorker.removeTask(randomTickTask)
}
assetsManager.unload()
state = PlayConnectionStates.DISCONNECTED
ACTIVE_CONNECTIONS -= this
@ -164,24 +151,6 @@ class PlayConnection(
if (CLI.getCurrentConnection() == null) {
CLI.setCurrentConnection(this)
}
entityTickTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME / 5, maxDelayTime = ProtocolDefinition.TICK_TIME) {
world.entities.lock.acquire()
for (entity in world.entities) {
entity.tick()
}
world.entities.lock.release()
}
TimeWorker += entityTickTask
worldTickTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) {
world.tick()
}
TimeWorker += worldTickTask
randomTickTask = TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) {
world.randomTick()
}
TimeWorker += randomTickTask
registerEvent(CallbackEventInvoker.of<ChatMessageReceiveEvent> {
val additionalPrefix = when (it.position) {
@ -194,6 +163,7 @@ class PlayConnection(
}
}
}
ticker.init()
}
fun connect(latch: CountUpAndDownLatch = CountUpAndDownLatch(0)) {

View File

@ -0,0 +1,75 @@
/*
* Minosoft
* Copyright (C) 2020-2022 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.protocol.network.connection.play.tick
import de.bixilon.kutil.concurrent.lock.simple.SimpleLock
import de.bixilon.kutil.concurrent.time.TimeWorker
import de.bixilon.kutil.concurrent.time.TimeWorkerTask
import de.bixilon.kutil.watcher.DataWatcher.Companion.observe
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnectionStates
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
class ConnectionTicker(private val connection: PlayConnection) {
private val lock = SimpleLock()
private val tasks: MutableSet<TimeWorkerTask> = mutableSetOf()
fun init() {
connection::state.observe(this) {
if (it != PlayConnectionStates.PLAYING) {
unregister()
} else {
register()
}
}
}
private fun register() {
lock.lock()
_unregister()
tasks += TimeWorkerTask(INTERVAL, maxDelayTime = MAX_DELAY) {
connection.world.entities.tick()
}
tasks += TimeWorkerTask(INTERVAL, maxDelayTime = MAX_DELAY) {
connection.world.tick()
}
tasks += TimeWorkerTask(INTERVAL, maxDelayTime = MAX_DELAY) {
connection.world.randomTick()
}
for (task in tasks) {
TimeWorker += task
}
lock.unlock()
}
private fun _unregister() {
for (task in tasks) {
TimeWorker -= task
}
tasks.clear()
}
private fun unregister() {
lock.lock()
_unregister()
lock.unlock()
}
private companion object {
const val INTERVAL = ProtocolDefinition.TICK_TIME
const val MAX_DELAY = INTERVAL / 2
}
}

View File

@ -150,6 +150,7 @@ class InitializeS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
}
override fun handle(connection: PlayConnection) {
connection.util.prepareSpawn()
val playerEntity = connection.player
val previousGamemode = playerEntity.tabListItem.gamemode

View File

@ -12,13 +12,11 @@
*/
package de.bixilon.minosoft.protocol.packets.s2c.play
import de.bixilon.kotlinglm.vec3.Vec3d
import de.bixilon.kutil.json.JsonUtil.asJsonObject
import de.bixilon.minosoft.data.Difficulties
import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY
import de.bixilon.minosoft.modding.event.events.RespawnEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnectionStates
@ -92,16 +90,10 @@ class RespawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
}
override fun handle(connection: PlayConnection) {
// clear all chunks
connection.state = PlayConnectionStates.SPAWNING
connection.world.chunks.clear()
connection.world.dimension = dimension
connection.player.isSpawnConfirmed = false
connection.util.prepareSpawn()
connection.player.tabListItem.gamemode = gamemode
connection.player.velocity = Vec3d.EMPTY
// connection.world.view.serverViewDistance = 0
connection.world.dimension = dimension
connection.state = PlayConnectionStates.SPAWNING
connection.fireEvent(RespawnEvent(connection, this))
}