Hart (#723)
* initial OrbitalShuttleTimeMsg packet and tests; new objects to support HART shuttle transport system
* master was stale
* grouped scheduling for timing orbital shuttle activity
* door lock controls for HART shuttle lifecycle, and specifically for the doors that lead into the shuttle boarding hallway
* separation of the door from the door unlocking logic, which now has to be provided if performed by an outside source; a door that is locked either by bolt, HART routine, or other reason, can now be shut immediately; message when HART is not docked with a corresponding entry hallway door
* better degree of door logic control; all shuttle-related messages have been moved to LocalService; careful managing of 'original state' for the shuttle's cycle
* modification of seat mounting and cargo mounting support entities to expand functionality
* absolutely very little to do with the feature of this branch and a lot to do with yak-shaving; long story short, class inheritance is greatly modified and mountable seats can now accept multiple players if initialized properly
* a lot has changed: distribution of MountableBehavior, mount point information is more complex, vehicles convert differently, the routine of the shuttle timer is initialized differently; you can now successfully utilize the HART shuttle to drop into a zone
* swap of shutle from pad to pad control; tests and comments
* eject players from HART gantry hallway as if passengers dismounting from seat when not boarding through the use of environmental geometry; HART system uses duration from config settings to set scheduler
* rebase to curious master; repairs to vector rotation calculations; regression of mountable changes involving seats with occupancy greater than 1; orbital shuttle as a unique vehicle and amenity; corrected dismount offsets and offset calculations; weird angle of nc hart a building has been properly accommodated; hart events have prerequisite animation states
* rebase with master; looks like rebase with merged_master, which is also a commit
* lots of tests (though not nearly enough); checking the permission group of a shuttle seat no longer creates that seat
* fixing explosions
* fixed the persistence monitor service potentially using non-printable unicode in actor names
* can not use a droppod to gain access to one's own sanctuary
* removed hart facility update that causing open bay doors and beeping
* PR review changes
* fix for aggravation issues
2021-03-23 09:44:10 -04:00
|
|
|
// Copyright (c) 2021 PSForever
|
|
|
|
|
package objects
|
|
|
|
|
|
|
|
|
|
import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
|
|
|
|
|
import net.psforever.objects.avatar.Avatar
|
|
|
|
|
import net.psforever.objects.serverobject.shuttle.OrbitalShuttle
|
|
|
|
|
import net.psforever.objects.vehicles.AccessPermissionGroup
|
2021-03-25 15:15:51 -04:00
|
|
|
import net.psforever.types.{CharacterSex, CharacterVoice, PlanetSideEmpire}
|
Hart (#723)
* initial OrbitalShuttleTimeMsg packet and tests; new objects to support HART shuttle transport system
* master was stale
* grouped scheduling for timing orbital shuttle activity
* door lock controls for HART shuttle lifecycle, and specifically for the doors that lead into the shuttle boarding hallway
* separation of the door from the door unlocking logic, which now has to be provided if performed by an outside source; a door that is locked either by bolt, HART routine, or other reason, can now be shut immediately; message when HART is not docked with a corresponding entry hallway door
* better degree of door logic control; all shuttle-related messages have been moved to LocalService; careful managing of 'original state' for the shuttle's cycle
* modification of seat mounting and cargo mounting support entities to expand functionality
* absolutely very little to do with the feature of this branch and a lot to do with yak-shaving; long story short, class inheritance is greatly modified and mountable seats can now accept multiple players if initialized properly
* a lot has changed: distribution of MountableBehavior, mount point information is more complex, vehicles convert differently, the routine of the shuttle timer is initialized differently; you can now successfully utilize the HART shuttle to drop into a zone
* swap of shutle from pad to pad control; tests and comments
* eject players from HART gantry hallway as if passengers dismounting from seat when not boarding through the use of environmental geometry; HART system uses duration from config settings to set scheduler
* rebase to curious master; repairs to vector rotation calculations; regression of mountable changes involving seats with occupancy greater than 1; orbital shuttle as a unique vehicle and amenity; corrected dismount offsets and offset calculations; weird angle of nc hart a building has been properly accommodated; hart events have prerequisite animation states
* rebase with master; looks like rebase with merged_master, which is also a commit
* lots of tests (though not nearly enough); checking the permission group of a shuttle seat no longer creates that seat
* fixing explosions
* fixed the persistence monitor service potentially using non-printable unicode in actor names
* can not use a droppod to gain access to one's own sanctuary
* removed hart facility update that causing open bay doors and beeping
* PR review changes
* fix for aggravation issues
2021-03-23 09:44:10 -04:00
|
|
|
import org.specs2.mutable.Specification
|
|
|
|
|
|
|
|
|
|
class OrbitalShuttleTest extends Specification {
|
2021-03-25 15:15:51 -04:00
|
|
|
val testAvatar1 = Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)
|
|
|
|
|
val testAvatar2 = Avatar(1, "TestCharacter2", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)
|
|
|
|
|
val testAvatar3 = Avatar(2, "TestCharacter3", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)
|
Hart (#723)
* initial OrbitalShuttleTimeMsg packet and tests; new objects to support HART shuttle transport system
* master was stale
* grouped scheduling for timing orbital shuttle activity
* door lock controls for HART shuttle lifecycle, and specifically for the doors that lead into the shuttle boarding hallway
* separation of the door from the door unlocking logic, which now has to be provided if performed by an outside source; a door that is locked either by bolt, HART routine, or other reason, can now be shut immediately; message when HART is not docked with a corresponding entry hallway door
* better degree of door logic control; all shuttle-related messages have been moved to LocalService; careful managing of 'original state' for the shuttle's cycle
* modification of seat mounting and cargo mounting support entities to expand functionality
* absolutely very little to do with the feature of this branch and a lot to do with yak-shaving; long story short, class inheritance is greatly modified and mountable seats can now accept multiple players if initialized properly
* a lot has changed: distribution of MountableBehavior, mount point information is more complex, vehicles convert differently, the routine of the shuttle timer is initialized differently; you can now successfully utilize the HART shuttle to drop into a zone
* swap of shutle from pad to pad control; tests and comments
* eject players from HART gantry hallway as if passengers dismounting from seat when not boarding through the use of environmental geometry; HART system uses duration from config settings to set scheduler
* rebase to curious master; repairs to vector rotation calculations; regression of mountable changes involving seats with occupancy greater than 1; orbital shuttle as a unique vehicle and amenity; corrected dismount offsets and offset calculations; weird angle of nc hart a building has been properly accommodated; hart events have prerequisite animation states
* rebase with master; looks like rebase with merged_master, which is also a commit
* lots of tests (though not nearly enough); checking the permission group of a shuttle seat no longer creates that seat
* fixing explosions
* fixed the persistence monitor service potentially using non-printable unicode in actor names
* can not use a droppod to gain access to one's own sanctuary
* removed hart facility update that causing open bay doors and beeping
* PR review changes
* fix for aggravation issues
2021-03-23 09:44:10 -04:00
|
|
|
|
|
|
|
|
"OrbitalShuttle" should {
|
|
|
|
|
"construct (proper definition)" in {
|
|
|
|
|
new OrbitalShuttle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"construct (any type of vehicle)" in {
|
|
|
|
|
new OrbitalShuttle(GlobalDefinitions.fury)
|
|
|
|
|
ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"only use known mount points" in {
|
|
|
|
|
val fury = new OrbitalShuttle(GlobalDefinitions.fury)
|
|
|
|
|
fury.MountPoints.get(0).isEmpty mustEqual true
|
|
|
|
|
fury.MountPoints.get(1).nonEmpty mustEqual true
|
|
|
|
|
fury.MountPoints.get(2).nonEmpty mustEqual true
|
|
|
|
|
fury.MountPoints.get(3).isEmpty mustEqual true
|
|
|
|
|
|
|
|
|
|
val shuttle = new OrbitalShuttle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
shuttle.MountPoints.get(0).isEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(1).nonEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(2).nonEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(3).nonEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(4).nonEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(5).nonEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(6).nonEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(7).nonEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(8).nonEmpty mustEqual true
|
|
|
|
|
shuttle.MountPoints.get(9).isEmpty mustEqual true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"will only discover unoccupied seats" in {
|
|
|
|
|
val fury1 = new OrbitalShuttle(GlobalDefinitions.fury)
|
|
|
|
|
val player1 = Player(testAvatar1)
|
|
|
|
|
fury1.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => fury1.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player1).contains(player1) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
fury1.GetSeatFromMountPoint(mountPoint = 1).isEmpty mustEqual true //seat is occupied
|
|
|
|
|
|
|
|
|
|
//comparison with normal Vehicle
|
|
|
|
|
val fury2 = new Vehicle(GlobalDefinitions.fury)
|
|
|
|
|
val player2 = Player(testAvatar2)
|
|
|
|
|
fury2.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => fury2.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player2).contains(player2) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
fury2.GetSeatFromMountPoint(mountPoint = 1).contains(0) mustEqual true //even though seat is occupied
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"have a fixed number of normal seats (using normal definition)" in {
|
|
|
|
|
val fury1 = new OrbitalShuttle(GlobalDefinitions.fury)
|
|
|
|
|
fury1.Seats.size mustEqual 1
|
|
|
|
|
fury1.MountPoints.size mustEqual 2
|
|
|
|
|
val player1 = Player(testAvatar1)
|
|
|
|
|
fury1.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => fury1.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player1).contains(player1) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
fury1.Seats.size mustEqual 1
|
|
|
|
|
fury1.MountPoints.size mustEqual 2
|
|
|
|
|
val player2 = Player(testAvatar2)
|
|
|
|
|
fury1.GetSeatFromMountPoint(mountPoint = 1).isEmpty mustEqual true
|
|
|
|
|
fury1.Seats.size mustEqual 1
|
|
|
|
|
fury1.MountPoints.size mustEqual 2
|
|
|
|
|
|
|
|
|
|
//congruent with normal Vehicle
|
|
|
|
|
val fury2 = new Vehicle(GlobalDefinitions.fury)
|
|
|
|
|
fury2.Seats.size mustEqual 1
|
|
|
|
|
fury2.MountPoints.size mustEqual 2
|
|
|
|
|
val player3 = Player(testAvatar3)
|
|
|
|
|
fury2.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => fury2.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player3).contains(player3) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
fury2.Seats.size mustEqual 1
|
|
|
|
|
fury2.MountPoints.size mustEqual 2
|
|
|
|
|
fury2.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => fury2.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player2).contains(player2) mustEqual false
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
fury2.Seats.size mustEqual 1
|
|
|
|
|
fury2.MountPoints.size mustEqual 2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"create seats as needed (with appropriate definition)" in {
|
|
|
|
|
GlobalDefinitions.fury
|
|
|
|
|
.Seats(0).occupancy == 1 mustEqual true
|
|
|
|
|
GlobalDefinitions.orbital_shuttle
|
|
|
|
|
.Seats(0).occupancy > 1 mustEqual true
|
|
|
|
|
|
|
|
|
|
val shuttle1 = new OrbitalShuttle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
shuttle1.Seats.size mustEqual 1
|
|
|
|
|
shuttle1.MountPoints.size mustEqual 8
|
|
|
|
|
val player1 = Player(testAvatar1)
|
|
|
|
|
shuttle1.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => shuttle1.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player1).contains(player1) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
shuttle1.Seats.size mustEqual 1
|
|
|
|
|
shuttle1.MountPoints.size mustEqual 8
|
|
|
|
|
val player2 = Player(testAvatar2)
|
|
|
|
|
shuttle1.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => shuttle1.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player2).contains(player2) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
shuttle1.Seats.size mustEqual 2
|
|
|
|
|
shuttle1.MountPoints.size mustEqual 8
|
|
|
|
|
|
|
|
|
|
//comparison with normal Vehicle
|
|
|
|
|
val shuttle2 = new Vehicle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
shuttle2.Seats.size mustEqual 1
|
|
|
|
|
shuttle2.MountPoints.size mustEqual 8
|
|
|
|
|
val player3 = Player(testAvatar3)
|
|
|
|
|
shuttle2.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => shuttle2.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player3).contains(player3) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
shuttle2.Seats.size mustEqual 1
|
|
|
|
|
shuttle2.MountPoints.size mustEqual 8
|
|
|
|
|
shuttle2.GetSeatFromMountPoint(mountPoint = 1) match {
|
|
|
|
|
case Some(seatNumber) => shuttle2.Seat(seatNumber) match {
|
|
|
|
|
case Some(seat) => seat.mount(player2).contains(player2) mustEqual false
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
shuttle2.Seats.size mustEqual 1
|
|
|
|
|
shuttle2.MountPoints.size mustEqual 8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"not create new seats out of order" in {
|
|
|
|
|
val shuttle = new OrbitalShuttle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
val player1 = Player(testAvatar1)
|
|
|
|
|
shuttle.Seat(seatNumber = 0) match {
|
|
|
|
|
case Some(seat) => seat.mount(player1).contains(player1) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
val player2 = Player(testAvatar2)
|
|
|
|
|
shuttle.Seat(seatNumber = 2).isEmpty mustEqual true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"recognize proper seating arrangements" in {
|
|
|
|
|
val shuttle = new OrbitalShuttle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
val player1 = Player(testAvatar1)
|
|
|
|
|
shuttle.Seat(seatNumber = 0) match {
|
|
|
|
|
case Some(seat) => seat.mount(player1).contains(player1) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
val player2 = Player(testAvatar2)
|
|
|
|
|
shuttle.Seat(seatNumber = 1) match {
|
|
|
|
|
case Some(seat) => seat.mount(player2).contains(player2) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
val player3 = Player(testAvatar3)
|
|
|
|
|
shuttle.Seat(seatNumber = 2) match {
|
|
|
|
|
case Some(seat) => seat.mount(player3).contains(player3) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
shuttle.PassengerInSeat(player1).contains(0) mustEqual true
|
|
|
|
|
shuttle.PassengerInSeat(player2).contains(1) mustEqual true
|
|
|
|
|
shuttle.PassengerInSeat(player3).contains(2) mustEqual true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"retain created seats after dismount" in {
|
|
|
|
|
val shuttle = new OrbitalShuttle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
val player1 = Player(testAvatar1)
|
|
|
|
|
shuttle.Seat(seatNumber = 0) match {
|
|
|
|
|
case Some(seat) => seat.mount(player1).contains(player1) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
val player2 = Player(testAvatar2)
|
|
|
|
|
shuttle.Seat(seatNumber = 1) match {
|
|
|
|
|
case Some(seat) => seat.mount(player2).contains(player2) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
val player3 = Player(testAvatar3)
|
|
|
|
|
shuttle.Seat(seatNumber = 2) match {
|
|
|
|
|
case Some(seat) => seat.mount(player3).contains(player3) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shuttle.Seats(0).isOccupied mustEqual true
|
|
|
|
|
shuttle.Seats(1).isOccupied mustEqual true
|
|
|
|
|
shuttle.Seats(2).isOccupied mustEqual true
|
|
|
|
|
shuttle.Seats.size mustEqual 3
|
|
|
|
|
//IMPORTANT TO NOTE
|
|
|
|
|
shuttle.GetSeatFromMountPoint(mountPoint = 1).contains(3) mustEqual true //new seat
|
|
|
|
|
|
|
|
|
|
shuttle.Seat(seatNumber = 1) match {
|
|
|
|
|
case Some(seat) => seat.unmount(player2).isEmpty mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
shuttle.Seats(0).isOccupied mustEqual true
|
|
|
|
|
shuttle.Seats(1).isOccupied mustEqual false
|
|
|
|
|
shuttle.Seats(2).isOccupied mustEqual true
|
|
|
|
|
shuttle.Seats.size mustEqual 3
|
|
|
|
|
//IMPORTANT TO NOTE
|
|
|
|
|
shuttle.GetSeatFromMountPoint(mountPoint = 1).contains(1) mustEqual true //reuse newly unoccupied seat
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"consider all seats as passenger seats" in {
|
|
|
|
|
val fury1 = Vehicle(GlobalDefinitions.fury)
|
|
|
|
|
fury1.SeatPermissionGroup(seatNumber = 0).contains(AccessPermissionGroup.Driver)
|
|
|
|
|
fury1.SeatPermissionGroup(seatNumber = 1).isEmpty mustEqual true
|
|
|
|
|
|
|
|
|
|
val fury2 = Vehicle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
fury2.SeatPermissionGroup(seatNumber = 0).contains(AccessPermissionGroup.Driver)
|
|
|
|
|
fury2.SeatPermissionGroup(seatNumber = 1).isEmpty mustEqual true
|
|
|
|
|
|
|
|
|
|
val shuttle1 = new OrbitalShuttle(GlobalDefinitions.fury)
|
|
|
|
|
shuttle1.SeatPermissionGroup(seatNumber = 0).contains(AccessPermissionGroup.Passenger)
|
|
|
|
|
shuttle1.SeatPermissionGroup(seatNumber = 1).isEmpty mustEqual true
|
|
|
|
|
|
|
|
|
|
val shuttle2 = new OrbitalShuttle(GlobalDefinitions.orbital_shuttle)
|
|
|
|
|
shuttle2.SeatPermissionGroup(seatNumber = 0).contains(AccessPermissionGroup.Passenger)
|
|
|
|
|
shuttle2.SeatPermissionGroup(seatNumber = 1).contains(AccessPermissionGroup.Passenger) //seat does not exist yet
|
|
|
|
|
shuttle2.SeatPermissionGroup(seatNumber = 2).isEmpty mustEqual true
|
|
|
|
|
val player1 = Player(testAvatar1)
|
|
|
|
|
shuttle2.Seat(seatNumber = 0) match {
|
|
|
|
|
case Some(seat) => seat.mount(player1).contains(player1) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
val player2 = Player(testAvatar2)
|
|
|
|
|
shuttle2.Seat(seatNumber = 1) match {
|
|
|
|
|
case Some(seat) => seat.mount(player2).contains(player2) mustEqual true
|
|
|
|
|
case _ => ko
|
|
|
|
|
}
|
|
|
|
|
shuttle2.SeatPermissionGroup(seatNumber = 0).contains(AccessPermissionGroup.Passenger)
|
|
|
|
|
shuttle2.SeatPermissionGroup(seatNumber = 1).contains(AccessPermissionGroup.Passenger)
|
|
|
|
|
shuttle2.SeatPermissionGroup(seatNumber = 2).contains(AccessPermissionGroup.Passenger) //seat does not exist yet
|
|
|
|
|
shuttle2.SeatPermissionGroup(seatNumber = 3).isEmpty mustEqual true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|