diff --git a/.gitignore b/.gitignore index 4c334d58..7a0607ad 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ out/ project/metals.sbt /docs .vscode +.bsp # User configs config/psforever.conf diff --git a/project/build.properties b/project/build.properties index cb6a5a8a..ed145bbb 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version = 1.3.13 +sbt.version = 1.4.5 diff --git a/src/main/scala/net/psforever/actors/net/MiddlewareActor.scala b/src/main/scala/net/psforever/actors/net/MiddlewareActor.scala index 3bb5a51d..0b793974 100644 --- a/src/main/scala/net/psforever/actors/net/MiddlewareActor.scala +++ b/src/main/scala/net/psforever/actors/net/MiddlewareActor.scala @@ -166,6 +166,7 @@ class MiddlewareActor( val queueProcessor: Cancellable = { context.system.scheduler.scheduleWithFixedDelay(10.milliseconds, 10.milliseconds)(() => { try { + if (outQueue.nonEmpty && outQueueBundled.isEmpty) { var length = 0L val bundle = outQueue diff --git a/src/main/scala/net/psforever/actors/session/AvatarActor.scala b/src/main/scala/net/psforever/actors/session/AvatarActor.scala index 67f74b08..8143bfc0 100644 --- a/src/main/scala/net/psforever/actors/session/AvatarActor.scala +++ b/src/main/scala/net/psforever/actors/session/AvatarActor.scala @@ -407,6 +407,10 @@ class AvatarActor( case ReplaceAvatar(newAvatar) => avatar = newAvatar + avatar.deployables.UpdateMaxCounts(avatar.certifications) + updateDeployableUIElements( + avatar.deployables.UpdateUI() + ) Behaviors.same case AddFirstTimeEvent(event) => @@ -461,15 +465,12 @@ class AvatarActor( sessionActor ! SessionActor.SendResponse( PlanetsideAttributeMessage(session.get.player.GUID, 24, certification.value) ) - avatar = avatar.copy(certifications = avatar.certifications.diff(replace) + certification) + context.self ! ReplaceAvatar( + avatar.copy(certifications = avatar.certifications.diff(replace) + certification) + ) sessionActor ! SessionActor.SendResponse( ItemTransactionResultMessage(terminalGuid, TransactionType.Sell, success = true) ) - - avatar.deployables.UpdateMaxCounts(avatar.certifications) - updateDeployableUIElements( - avatar.deployables.UpdateUI() - ) } } @@ -510,19 +511,15 @@ class AvatarActor( ItemTransactionResultMessage(terminalGuid, TransactionType.Sell, success = false) ) case Success(certs) => + context.self ! ReplaceAvatar(avatar.copy(certifications = avatar.certifications.diff(remove))) certs.foreach { cert => sessionActor ! SessionActor.SendResponse( PlanetsideAttributeMessage(session.get.player.GUID, 25, cert.value) ) } - avatar = avatar.copy(certifications = avatar.certifications.diff(remove)) sessionActor ! SessionActor.SendResponse( ItemTransactionResultMessage(terminalGuid, TransactionType.Sell, success = true) ) - avatar.deployables.UpdateMaxCounts(avatar.certifications) - updateDeployableUIElements( - avatar.deployables.UpdateUI() - ) } } Behaviors.same @@ -560,11 +557,7 @@ class AvatarActor( ) .onComplete { case Success(_) => - avatar = avatar.copy(certifications = certifications) - avatar.deployables.UpdateMaxCounts(avatar.certifications) - updateDeployableUIElements( - avatar.deployables.UpdateUI() - ) + context.self ! ReplaceAvatar(avatar.copy(certifications = certifications)) case Failure(exception) => log.error(exception)("db failure") } @@ -600,7 +593,9 @@ class AvatarActor( .run(query[persistence.Implant].insert(_.name -> lift(definition.Name), _.avatarId -> lift(avatar.id))) .onComplete { case Success(_) => - avatar = avatar.copy(implants = avatar.implants.updated(index, Some(Implant(definition)))) + context.self ! ReplaceAvatar( + avatar.copy(implants = avatar.implants.updated(index, Some(Implant(definition)))) + ) sessionActor ! SessionActor.SendResponse( AvatarImplantMessage( session.get.player.GUID, @@ -641,7 +636,7 @@ class AvatarActor( ) .onComplete { case Success(_) => - avatar = avatar.copy(implants = avatar.implants.updated(index, None)) + context.self ! ReplaceAvatar(avatar.copy(implants = avatar.implants.updated(index, None))) sessionActor ! SessionActor.SendResponse( AvatarImplantMessage(session.get.player.GUID, ImplantAction.Remove, index, 0) ) @@ -668,7 +663,7 @@ class AvatarActor( case Success(_) => loadLoadouts().onComplete { case Success(loadouts) => - avatar = avatar.copy(loadouts = loadouts) + context.self ! ReplaceAvatar(avatar.copy(loadouts = loadouts)) context.self ! RefreshLoadouts() case Failure(exception) => log.error(exception)("db failure") } @@ -694,7 +689,7 @@ class AvatarActor( ) .onComplete { case Success(_) => - avatar = avatar.copy(loadouts = avatar.loadouts.updated(number, None)) + context.self ! ReplaceAvatar(avatar.copy(loadouts = avatar.loadouts.updated(number, None))) sessionActor ! SessionActor.SendResponse(FavoritesMessage(loadoutType, player.GUID, number, "")) case Failure(exception) => log.error(exception)("db failure") diff --git a/src/main/scala/net/psforever/packet/PacketCoding.scala b/src/main/scala/net/psforever/packet/PacketCoding.scala index 09831325..e76d3541 100644 --- a/src/main/scala/net/psforever/packet/PacketCoding.scala +++ b/src/main/scala/net/psforever/packet/PacketCoding.scala @@ -249,7 +249,6 @@ object PacketCoding { macEncryptionKey: ByteVector, macDecryptionKey: ByteVector ) { - private val iv = BigInt(64, random) private val rc5Spec = new RC5ParameterSpec(0, 16, 32) private val rc5Encrypt = Cipher.getInstance("RC5/ECB/NoPadding") private val rc5Decrypt = Cipher.getInstance("RC5/ECB/NoPadding") @@ -276,7 +275,9 @@ object PacketCoding { val packetWithPadding = packetNoPadding ++ ByteVector.fill(paddingNeeded)(0x00) ++ paddingEncoded.toByteVector // raw packets plus MAC, padded to the nearest 8 byte boundary try { - Successful(ByteVector.view(rc5Encrypt.doFinal(packetWithPadding.toArray))) + rc5Encrypt.synchronized { + Successful(ByteVector.view(rc5Encrypt.doFinal(packetWithPadding.toArray))) + } } catch { case e: Throwable => Failure(Err(s"encrypt error: '${e.getMessage}' data: ${packetWithPadding.toHex}")) } @@ -285,7 +286,9 @@ object PacketCoding { def decrypt(data: ByteVector): Attempt[ByteVector] = { val payloadDecrypted = try { - ByteVector.view(rc5Decrypt.doFinal(data.toArray)) + rc5Decrypt.synchronized { + ByteVector.view(rc5Decrypt.doFinal(data.toArray)) + } } catch { case e: Throwable => return Failure(Err(e.getMessage)) } diff --git a/src/main/scala/net/psforever/util/Md5Mac.scala b/src/main/scala/net/psforever/util/Md5Mac.scala index 1f1141a2..f84a079c 100644 --- a/src/main/scala/net/psforever/util/Md5Mac.scala +++ b/src/main/scala/net/psforever/util/Md5Mac.scala @@ -57,7 +57,7 @@ class Md5Mac(val key: ByteVector) { assert(key.length == KEYLENGTH, s"key length must be ${KEYLENGTH}, not ${key.length}") doKey() - private def doKey() = { + private def doKey(): Unit = { val ek: ListBuffer[Byte] = ListBuffer.fill(48)(0) val data: ListBuffer[Byte] = ListBuffer.fill(128)(0) (0 until 16).foreach(j => {