From cffb98229c67c8bf8b1f3926acd0b230ce15dee8 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 31 Dec 2016 04:43:43 -0500 Subject: [PATCH] Add killable objects (ships, etc.) to universe data. --- calefaction/eve/universe.py | 62 +++++++++++++++++++++++++-- scripts/import_sde.py | 88 ++++++++++++++++++++++++++++++-------- templates/campaigns/renderers.mako | 3 +- 3 files changed, 131 insertions(+), 22 deletions(-) diff --git a/calefaction/eve/universe.py b/calefaction/eve/universe.py index 42178bb..f2864a0 100644 --- a/calefaction/eve/universe.py +++ b/calefaction/eve/universe.py @@ -113,6 +113,39 @@ class _Faction(_UniqueObject): return self._data["name"] +class _Killable(_UniqueObject): + """Represents a killable object, like a ship, structure, or fighter.""" + + def __init__(self, universe, kid, cat, data): + super().__init__(universe, kid, data) + self._cat = cat + + @property + def name(self): + """The killable object's name, as a string.""" + return self._data["name"] + + @property + def group(self): + """The killable object's group, as a string.""" + return self._data["group"] + + @property + def is_ship(self): + """Whether the killable object is a ship.""" + return self._cat == "ships" + + @property + def is_structure(self): + """Whether the killable object is a structure.""" + return self._cat == "structures" + + @property + def is_fighter(self): + """Whether the killable object is a fighter.""" + return self._cat == "fighters" + + class _DummySolarSystem(_SolarSystem): """Represents an unknown or invalid solar system.""" @@ -153,6 +186,16 @@ class _DummyFaction(_Faction): }) +class _DummyKillable(_Killable): + """Represents an unknown or invalid killable object.""" + + def __init__(self, universe): + super().__init__(universe, -1, None, { + "name": "Unknown", + "group": "Unknown" + }) + + class Universe: """EVE API module for static universe data.""" @@ -166,6 +209,8 @@ class Universe: self._constellations = {} self._regions = {} self._factions = {} + self._killable_idx = {} + self._killable_tab = {} @staticmethod def _load_yaml(path): @@ -192,6 +237,12 @@ class Universe: self._factions = entities["factions"] del entities + types = self._load_yaml(self._dir / "types.yml.gz") + self._killable_idx = {kid: cat for cat, kids in types.items() + for kid in kids} + self._killable_tab = types + del types + self._loaded = True def system(self, sid): @@ -234,10 +285,13 @@ class Universe: return _DummyFaction(self) return _Faction(self, fid, self._factions[fid]) - def ship(self, sid): - """Return a _Ship with the given ID. + def killable(self, kid): + """Return a _Killable with the given ID. If the ID is invalid, return a dummy unknown object with ID -1. """ - ... - raise NotImplementedError() + self._load() + if kid not in self._killable_idx: + return _DummyKillable(self) + cat = self._killable_idx[kid] + return _Killable(self, kid, cat, self._killable_tab[cat][kid]) diff --git a/scripts/import_sde.py b/scripts/import_sde.py index a33f3b2..d3349fe 100755 --- a/scripts/import_sde.py +++ b/scripts/import_sde.py @@ -8,6 +8,10 @@ import sys import yaml +_SHIP_CAT = 6 +_FIGHTER_CAT = 87 +_STRUCT_CATS = [22, 23, 40, 46, 65] + _REGION = 3 _CONSTELLATION = 4 _SOLAR_SYSTEM = 5 @@ -16,12 +20,40 @@ def _load_yaml(filename): with filename.open("rb") as fp: return yaml.load(fp, Loader=yaml.CLoader) -def _verify_typeids(sde_dir): - print("Verifying typeIDs... ", end="", flush=True) +def _save_yaml(filename, data): + with filename.open("w") as fp: + fp.write(yaml.dump(data, Dumper=yaml.CDumper)) - filename = sde_dir / "fsd" / "typeIDs.yaml" - with filename.open("rb") as fp: - data = yaml.load(fp.read(1024 * 16), Loader=yaml.CLoader) +def _verify_categoryids(sde_dir): + print("Verifying categoryIDs... ", end="", flush=True) + + data = _load_yaml(sde_dir / "fsd" / "categoryIDs.yaml") + + assert data[_SHIP_CAT]["name"]["en"] == "Ship" + + print("done.") + +def _load_groupids(sde_dir): + print("Loading groupIDs... ", end="", flush=True) + + data = _load_yaml(sde_dir / "fsd" / "groupIDs.yaml") + + groups = {cid: {} for cid in [_SHIP_CAT, _FIGHTER_CAT] + _STRUCT_CATS} + for gid, group in data.items(): + cat = group["categoryID"] + if cat in groups: + name = group["name"]["en"] + assert isinstance(gid, int) + assert isinstance(name, str) + groups[cat][gid] = name + + print("done.") + return groups + +def _load_typeids(sde_dir, groups): + print("Loading typeIDs... ", end="", flush=True) + + data = _load_yaml(sde_dir / "fsd" / "typeIDs.yaml") assert data[_REGION]["groupID"] == _REGION assert data[_REGION]["name"]["en"] == "Region" @@ -30,7 +62,23 @@ def _verify_typeids(sde_dir): assert data[_SOLAR_SYSTEM]["groupID"] == _SOLAR_SYSTEM assert data[_SOLAR_SYSTEM]["name"]["en"] == "Solar System" + types = {"ships": {}, "structures": {}, "fighters": {}} + cat_conv = {_SHIP_CAT: "ships", _FIGHTER_CAT: "fighters"} + cat_conv.update({cid: "structures" for cid in _STRUCT_CATS}) + group_conv = {gid: cid for cid, gids in groups.items() for gid in gids} + + for tid, type_ in data.items(): + gid = type_["groupID"] + if gid in group_conv: + cid = group_conv[gid] + cname = cat_conv[cid] + name = type_["name"]["en"] + group = groups[cid][gid] + assert isinstance(tid, int) + types[cname][tid] = {"name": name, "group": group} + print("done.") + return types def _load_ids(sde_dir): print("Loading itemIDs... ", end="", flush=True) @@ -194,12 +242,17 @@ def _load_factions(sde_dir): print("done.") return factions +def _dump_types(out_dir, types): + print("Dumping types... ", end="", flush=True) + + _save_yaml(out_dir / "types.yml", types) + + print("done.") + def _dump_galaxy(out_dir, galaxy): print("Dumping galaxy... ", end="", flush=True) - filename = out_dir / "galaxy.yml" - with filename.open("w") as fp: - fp.write(yaml.dump(galaxy, Dumper=yaml.CDumper)) + _save_yaml(out_dir / "galaxy.yml", galaxy) print("done.") @@ -207,15 +260,12 @@ def _dump_entities(out_dir, factions): print("Dumping entities... ", end="", flush=True) entities = {"factions": factions} - - filename = out_dir / "entities.yml" - with filename.open("w") as fp: - fp.write(yaml.dump(entities, Dumper=yaml.CDumper)) + _save_yaml(out_dir / "entities.yml", entities) print("done.") def _compress(out_dir): - targets = ["galaxy", "entities"] + targets = ["types", "galaxy", "entities"] for basename in targets: print("Compressing %s... " % basename, end="", flush=True) @@ -231,7 +281,7 @@ def _compress(out_dir): def _cleanup(out_dir): print("Cleaning up... ", end="", flush=True) - targets = ["galaxy", "entities"] + targets = ["types", "galaxy", "entities"] for basename in targets: (out_dir / (basename + ".yml")).unlink() @@ -243,15 +293,19 @@ def import_sde(sde_dir, out_dir): print("- from: %s" % sde_dir) print("- to: %s" % out_dir) - _verify_typeids(sde_dir) + _verify_categoryids(sde_dir) + groups = _load_groupids(sde_dir) + types = _load_typeids(sde_dir, groups) + _dump_types(out_dir, types) + del groups, types + ids = _load_ids(sde_dir) print("Counts: regions=%d, constellations=%d, systems=%d" % ( len(ids[_REGION]), len(ids[_CONSTELLATION]), len(ids[_SOLAR_SYSTEM]))) names = _load_names(sde_dir) galaxy = _build_galaxy_skeleton(ids, names) - del ids - del names + del ids, names _load_galaxy_associations(sde_dir, galaxy) _dump_galaxy(out_dir, galaxy) del galaxy diff --git a/templates/campaigns/renderers.mako b/templates/campaigns/renderers.mako index 7c9f729..19885b4 100644 --- a/templates/campaigns/renderers.mako +++ b/templates/campaigns/renderers.mako @@ -7,6 +7,7 @@ <% victim = kill["victim"] system = g.eve.universe.system(kill["system"]) + killed = g.eve.universe.killable(victim["ship_id"]) %> @@ -21,7 +22,7 @@ - Kill ${kill['id']}: ... + Kill ${kill['id']}: ${killed.name}