group
- class Group(id: str = None, name: str = 'group', type: str = 'group', position: dict | list | tuple = (0, 0), entities: list = [], string: str = None)
Bases:
Transformable
,EntityCollection
,EntityLike
Group entities together, so you can manipulate them all as one unit.
Allows for the creation of “blocks” that can be added multiple times very easily to a blueprint. This allows you to create a section with complex circuit connections, and then add that
Group
multiple times and the circuit connections will be the same for every block with no extra work.Groups can also be used to organize Blueprints at the structure level. You can give entities the same name in a Blueprint as long as they exist in different groups. For example, the following is a perfectly valid structure for a Blueprint to have:
<Blueprint>.entities => [ <Group "1">.entities => [<Entity "A">, <Entity "B">, <Entity "C">], <Group "2">.entities => [<Entity "A">, <Entity "B">, <Entity "C">], ]
This is particularly useful if each group has a similar function, but just exists as a different “part” of the overall blueprint.
To aid in quickly accessing nested entities in such structures,
EntityLists
support indexing with a sequence, usually a tuple. For example, assuming the Blueprint structure above, all of the following assertions are true:assert blueprint.entities[("1", "A")].id == "A" assert isinstance(blueprint.entities[("2", "A")], Entity) assert blueprint.entities[("1", "C")] is blueprint.entities["1"].entities["C"]
EntityLike
instances in a Group are considered to be in “group-space”; meaning their positions are offset by the position of the Group they reside in. If a Group is located at position(5, 5)
, and an entity inside of it is located at(5, 5)
, when added to a Blueprint the entity will be located at(10, 10)
. This effect continues if Groups nest inside of other Groups, which is also perfectly legal.Groups have their own
SpatialHashMap
instances, so they will issueOverlappingObjectsWarning
when entities overlap, both when adding entities to the Group and when adding the Group to anotherEntityCollection
.- add_circuit_connection(color: str, entity_1: EntityLike | int | str, entity_2: EntityLike | int | str, side1: int = 1, side2: int = 1) None
Adds a circuit wire connection between two entities. Each entity can be either a reference to the original entity to connect, the index of the entity in the
entities
list, or it’s string ID. Color specifies the color of the wire to make the connection with, and is either"red"
or"green"
.side1
specifies which side of the first entity to connect to (if applicable), andside2
specifies which side of the second entity to connect to (if applicable). Does nothing if the connection already exists.Raises
ConnectionSideWarning
if the side of either of the entities is2
when the entity is not dual-circuit-connectable.Raises
ConnectionRangeWarning
if the distance between the two entities exceeds the maximum wire distance between the two.- Parameters:
color – Color of the wire to make the connection with. Must be either
"red"
or"green"
.id1 – ID or index of the first entity to join.
id2 – ID or index of the second entity to join.
side1 – Which side of the first dual-circuit-entity to connect to, where
1
is “input” and2
is “output”. Only used when the first entity is dual-circuit-connectable. Defaults to1
.side2 – Which side of the second dual-circuit-entity to connect to, where
1
is “input” and2
is “output”. Only used when the second entity is dual-circuit-connectable. Defaults to1
.
- Raises:
KeyError, IndexError – If
entity_1
and/orentity_2
are invalid ID’s or indices to the parent Collection.InvalidAssociationError – If
entity_1
and/orentity_2
are not inside the parent Collection.InvalidWireTypeError – If
color
is neither"red"
nor"green"
.InvalidConnectionSideError – If
side1
orside2
are neither1
nor2
.EntityNotCircuitConnectableError – If either entity_1 or entity_2 do not have the capability to be circuit wire connected.
- add_power_connection(entity_1: EntityLike | int | str, entity_2: EntityLike | int | str, side: int = 1) None
Adds a copper wire power connection between two entities. Each entity can be either a reference to the original entity to connect, the index of the entity in the
entities
list, or it’s string ID. Tuples of strings and ints mean to recursively search throughEntityCollection
instances in the base level, following the logic ofEntityList.__getitem__()
. For example:blueprint.entities.append("small-electric-pole") group = Group("group") # Type of EntityCollection group.entities.append("small-electric-pole", tile_position=(5, 0)) blueprint.entities.append(group) # Add a connection between the first power pole and the first entity # in the group blueprint.add_power_connection(blueprint.entities[0], ("group", 0))
Side specifies which side to connect to when establishing a connection to a dual-power-connectable entity (usually a power-switch). Does nothing if the connection already exists.
Raises
ConnectionRangeWarning
if the distance between the two entities exceeds the maximum wire distance between the two.Raises
TooManyConnectionsWarning
if either of the power poles exceed 5 connections when this connection is added.Note
side
is in 1-based notation (1 and 2, input and output) which is identical to circuit connections. Internally, however, the connections are represented in 0-based notation as “Cu0” and “Cu1” respectively.Note
You might notice that unlike
add_circuit_connection()
, there is only oneside
argument. This is because it is actually impossible to connect two dual-power-connectable entities with one another; they must be connected to a power pole in-between.- Parameters:
entity_1 – EntityLike, ID, or index of the first entity to join.
entity_2 – EntityLike, ID or index of the second entity to join.
side – Which side of a dual-power-connectable entity to connect to, where
1
is “input” and2
is “output”. Only used when connecting a dual-power-connectable entity. Defaults to1
.
- Raises:
KeyError, IndexError – If
entity_1
and/orentity_2
are invalid ID’s or indices to the parent Collection.InvalidAssociationError – If
entity_1
and/orentity_2
are not inside the parent Collection.InvalidConnectionSideError – If
side
is neither1
nor2
.EntityNotPowerConnectableError – If either entity_1 or entity_2 do not have the capability to be copper wire connected.
DraftsmanError – If both entity_1 and entity_2 are dual-power-connectable, of which a connection is forbidden.
- find_entities(aabb: AABB | list[list[float, float], list[float, float]] | None = None) list[EntityLike]
Returns a
list
of all entities within the areaaabb
. Works similiarly to LuaSurface.find_entities. If noaabb
is provided then the method simply returns all the entities in the blueprint.- Parameters:
aabb – An
AABB
, or aSequence
of 4 floats, usually alist
ortuple
.- Returns:
A regular
list
ofEntityLikes
whosecollision_box
overlaps the queried AABB.
- find_entities_filtered(**kwargs: dict) list[EntityLike]
Returns a filtered list of entities within the
Collection
. Works similarly to LuaSurface.find_entities_filtered.Keywords are organized into two main categrories: region and criteria:
Name
Type
Description
position
Vector
orPrimitiveVector
Grid position to search.
radius
float
Radius of the circle around position to search.
area
AABB
orPrimitiveAABB
AABB to search in.
Name
Type
Description
name
str
orset{str}
The name(s) of the entities that you want to search for.
type
str
orset{str}
The type(s) of the entities that you want to search for.
direction
Direction
orset{Direction}
The direction(s) of the entities that you want to search for.Excludes entities that have no direction.limit
int
Limit the maximum size of the returned list to this amount.Unlimited by default.invert
bool
Whether or not to return the inverse of the search.False by default.position
andradius
take precidence overaabb
if all are specified. If no region keywords are specified, the entire Collection is searched.
- find_entity(name: str, position: Vector | PrimitiveVector) EntityLike
Finds an entity with
name
at a positionposition
. If multiple entities exist at the queried position, the one that was first placed is returned.- Parameters:
name – The name of the entity to look for.
position – The position to search, either a PrimitiveVector or a
Vector
.
- Retuns:
The
EntityLike
atposition
, orNone
of none were found.
- find_entity_at_position(position: Vector | PrimitiveVector) EntityLike
Finds any entity at the position
position
. If multiple entities exist at the queried position, the one that was first placed is returned.- Parameters:
position – The position to search, either a PrimitiveVector or a
Vector
.- Retuns:
The
EntityLike
atposition
, orNone
of none were found.
- flip(direction: str = 'horizontal') None
Flip the blueprint across an axis, if possible. Flipping is done over the x or y axis, depeding on the input
direction
.Warning
This function is currently under active development.
- Parameters:
direction – The direction to flip by; either
"horizontal"
or"vertical"
- generate_power_connections(prefer_axis: bool = True, only_axis: bool = False) None
Automatically create power connections between all electric poles.
The algorithm used is similar to demi-pixel’s generateElectricalConnections() function, but with some slight differences. Power poles are still prioritized closest first, but can be selected to prefer to connect neighbours on the same axis, as well as only connect to neighbours on the same axis. This function will only connect power poles that have less than 5 power connections already made, preserving power connections that were manually specified. This function does not generate connections between power-switches.
- Parameters:
prefer_axis – Determines whether or not to rank power-poles on the same x or y coordinate higher than poles that are closer, but not on either axis. Used to prefer creating neat, regular grids when possible.
only_axis – Removes any neighbour that does not lie on the same x or y axis from the candidate pool, preventing non-grid connections.
- get()
Gets all the child-most
Entity
instances in thisGroup
and returns them as a “flattened” 1-dimensional list. Offsets all of their positions by the position of the parentGroup
.- Returns:
A
list
ofEntity
instances associated with thisGroup
.
- get_world_collision_set() CollisionSet
Get’s the world-space coordinate CollisionSet of the object, or the collection of all shapes that this EntityLike interacts with.
- Returns:
A new
CollisionSet
with it’s content’s copied.
- load_from_string(blueprint_string: str) None
Load the Blueprint with the contents of
blueprint_string
. Raisesdraftsman.warning.DraftsmanWarning
if there are any unrecognized keywords in the blueprint string.- Parameters:
blueprint_string – Factorio-encoded blueprint string.
- Raises:
MalformedBlueprintStringError – If the input string is not decodable to a JSON object.
IncorrectBlueprintTypeError – If the input string is of a different type than the base class, such as a
BlueprintBook
.
- mergable_with(other: Group) bool
Checks to see if an entity is “mergable” with another entity. This means that if a certain set of criteria is met, the attributes of
other
will be combined to the attributes of this entity. This is useful for mimicking cases where entities of the same name and type are placed on top of each other, merging them together into a single entity with shared attributes.For the full list of all merging rules, see (TODO).
Note
This function does not actually merge the two, it simply checks to see if such a merge is considered valid. To actually merge two entities use
merge()
.- Parameters:
other – The other
EntityLike
to check against.- Returns:
True
if they can be merged,False
otherwise.
- merge(other: Group) None
Changes the attributes of the calling entity with the attributes of the passed in entity. The attributes of
other
take precedence over the attributes of the calling entity. They can be either copied or merged together, depending on the specific attribute being merged.For the full list of all merging rules, see (TODO).
- Parameters:
other – The other
EntityLike
to merge with.
- on_entity_insert(entitylike: EntityLike, merge: bool) EntityLike
Callback function for when an
EntityLike
is added to this Group’sentities
list. Handles the addition of the entity into the Group’sSpatialHashMap
, and recalculates it’s dimensions.
- on_entity_remove(entitylike: EntityLike) None
Callback function for when an entity is removed from a Blueprint’s
entities
list. Handles the removal of theEntityLike
from theSpatialHashMap
.
- on_entity_set(old_entitylike: EntityLike, new_entitylike: EntityLike) None
Callback function for when an entity is overwritten in a Group’s
entities
list. Handles the removal of the oldEntityLike
from theSpatialHashMap
and adds the new one in it’s stead.
- on_insert(parent: EntityCollection) None
TODO
- on_remove(parent: EntityCollection) None
TODO
- recalculate_area() None
Recalculates the dimensions of the area and tile_width and height. Called when an
EntityLike
object is altered or removed.
- remove_circuit_connection(color: str, entity_1: EntityLike | int | str, entity_2: EntityLike | int | str, side1: int = 1, side2: int = 1) None
Removes a circuit wire connection between two entities. Each entity can be either a reference to the original entity to connect, the index of the entity in the
entities
list, or it’s string ID.side1
specifies which side of the first entity to remove the connection from (if applicable), andside2
specifies which side of the second entity to remove the connection from (if applicable). Does nothing if the specified connection doesn’t exist.- Parameters:
color – Color of the wire to remove. Either
"red"
or"green"
.entity_1 – ID or index of the first entity to remove the connection to.
entity_@ – ID or index of the second entity to remove the connection to.
side1 – Which side of the first dual-circuit-connectable entity to remove the connection from, where
1
is “input” and2
is “output”. Only used when disjoining a dual-circuit-connectable entity. Defaults to1
.side2 – Which side of the second dual-circuit-connectable entity to remove the connection from, where
1
is “input” and2
is “output”. Only used when disjoining a dual-circuit-connectable entity. Defaults to1
.
- Raises:
KeyError, IndexError – If
entity_1
and/orentity_2
are invalid ID’s or indices to the parent Collection.InvalidAssociationError – If
entity_1
and/orentity_2
are not inside the parent Collection.
- remove_circuit_connections() None
Remove all circuit connections in the Collection. Recurses through all subgroups and removes circuit connections from them as well. Does nothing if there are no circuit connections in the Collection.
- remove_power_connection(entity_1: EntityLike | int | str, entity_2: EntityLike | int | str, side: int = 1) None
Removes a copper wire power connection between two entities. Each entity can be either a reference to the original entity to connect, the index of the entity in the
entities
list, or it’s string ID.side
specifies which side to remove the connection from when removing a connection to a dual-power-connectable entity (usually a power-switch). Does nothing if the specified connection does not exist.- Parameters:
entity_1 – EntityLike, ID or index of the first entity to remove the connection to.
entity_2 – EntityLike, ID or index of the second entity to remove the connection to.
side – Which side of a dual-power-connectable entity to remove the connection from, where
1
is “input” and2
is “output”. Only used when disjoining a dual-power-connectable entity. Defaults to1
.
- Raises:
KeyError, IndexError – If
entity_1
and/orentity_2
are invalid ID’s or indices to the parent Collection.InvalidAssociationError – If
entity_1
and/orentity_2
are not inside the parent Collection.
- remove_power_connections() None
Remove all power connections in the Collection, including any power connections between power switches. Recurses through any subgroups, and removes power connections from them as well. Does nothing if there are no power connections in the Collection.
- rotate(angle: int) None
Rotate the blueprint by
angle
, if possible. Operates the same as pressing ‘r’ with a blueprint selected.angle
is specified in terms of Direction enum, meaning that a rotation of 2 is 90 degrees clockwise.Because eight-way rotatable entities exist in a weird gray area, this function behaves like the feature in-game and only rotates on 90 degree intervals. Attempting to rotate the blueprint an odd amount raises an
RotationError
.Warning
This function is currently under active development.
- Parameters:
angle – The angle to rotate the blueprint by.
- Raises:
RotationError – If the rotation is attempted with an odd value.
- setup(**kwargs: dict) None
Sets up a Group using a blueprint JSON dict. Currently only reads the
"entities"
key and loads them intoGroup.entities
.
- translate(x: int, y: int) None
Translates all entities and tiles in the blueprint by
x
andy
. RaisesRailAlignmentWarning
if the parent class contains double-grid-aligned entities and the translation amount is an odd value on either x or y.- Parameters:
x – A number indicating how much to translate along x.
y – A number indicating how much to translate along y.
- property circuit_connectable: bool
Whether or not this EntityLike can be connected using circuit wires. Not exported; read only.
- Type:
bool
- property collision_mask: set
The set of all collision layers that this Entity collides with, specified as strings. Defaults to an empty
set
. Not exported.- Getter:
Gets the collision mask of the Group.
- Setter:
Sets the collision mask of the Group, or sets it to an empty set if
None
was input.- Type:
set{str}
- Raises:
TypeError – If set to anything other than a set or None.
- property collision_set: CollisionSet
TODO: is this even a good idea to have in the first place? It seems like having this set be the union of all entities it contains would make the most sense, but that would be slow to compute instead of using a spatial map for that. The user could specify a custom collision set, but how is that supposed to interact with the hashmap? no idea
- property double_grid_aligned: bool
Whether or not this EntityLike is “double-grid-aligned”, which applies to a number of rail entities. Not exported; read only.
- Type:
bool
- property dual_circuit_connectable: bool
Whether or not this EntityLike has two circuit connection points. Not exported; read only.
- Type:
bool
- property dual_power_connectable: bool
Whether or not this EntityLike has two power connection points. Not exported; read only.
- Type:
bool
- property entities: EntityList
The list of the Group’s entities. Internally the list is a custom class named
draftsman.classes.EntityList
, which has all the normal properties of a regular list, as well as some extra features. For more information onEntityList
, check out this writeup here.
- property entity_map: SpatialDataStructure
An implementation of
SpatialDataStructure
forentities
. Not exported; read only.
- property flippable: bool
Whether or not this collection can be flipped or not. This is determined by whether or not any of the entities contained can be flipped or not. Read only.
- Type:
bool
- property global_position: dict
The “global”, or root-most position of the Group. This value is always equivalent to
position
, unless the group exists inside anotherEntityCollection
. If it does, then it’s global position is equivalent to the sum of all parent positions plus it’s own position. Used when recursing the position of any sub-entity contained within theGroup
. Read only.- Type:
dict{"x": float, "y": float}
- property id: str
The ID of the Group. The most local form of identification between Groups.
- Getter:
Gets the ID of the Group.
- Setter:
Sets the ID of the Group.
- Type:
str
- Raises:
TypeError – If set to anything other than a
str
orNone
.
- property name: str
The name of the Group. Defaults to
"group"
. Can be specified to any string to aid in organization. For example:blueprint.entities.append(Group("A")) blueprint.entities.append(Group("B", name="different_name")) diff = blueprint.find_entities_filtered(name="different_name") assert diff[0] is blueprint.entities["B"]
- Getter:
Gets the name of the Group.
- Setter:
Sets the name of the Group.
- Type:
str
- Raises:
TypeError – If set to anything other than a
str
.
- property parent: EntityCollection
The parent
EntityCollection
object that contains the entity, orNone
if the entity does not currently exist within anEntityCollection
. Not exported; read only.- Type:
EntityCollection
- property position: dict
The position of the Group. Acts as the origin of all the entities contained within, and offsets them on export.
position
can be specified as adict
with"x"
and"y"
keys, or more succinctly as a sequence of floats, usually alist
ortuple
.- Getter:
Gets the position of the Group.
- Setter:
Sets the position of the Group.
- Type:
dict{"x": float, "y": float}
- Raises:
IndexError – If the set value does not match the above specification.
DraftsmanError – If the Group’s position is modified when inside a EntityCollection, which is forbidden.
- property power_connectable: bool
Whether or not this EntityLike can be connected using power wires. Not exported; read only.
- Type:
bool
- property rotatable: bool
Whether or not this collection can be rotated or not. Included for posterity; always returns True, even when containing entities that have no direction component. Read only.
- Type:
bool
- property tile_height: int
The width of the Group’s
collision_box
, rounded up to the nearest tile. Read only.- Type:
int
- property tile_width: int
The width of the Group’s
collision_box
, rounded up to the nearest tile. Read only.- Type:
int
- property type: str
The type of the Group. Defaults to
"group"
. Can be specified to any string to aid in organization. For example:blueprint.entities.append(Group("A")) blueprint.entities.append(Group("B", type="different_type")) diff = blueprint.find_entities_filtered(type="different_type") assert diff[0] is blueprint.entities["B"]
- Getter:
Gets the type of the Group.
- Setter:
Sets the type of the Group.
- Type:
str
- Raises:
TypeError – If set to anything other than a
str
.