ObjectCreateMessage Alterations, Class Object Adjustments (#243)

* power outage failure resulting in the destruction of the original ocm-fixes branch; the git branch refs were corrupted during commit, but the up-to-date changed files remained intact

* eliminating the need for CommonFieldData2 and CommonFieldData2WithPlacement

* in the middle of integrating CommonFieldData into DetailedLockerContainerData (but not standard LockerContainerData); added field for final boolean in WeaponData

* adding faction affinity to Equipment (to match functionality; not becuase I know what ends ...)

* in the middle of integrating CommonFieldData into DetailedCommandDetonaterData

* applying faction affinity to objects at time of terminal production (but to what ends?); required BoomerTrigger and AmmoBox to always report as NEUTRAL internally

* completed the transition from using the old class-based order terminal system to the page-based order terminal system; unused terminal classes have been eliminated

* more closely aligned TelepadDeployableData and InternalTelepadDeployableData

* modifying TelepadDeployableData make it generic and eliminate the need for InternalTelepadDeployableData after fixing a packet converter to utilize DroppedItemData

* modified Terminal operation to branch further outwards from Terminal.Request to the TerminalDefinition's Request method; modified tests to reflect update

* loosening up matrix terminal definition limitations

* modified ProximityTerminal to support a custom defintition class

* rendered the message passing system for Terminals general (Any) in the full scale so it can be specific in instance cases

* refactored and moved both EquipmentSlot and ExoSuitDefinition

* (re)load Favorites each time player (re)spawns
This commit is contained in:
Fate-JH 2019-03-03 08:23:30 -05:00 committed by GitHub
parent 5fc9e191fe
commit 337cfbe5d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
174 changed files with 6281 additions and 5477 deletions

View file

@ -17,7 +17,7 @@ import net.psforever.objects._
import net.psforever.objects.avatar.{Certification, DeployableToolbox}
import net.psforever.objects.ballistics._
import net.psforever.objects.ce._
import net.psforever.objects.definition.{ConstructionFireMode, DeployableDefinition, ObjectDefinition, ToolDefinition}
import net.psforever.objects.definition._
import net.psforever.objects.definition.converter.{CorpseConverter, DestroyedVehicleConverter}
import net.psforever.objects.equipment.{CItem, _}
import net.psforever.objects.loadouts._
@ -543,7 +543,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
val factionOnContinentChannel = s"${continent.Id}/${player.Faction}"
obj.Owner = None
obj.OwnerName = None
obj.Faction = PlanetSideEmpire.NEUTRAL
avatar.Deployables.Remove(obj)
UpdateDeployableUIElements(avatar.Deployables.UpdateUIElement(obj.Definition.Item))
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, continent))
@ -1332,20 +1331,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
MountingAction(tplayer, obj, seat_num)
sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, 1000L)) //health of mech
case Mountable.CanMount(obj : PlanetSideGameObject with WeaponTurret, seat_num) =>
obj.WeaponControlledFromSeat(seat_num) match {
case Some(weapon : Tool) =>
//update mounted weapon belonging to seat
weapon.AmmoSlots.foreach(slot => {
//update the magazine(s) in the weapon, specifically
val magazine = slot.Box
sendResponse(InventoryStateMessage(magazine.GUID, weapon.GUID, magazine.Capacity.toLong))
})
case _ => ; //no weapons to update
}
sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health))
MountingAction(tplayer, obj, seat_num)
case Mountable.CanMount(obj : Vehicle, seat_num) =>
val obj_guid : PlanetSideGUID = obj.GUID
val player_guid : PlanetSideGUID = tplayer.GUID
@ -1384,15 +1369,26 @@ class WorldSessionActor extends Actor with MDCContextAware {
AccessContents(obj)
MountingAction(tplayer, obj, seat_num)
case Mountable.CanMount(obj : PlanetSideGameObject with WeaponTurret, seat_num) =>
obj.WeaponControlledFromSeat(seat_num) match {
case Some(weapon : Tool) =>
//update mounted weapon belonging to seat
weapon.AmmoSlots.foreach(slot => {
//update the magazine(s) in the weapon, specifically
val magazine = slot.Box
sendResponse(InventoryStateMessage(magazine.GUID, weapon.GUID, magazine.Capacity.toLong))
})
case _ => ; //no weapons to update
}
sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health))
MountingAction(tplayer, obj, seat_num)
case Mountable.CanMount(obj : Mountable, _) =>
log.warn(s"MountVehicleMsg: $obj is some generic mountable object and nothing will happen")
case Mountable.CanDismount(obj : ImplantTerminalMech, seat_num) =>
DismountAction(tplayer, obj, seat_num)
case Mountable.CanDismount(obj : PlanetSideGameObject with WeaponTurret, seat_num) =>
DismountAction(tplayer, obj, seat_num)
case Mountable.CanDismount(obj : Vehicle, seat_num) =>
val player_guid : PlanetSideGUID = tplayer.GUID
if(player_guid == player.GUID) {
@ -1405,6 +1401,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(player_guid, seat_num, true, obj.GUID))
}
case Mountable.CanDismount(obj : PlanetSideGameObject with WeaponTurret, seat_num) =>
DismountAction(tplayer, obj, seat_num)
case Mountable.CanDismount(obj : Mountable, _) =>
log.warn(s"DismountVehicleMsg: $obj is some generic mountable object and nothing will happen")
@ -1562,6 +1561,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
case Terminal.BuyEquipment(item) =>
tplayer.Fit(item) match {
case Some(index) =>
item.Faction = tplayer.Faction
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, true))
taskResolver ! PutEquipmentInSlot(tplayer, item, index)
case None =>
@ -1633,10 +1633,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
else {
afterHolsters
}.foreach(entry => {
entry.obj.Faction = tplayer.Faction
taskResolver ! PutEquipmentInSlot(tplayer, entry.obj, entry.start)
})
//put items into inventory
afterInventory.foreach(entry => {
entry.obj.Faction = tplayer.Faction
taskResolver ! PutEquipmentInSlot(tplayer, entry.obj, entry.start)
})
//drop stuff on ground
@ -1646,6 +1648,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
case Some(item) => List(InventoryItem(item, -1)) //add the item previously in free hand, if any
case None => Nil
}) ++ dropHolsters ++ dropInventory).foreach(entry => {
entry.obj.Faction = PlanetSideEmpire.NEUTRAL
continent.Ground ! Zone.Ground.DropItem(entry.obj, pos, orient)
})
lastTerminalOrderFulfillment = true
@ -1690,6 +1693,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
stow
}
}).foreach({ case InventoryItem(obj, index) =>
obj.Faction = tplayer.Faction
taskResolver ! stowEquipment(index, obj)
})
case None =>
@ -1826,8 +1830,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
case Terminal.BuyVehicle(vehicle, weapons, trunk) =>
continent.Map.TerminalToSpawnPad.get(msg.terminal_guid.guid) match {
case Some(pad_guid) =>
val toFaction = tplayer.Faction
val pad = continent.GUID(pad_guid).get.asInstanceOf[VehicleSpawnPad]
vehicle.Faction = tplayer.Faction
vehicle.Faction = toFaction
vehicle.Continent = continent.Id
vehicle.Position = pad.Position
vehicle.Orientation = pad.Orientation
@ -1837,6 +1842,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
val index = entry.start
vWeapons.get(index) match {
case Some(slot) =>
entry.obj.Faction = toFaction
slot.Equipment = None
slot.Equipment = entry.obj
case None =>
@ -1847,6 +1853,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
val vTrunk = vehicle.Trunk
vTrunk.Clear()
trunk.foreach(entry => {
entry.obj.Faction = toFaction
vTrunk += entry.start -> entry.obj
})
taskResolver ! RegisterNewVehicle(vehicle, pad)
@ -2419,7 +2426,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
//TODO if Medkit does not have shortcut, add to a free slot or write over slot 64
sendResponse(CreateShortcutMessage(guid, 1, 0, true, Shortcut.MEDKIT))
sendResponse(ChangeShortcutBankMessage(guid, 0))
//FavoritesMessage
//Favorites lists
val (inf, veh) = avatar.Loadouts.partition { case (index, _) => index < 10 }
inf.foreach {
case (index, loadout : InfantryLoadout) =>
sendResponse(FavoritesMessage(LoadoutType.Infantry, guid, index, loadout.label, loadout.exosuit.id + loadout.subtype))
}
veh.foreach {
case (index, loadout : VehicleLoadout) =>
sendResponse(FavoritesMessage(LoadoutType.Vehicle, guid, index - 10, loadout.label))
}
sendResponse(SetChatFilterMessage(ChatChannel.Local, false, ChatChannel.values.toList)) //TODO will not always be "on" like this
deadState = DeadState.Alive
sendResponse(AvatarDeadStateMessage(DeadState.Alive, 0, 0, tplayer.Position, player.Faction, true))
@ -2472,7 +2488,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
//TODO begin temp player character auto-loading; remove later
import net.psforever.objects.GlobalDefinitions._
import net.psforever.types.CertificationType._
val avatar = Avatar(s"TestCharacter$sessionId", PlanetSideEmpire.VS, CharacterGender.Female, 41, CharacterVoice.Voice1)
val faction = PlanetSideEmpire.VS
val avatar = Avatar(s"TestCharacter$sessionId", faction, CharacterGender.Female, 41, CharacterVoice.Voice1)
avatar.Certifications += StandardAssault
avatar.Certifications += MediumAssault
avatar.Certifications += StandardExoSuit
@ -2529,6 +2546,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
player.Slot(36).Equipment = AmmoBox(GlobalDefinitions.StandardPistolAmmo(player.Faction))
player.Slot(39).Equipment = SimpleItem(remote_electronics_kit)
player.Locker.Inventory += 0 -> SimpleItem(remote_electronics_kit)
player.Inventory.Items.foreach { _.obj.Faction = faction }
//TODO end temp player character auto-loading
self ! ListAccountCharacters
import scala.concurrent.ExecutionContext.Implicits.global
@ -3761,7 +3779,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.error("UseItem: expected seated vehicle, but found none")
}
}
else if(tdef.isInstanceOf[TeleportPadTerminalDefinition]) {
else if(tdef == GlobalDefinitions.teleportpad_terminal) {
//explicit request
terminal.Actor ! Terminal.Request(
player,
@ -5389,15 +5407,18 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
source match {
case obj : Vehicle =>
item2.Faction = PlanetSideEmpire.NEUTRAL
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.StowEquipment(player_guid, source_guid, index, item2))
case obj : Player =>
item2.Faction = obj.Faction
if(source.VisibleSlots.contains(index)) { //item is put in hands
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.EquipmentInHand(player_guid, source_guid, index, item2))
}
else if(obj.isBackpack) { //corpse being given item
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.StowEquipment(player_guid, source_guid, index, item2))
}
case _ => ;
case _ =>
item2.Faction = PlanetSideEmpire.NEUTRAL
}
case None => //item2 does not fit; drop on ground
@ -5437,15 +5458,19 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
destination match {
case obj : Vehicle =>
item.Faction = PlanetSideEmpire.NEUTRAL
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.StowEquipment(player_guid, destination_guid, dest, item))
case obj : Player =>
if(destination.VisibleSlots.contains(dest)) { //item is put in hands
item.Faction = obj.Faction
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.EquipmentInHand(player_guid, destination_guid, dest, item))
}
else if(obj.isBackpack) { //corpse being given item
item.Faction = PlanetSideEmpire.NEUTRAL
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.StowEquipment(player_guid, destination_guid, dest, item))
}
case _ => ;
case _ =>
item.Faction = PlanetSideEmpire.NEUTRAL
}
}
@ -5842,7 +5867,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
/**
* For a given facility structure, configure a client by dispatching the appropriate packets.
* Pay special attention to the details of `BuildingInfoUpdateMessage` when preparing this packet.
* Pay special attention to the details of `BuildingInfoUpdateMessage` when preparing this packet.<br>
* <br>
* 24 Janurtay 2019:<br>
* Manual `BIUM` construction to alleviate player login.
* @see `BuildingInfoUpdateMessage`
* @see `DensityLevelUpdateMessage`
* @param continentNumber the zone id
@ -5850,7 +5878,31 @@ class WorldSessionActor extends Actor with MDCContextAware {
* @param building the building object
*/
def initFacility(continentNumber : Int, buildingNumber : Int, building : Building) : Unit = {
building.Actor ! Building.SendMapUpdate(all_clients = false)
sendResponse(
BuildingInfoUpdateMessage(
continentNumber,
buildingNumber,
ntu_level = 8,
is_hacked = false,
empire_hack = PlanetSideEmpire.NEUTRAL,
hack_time_remaining = 0,
building.Faction,
unk1 = 0, //!! Field != 0 will cause malformed packet. See class def.
unk1x = None,
PlanetSideGeneratorState.Normal,
spawn_tubes_normal = true,
force_dome_active = false,
lattice_benefit = 0,
cavern_benefit = 0, //!! Field > 0 will cause malformed packet. See class def.
unk4 = Nil,
unk5 = 0,
unk6 = false,
unk7 = 8, //!! Field != 8 will cause malformed packet. See class def.
unk7x = None,
boost_spawn_pain = false,
boost_generator_pain = false
)
)
sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0)))
}
@ -6104,6 +6156,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
obj.Slot(33).Equipment = AmmoBox(bullet_9mm_AP)
obj.Slot(36).Equipment = AmmoBox(StandardPistolAmmo(faction))
obj.Slot(39).Equipment = SimpleItem(remote_electronics_kit)
obj.Inventory.Items.foreach { _.obj.Faction = faction }
obj
}
@ -6599,7 +6652,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
//TODO charId should reflect the player more properly
val killerCharId = math.abs(killer.Name.hashCode)
var victimCharId = math.abs(victim.Name.hashCode)
if(killerCharId == victimCharId && killer.Name != victim.Name) {
if(killerCharId == victimCharId && !killer.Name.equals(victim.Name)) {
//odds of hash collision in a populated zone should be close to odds of being struck by lightning
victimCharId = Int.MaxValue - victimCharId + 1
}
@ -6719,11 +6772,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
* Ownership causes icon to be drawn in yellow to the player (as opposed to a white icon)
* and that signifies a certain level of control over the deployable, at least the ability to quietly deconstruct it.
* Under normal death/respawn cycles while the player is in a given zone,
* the map icons for owned deployables ramin manipulable to that given user.
* They do not havwe to be redrawn to stay accurate.
* the map icons for owned deployables remain manipulable by that given user.
* They do not have to be redrawn to stay accurate.
* Upon leaving a zone, where the icons are erased, and returning back to the zone, where they are drawn again,
* the deployables that a player owned should be restored in terms of their map icon visibility.
* TThis control can not be recovered, however, until they are updated with the player's globally unique identifier.
* This control can not be recovered, however, until they are updated with the player's globally unique identifier.
* Since the player does not need to redraw his own deployable icons each time he respawns,
* but will not possess a valid GUID for that zone until he spawns in it at least once,
* this function swaps out with another after the first spawn in any given zone.
@ -7298,6 +7351,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
//TODO delay or reverse dropping item when player is falling down
item.Position = pos
item.Orientation = Vector3.z(orient.z)
item.Faction = PlanetSideEmpire.NEUTRAL
//dropped items rotate towards the user's standing direction
val exclusionId = player.Find(item) match {
//if the item is in our hands ...
@ -7324,6 +7378,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
def PutItemInHand(item : Equipment) : Boolean = {
player.Fit(item) match {
case Some(slotNum) =>
item.Faction = player.Faction
val item_guid = item.GUID
val player_guid = player.GUID
player.Slot(slotNum).Equipment = item
@ -7509,7 +7564,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
/**
* For a certain weapon that cna load ammunition, enforce that its magazine is empty.
* For a certain weapon that can load ammunition, enforce that its magazine is empty.
* Punctuate that emptiness with a ceasation of weapons fire and a dry fire sound effect.
* @param weapon_guid the weapon (GUID)
* @param tool the weapon (object)
@ -7590,6 +7645,32 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
}
def GetPlayerHackSpeed(obj: PlanetSideServerObject with Hackable): Float = {
val playerHackLevel = GetPlayerHackLevel()
val timeToHack = obj.HackDuration(playerHackLevel)
if(timeToHack == 0) {
log.warn(s"Player ${player.GUID} tried to hack an object ${obj.GUID} - ${obj.Definition.Name} that they don't have the correct hacking level for")
0f
}
// 250 ms per tick on the hacking progress bar
val ticks = (timeToHack * 1000) / 250
100f / ticks
}
def GetPlayerHackLevel(): Int = {
if(player.Certifications.contains(CertificationType.ExpertHacking) || player.Certifications.contains(CertificationType.ElectronicsExpert)) {
3
} else if(player.Certifications.contains(CertificationType.AdvancedHacking)) {
2
} else if (player.Certifications.contains(CertificationType.Hacking)) {
1
} else {
0
}
}
def failWithError(error : String) = {
log.error(error)
sendResponse(ConnectionClose())
@ -7667,13 +7748,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
/**
* `KeepAliveMessage` is a special `PlanetSideGamePacket` that is excluded from being bundled when it is sent to the network.<br>
* <br>
* The risk of the server getting caught in a state where the packets dispatched to the client are alwaysd bundled is posible.
* The risk of the server getting caught in a state where the packets dispatched to the client are always bundled is posible.
* Starting the bundling functionality but forgetting to transition into a state where it is deactivated can lead to this problem.
* No packets except for `KeepAliveMessage` will ever be sent until the ever-accumulating packets overflow.
* To avoid this state, whenever a `KeepAliveMessage` is sent, the packet collector empties its current contents to the network.
* @see `StartBundlingPackets`<br>
* `StopBundlingPackets`<br>
* `clientKeepAlive`
* @see `StartBundlingPackets`
* @see `StopBundlingPackets`
* @see `clientKeepAlive`
* @param cont a `KeepAliveMessage` packet
*/
def sendResponse(cont : KeepAliveMessage) : Unit = {
@ -7704,32 +7785,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.trace("WORLD SEND RAW: " + pkt)
sendResponse(RawPacket(pkt))
}
def GetPlayerHackSpeed(obj: PlanetSideServerObject with Hackable): Float = {
val playerHackLevel = GetPlayerHackLevel()
val timeToHack = obj.HackDuration(playerHackLevel)
if(timeToHack == 0) {
log.warn(s"Player ${player.GUID} tried to hack an object ${obj.GUID} - ${obj.Definition.Name} that they don't have the correct hacking level for")
0f
}
// 250 ms per tick on the hacking progress bar
val ticks = (timeToHack * 1000) / 250
100f / ticks
}
def GetPlayerHackLevel(): Int = {
if(player.Certifications.contains(CertificationType.ExpertHacking) || player.Certifications.contains(CertificationType.ElectronicsExpert)) {
3
} else if(player.Certifications.contains(CertificationType.AdvancedHacking)) {
2
} else if (player.Certifications.contains(CertificationType.Hacking)) {
1
} else {
0
}
}
}
object WorldSessionActor {

View file

@ -554,14 +554,18 @@ class PacketCodingActorKTest extends ActorTest {
41,
CharacterVoice.Voice1
),
false,
false,
true,
None,
false,
CommonFieldData(
PlanetSideEmpire.VS,
false,
false,
true,
None,
false,
None,
None,
PlanetSideGUID(0)
),
ExoSuitType.Standard,
None,
0,
0,
41605313L,
0,