diff --git a/changelog.md b/changelog.md index e16687e..7031d35 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # Changelog +# 1.1.0 +* Added a number of missing prototype objects that are blueprintable: + * `SimpleEntityWithOwner` + * `SimpleEntityWithForce` + * `PlayerPort` +* Fixed an issue where color settings were not recognized in the settings stage (#103) * Fixed issue loading IndustrialRevolution modpack (regression) (#98) ## 1.0.6 diff --git a/draftsman/_factorio_version.py b/draftsman/_factorio_version.py index 26960bd..c5ddd56 100644 --- a/draftsman/_factorio_version.py +++ b/draftsman/_factorio_version.py @@ -1,4 +1,4 @@ # _factorio_version.py -__factorio_version__ = "1.1.88.0" -__factorio_version_info__ = (1, 1, 88, 0) +__factorio_version__ = "1.1.89.0" +__factorio_version_info__ = (1, 1, 89, 0) diff --git a/draftsman/_version.py b/draftsman/_version.py index 4c4b01c..a99ca72 100644 --- a/draftsman/_version.py +++ b/draftsman/_version.py @@ -1,4 +1,4 @@ # version.py -__version__ = "1.0.6" -__version_info__ = (1, 0, 6) +__version__ = "1.1.0" +__version_info__ = (1, 1, 0) diff --git a/draftsman/compatibility/settings.lua b/draftsman/compatibility/settings.lua index 6fa025d..7101145 100644 --- a/draftsman/compatibility/settings.lua +++ b/draftsman/compatibility/settings.lua @@ -30,4 +30,5 @@ end set_settings("bool-setting") set_settings("int-setting") set_settings("double-setting") -set_settings("string-setting") \ No newline at end of file +set_settings("string-setting") +set_settings("color-setting") \ No newline at end of file diff --git a/draftsman/data/entities.pkl b/draftsman/data/entities.pkl index 17e8bd9..7de346e 100644 Binary files a/draftsman/data/entities.pkl and b/draftsman/data/entities.pkl differ diff --git a/draftsman/data/entities.py b/draftsman/data/entities.py index 1e3c9a7..f8bc164 100644 --- a/draftsman/data/entities.py +++ b/draftsman/data/entities.py @@ -75,6 +75,8 @@ gates = _data["gates"] turrets = _data["turrets"] radars = _data["radars"] + simple_entities_with_owner = _data["simple_entities_with_owner"] + simple_entities_with_force = _data["simple_entities_with_force"] electric_energy_interfaces = _data["electric_energy_interfaces"] linked_containers = _data["linked_containers"] heat_interfaces = _data["heat_interfaces"] @@ -82,3 +84,4 @@ infinity_containers = _data["infinity_containers"] infinity_pipes = _data["infinity_pipes"] burner_generators = _data["burner_generators"] + player_ports = _data["player_ports"] diff --git a/draftsman/data/items.pkl b/draftsman/data/items.pkl index a1511c0..cea80f1 100644 Binary files a/draftsman/data/items.pkl and b/draftsman/data/items.pkl differ diff --git a/draftsman/data/mods.pkl b/draftsman/data/mods.pkl index 11c85c3..3382499 100644 Binary files a/draftsman/data/mods.pkl and b/draftsman/data/mods.pkl differ diff --git a/draftsman/data/modules.pkl b/draftsman/data/modules.pkl index 6f196c2..62e655b 100644 Binary files a/draftsman/data/modules.pkl and b/draftsman/data/modules.pkl differ diff --git a/draftsman/data/recipes.pkl b/draftsman/data/recipes.pkl index 65b595a..4bb59dc 100644 Binary files a/draftsman/data/recipes.pkl and b/draftsman/data/recipes.pkl differ diff --git a/draftsman/data/signals.pkl b/draftsman/data/signals.pkl index 3a7fb07..bf68a96 100644 Binary files a/draftsman/data/signals.pkl and b/draftsman/data/signals.pkl differ diff --git a/draftsman/data/tiles.pkl b/draftsman/data/tiles.pkl index fe49dc1..8853945 100644 Binary files a/draftsman/data/tiles.pkl and b/draftsman/data/tiles.pkl differ diff --git a/draftsman/entity.py b/draftsman/entity.py index 2b9e239..f811153 100644 --- a/draftsman/entity.py +++ b/draftsman/entity.py @@ -61,6 +61,8 @@ from draftsman.prototypes.gate import Gate, gates from draftsman.prototypes.turret import Turret, turrets from draftsman.prototypes.radar import Radar, radars +from draftsman.prototypes.simple_entity_with_owner import SimpleEntityWithOwner, simple_entities_with_owner +from draftsman.prototypes.simple_entity_with_force import SimpleEntityWithForce, simple_entities_with_force from draftsman.prototypes.electric_energy_interface import ElectricEnergyInterface, electric_energy_interfaces from draftsman.prototypes.linked_container import LinkedContainer, linked_containers from draftsman.prototypes.heat_interface import HeatInterface, heat_interfaces @@ -68,6 +70,7 @@ from draftsman.prototypes.infinity_container import InfinityContainer, infinity_containers from draftsman.prototypes.infinity_pipe import InfinityPipe, infinity_pipes from draftsman.prototypes.burner_generator import BurnerGenerator, burner_generators +from draftsman.prototypes.player_port import PlayerPort, player_ports # fmt: on @@ -195,6 +198,10 @@ def new_entity(name, **kwargs): return Turret(name, **kwargs) if name in radars: return Radar(name, **kwargs) + if name in simple_entities_with_owner: + return SimpleEntityWithOwner(name, **kwargs) + if name in simple_entities_with_force: + return SimpleEntityWithForce(name, **kwargs) if name in electric_energy_interfaces: return ElectricEnergyInterface(name, **kwargs) if name in linked_containers: @@ -209,5 +216,7 @@ def new_entity(name, **kwargs): return InfinityPipe(name, **kwargs) if name in burner_generators: return BurnerGenerator(name, **kwargs) + if name in player_ports: + return PlayerPort(name, **kwargs) raise InvalidEntityError("'{}'".format(name)) diff --git a/draftsman/env.py b/draftsman/env.py index 847ee1d..af03f08 100644 --- a/draftsman/env.py +++ b/draftsman/env.py @@ -917,6 +917,20 @@ def sort(target_list): categorize_entities(data.raw["radar"], entities["radars"]) sort(entities["radars"]) + # Simple Entities with Owner + entities["simple_entities_with_owner"] = [] + categorize_entities( + data.raw["simple-entity-with-owner"], entities["simple_entities_with_owner"] + ) + sort(entities["simple_entities_with_owner"]) + + # Simple Entities with Force + entities["simple_entities_with_force"] = [] + categorize_entities( + data.raw["simple-entity-with-force"], entities["simple_entities_with_force"] + ) + sort(entities["simple_entities_with_force"]) + # Electric Energy Interfaces entities["electric_energy_interfaces"] = [] categorize_entities( @@ -962,6 +976,11 @@ def sort(target_list): categorize_entities(data.raw["burner-generator"], entities["burner_generators"]) sort(entities["burner_generators"]) + # Player Ports + entities["player_ports"] = [] + categorize_entities(data.raw["player-port"], entities["player_ports"]) + sort(entities["player_ports"]) + raw_order = get_order(unordered_entities_raw, *sort_tuple) entities["raw"] = OrderedDict() for name in raw_order: @@ -1545,7 +1564,7 @@ def update(verbose=False, path=None, show_logs=False, no_mods=False, report=None internal_folder=mod_folder, version=mod_version, archive=archive, - location=location.replace("\\", "/"), # Make sure forward slashes + location=location.replace("\\", "/"), # Make sure forward slashes info=mod_info, files=files, data=mod_data, diff --git a/draftsman/factorio-data b/draftsman/factorio-data index 3e4fb3a..ec79bdc 160000 --- a/draftsman/factorio-data +++ b/draftsman/factorio-data @@ -1 +1 @@ -Subproject commit 3e4fb3ae617547a19427c50856ccc7c6301d277b +Subproject commit ec79bdc77c4cdba7958225268cc935012f554ebe diff --git a/draftsman/prototypes/player_port.py b/draftsman/prototypes/player_port.py new file mode 100644 index 0000000..0d35bd8 --- /dev/null +++ b/draftsman/prototypes/player_port.py @@ -0,0 +1,29 @@ +# player_port.py + +from draftsman.classes.entity import Entity +from draftsman.warning import DraftsmanWarning + +from draftsman.data import entities +from draftsman.data.entities import player_ports + +import warnings + + +class PlayerPort(Entity): + """ + A constructable respawn point typically used in scenarios. + """ + + _exports = {} + _exports.update(Entity._exports) + + def __init__(self, name=player_ports[0], **kwargs): + # type: (str, **dict) -> None + super(PlayerPort, self).__init__(name, player_ports, **kwargs) + + for unused_arg in self.unused_args: + warnings.warn( + "{} has no attribute '{}'".format(type(self), unused_arg), + DraftsmanWarning, + stacklevel=2, + ) diff --git a/draftsman/prototypes/simple_entity_with_force.py b/draftsman/prototypes/simple_entity_with_force.py new file mode 100644 index 0000000..26648ae --- /dev/null +++ b/draftsman/prototypes/simple_entity_with_force.py @@ -0,0 +1,60 @@ +# simple_entity_with_force.py + +from draftsman.classes.entity import Entity +from draftsman.warning import DraftsmanWarning + +from draftsman.data import entities +from draftsman.data.entities import simple_entities_with_force + +import warnings + + +class SimpleEntityWithForce(Entity): + """ + A generic entity associated with a team of players. + """ + + _exports = {} + _exports.update(Entity._exports) + _exports.update( + { + "variation": { + "format": "int", + "description": "Graphical variation of the entity", + "required": lambda x: x is not None, + }, + } + ) + + def __init__(self, name=simple_entities_with_force[0], **kwargs): + # type: (str, **dict) -> None + super(SimpleEntityWithForce, self).__init__( + name, simple_entities_with_force, **kwargs + ) + + self.variation = 1 + if "variation" in kwargs: + self.variation = kwargs["variation"] + self.unused_args.pop("variation") + + for unused_arg in self.unused_args: + warnings.warn( + "{} has no attribute '{}'".format(type(self), unused_arg), + DraftsmanWarning, + stacklevel=2, + ) + + @property + def variation(self): + # type: () -> int + """ + The number representing the graphical variation of the entity. + + :type: ``int`` + """ + return self._variation + + @variation.setter + def variation(self, value): + # type: (int) -> None + self._variation = value diff --git a/draftsman/prototypes/simple_entity_with_owner.py b/draftsman/prototypes/simple_entity_with_owner.py new file mode 100644 index 0000000..e44fdc0 --- /dev/null +++ b/draftsman/prototypes/simple_entity_with_owner.py @@ -0,0 +1,60 @@ +# simple_entity_with_owner.py + +from draftsman.classes.entity import Entity +from draftsman.warning import DraftsmanWarning + +from draftsman.data import entities +from draftsman.data.entities import simple_entities_with_owner + +import warnings + + +class SimpleEntityWithOwner(Entity): + """ + A generic entity owned by some other entity. + """ + + _exports = {} + _exports.update(Entity._exports) + _exports.update( + { + "variation": { + "format": "int", + "description": "Graphical variation of the entity", + "required": lambda x: x is not None, + }, + } + ) + + def __init__(self, name=simple_entities_with_owner[0], **kwargs): + # type: (str, **dict) -> None + super(SimpleEntityWithOwner, self).__init__( + name, simple_entities_with_owner, **kwargs + ) + + self.variation = 1 + if "variation" in kwargs: + self.variation = kwargs["variation"] + self.unused_args.pop("variation") + + for unused_arg in self.unused_args: + warnings.warn( + "{} has no attribute '{}'".format(type(self), unused_arg), + DraftsmanWarning, + stacklevel=2, + ) + + @property + def variation(self): + # type: () -> int + """ + The number representing the graphical variation of the entity. + + :type: ``int`` + """ + return self._variation + + @variation.setter + def variation(self, value): + # type: (int) -> None + self._variation = value diff --git a/test/entities/test_player_port.py b/test/entities/test_player_port.py new file mode 100644 index 0000000..52501eb --- /dev/null +++ b/test/entities/test_player_port.py @@ -0,0 +1,47 @@ +# test_player_port.py +# -*- encoding: utf-8 -*- + +from __future__ import unicode_literals + +from draftsman.entity import PlayerPort, player_ports +from draftsman.error import InvalidEntityError +from draftsman.warning import DraftsmanWarning + +import sys + +if sys.version_info >= (3, 3): # pragma: no coverage + import unittest +else: # pragma: no coverage + import unittest2 as unittest + + +class PlayerPortTesting(unittest.TestCase): + def test_contstructor_init(self): + turret = PlayerPort() + + with self.assertWarns(DraftsmanWarning): + PlayerPort(unused_keyword="whatever") + + with self.assertRaises(InvalidEntityError): + PlayerPort("this is not a player port") + + def test_mergable_with(self): + port1 = PlayerPort("player-port") + port2 = PlayerPort("player-port", tags={"some": "stuff"}) + + self.assertTrue(port1.mergable_with(port1)) + + self.assertTrue(port1.mergable_with(port2)) + self.assertTrue(port2.mergable_with(port1)) + + port2.tile_position = (1, 1) + self.assertFalse(port1.mergable_with(port2)) + + def test_merge(self): + port1 = PlayerPort("player-port") + port2 = PlayerPort("player-port", tags={"some": "stuff"}) + + port1.merge(port2) + del port2 + + self.assertEqual(port1.tags, {"some": "stuff"}) diff --git a/test/entities/test_simple_entity_with_force.py b/test/entities/test_simple_entity_with_force.py new file mode 100644 index 0000000..4d88b1b --- /dev/null +++ b/test/entities/test_simple_entity_with_force.py @@ -0,0 +1,74 @@ +# test_simple_entity_with_force.py +# -*- encoding: utf-8 -*- + +from __future__ import unicode_literals + +from draftsman.entity import SimpleEntityWithForce, simple_entities_with_force +from draftsman.error import InvalidEntityError +from draftsman.warning import DraftsmanWarning + +import sys + +if sys.version_info >= (3, 3): # pragma: no coverage + import unittest +else: # pragma: no coverage + import unittest2 as unittest + + +class SimpleEntityWithForceTesting(unittest.TestCase): + def test_contstructor_init(self): + entity = SimpleEntityWithForce(variation=13) + assert entity.name == simple_entities_with_force[0] + assert entity.variation == 13 + + with self.assertWarns(DraftsmanWarning): + SimpleEntityWithForce(unused_keyword="whatever") + + with self.assertRaises(InvalidEntityError): + SimpleEntityWithForce("this is not correct") + + def test_to_dict(self): + entity = SimpleEntityWithForce("simple-entity-with-force") + self.assertEqual(entity.variation, 1) + self.assertEqual( + entity.to_dict(), + { + "name": "simple-entity-with-force", + "position": {"x": 0.5, "y": 0.5}, + "variation": 1, + }, + ) + + entity.variation = None + self.assertEqual( + entity.to_dict(), + { + "name": "simple-entity-with-force", + "position": {"x": 0.5, "y": 0.5}, + }, + ) + + def test_mergable_with(self): + entity1 = SimpleEntityWithForce("simple-entity-with-force") + entity2 = SimpleEntityWithForce( + "simple-entity-with-force", tags={"some": "stuff"} + ) + + self.assertTrue(entity1.mergable_with(entity1)) + + self.assertTrue(entity1.mergable_with(entity2)) + self.assertTrue(entity2.mergable_with(entity1)) + + entity2.tile_position = (1, 1) + self.assertFalse(entity1.mergable_with(entity2)) + + def test_merge(self): + entity1 = SimpleEntityWithForce("simple-entity-with-force") + entity2 = SimpleEntityWithForce( + "simple-entity-with-force", tags={"some": "stuff"} + ) + + entity1.merge(entity2) + del entity2 + + self.assertEqual(entity1.tags, {"some": "stuff"}) diff --git a/test/entities/test_simple_entity_with_owner.py b/test/entities/test_simple_entity_with_owner.py new file mode 100644 index 0000000..f8558e5 --- /dev/null +++ b/test/entities/test_simple_entity_with_owner.py @@ -0,0 +1,74 @@ +# test_simple_entity_with_owner.py +# -*- encoding: utf-8 -*- + +from __future__ import unicode_literals + +from draftsman.entity import SimpleEntityWithOwner, simple_entities_with_owner +from draftsman.error import InvalidEntityError +from draftsman.warning import DraftsmanWarning + +import sys + +if sys.version_info >= (3, 3): # pragma: no coverage + import unittest +else: # pragma: no coverage + import unittest2 as unittest + + +class SimpleEntityWithOwnerTesting(unittest.TestCase): + def test_contstructor_init(self): + entity = SimpleEntityWithOwner(variation=13) + assert entity.name == simple_entities_with_owner[0] + assert entity.variation == 13 + + with self.assertWarns(DraftsmanWarning): + SimpleEntityWithOwner(unused_keyword="whatever") + + with self.assertRaises(InvalidEntityError): + SimpleEntityWithOwner("this is not correct") + + def test_to_dict(self): + entity = SimpleEntityWithOwner("simple-entity-with-owner") + self.assertEqual(entity.variation, 1) + self.assertEqual( + entity.to_dict(), + { + "name": "simple-entity-with-owner", + "position": {"x": 0.5, "y": 0.5}, + "variation": 1, + }, + ) + + entity.variation = None + self.assertEqual( + entity.to_dict(), + { + "name": "simple-entity-with-owner", + "position": {"x": 0.5, "y": 0.5}, + }, + ) + + def test_mergable_with(self): + entity1 = SimpleEntityWithOwner("simple-entity-with-owner") + entity2 = SimpleEntityWithOwner( + "simple-entity-with-owner", tags={"some": "stuff"} + ) + + self.assertTrue(entity1.mergable_with(entity1)) + + self.assertTrue(entity1.mergable_with(entity2)) + self.assertTrue(entity2.mergable_with(entity1)) + + entity2.tile_position = (1, 1) + self.assertFalse(entity1.mergable_with(entity2)) + + def test_merge(self): + entity1 = SimpleEntityWithOwner("simple-entity-with-owner") + entity2 = SimpleEntityWithOwner( + "simple-entity-with-owner", tags={"some": "stuff"} + ) + + entity1.merge(entity2) + del entity2 + + self.assertEqual(entity1.tags, {"some": "stuff"}) diff --git a/test/test_entity.py b/test/test_entity.py index 62e6902..26c6b1f 100644 --- a/test/test_entity.py +++ b/test/test_entity.py @@ -314,6 +314,12 @@ def test_turret(self): def test_radar(self): self.assertIsInstance(new_entity("radar"), Radar) + def test_simple_entity_with_owner(self): + self.assertIsInstance(new_entity("simple-entity-with-owner"), SimpleEntityWithOwner) + + def test_simple_entity_with_force(self): + self.assertIsInstance(new_entity("simple-entity-with-force"), SimpleEntityWithForce) + def test_electric_energy_interface(self): self.assertIsInstance(new_entity("electric-energy-interface"), ElectricEnergyInterface) @@ -337,6 +343,9 @@ def test_infinity_pipe(self): def test_burner_generator(self): self.assertIsInstance(new_entity("burner-generator"), BurnerGenerator) + def test_player_port(self): + self.assertIsInstance(new_entity("player-port"), PlayerPort) + def test_errors(self): self.assertRaises( InvalidEntityError, diff --git a/test/test_version.py b/test/test_version.py index 83ce9f1..e3cfc20 100644 --- a/test/test_version.py +++ b/test/test_version.py @@ -13,5 +13,5 @@ class ValidateVersion(unittest.TestCase): def test_versions(self): - self.assertEqual(draftsman.__version__, "1.0.6") - self.assertEqual(draftsman.__version_info__, (1, 0, 6)) + self.assertEqual(draftsman.__version__, "1.1.0") + self.assertEqual(draftsman.__version_info__, (1, 1, 0))