diff --git a/client/src/main/scala/hexacraft/client/ClientWorld.scala b/client/src/main/scala/hexacraft/client/ClientWorld.scala index 2e7f8910..624870dc 100644 --- a/client/src/main/scala/hexacraft/client/ClientWorld.scala +++ b/client/src/main/scala/hexacraft/client/ClientWorld.scala @@ -11,12 +11,9 @@ import hexacraft.world.coord.* import hexacraft.world.entity.{Entity, EntityFactory, EntityPhysicsSystem} import java.util.UUID -import java.util.concurrent.TimeUnit import scala.annotation.tailrec import scala.collection.mutable import scala.collection.mutable.ArrayBuffer -import scala.concurrent.{Await, Future} -import scala.concurrent.duration.Duration object ClientWorld { class WorldTickResult( @@ -27,8 +24,6 @@ object ClientWorld { class ClientWorld(val worldInfo: WorldInfo) extends BlockRepository with BlocksInWorld { given size: CylinderSize = worldInfo.worldSize - private val backgroundTasks: mutable.ArrayBuffer[Future[Unit]] = mutable.ArrayBuffer.empty - private val columns: mutable.LongMap[ChunkColumnTerrain] = mutable.LongMap.empty private val chunks: mutable.LongMap[Chunk] = mutable.LongMap.empty @@ -359,10 +354,6 @@ class ClientWorld(val worldInfo: WorldInfo) extends BlockRepository with BlocksI def unload(): Unit = { chunks.clear() columns.clear() - - for t <- backgroundTasks do { - Await.result(t, Duration(10, TimeUnit.SECONDS)) - } } private def onSetBlock(coords: BlockRelWorld, block: BlockState): Unit = { diff --git a/client/src/main/scala/hexacraft/client/GameClient.scala b/client/src/main/scala/hexacraft/client/GameClient.scala index 8fd9271c..9e19280d 100644 --- a/client/src/main/scala/hexacraft/client/GameClient.scala +++ b/client/src/main/scala/hexacraft/client/GameClient.scala @@ -18,7 +18,11 @@ import org.joml.{Matrix4f, Vector2f, Vector3d, Vector3f} import org.zeromq.* import java.util.UUID +import java.util.concurrent.TimeUnit import scala.collection.mutable +import scala.concurrent.{Await, Future} +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.duration.Duration import scala.util.Random object GameClient { @@ -490,12 +494,20 @@ class GameClient( .sum } + private var tickFut: Option[Future[Seq[Nbt]]] = None + def tick(ctx: TickContext): Unit = { + // Act on the server info requested last tick, and send a new request to be used in the next tick + val currentTickFut = tickFut + tickFut = Some(Future { + val packets = Seq(NetworkPacket.GetPlayerState, NetworkPacket.GetEvents, NetworkPacket.GetWorldLoadingEvents(5)) + socket.sendMultiplePacketsAndWait(packets) + }) + if currentTickFut.isEmpty then return // the first tick has no server data to act on + try { val Seq(playerNbt, worldEventsNbtPacket, worldLoadingEventsNbt) = - socket.sendMultiplePacketsAndWait( - Seq(NetworkPacket.GetPlayerState, NetworkPacket.GetEvents, NetworkPacket.GetWorldLoadingEvents(5)) - ) + Await.result(currentTickFut.get, Duration(1, TimeUnit.SECONDS)) val syncedPlayer = Player.fromNBT(player.id, playerNbt.asInstanceOf[Nbt.MapTag]) // println(syncedPlayer.position) diff --git a/client/src/main/scala/hexacraft/client/WorldRenderer.scala b/client/src/main/scala/hexacraft/client/WorldRenderer.scala index 7401c9ce..bf51132c 100644 --- a/client/src/main/scala/hexacraft/client/WorldRenderer.scala +++ b/client/src/main/scala/hexacraft/client/WorldRenderer.scala @@ -99,8 +99,8 @@ class WorldRenderer( } def tick(camera: Camera, renderDistance: Double, worldTickResult: WorldTickResult): Unit = { - // Step 1: Perform render updates using data calculated in the background since the previous frame - updateBlockData(futureRenderData.map((coords, fut) => (coords, Await.result(fut, Duration.Inf))).toSeq) + // Step 1: Collect render data calculated since the previous frame (used in step 3) + val blockDataToUpdate = futureRenderData.map((coords, fut) => (coords, Await.result(fut, Duration.Inf))).toSeq futureRenderData.clear() // Step 2: Start calculating render updates in the background @@ -139,6 +139,9 @@ class WorldRenderer( } } + // Step 3: Perform render updates using data calculated in the background since the previous frame + updateBlockData(blockDataToUpdate) + // performTerrainUpdates(camera) } diff --git a/main/src/test/scala/hexacraft/main/GameSceneTest.scala b/main/src/test/scala/hexacraft/main/GameSceneTest.scala index 22288a3b..18b55bf6 100644 --- a/main/src/test/scala/hexacraft/main/GameSceneTest.scala +++ b/main/src/test/scala/hexacraft/main/GameSceneTest.scala @@ -209,7 +209,8 @@ class GameSceneTest extends FunSuite { gameScene.tick(tickContext) Thread.sleep(20) gameScene.tick(tickContext) - Thread.sleep(2) + Thread.sleep(20) + gameScene.tick(tickContext) // start listening for audio events val audioTracker = Tracker.withStorage[AudioSystem.Event] diff --git a/server/src/main/scala/hexacraft/server/GameServer.scala b/server/src/main/scala/hexacraft/server/GameServer.scala index de0c0a1e..20764f05 100644 --- a/server/src/main/scala/hexacraft/server/GameServer.scala +++ b/server/src/main/scala/hexacraft/server/GameServer.scala @@ -368,7 +368,7 @@ class GameServer( } } } - println("Received login message from a new client") + // println("Received login message from a new client") return Some(Nbt.makeMap("success" -> Nbt.ByteTag(true))) } else { println("Received login message from a logged in client") diff --git a/server/src/main/scala/hexacraft/server/ServerWorld.scala b/server/src/main/scala/hexacraft/server/ServerWorld.scala index 8c8276f3..af58522d 100644 --- a/server/src/main/scala/hexacraft/server/ServerWorld.scala +++ b/server/src/main/scala/hexacraft/server/ServerWorld.scala @@ -345,8 +345,8 @@ class ServerWorld(worldProvider: WorldProvider, val worldInfo: WorldInfo) requestedLoads: Seq[ChunkRelWorld], requestedUnloads: Seq[ChunkRelWorld] ): (Seq[ChunkRelWorld], Seq[ChunkRelWorld]) = { - val chunksToLoadPerTick = 8 - val chunksToUnloadPerTick = 12 + val chunksToLoadPerTick = if ServerWorld.shouldChillChunkLoader then 1 else 4 + val chunksToUnloadPerTick = if ServerWorld.shouldChillChunkLoader then 2 else 6 var unloadsLeft = chunksToUnloadPerTick for coords <- requestedUnloads do {