#[repr(transparent)]pub struct Position { /* private fields */ }
Expand description
Represents a position in a particular room in Screeps.
Note: This is analogous to the RoomPosition
JavaScript type.
We’ve renamed this type to Position
in screeps-game-api
to reflect the
fact that it’s implemented entirely as a local type, and does represent a
position located within an entire shard, not only within a single room.
This should be a very efficient type to use in most if not all situations.
It’s represented by a single u32
, all math operations are implemented in
pure-Rust code, and uploading to / downloading from JavaScript only requires
transferring a single i32
.
Using Position
You can retrieve a Position
by getting the position of a game object using
RoomObject::pos
, or by creating one from coordinates with
Position::new
.
You can use any of the math methods available on this page to manipulate
Position
, and you can pass it to any game methods expecting a position
or something with a position.
Serialization
Position
implements both serde::Serialize
and
serde::Deserialize
.
When serializing, it will use the format {roomName: String, x: u32, y: u32}
in “human readable” formats like JSON, and will serialize as a single
i32
in “non-human readable” formats like bincode
.
If you need a reference to a RoomPosition
in JavaScript,
convert the native Position
to a RoomPosition
:
use screeps::{Position, RoomCoordinate, RoomPosition};
use std::convert::TryFrom;
let pos = Position::new(
RoomCoordinate::try_from(20).unwrap(),
RoomCoordinate::try_from(21).unwrap(),
"E5N6".parse().unwrap(),
);
let js_pos = RoomPosition::from(pos);
let result = js_pos.room_name();
Deserialization
Position
implements TryFrom<Value>
, allowing conversion from values
retrieved from JavaScript. The implementation is fairly lenient, and will
try to accept the value as any of the following things, in order:
- an integer representing the packedPos
- this can be produced by retrieving the
__packedPos
field of aRoomPosition
- this can be produced by retrieving the
- an object with a
__packedPos
property- this allows converting from a JavaScript
RoomPosition
to aPosition
without referencing__packedPos
manually, but is less efficient since it requires an extra callback into JavaScript to grab that field from within the conversion code
- this allows converting from a JavaScript
- an object with
x
,y
androomName
properties- this is mainly intended to decode
Position
s which were previously sent to JavaScript using@{}
injs!{}
, or serialized usingserde::Serialize
- this will also understand
RoomPosition
s in private servers versions3.2.1
and below, prior to when__packedPos
was added
- this is mainly intended to decode
World vs. in-room coordinates
When converting Position
to integer x/y coordinates, there are two main
methods. The first is to use x
/y
as “in room” coordinates, which are
bounded within 0..=49
. These coordinates only identify the location within
a given room name. These are used by Position::x
, Position::y
,
Position::new
as well as Position::coords
,
Position::coords_signed
and the various implementations of Into<([ui*], [ui*])>
for Position
.
The second is to use x
/y
as “world” coordinates, which are coordinates
spread across the world. To ensures they agree with in-room coordinates,
south is positive y
, north is negative y
, east is positive x
and west
is negative x
. One way to think of them is as extending the room
coordinates of the room E0S0
throughout the entire map.
World coordinates are used by Position::world_x
, Position::world_y
,
Position::world_coords
, Position::from_world_coords
, and by all
implementations which allow adding or subtracting positions (see Addition
and subtraction).
Method Behavior
While this corresponds with the JavaScript RoomPosition
type, it is not
identical. In particular, all “calculation” methods which take in another
position are re-implemented in pure Rust code, and some behave slightly
different.
For instance, Position::get_range_to
operates on positions as world
coordinates, and will return accurate distances for positions in different
rooms. This is in contrast to RoomPosition.getRangeTo
in JavaScript, which
will return Infinity
for positions from different rooms.
Position::in_range_to
has a similar difference.
Besides extending behavior to work between rooms, we’ve tried to keep methods as in-sync with the JavaScript versions as possible. Everything will “just work”, and there should be some speed advantage because of not having to call into JavaScript to perform calculations.
Addition and subtraction
Position
implements Add<(i32, i32)>
, Sub<(i32, i32)>
and
Sub<Position>
. All of these implementations work on positions as world
positions, and will treat positions from different rooms just as if they’re
further apart.
The Add
implementation can be used to add an offset to a position:
let pos1 = Position::new(
RoomCoordinate::try_from(0).unwrap(),
RoomCoordinate::try_from(0).unwrap(),
"E1N1".parse().unwrap(),
);
let pos2 = Position::new(
RoomCoordinate::try_from(40).unwrap(),
RoomCoordinate::try_from(20).unwrap(),
"E1N1".parse().unwrap(),
);
assert_eq!(pos1 + (40, 20), pos2);
And the Sub
implementation can be used to get the offset between two
positions:
let pos1 = Position::new(
RoomCoordinate::try_from(4).unwrap(),
RoomCoordinate::try_from(20).unwrap(),
"E20S21".parse().unwrap(),
);
let pos2 = Position::new(
RoomCoordinate::try_from(4).unwrap(),
RoomCoordinate::try_from(30).unwrap(),
"E20S22".parse().unwrap(),
);
assert_eq!(pos2 - pos1, (0, 60));
let pos3 = Position::new(
RoomCoordinate::try_from(0).unwrap(),
RoomCoordinate::try_from(0).unwrap(),
"E20S21".parse().unwrap(),
);
assert_eq!(pos3 - pos1, (-4, -20));
Ordering
To facilitate use as a key in a BTreeMap
or other similar data
structures, Position
implements PartialOrd
and Ord
.
Position
s are ordered first by ascending world y
position, then by
ascending world x
position. World x
and y
here simply extend the x,y
coords within the room E0S0
throughout the map.
Looking at positions as tuples (world_x, world_y)
, the sorting obeys rules
such as:
(a, 0) < (b, 1)
for anya
,b
(0, c) < (1, c)
for anyc
This follows left-to-right reading order when looking at the Screeps map from above.
Implementations§
source§impl Position
impl Position
sourcepub fn towards(self, target: Position, distance_towards_target: i32) -> Position
pub fn towards(self, target: Position, distance_towards_target: i32) -> Position
Calculates an approximate midpoint between this point and the target.
In case of a tie, rounds towards this point.
If distance_towards_target
is bigger than the distance to the target,
the target is returned.
sourcepub fn between(self, target: Position, distance_from_target: i32) -> Position
pub fn between(self, target: Position, distance_from_target: i32) -> Position
Calculates an approximate midpoint between this point and the target.
In case of a tie, rounds towards the target.
If distance_from_target
is bigger than the distance to the target,
this position is returned.
sourcepub fn midpoint_between(self, target: Position) -> Position
pub fn midpoint_between(self, target: Position) -> Position
Calculates an approximate midpoint between this point and the target.
In case of a tie, rounds towards the target.
source§impl Position
impl Position
sourcepub fn offset(&mut self, x: i32, y: i32)
pub fn offset(&mut self, x: i32, y: i32)
Returns a new position offset from this position by the specified x coords and y coords.
This function operates on world coordinates, and will wrap between rooms if necessary.
To return a new position rather than modifying in place, use pos + (x, y)
. See the implementation of Add<(i32, i32)>
for
Position
further down on this page.
Panics
Will panic if the new position overflows the world. See
Position::from_world_coords
.
Example
let e21s21 = "E21S21".parse().unwrap();
let e21s22 = "E21S22".parse().unwrap();
let mut pos = Position::new(
RoomCoordinate::try_from(21).unwrap(),
RoomCoordinate::try_from(21).unwrap(),
e21s21,
);
pos.offset(5, 5);
assert_eq!(
pos,
Position::new(
RoomCoordinate::try_from(26).unwrap(),
RoomCoordinate::try_from(26).unwrap(),
e21s21
)
);
pos.offset(0, 49);
assert_eq!(
pos,
Position::new(
RoomCoordinate::try_from(26).unwrap(),
RoomCoordinate::try_from(25).unwrap(),
e21s22
)
);
source§impl Position
impl Position
sourcepub fn get_direction_to(self, target: Position) -> Option<Direction>
pub fn get_direction_to(self, target: Position) -> Option<Direction>
Gets linear direction to the specified position.
Note that this chooses between Top
/Bottom
/Left
/Right
and
TopLeft
/TopRight
/BottomLeft
/BottomRight
by the magnitude in both
directions. For instance, Direction::Top
can be returned even
if the target has a slightly different x
coordinate.
sourcepub fn get_range_to(self, target: Position) -> u32
pub fn get_range_to(self, target: Position) -> u32
Gets linear range to the specified position.
This operates on positions as “world positions”, and will return an
accurate range for positions in different rooms. Note that the
corresponding JavaScript method, RoomPosition.getRangeTo
returns
Infinity
if given positions in different rooms.
sourcepub fn in_range_to(self, target: Position, range: u32) -> bool
pub fn in_range_to(self, target: Position, range: u32) -> bool
Checks whether this position is in the given range of another position.
This operates on positions as “world positions”, and may return true for
positions in different rooms which are still within the given range.
Note that the corresponding JavaScript method, RoomPosition.inRangeTo
,
will always return false
for positions from different rooms.
sourcepub fn is_equal_to(self, target: Position) -> bool
pub fn is_equal_to(self, target: Position) -> bool
Checks whether this position is the same as the specified position.
Note that this is equivalent to this_pos == target.pos()
.
sourcepub fn is_near_to(self, target: Position) -> bool
pub fn is_near_to(self, target: Position) -> bool
True if this position is in the same room as the target, and the range is at most 1.
source§impl Position
impl Position
sourcepub fn create_construction_site(
self,
ty: StructureType,
name: Option<&JsString>
) -> ReturnCode
pub fn create_construction_site( self, ty: StructureType, name: Option<&JsString> ) -> ReturnCode
Creates a ConstructionSite
at this position. If it’s a
StructureSpawn
, a name can optionally be assigned for the structure.
sourcepub fn create_flag(
self,
name: Option<&JsString>,
color: Option<Color>,
secondary_color: Option<Color>
) -> Result<JsString, ErrorCode>
pub fn create_flag( self, name: Option<&JsString>, color: Option<Color>, secondary_color: Option<Color> ) -> Result<JsString, ErrorCode>
Creates a Flag
at this position. If successful, returns the name of
the created flag.
sourcepub fn find_closest_by_path<T>(
self,
ty: T,
options: Option<&Object>
) -> Option<T::Item>where
T: FindConstant,
<T as FindConstant>::Item: From<JsValue>,
pub fn find_closest_by_path<T>( self, ty: T, options: Option<&Object> ) -> Option<T::Item>where T: FindConstant, <T as FindConstant>::Item: From<JsValue>,
Find the closest object by path among a list of objects, or use
a find
constant to search for all objects of that type in the room.
sourcepub fn find_closest_by_range<T>(self, ty: T) -> Option<T::Item>where
T: FindConstant,
pub fn find_closest_by_range<T>(self, ty: T) -> Option<T::Item>where T: FindConstant,
Find the closest object by range among a list of objects, or use
a find
constant to search for all objects of that type in the room.
Will not work for objects in other rooms.
sourcepub fn find_in_range<T>(self, ty: T, range: u8) -> Vec<T::Item>where
T: FindConstant,
pub fn find_in_range<T>(self, ty: T, range: u8) -> Vec<T::Item>where T: FindConstant,
Find all relevant objects within a certain range among a list of
objects, or use a find
constant to search all objects of that type
in the room.
sourcepub fn find_path_to<T, F, R>(
&self,
target: &T,
options: Option<FindPathOptions<F, R>>
) -> Pathwhere
T: HasPosition,
F: FnMut(RoomName, CostMatrix) -> R,
R: RoomCostResult,
pub fn find_path_to<T, F, R>( &self, target: &T, options: Option<FindPathOptions<F, R>> ) -> Pathwhere T: HasPosition, F: FnMut(RoomName, CostMatrix) -> R, R: RoomCostResult,
Find a path from this position to a position or room object, with an optional options object
sourcepub fn find_path_to_xy<F, R>(
self,
x: RoomCoordinate,
y: RoomCoordinate,
options: Option<FindPathOptions<F, R>>
) -> Pathwhere
F: FnMut(RoomName, CostMatrix) -> R,
R: RoomCostResult,
pub fn find_path_to_xy<F, R>( self, x: RoomCoordinate, y: RoomCoordinate, options: Option<FindPathOptions<F, R>> ) -> Pathwhere F: FnMut(RoomName, CostMatrix) -> R, R: RoomCostResult,
Find a path from this position to the given coordinates in the same room, with an optional options object.
sourcepub fn look(self) -> Vec<LookResult>
pub fn look(self) -> Vec<LookResult>
Get all objects at this position.
sourcepub fn look_for<T>(self, ty: T) -> Vec<T::Item>where
T: LookConstant,
pub fn look_for<T>(self, ty: T) -> Vec<T::Item>where T: LookConstant,
Get all objects of a given type at this position, if any.
source§impl Position
impl Position
sourcepub fn world_x(self) -> i32
pub fn world_x(self) -> i32
Returns this position’s horizontal “world coordinate”.
The value is equal to 50 * room_x + x
, where room_x
is defined as
room_x = -xx - 1
for Wxx
rooms and as room_x = xx
for Exx
rooms.
sourcepub fn world_y(self) -> i32
pub fn world_y(self) -> i32
Returns this position’s vertical “world coordinate”.
The value is equal to 50 * room_y + y
, where room_y
is defined as
room_y = -yy - 1
for Nyy
rooms and as room_y = yy
for Syy
rooms.
sourcepub fn world_coords(self) -> (i32, i32)
pub fn world_coords(self) -> (i32, i32)
Returns this position’s “world coordinates”.
The first value is equal to 50 * room_x + x
, where room_x
is defined
as room_x = -xx - 1
for Wxx
rooms and as room_x = xx
for Exx
rooms.
The second value is equal to 50 * room_y + y
, where room_y
is
defined as room_y = -yy - 1
for Nyy
rooms and as room_y = yy
for Syy
rooms.
See also Position::world_x
and
Position::world_y
.
sourcepub fn from_world_coords(x: i32, y: i32) -> Self
pub fn from_world_coords(x: i32, y: i32) -> Self
Creates a room position from world coords.
Panics
Panics if either x or y is out of the range -128 * 50 .. +128 * 50
.
source§impl Position
impl Position
sourcepub fn new(x: RoomCoordinate, y: RoomCoordinate, room_name: RoomName) -> Self
pub fn new(x: RoomCoordinate, y: RoomCoordinate, room_name: RoomName) -> Self
Create a new Position
Panics
Will panic if either x
or y
is larger than 49, or if room_name
is
outside of the range E127N127 - W127S127
.
pub fn packed_repr(self) -> u32
pub fn from_packed(packed: u32) -> Self
sourcepub fn x(self) -> RoomCoordinate
pub fn x(self) -> RoomCoordinate
Gets this position’s in-room x coordinate.
sourcepub fn y(self) -> RoomCoordinate
pub fn y(self) -> RoomCoordinate
Gets this position’s in-room y coordinate.
pub fn room_name(self) -> RoomName
pub fn set_x(&mut self, x: RoomCoordinate)
pub fn set_y(&mut self, y: RoomCoordinate)
pub fn set_room_name(&mut self, room_name: RoomName)
pub fn with_x(self, x: RoomCoordinate) -> Self
pub fn with_y(self, y: RoomCoordinate) -> Self
pub fn with_room_name(self, room_name: RoomName) -> Self
Trait Implementations§
source§impl Add<(i32, i32)> for Position
impl Add<(i32, i32)> for Position
source§fn add(self, (x, y): (i32, i32)) -> Self
fn add(self, (x, y): (i32, i32)) -> Self
Adds an (x, y)
pair to this room position’s world coordinates.
Will change rooms if necessary.
Panics
Will panic if the new position’s room is outside bounds. See
Position::from_world_coords
.
Example
let w5s6 = "W5S6".parse().unwrap();
let w5s5 = "W5S5".parse().unwrap();
let pos1 = Position::new(
RoomCoordinate::try_from(42).unwrap(),
RoomCoordinate::try_from(42).unwrap(),
w5s6,
);
let pos2 = pos1 + (7, 7);
assert_eq!(
pos2,
Position::new(
RoomCoordinate::try_from(49).unwrap(),
RoomCoordinate::try_from(49).unwrap(),
w5s6
)
);
let pos3 = pos2 + (0, -59);
assert_eq!(
pos3,
Position::new(
RoomCoordinate::try_from(49).unwrap(),
RoomCoordinate::try_from(40).unwrap(),
w5s5
)
);
let pos4 = pos3 - (49, 0);
assert_eq!(
pos4,
Position::new(
RoomCoordinate::try_from(0).unwrap(),
RoomCoordinate::try_from(40).unwrap(),
w5s5
)
);
source§impl<'de> Deserialize<'de> for Position
impl<'de> Deserialize<'de> for Position
source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where D: Deserializer<'de>,
source§impl From<&Position> for RoomPosition
impl From<&Position> for RoomPosition
source§impl From<&RoomPosition> for Position
impl From<&RoomPosition> for Position
source§fn from(js_pos: &RoomPosition) -> Self
fn from(js_pos: &RoomPosition) -> Self
source§impl From<Position> for RoomPosition
impl From<Position> for RoomPosition
source§impl From<RoomPosition> for Position
impl From<RoomPosition> for Position
source§fn from(js_pos: RoomPosition) -> Self
fn from(js_pos: RoomPosition) -> Self
source§impl Index<Position> for LocalCostMatrix
impl Index<Position> for LocalCostMatrix
source§impl IndexMut<Position> for LocalCostMatrix
impl IndexMut<Position> for LocalCostMatrix
source§impl Ord for Position
impl Ord for Position
source§impl PartialEq<Position> for Position
impl PartialEq<Position> for Position
source§impl PartialOrd<Position> for Position
impl PartialOrd<Position> for Position
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self
and other
) and is used by the <=
operator. Read moresource§impl Sub<Position> for Position
impl Sub<Position> for Position
source§fn sub(self, other: Position) -> (i32, i32)
fn sub(self, other: Position) -> (i32, i32)
Subtracts the other room position from this one, extracting the difference as the output.
Example
let e5n5 = "E5N5".parse().unwrap();
let e5n6 = "E5N6".parse().unwrap();
let pos1 = Position::new(
RoomCoordinate::try_from(40).unwrap(),
RoomCoordinate::try_from(40).unwrap(),
e5n5,
);
let pos2 = Position::new(
RoomCoordinate::try_from(0).unwrap(),
RoomCoordinate::try_from(20).unwrap(),
e5n6,
);
assert_eq!(pos1 - pos2, (40, 70));