diff --git a/client/src/main/scala/hexacraft/client/GameClient.scala b/client/src/main/scala/hexacraft/client/GameClient.scala index 3637e851..89720140 100644 --- a/client/src/main/scala/hexacraft/client/GameClient.scala +++ b/client/src/main/scala/hexacraft/client/GameClient.scala @@ -41,22 +41,13 @@ object GameClient { ): Result[(GameClient, Channel.Receiver[GameClient.Event]), String] = { val socket = GameClientSocket(serverIp, serverPort) - val loginResponse = socket.sendPacketAndWait(NetworkPacket.Login(playerId, "Some name")).asMap.get - val loginSuccessful = loginResponse.getBoolean("success", false) - if !loginSuccessful then { - val errorMessage = loginResponse.getString("error", "") - return Result.Err(s"failed to login: $errorMessage") + val (worldInfo, player) = fetchWorldInfo(socket, playerId) match { + case Result.Ok(value) => value + case Result.Err(message) => + socket.close() + return Result.Err(s"failed to connect to server: $message") } - val worldInfo = WorldInfo.fromNBT( - socket.sendPacketAndWait(NetworkPacket.GetWorldInfo).asInstanceOf[Nbt.MapTag], - null, - WorldSettings.none - ) - - val playerNbt = socket.sendPacketAndWait(NetworkPacket.GetPlayerState) - val player = Player.fromNBT(playerId, playerNbt.asInstanceOf[Nbt.MapTag]) - val blockSpecs = BlockSpecs.default val blockTextureMapping = loadBlockTextures(blockSpecs, blockLoader) val blockTextureIndices: Map[String, IndexedSeq[Int]] = @@ -133,6 +124,29 @@ object GameClient { Result.Ok((client, rx)) } + private def fetchWorldInfo(socket: GameClientSocket, playerId: UUID): Result[(WorldInfo, Player), String] = try { + val loginResponse = socket.sendPacketAndWait(NetworkPacket.Login(playerId, "Some name")).asMap.get + val loginSuccessful = loginResponse.getBoolean("success", false) + if !loginSuccessful then { + val errorMessage = loginResponse.getString("error", "") + return Result.Err(s"failed to login: $errorMessage") + } + + val worldInfo = WorldInfo.fromNBT( + socket.sendPacketAndWait(NetworkPacket.GetWorldInfo).asMap.get, + null, + WorldSettings.none + ) + + val playerNbt = socket.sendPacketAndWait(NetworkPacket.GetPlayerState) + val player = Player.fromNBT(playerId, playerNbt.asMap.get) + + Result.Ok((worldInfo, player)) + } catch { + case e: Exception => + Result.Err(e.getMessage) + } + private def calculateTextureColor(texture: PixelArray): Vector3f = { var r = 0L var g = 0L @@ -918,5 +932,9 @@ class GameClientSocket(serverIp: String, serverPort: Int) { context.synchronized { context.close() } + + if monitoringThread != null then { + monitoringThread.interrupt() + } } } diff --git a/main/src/main/scala/hexacraft/main/GameScene.scala b/main/src/main/scala/hexacraft/main/GameScene.scala index 04484e72..378e0be3 100644 --- a/main/src/main/scala/hexacraft/main/GameScene.scala +++ b/main/src/main/scala/hexacraft/main/GameScene.scala @@ -9,7 +9,6 @@ import hexacraft.main.GameScene.Event.{CursorCaptured, CursorReleased, GameQuit} import hexacraft.server.GameServer import hexacraft.util.{Channel, Result} import hexacraft.world.WorldProvider -import hexacraft.world.block.BlockSpec import java.util.UUID @@ -50,8 +49,12 @@ object GameScene { c.initialWindowSize, c.audioSystem ) match { - case Result.Ok(res) => res - case Result.Err(message) => return Result.Err(s"failed to start game: $message") + case Result.Ok(res) => res + case Result.Err(message) => + if server.isDefined then { + server.get.unload() + } + return Result.Err(s"failed to start game: $message") } clientEvents.onEvent { diff --git a/server/src/test/scala/hexacraft/world/ServerWorldTest.scala b/server/src/test/scala/hexacraft/world/ServerWorldTest.scala index f8aff7f8..7e2d95a8 100644 --- a/server/src/test/scala/hexacraft/world/ServerWorldTest.scala +++ b/server/src/test/scala/hexacraft/world/ServerWorldTest.scala @@ -127,6 +127,8 @@ class ServerWorldTest extends FunSuite { Thread.sleep(20) world.tick(Seq(camera), Seq(), Seq()) + assert(world.getChunk(ChunkRelWorld(0, 0, 0)).isDefined) + val entity = Entity( UUID.randomUUID(), "scorpion",