I am trying to port the JavaScript tutorial code to Scala.js and got stuck on filtering Structures - any suggestions would be appreciated.
// If creep is supposed to transfer energy to a structure
if (creep.memory.working == true) {
// Find closest spawn, extension or tower which is not full
var structure = creep.pos.findClosestByPath(FIND_MY_STRUCTURES, {
filter: (s) => (s.structureType == STRUCTURE_SPAWN
|| s.structureType == STRUCTURE_EXTENSION
|| s.structureType == STRUCTURE_TOWER)
&& s.energy < s.energyCapacity });
val structure = Option[Structure](creep.pos.findClosestByPath[Structure](FIND_MY_STRUCTURES,
FindFilter[Structure](structure => {
(structure.structureType == STRUCTURE_SPAWN ||
structure.structureType == STRUCTURE_EXTENSION ||
structure.structureType == STRUCTURE_TOWER) &&
structure.energy < structure.energyCapacity })))
The problem is that not all structure types have .energy
so this won't compile, despite the fact that the filtered ones have?
I tried to define a trait HasEnergy (similar to a JavaScript interface) and using it like FindFilter[Structure with HasEnergy], which compiles, but now I am getting a type error at runtime -> TypeError: a.k is not a function
.
My Facades look like this:
@js.native
trait HasEnergy extends js.Object {
val energy: Int
val energyCapacity: Int
}
@js.native
trait Structure extends RoomObject with HasID {
val hits: UndefOr[Int]
val hitsMax: UndefOr[Int]
val id: String
val structureType: String
def destroy(): Int
def isActive(): Boolean
def notifyWhenAttacked(enabled: Boolean): Int
}
OK, here is the solution I came up with:
val structure = {
Option(creep.pos.findClosestByPath[OwnedStructureWithEnergy](FIND_MY_STRUCTURES, FindFilter[OwnedStructureWithEnergy](s =>
((s.structureType == STRUCTURE_SPAWN) ||
(s.structureType == STRUCTURE_EXTENSION) ||
(s.structureType == STRUCTURE_TOWER)) &&
(s.energy < s.energyCapacity))))
}
It turns out there was an error in my findClosestByPath Facade. The correct version per API supports FindFilter and FindFilterAlgorithm - the former was missing from my mapping. The correct one now looks like this:
def findClosestByPath[T](typ: Int, opts: FindFilter[T] | FindFilterAlgorithm[T] = ???): T
@JSName("findClosestByPath")
Now to use member access via dot, I added the trait OwnedStructureWithEnergy:
@js.native
trait OwnedStructureWithEnergy extends OwnedStructure {
val energy: Int = js.native
val energyCapacity: Int = js.native
}