mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-20 02:54:46 +00:00
corrected missing Tile size for CUD and Laze Pointer; changed MoveItem tests to account for spatial inconsistency between modular holster slots and regional inventory cells
This commit is contained in:
parent
7af2e4b572
commit
02ee06fd97
|
|
@ -21,12 +21,26 @@ class EquipmentSlot {
|
|||
Size
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine what `Equipment` is stowed in the given position.
|
||||
* @return the `Equipment` in this slot
|
||||
*/
|
||||
def Equipment : Option[Equipment] = tool
|
||||
|
||||
/**
|
||||
* Attempt to stow an item at the given position.
|
||||
* @param assignEquipment the change in `Equipment` for this slot
|
||||
* @return the `Equipment` in this slot
|
||||
*/
|
||||
def Equipment_=(assignEquipment : Equipment) : Option[Equipment] = {
|
||||
Equipment = Some(assignEquipment)
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to stow an item at the given position.
|
||||
* @param assignEquipment the change in `Equipment` for this slot
|
||||
* @return the `Equipment` in this slot
|
||||
*/
|
||||
def Equipment_=(assignEquipment : Option[Equipment]) : Option[Equipment] = {
|
||||
if(assignEquipment.isDefined) { //if new equipment is defined, don't put it in the slot if the slot is being used
|
||||
if(tool.isEmpty && EquipmentSize.isEqual(size, assignEquipment.get.Size)) {
|
||||
|
|
|
|||
|
|
@ -1117,10 +1117,12 @@ object GlobalDefinitions {
|
|||
val
|
||||
flail_targeting_laser = SimpleItemDefinition(SItem.flail_targeting_laser)
|
||||
flail_targeting_laser.Packet = new CommandDetonaterConverter
|
||||
flail_targeting_laser.Tile = InventoryTile.Tile33
|
||||
|
||||
val
|
||||
command_detonater = SimpleItemDefinition(SItem.command_detonater)
|
||||
command_detonater.Packet = new CommandDetonaterConverter
|
||||
command_detonater.Tile = InventoryTile.Tile33
|
||||
|
||||
val
|
||||
ace = ConstructionItemDefinition(CItem.Unit.ace)
|
||||
|
|
|
|||
|
|
@ -116,12 +116,7 @@ class GridInventory {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test whether a given piece of `Equipment` would collide with any stowed content in the inventory.<br>
|
||||
* <br>
|
||||
* If there are fewer items stored in the inventory than there are cells required to represent the testing item,
|
||||
* test the collision by iterating through the list of items.
|
||||
* If there are more items, check that each cell that would be used for the testing items tile does not collide.
|
||||
* The "testing item" in this case has already been transformed into its tile dimensions.
|
||||
* Test whether a given piece of `Equipment` would collide with any stowed content in the inventory.
|
||||
* @param start the cell index to test this `Equipment` for insertion
|
||||
* @param w the width of the `Equipment` to be tested
|
||||
* @param h the height of the `Equipment` to be tested
|
||||
|
|
@ -132,8 +127,33 @@ class GridInventory {
|
|||
Success(List.empty[Int])
|
||||
}
|
||||
else {
|
||||
def check : (Int,Int,Int) => Try[List[Int]] = if(items.size < w * h) { CheckCollisionsAsList } else { CheckCollisionsAsGrid }
|
||||
check(start, w, h)
|
||||
CheckCollisionsVar(start, w, h) match {
|
||||
case Success(list) =>
|
||||
Success(list.map({ f => f.obj.GUID.guid }))
|
||||
case Failure(ex) =>
|
||||
Failure(ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a given piece of `Equipment` would collide with any stowed content in the inventory.<br>
|
||||
* <br>
|
||||
* If there are fewer items stored in the inventory than there are cells required to represent the testing item,
|
||||
* test the collision by iterating through the list of items.
|
||||
* If there are more items, check that each cell that would be used for the testing items tile does not collide.
|
||||
* The "testing item" in this case has already been transformed into its tile dimensions.
|
||||
* @param start the cell index to test this `Equipment` for insertion
|
||||
* @param w the width of the `Equipment` to be tested
|
||||
* @param h the height of the `Equipment` to be tested
|
||||
* @return a `List` of existing items that an item of this scale would overlap if inserted
|
||||
*/
|
||||
def CheckCollisionsVar(start : Int, w : Int, h : Int) : Try[List[InventoryItem]] = {
|
||||
if(items.size < w * h) {
|
||||
CheckCollisionsAsList(start, w, h)
|
||||
}
|
||||
else {
|
||||
CheckCollisionsAsGrid(start, w, h)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -145,10 +165,10 @@ class GridInventory {
|
|||
* @param start the cell index to test this `Equipment` for insertion
|
||||
* @param w the width of the `Equipment` to be tested
|
||||
* @param h the height of the `Equipment` to be tested
|
||||
* @return a `List` of GUID values for all existing contents that this item would overlap if inserted
|
||||
* @return a `List` of existing items that an item of this scale would overlap if inserted
|
||||
* @throws IndexOutOfBoundsException if the region extends outside of the grid boundaries
|
||||
*/
|
||||
def CheckCollisionsAsList(start : Int, w : Int, h : Int) : Try[List[Int]] = {
|
||||
def CheckCollisionsAsList(start : Int, w : Int, h : Int) : Try[List[InventoryItem]] = {
|
||||
val actualSlot = start - offset
|
||||
val startx : Int = actualSlot % width
|
||||
val starty : Int = actualSlot / width
|
||||
|
|
@ -159,7 +179,7 @@ class GridInventory {
|
|||
Failure(new IndexOutOfBoundsException(s"requested region escapes the $bounds edge of the grid inventory - $startx, $starty; $w x $h"))
|
||||
}
|
||||
else {
|
||||
val collisions : mutable.Set[Int] = mutable.Set[Int]()
|
||||
val collisions : mutable.Set[InventoryItem] = mutable.Set[InventoryItem]()
|
||||
items.values.foreach({ item : InventoryItem =>
|
||||
val actualItemStart : Int = item.start - offset
|
||||
val itemx : Int = actualItemStart % width
|
||||
|
|
@ -168,7 +188,7 @@ class GridInventory {
|
|||
val clipsOnX : Boolean = if(itemx < startx) { itemx + tile.width > startx } else { itemx <= startw }
|
||||
val clipsOnY : Boolean = if(itemy < starty) { itemy + tile.height > starty } else { itemy <= starth }
|
||||
if(clipsOnX && clipsOnY) {
|
||||
collisions += item.GUID.guid
|
||||
collisions += item
|
||||
}
|
||||
})
|
||||
Success(collisions.toList)
|
||||
|
|
@ -183,10 +203,10 @@ class GridInventory {
|
|||
* @param start the cell index to test this `Equipment` for insertion
|
||||
* @param w the width of the `Equipment` to be tested
|
||||
* @param h the height of the `Equipment` to be tested
|
||||
* @return a `List` of GUID values for all existing contents that this item would overlap if inserted
|
||||
* @return a `List` of existing items that an item of this scale would overlap if inserted
|
||||
* @throws IndexOutOfBoundsException if the region extends outside of the grid boundaries
|
||||
*/
|
||||
def CheckCollisionsAsGrid(start : Int, w : Int, h : Int) : Try[List[Int]] = {
|
||||
def CheckCollisionsAsGrid(start : Int, w : Int, h : Int) : Try[List[InventoryItem]] = {
|
||||
val actualSlot = start - offset
|
||||
if(actualSlot < 0 || actualSlot >= grid.length || (actualSlot % width) + w > width || (actualSlot / width) + h > height) {
|
||||
val startx : Int = actualSlot % width
|
||||
|
|
@ -196,12 +216,12 @@ class GridInventory {
|
|||
Failure(new IndexOutOfBoundsException(s"requested region escapes the $bounds edge of the grid inventory - $startx, $starty; $w x $h"))
|
||||
}
|
||||
else {
|
||||
val collisions : mutable.Set[Int] = mutable.Set[Int]()
|
||||
val collisions : mutable.Set[InventoryItem] = mutable.Set[InventoryItem]()
|
||||
var curr = actualSlot
|
||||
for(_ <- 0 until h) {
|
||||
for(col <- 0 until w) {
|
||||
if(grid(curr + col) > -1) {
|
||||
collisions += items(grid(curr + col)).GUID.guid
|
||||
collisions += items(grid(curr + col))
|
||||
}
|
||||
}
|
||||
curr += width
|
||||
|
|
|
|||
|
|
@ -4,40 +4,57 @@ package net.psforever.objects.inventory
|
|||
import net.psforever.objects.OffhandEquipmentSlot
|
||||
import net.psforever.objects.equipment.{Equipment, EquipmentSize}
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
/**
|
||||
* A slot-like interface for a specific grid position in an inventory.
|
||||
* The size is bound to anything that can be stowed, which encompasses most all `Equipment`.
|
||||
* Furthermore, rather than operating on a fixed-size slot, this "slot" represents an inventory region that either includes `slot` or starts at `slot`.
|
||||
* An object added to the underlying inventory from here can only be added with its initial point at `slot`.
|
||||
* An object found at `slot`, however, can be removed even if the starting cell is prior to `slot.`
|
||||
* The size is typically bound to anything that can be stowed which encompasses most all `Equipment`.
|
||||
* The capacity of this `EquipmentSlot` is essentially treated as 1x1.
|
||||
* Upon insertions, however, the capacity temporarily is treated as the size of the item being inserted (unless `None`).
|
||||
* This allows a proper check for insertion collision.<br>
|
||||
* <br>
|
||||
* Rather than operating on a fixed-size slot, this "slot" represents an inventory region that either includes `slot` or starts at `slot`.
|
||||
* When determining the contents of the inventory at `slot`, only that singular cell is checked.
|
||||
* When removing an item from `slot`, the item in inventory only has to be positioned in such a way that overlaps with `slot`.
|
||||
* When adding an item to `slot`, `slot` is treated as the upper left corner (the initial point) of a larger capacity region.<br>
|
||||
* <br>
|
||||
* The following diagrams demonstrate the coordinate association:<br>
|
||||
* ` - - - - - - - - - - - - - - -`<br>
|
||||
* ` - - - - - - r r x - - - - - -`<br>
|
||||
* ` - - s - - - r r x - - - i i -`<br>
|
||||
* ` - - - - - - x x x - - - i i -`<br>
|
||||
* ` - - - - - - - - - - - - - - -`<br>
|
||||
* ... where 's' is the 1x1 slot,
|
||||
* 'r' is the corner of any 2x2 item that can be removed ('x' is a potential affected edge),
|
||||
* and 'i' is the region checked for a 2x2 insertion into `slot`.
|
||||
*/
|
||||
class InventoryEquipmentSlot(private val slot : Int, private val inv : GridInventory) extends OffhandEquipmentSlot(EquipmentSize.Inventory) {
|
||||
/**
|
||||
* Attempt to stow an item into the inventory at the given position.
|
||||
* @param assignEquipment the change in `Equipment` for this slot
|
||||
* @return the `Equipment` in this slot
|
||||
*/
|
||||
override def Equipment_=(assignEquipment : Option[Equipment]) : Option[Equipment] = {
|
||||
assignEquipment match {
|
||||
case Some(equip) =>
|
||||
inv += slot -> equip
|
||||
val tile = equip.Definition.Tile
|
||||
inv.CheckCollisionsVar(slot, tile.Width, tile.Height) match {
|
||||
case Success(Nil) => inv += slot -> equip
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
case None =>
|
||||
inv -= slot
|
||||
}
|
||||
Equipment
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine what `Equipment`, if any, is stowed in the inventory in the given position.
|
||||
* @return the `Equipment` in this slot
|
||||
*/
|
||||
override def Equipment : Option[Equipment] = {
|
||||
inv.Items.find({ case ((_, item : InventoryItem)) => item.start == slot }) match {
|
||||
case Some((_, item : InventoryItem)) =>
|
||||
Some(item.obj)
|
||||
case None =>
|
||||
inv.CheckCollisionsAsGrid(slot,1,1) match {
|
||||
case Success(list) =>
|
||||
list.headOption match {
|
||||
case Some(found) =>
|
||||
Some(found.obj)
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
case Failure(_) =>
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,14 +59,30 @@ class InventoryTest extends Specification {
|
|||
obj.Capacity mustEqual 45
|
||||
val w = bullet9mmBox2.Tile.width
|
||||
val h = bullet9mmBox2.Tile.height
|
||||
obj.CheckCollisionsAsList(0, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(1, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(2, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(3, w, h) mustEqual Success(Nil)
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(1, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(2, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(3, w, h) mustEqual Success(Nil)
|
||||
val list0 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list0 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(1, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(2, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(3, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(1, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(2, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(3, w, h) mustEqual list3
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
|
@ -77,14 +93,30 @@ class InventoryTest extends Specification {
|
|||
obj.Capacity mustEqual 45
|
||||
val w = bullet9mmBox2.Tile.width
|
||||
val h = bullet9mmBox2.Tile.height
|
||||
obj.CheckCollisionsAsList(3, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(2, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(1, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(0, w, h) mustEqual Success(Nil)
|
||||
obj.CheckCollisionsAsGrid(3, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(2, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(1, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual Success(Nil)
|
||||
val list0 = obj.CheckCollisionsAsList(3, w, h)
|
||||
list0 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(2, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(1, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(3, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(2, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(1, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list3
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
|
@ -95,14 +127,30 @@ class InventoryTest extends Specification {
|
|||
obj.Capacity mustEqual 45
|
||||
val w = bullet9mmBox2.Tile.width
|
||||
val h = bullet9mmBox2.Tile.height
|
||||
obj.CheckCollisionsAsList(0, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(9, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(18, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(27, w, h) mustEqual Success(Nil)
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(9, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(18, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(27, w, h) mustEqual Success(Nil)
|
||||
val list0 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list0 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(9, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(18, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(27, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(9, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(18, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(27, w, h) mustEqual list3
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
|
@ -113,14 +161,100 @@ class InventoryTest extends Specification {
|
|||
obj.Capacity mustEqual 45
|
||||
val w = bullet9mmBox2.Tile.width
|
||||
val h = bullet9mmBox2.Tile.height
|
||||
obj.CheckCollisionsAsList(27, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(19, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(9, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsList(0, w, h) mustEqual Success(Nil)
|
||||
obj.CheckCollisionsAsGrid(27, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(19, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(9, w, h) mustEqual Success(1 :: Nil)
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual Success(Nil)
|
||||
val list0 = obj.CheckCollisionsAsList(27, w, h)
|
||||
list0 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(18, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(9, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(27, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(18, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(9, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list3
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"check for item collision (diagonal insert)" in {
|
||||
/*
|
||||
Number indicates upper-left corner of attempted 3x3 insertion by list#
|
||||
0 - - - - - 2 - - - - -
|
||||
- 1 - - - 3 - - - - - -
|
||||
- - - - - - - - - - - -
|
||||
- - - X X X - - - - - -
|
||||
- - - X X X - - - - - -
|
||||
- 5 - X X 7 - - - - - -
|
||||
4 - - - - - 6 - - - - -
|
||||
- - - - - - - - - - - -
|
||||
- - - - - - - - - - - -
|
||||
*/
|
||||
val obj : GridInventory = GridInventory(12, 9)
|
||||
obj += 39 -> bullet9mmBox1
|
||||
obj.Capacity mustEqual 99 //108 - 9
|
||||
val w = bullet9mmBox2.Tile.width
|
||||
val h = bullet9mmBox2.Tile.height
|
||||
val list0 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list0 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(13, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(6, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) =>list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(17, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list4 = obj.CheckCollisionsAsList(72, w, h)
|
||||
list4 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list5 = obj.CheckCollisionsAsList(61, w, h)
|
||||
list5 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list6 = obj.CheckCollisionsAsList(78, w, h)
|
||||
list6 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list7 = obj.CheckCollisionsAsList(65, w, h)
|
||||
list7 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(13, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(6, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(17, w, h) mustEqual list3
|
||||
obj.CheckCollisionsAsGrid(72, w, h) mustEqual list4
|
||||
obj.CheckCollisionsAsGrid(61, w, h) mustEqual list5
|
||||
obj.CheckCollisionsAsGrid(78, w, h) mustEqual list6
|
||||
obj.CheckCollisionsAsGrid(65, w, h) mustEqual list7
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import net.psforever.packet.game.objectcreate._
|
|||
import net.psforever.types._
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.util.Success
|
||||
|
||||
class WorldSessionActor extends Actor with MDCContextAware {
|
||||
private[this] val log = org.log4s.getLogger
|
||||
|
|
@ -857,50 +858,68 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
player.Find(item_guid) match {
|
||||
case Some(index) =>
|
||||
val indexSlot = player.Slot(index)
|
||||
var itemOpt = indexSlot.Equipment //use this to short circuit
|
||||
val item = itemOpt.get
|
||||
val destSlot = player.Slot(dest)
|
||||
val item = indexSlot.Equipment.get
|
||||
val destItem = destSlot.Equipment
|
||||
indexSlot.Equipment = None
|
||||
destSlot.Equipment = None
|
||||
|
||||
(destSlot.Equipment = item) match {
|
||||
case Some(_) => //move item
|
||||
log.info(s"MoveItem: $item_guid moved from $avatar_guid_1 @ $index to $avatar_guid_1 @ $dest")
|
||||
//continue on to the code following the next match statement after resolving the match statement
|
||||
destItem match {
|
||||
case Some(item2) => //second item to swap?
|
||||
(indexSlot.Equipment = destItem) match {
|
||||
case Some(_) => //yes, swap
|
||||
log.info(s"MoveItem: ${item2.GUID} swapped to $avatar_guid_1 @ $index")
|
||||
//we must shuffle items around cleanly to avoid causing icons to "disappear"
|
||||
if(index == Player.FreeHandSlot) { //temporarily put in safe location, A -> C
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDetachMessage(player.GUID, item.GUID, Vector3(0f, 0f, 0f), 0f, 0f, 0f))) //ground
|
||||
}
|
||||
else {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(player.GUID, item.GUID, Player.FreeHandSlot))) //free hand
|
||||
}
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(player.GUID, item2.GUID, index))) //B -> A
|
||||
if(0 <= index && index < 5) {
|
||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentInHand(player.GUID, index, item2))
|
||||
}
|
||||
|
||||
case None => //can't complete the swap; drop the other item on the ground
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDetachMessage(player.GUID, item2.GUID, player.Position, 0f, 0f, player.Orientation.z))) //ground
|
||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentOnGround(player.GUID, player.Position, player.Orientation, item2))
|
||||
}
|
||||
|
||||
case None => ; //just move item over
|
||||
}
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(avatar_guid_1, item_guid, dest)))
|
||||
if(0 <= dest && dest < 5) {
|
||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentInHand(player.GUID, dest, item))
|
||||
}
|
||||
|
||||
case None => //restore original contents
|
||||
indexSlot.Equipment = item
|
||||
destSlot.Equipment = destItem
|
||||
val destItem = if((-1 < dest && dest < 5) || dest == Player.FreeHandSlot) {
|
||||
destSlot.Equipment match {
|
||||
case Some(found) =>
|
||||
Some(InventoryItem(found, dest))
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
case None => ;
|
||||
else {
|
||||
val tile = item.Definition.Tile
|
||||
player.Inventory.CheckCollisionsVar(dest, tile.Width, tile.Height) match {
|
||||
case Success(Nil) => None //no item swap
|
||||
case Success(entry :: Nil) => Some(entry) //one item to swap
|
||||
case Success(_) | scala.util.Failure(_) => itemOpt = None; None //abort item move altogether
|
||||
}
|
||||
}
|
||||
|
||||
if(itemOpt.isDefined) {
|
||||
log.info(s"MoveItem: $item_guid moved from $avatar_guid_1 @ $index to $avatar_guid_1 @ $dest")
|
||||
indexSlot.Equipment = None
|
||||
destItem match { //do we have a swap item?
|
||||
case Some(entry) => //yes, swap
|
||||
val item2 = entry.obj
|
||||
player.Slot(entry.start).Equipment = None //remove item2 to make room for item
|
||||
destSlot.Equipment = item //in case dest and index could block each other
|
||||
(indexSlot.Equipment = entry.obj) match {
|
||||
case Some(_) => //item and item2 swapped places successfully
|
||||
log.info(s"MoveItem: ${item2.GUID} swapped to $avatar_guid_1 @ $index")
|
||||
//we must shuffle items around cleanly to avoid causing icons to "disappear"
|
||||
if(index == Player.FreeHandSlot) { //temporarily put in safe location, A -> C
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDetachMessage(player.GUID, item.GUID, Vector3(0f, 0f, 0f), 0f, 0f, 0f))) //ground
|
||||
}
|
||||
else {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(player.GUID, item.GUID, Player.FreeHandSlot))) //free hand
|
||||
}
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(player.GUID, item2.GUID, index))) //B -> A
|
||||
if(0 <= index && index < 5) {
|
||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentInHand(player.GUID, index, item2))
|
||||
}
|
||||
|
||||
case None => //item2 does not fit; drop on ground
|
||||
val pos = player.Position
|
||||
val orient = player.Orientation
|
||||
DropItemOnGround(item2, pos, player.Orientation)
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDetachMessage(player.GUID, item2.GUID, pos, 0f, 0f, orient.z))) //ground
|
||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentOnGround(player.GUID, pos, orient, item2))
|
||||
}
|
||||
|
||||
case None => //just move item over
|
||||
destSlot.Equipment = item
|
||||
}
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(avatar_guid_1, item_guid, dest)))
|
||||
if(0 <= dest && dest < 5) {
|
||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentInHand(player.GUID, dest, item))
|
||||
}
|
||||
}
|
||||
case None =>
|
||||
log.info(s"MoveItem: $avatar_guid_1 wanted to move the item $item_guid but could not find it")
|
||||
}
|
||||
|
||||
case msg @ ChangeAmmoMessage(item_guid, unk1) =>
|
||||
|
|
|
|||
Loading…
Reference in a new issue