diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1576bbe3e5..4168fdf742f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,7 @@ jobs: python tools/ci/check_random_spawner_prefabs.py python -m tools.ci.check_map_sizes python -m tools.ci.check_legacy_attack_chain + python -m tools.ci.check_simplemob_additions python -m tools.maplint.source --github - name: Run DreamChecker diff --git a/tools/ci/check_legacy_attack_chain.py b/tools/ci/check_legacy_attack_chain.py index 0a69d815528..be18a0a502e 100644 --- a/tools/ci/check_legacy_attack_chain.py +++ b/tools/ci/check_legacy_attack_chain.py @@ -2,11 +2,11 @@ import os import sys import time from dataclasses import dataclass -from collections import namedtuple, defaultdict +from collections import defaultdict +from typing import Any from avulto import DME, Path as p, ProcDecl, TypeDecl from avulto.ast import NodeKind -from avulto import exceptions RED = "\033[0;31m" @@ -21,7 +21,7 @@ class AttackChainCall: var_name: str var_type: p | None call_name: str - source_info: any + source_info: Any legacy: bool def make_error_message(self): diff --git a/tools/ci/check_simplemob_additions.py b/tools/ci/check_simplemob_additions.py new file mode 100644 index 00000000000..56b8aff677d --- /dev/null +++ b/tools/ci/check_simplemob_additions.py @@ -0,0 +1,308 @@ +import os +from pathlib import Path +import sys +import time + +from avulto import DME, Path as p +from avulto.ast import SourceLoc + + +RED = "\033[0;31m" +GREEN = "\033[0;32m" +BLUE = "\033[0;34m" +NC = "\033[0m" # No Color + +BURNDOWN_LIST = { + p(x) + for x in { + "/mob/living/simple_animal/bot", + "/mob/living/simple_animal/bot/cleanbot", + "/mob/living/simple_animal/bot/ed209", + "/mob/living/simple_animal/bot/ed209/bluetag", + "/mob/living/simple_animal/bot/ed209/redtag", + "/mob/living/simple_animal/bot/ed209/syndicate", + "/mob/living/simple_animal/bot/floorbot", + "/mob/living/simple_animal/bot/honkbot", + "/mob/living/simple_animal/bot/medbot", + "/mob/living/simple_animal/bot/medbot/adv", + "/mob/living/simple_animal/bot/medbot/brute", + "/mob/living/simple_animal/bot/medbot/fire", + "/mob/living/simple_animal/bot/medbot/fish", + "/mob/living/simple_animal/bot/medbot/machine", + "/mob/living/simple_animal/bot/medbot/mysterious", + "/mob/living/simple_animal/bot/medbot/o2", + "/mob/living/simple_animal/bot/medbot/syndicate", + "/mob/living/simple_animal/bot/medbot/syndicate/emagged", + "/mob/living/simple_animal/bot/medbot/tox", + "/mob/living/simple_animal/bot/mulebot", + "/mob/living/simple_animal/bot/secbot", + "/mob/living/simple_animal/bot/secbot/armsky", + "/mob/living/simple_animal/bot/secbot/beepsky", + "/mob/living/simple_animal/bot/secbot/buzzsky", + "/mob/living/simple_animal/bot/secbot/buzzsky/telecomms", + "/mob/living/simple_animal/bot/secbot/buzzsky/telecomms/doomba", + "/mob/living/simple_animal/bot/secbot/griefsky", + "/mob/living/simple_animal/bot/secbot/griefsky/toy", + "/mob/living/simple_animal/bot/secbot/ofitser", + "/mob/living/simple_animal/bot/secbot/pingsky", + "/mob/living/simple_animal/chick", + "/mob/living/simple_animal/chicken", + "/mob/living/simple_animal/chicken/clucky", + "/mob/living/simple_animal/chicken/featherbottom", + "/mob/living/simple_animal/chicken/kentucky", + "/mob/living/simple_animal/crab", + "/mob/living/simple_animal/crab/coffee", + "/mob/living/simple_animal/crab/evil", + "/mob/living/simple_animal/demon", + "/mob/living/simple_animal/demon/pulse_demon", + "/mob/living/simple_animal/demon/pulse_demon/wizard", + "/mob/living/simple_animal/demon/shadow", + "/mob/living/simple_animal/demon/slaughter", + "/mob/living/simple_animal/demon/slaughter/cult", + "/mob/living/simple_animal/demon/slaughter/laughter", + "/mob/living/simple_animal/demon/slaughter/lesser", + "/mob/living/simple_animal/diona", + "/mob/living/simple_animal/drone", + "/mob/living/simple_animal/goose", + "/mob/living/simple_animal/hostile", + "/mob/living/simple_animal/hostile/ancient_robot_leg", + "/mob/living/simple_animal/hostile/asteroid", + "/mob/living/simple_animal/hostile/asteroid/abandoned_minebot", + "/mob/living/simple_animal/hostile/asteroid/elite", + "/mob/living/simple_animal/hostile/asteroid/elite/broodmother", + "/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child", + "/mob/living/simple_animal/hostile/asteroid/elite/herald", + "/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror", + "/mob/living/simple_animal/hostile/asteroid/elite/legionnaire", + "/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead", + "/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/xenobiology", + "/mob/living/simple_animal/hostile/asteroid/elite/pandora", + "/mob/living/simple_animal/hostile/asteroid/goliath", + "/mob/living/simple_animal/hostile/asteroid/goliath/beast", + "/mob/living/simple_animal/hostile/asteroid/goliath/beast/ancient", + "/mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril", + "/mob/living/simple_animal/hostile/asteroid/goliath/space", + "/mob/living/simple_animal/hostile/blob", + "/mob/living/simple_animal/hostile/blob/blobbernaut", + "/mob/living/simple_animal/hostile/blob/blobspore", + "/mob/living/simple_animal/hostile/clockwork_construct", + "/mob/living/simple_animal/hostile/clockwork_construct/clockwork_marauder", + "/mob/living/simple_animal/hostile/clockwork_construct/clockwork_marauder/hostile", + "/mob/living/simple_animal/hostile/construct", + "/mob/living/simple_animal/hostile/construct/armoured", + "/mob/living/simple_animal/hostile/construct/armoured/hostile", + "/mob/living/simple_animal/hostile/construct/behemoth", + "/mob/living/simple_animal/hostile/construct/behemoth/hostile", + "/mob/living/simple_animal/hostile/construct/builder", + "/mob/living/simple_animal/hostile/construct/builder/hostile", + "/mob/living/simple_animal/hostile/construct/harvester", + "/mob/living/simple_animal/hostile/construct/harvester/hostile", + "/mob/living/simple_animal/hostile/construct/proteon", + "/mob/living/simple_animal/hostile/construct/proteon/hostile", + "/mob/living/simple_animal/hostile/construct/wraith", + "/mob/living/simple_animal/hostile/construct/wraith/hostile", + "/mob/living/simple_animal/hostile/construct/wraith/hostile/bubblegum", + "/mob/living/simple_animal/hostile/deathsquid", + "/mob/living/simple_animal/hostile/deathsquid/joke", + "/mob/living/simple_animal/hostile/floor_cluwne", + "/mob/living/simple_animal/hostile/guardian", + "/mob/living/simple_animal/hostile/guardian/assassin", + "/mob/living/simple_animal/hostile/guardian/beam", + "/mob/living/simple_animal/hostile/guardian/bomb", + "/mob/living/simple_animal/hostile/guardian/charger", + "/mob/living/simple_animal/hostile/guardian/gaseous", + "/mob/living/simple_animal/hostile/guardian/healer", + "/mob/living/simple_animal/hostile/guardian/healer/sealhealer", + "/mob/living/simple_animal/hostile/guardian/protector", + "/mob/living/simple_animal/hostile/guardian/punch", + "/mob/living/simple_animal/hostile/guardian/punch/sealpunch", + "/mob/living/simple_animal/hostile/guardian/ranged", + "/mob/living/simple_animal/hostile/headslug", + "/mob/living/simple_animal/hostile/illusion", + "/mob/living/simple_animal/hostile/illusion/cult", + "/mob/living/simple_animal/hostile/illusion/escape", + "/mob/living/simple_animal/hostile/illusion/escape/cult", + "/mob/living/simple_animal/hostile/illusion/escape/stealth", + "/mob/living/simple_animal/hostile/illusion/mirage", + "/mob/living/simple_animal/hostile/malf_drone", + "/mob/living/simple_animal/hostile/megafauna", + "/mob/living/simple_animal/hostile/megafauna/ancient_robot", + "/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner", + "/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance", + "/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter", + "/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/syndicate", + "/mob/living/simple_animal/hostile/megafauna/bubblegum", + "/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination", + "/mob/living/simple_animal/hostile/megafauna/bubblegum/round_2", + "/mob/living/simple_animal/hostile/megafauna/colossus", + "/mob/living/simple_animal/hostile/megafauna/dragon", + "/mob/living/simple_animal/hostile/megafauna/dragon/lesser", + "/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon", + "/mob/living/simple_animal/hostile/megafauna/fleshling", + "/mob/living/simple_animal/hostile/megafauna/hierophant", + "/mob/living/simple_animal/hostile/megafauna/legion", + "/mob/living/simple_animal/hostile/mimic", + "/mob/living/simple_animal/hostile/mimic/copy", + "/mob/living/simple_animal/hostile/mimic/copy/machine", + "/mob/living/simple_animal/hostile/mimic/copy/ranged", + "/mob/living/simple_animal/hostile/mimic/copy/vendor", + "/mob/living/simple_animal/hostile/mimic/crate", + "/mob/living/simple_animal/hostile/morph", + "/mob/living/simple_animal/hostile/morph/wizard", + "/mob/living/simple_animal/hostile/mushroom", + "/mob/living/simple_animal/hostile/panther", + "/mob/living/simple_animal/hostile/poison", + "/mob/living/simple_animal/hostile/poison/bees", + "/mob/living/simple_animal/hostile/poison/bees/queen", + "/mob/living/simple_animal/hostile/poison/bees/syndi", + "/mob/living/simple_animal/hostile/poison/terror_spider", + "/mob/living/simple_animal/hostile/poison/terror_spider/black", + "/mob/living/simple_animal/hostile/poison/terror_spider/brown", + "/mob/living/simple_animal/hostile/poison/terror_spider/gray", + "/mob/living/simple_animal/hostile/poison/terror_spider/green", + "/mob/living/simple_animal/hostile/poison/terror_spider/mother", + "/mob/living/simple_animal/hostile/poison/terror_spider/prince", + "/mob/living/simple_animal/hostile/poison/terror_spider/purple", + "/mob/living/simple_animal/hostile/poison/terror_spider/queen", + "/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress", + "/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess", + "/mob/living/simple_animal/hostile/poison/terror_spider/red", + "/mob/living/simple_animal/hostile/poison/terror_spider/white", + "/mob/living/simple_animal/hostile/retaliate", + "/mob/living/simple_animal/hostile/retaliate/carp", + "/mob/living/simple_animal/hostile/retaliate/carp/koi", + "/mob/living/simple_animal/hostile/retaliate/carp/koi/honk", + "/mob/living/simple_animal/hostile/retaliate/goat", + "/mob/living/simple_animal/hostile/retaliate/goat/chef", + "/mob/living/simple_animal/hostile/spaceinfected", + "/mob/living/simple_animal/hostile/spaceinfected/default", + "/mob/living/simple_animal/hostile/spaceinfected/default/ranged", + "/mob/living/simple_animal/hostile/spaceinfected/gateopener", + "/mob/living/simple_animal/hostile/statue", + "/mob/living/simple_animal/hostile/syndicate", + "/mob/living/simple_animal/hostile/syndicate/depot", + "/mob/living/simple_animal/hostile/syndicate/depot/modsuit", + "/mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup", + "/mob/living/simple_animal/hostile/syndicate/depot/modsuit/elite", + "/mob/living/simple_animal/hostile/syndicate/depot/officer", + "/mob/living/simple_animal/hostile/syndicate/modsuit", + "/mob/living/simple_animal/hostile/syndicate/modsuit/elite", + "/mob/living/simple_animal/hostile/syndicate/modsuit/ranged", + "/mob/living/simple_animal/hostile/syndicate/ranged", + "/mob/living/simple_animal/hostile/syndicate/ranged/orion", + "/mob/living/simple_animal/hostile/syndicate/shield", + "/mob/living/simple_animal/hostile/tree", + "/mob/living/simple_animal/hostile/venus_human_trap", + "/mob/living/simple_animal/hostile/viscerator", + "/mob/living/simple_animal/hostile/winter", + "/mob/living/simple_animal/hostile/winter/reindeer", + "/mob/living/simple_animal/hostile/winter/santa", + "/mob/living/simple_animal/hostile/winter/santa/stage_1", + "/mob/living/simple_animal/hostile/winter/santa/stage_2", + "/mob/living/simple_animal/hostile/winter/santa/stage_3", + "/mob/living/simple_animal/hostile/winter/santa/stage_4", + "/mob/living/simple_animal/hostile/winter/snowman", + "/mob/living/simple_animal/hostile/winter/snowman/ranged", + "/mob/living/simple_animal/mouse", + "/mob/living/simple_animal/mouse/blobinfected", + "/mob/living/simple_animal/mouse/brown", + "/mob/living/simple_animal/mouse/brown/tom", + "/mob/living/simple_animal/mouse/gray", + "/mob/living/simple_animal/mouse/white", + "/mob/living/simple_animal/mouse/white/brain", + "/mob/living/simple_animal/mouse/white/linter", + "/mob/living/simple_animal/parrot", + "/mob/living/simple_animal/parrot/poly", + "/mob/living/simple_animal/pet", + "/mob/living/simple_animal/pet/cat", + "/mob/living/simple_animal/pet/cat/cak", + "/mob/living/simple_animal/pet/cat/kitten", + "/mob/living/simple_animal/pet/cat/proc_cat", + "/mob/living/simple_animal/pet/cat/runtime", + "/mob/living/simple_animal/pet/cat/syndi", + "/mob/living/simple_animal/pet/cat/var_cat", + "/mob/living/simple_animal/pet/dog", + "/mob/living/simple_animal/pet/dog/corgi", + "/mob/living/simple_animal/pet/dog/corgi/borgi", + "/mob/living/simple_animal/pet/dog/corgi/exoticcorgi", + "/mob/living/simple_animal/pet/dog/corgi/ian", + "/mob/living/simple_animal/pet/dog/corgi/lisa", + "/mob/living/simple_animal/pet/dog/corgi/narsie", + "/mob/living/simple_animal/pet/dog/corgi/puppy", + "/mob/living/simple_animal/pet/dog/corgi/puppy/void", + "/mob/living/simple_animal/pet/dog/fox", + "/mob/living/simple_animal/pet/dog/fox/renault", + "/mob/living/simple_animal/pet/dog/fox/syndifox", + "/mob/living/simple_animal/pet/dog/pug", + "/mob/living/simple_animal/revenant", + "/mob/living/simple_animal/seal", + "/mob/living/simple_animal/shade", + "/mob/living/simple_animal/shade/cult", + "/mob/living/simple_animal/shade/holy", + "/mob/living/simple_animal/shade/sword", + "/mob/living/simple_animal/shade/sword/generic_item", + "/mob/living/simple_animal/slime", + "/mob/living/simple_animal/slime/pet", + "/mob/living/simple_animal/slime/random", + "/mob/living/simple_animal/slime/unit_test_dummy", + "/mob/living/simple_animal/spiderbot", + "/mob/living/simple_animal/turkey", + "/mob/living/simple_animal/walrus", + } +} + + +def format_error(source_loc: SourceLoc | Path, message): + if isinstance(source_loc, SourceLoc): + if os.getenv("GITHUB_ACTIONS") == "true": + return f"::error file={source_loc.file_path},line={source_loc.line},title=Simplemob Additions::{source_loc.file_path}:{source_loc.line}: {RED}{message}{NC}" + else: + return f"{source_loc.file_path}:{source_loc.line}: {RED}{message}{NC}" + else: + if os.getenv("GITHUB_ACTIONS") == "true": + return f"::error file={source_loc},title=Simplemob Additions::{source_loc}: {RED}{message}{NC}" + else: + return f"{source_loc}: {RED}{message}{NC}" + + +if __name__ == "__main__": + print("check_simplemob_additions started") + + exit_code = 0 + start = time.time() + + dme = DME.from_file("paradise.dme") + + simplemobs = set(dme.subtypesof("/mob/living/simple_animal")) + additions = simplemobs - BURNDOWN_LIST + + if additions: + exit_code = 1 + print("unexpected simplemobs found:") + type_decls = [dme.types[pth] for pth in additions] + for type_decl in type_decls: + print( + format_error( + type_decl.source_loc, + f"unexpected simplemob addition {type_decl.path}.", + ) + ) + print("Please implement all new mobs as /mob/living/basic mobs.") + + unexpected = BURNDOWN_LIST - simplemobs + if unexpected: + exit_code = 1 + print("the following paths were allowed but not found:") + for pth in sorted(unexpected): + print( + format_error( + Path(__file__).relative_to(dme.filepath.resolve().parent), + f"stale path {pth}.", + ) + ) + print("Please remove the offending paths from check_simplemob_additions.py.") + + end = time.time() + print(f"check_simplemob_additions tests completed in {end - start:.2f}s\n") + + sys.exit(exit_code) diff --git a/tools/requirements.txt b/tools/requirements.txt index f70ccfa61a8..f8f62d8f790 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -8,4 +8,4 @@ PyYaml>=6.0.1 # maplint also beautifulsoup4>=4.12.2 # various CI checks -avulto==0.1.16 +avulto==0.1.17