better timing for refresh of the character select screen; potential to stop moving vehicles from anothers's perspectives

This commit is contained in:
Fate-JH 2023-05-13 09:05:11 -04:00
parent 0d02d7b556
commit b4fbebb8d7
2 changed files with 77 additions and 33 deletions

View file

@ -1,24 +1,17 @@
// Copyright (c) 2019 PSForever
package net.psforever.actors.session
import java.util.concurrent.atomic.AtomicInteger
import akka.actor.Cancellable
import akka.actor.typed.scaladsl.{ActorContext, Behaviors, StashBuffer}
import akka.actor.typed.{ActorRef, Behavior, PostStop, SupervisorStrategy}
import net.psforever.objects.avatar.{ProgressDecoration, SpecialCarry}
import net.psforever.objects.avatar.scoring.{Death, EquipmentStat, KDAStat, Kill}
import net.psforever.objects.sourcing.SourceWithHealthEntry
import net.psforever.objects.vital.projectile.ProjectileReason
import net.psforever.objects.vital.{DamagingActivity, HealingActivity, SpawningActivity, Vitality}
import net.psforever.packet.game.objectcreate.BasicCharacterData
import net.psforever.types.ExperienceType
import java.util.concurrent.atomic.AtomicInteger
import org.joda.time.{LocalDateTime, Seconds}
import scala.collection.mutable
import scala.concurrent.{ExecutionContextExecutor, Future, Promise}
import scala.util.{Failure, Success}
import scala.concurrent.duration._
//
import net.psforever.objects._
import net.psforever.objects.avatar.{
Avatar,
BattleRank,
@ -29,25 +22,31 @@ import net.psforever.objects.avatar.{
Implant,
MemberLists,
PlayerControl,
Shortcut => AvatarShortcut
ProgressDecoration,
Shortcut => AvatarShortcut,
SpecialCarry
}
import net.psforever.objects.avatar.scoring.{Death, EquipmentStat, KDAStat, Kill}
import net.psforever.objects.definition._
import net.psforever.objects.definition.converter.CharacterSelectConverter
import net.psforever.objects.inventory.Container
import net.psforever.objects.equipment.{Equipment, EquipmentSlot}
import net.psforever.objects.inventory.InventoryItem
import net.psforever.objects.inventory.{Container, InventoryItem}
import net.psforever.objects.loadouts.{InfantryLoadout, Loadout, VehicleLoadout}
import net.psforever.objects._
import net.psforever.objects.locker.LockerContainer
import net.psforever.objects.sourcing.PlayerSource
import net.psforever.objects.vital.HealFromImplant
import net.psforever.packet.game.objectcreate.{ObjectClass, RibbonBars}
import net.psforever.objects.sourcing.{PlayerSource,SourceWithHealthEntry}
import net.psforever.objects.vital.projectile.ProjectileReason
import net.psforever.objects.vital.{DamagingActivity, HealFromImplant, HealingActivity, SpawningActivity, Vitality}
import net.psforever.packet.game.objectcreate.{BasicCharacterData, ObjectClass, RibbonBars}
import net.psforever.packet.game.{Friend => GameFriend, _}
import net.psforever.persistence
import net.psforever.services.Service
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import net.psforever.types.{
CharacterSex,
CharacterVoice,
Cosmetic,
ExoSuitType,
ExperienceType,
ImplantType,
LoadoutType,
MemberAction,
@ -57,11 +56,7 @@ import net.psforever.types.{
TransactionType
}
import net.psforever.util.Database._
import net.psforever.persistence
import net.psforever.util.{Config, Database, DefinitionUtil}
import net.psforever.services.Service
//import org.log4s.Logger
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
object AvatarActor {
def apply(sessionActor: ActorRef[SessionActor.Command]): Behavior[Command] =
@ -3009,7 +3004,7 @@ class AvatarActor(
case Success(_) =>
//create new character
actuallyCreateNewCharacter(account.id, account.name, name, sex, empire, head, voice)
sendAvatars(account)
.onComplete(_ => sendAvatars(account))
case Failure(e) =>
log.error(e)("db failure")
sessionActor ! SessionActor.SendResponse(ActionResultMessage.Fail(error = 3))
@ -3029,7 +3024,7 @@ class AvatarActor(
} else {
//reactivate character
reactivateCharacter(account.id, account.name, name)
sendAvatars(account)
.onComplete(_ => sendAvatars(account))
}
}
@ -3043,7 +3038,8 @@ class AvatarActor(
voice: CharacterVoice.Value,
bep: Long = Config.app.game.newAvatar.br.experience,
cep: Long = Config.app.game.newAvatar.cr.experience
): Unit = {
): Future[Boolean] = {
val output: Promise[Boolean] = Promise[Boolean]()
import ctx._
val result = for {
_ <- ctx.run(
@ -3064,26 +3060,40 @@ class AvatarActor(
case Success(_) =>
log.debug(s"AvatarActor: created character $name for account $accountName")
sessionActor ! SessionActor.SendResponse(ActionResultMessage.Pass)
output.success(true)
case Failure(e) =>
log.error(e)("db failure")
sessionActor ! SessionActor.SendResponse(ActionResultMessage.Fail(error = 3))
output.success(false)
}
output.future
}
private def reactivateCharacter(accountId: Int, accountName: String, characterName: String): Unit = {
private def reactivateCharacter(
accountId: Int,
accountName: String,
characterName: String
): Future[Boolean] = {
val output: Promise[Boolean] = Promise[Boolean]()
import ctx._
ctx.run(
query[persistence.Avatar]
.filter(a => a.accountId == lift(accountId))
.filter(a => a.name ilike lift(characterName))
.update(_.deleted -> lift(false))
).onComplete {
val result = for {
out <- ctx.run(
query[persistence.Avatar]
.filter(a => a.accountId == lift(accountId))
.filter(a => a.name ilike lift(characterName))
.update(_.deleted -> lift(false))
)
} yield out
result.onComplete {
case Success(_) =>
log.debug(s"AvatarActor: character belonging to $accountName with name $characterName reactivated")
sessionActor ! SessionActor.SendResponse(ActionResultMessage.Pass)
output.success(true)
case Failure(e) =>
log.error(e)("db failure")
sessionActor ! SessionActor.SendResponse(ActionResultMessage.Fail(error = 3))
output.success(false)
}
output.future
}
}

View file

@ -16,7 +16,7 @@ import net.psforever.packet.game.{ChatMsg, DelayedPathMountMsg, DismountVehicleM
import net.psforever.services.Service
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import net.psforever.types.{BailType, ChatMessageType, PlanetSideGUID}
import net.psforever.types.{BailType, ChatMessageType, PlanetSideGUID, Vector3}
class SessionMountHandlers(
val sessionData: SessionData,
@ -238,7 +238,7 @@ class SessionMountHandlers(
}")
sessionData.vehicles.ConditionalDriverVehicleControl(obj)
sessionData.unaccessContainer(obj)
DismountAction(tplayer, obj, seatNum)
DismountVehicleAction(tplayer, obj, seatNum)
case Mountable.CanDismount(obj: Vehicle, seat_num, _) =>
continent.VehicleEvents ! VehicleServiceMessage(
@ -289,6 +289,40 @@ class SessionMountHandlers(
)
}
/**
* Common activities/procedure when a player dismounts a valid mountable object.
* @param tplayer the player
* @param obj the mountable object
* @param seatNum the mount out of which which the player is disembarking
*/
def DismountVehicleAction(tplayer: Player, obj: PlanetSideGameObject with Mountable, seatNum: Int): Unit = {
DismountAction(tplayer, obj, seatNum)
//until vehicles maintain synchronized momentum without a driver
obj match {
case v: Vehicle
if seatNum == 0 && Vector3.MagnitudeSquared(v.Velocity.getOrElse(Vector3.Zero)) > 0f =>
v.Velocity = Vector3.Zero
continent.VehicleEvents ! VehicleServiceMessage(
continent.id,
VehicleAction.VehicleState(
tplayer.GUID,
v.GUID,
unk1 = 0,
v.Position,
v.Orientation,
vel = None,
v.Flying,
unk3 = 0,
unk4 = 0,
wheel_direction = 15,
unk5 = false,
unk6 = v.Cloaked
)
)
case _ => ()
}
}
/**
* Common activities/procedure when a player dismounts a valid mountable object.
* @param tplayer the player
@ -306,7 +340,7 @@ class SessionMountHandlers(
sendResponse(DismountVehicleMsg(playerGuid, bailType, wasKickedByDriver = false))
continent.VehicleEvents ! VehicleServiceMessage(
continent.id,
VehicleAction.DismountVehicle(playerGuid, bailType, unk2=false)
VehicleAction.DismountVehicle(playerGuid, bailType, unk2 = false)
)
}
}