Skip to content

Commit 6e172c7

Browse files
committed
Validate tags are known to unify_fgd, fix some typos
1 parent 708a2b2 commit 6e172c7

File tree

5 files changed

+55
-6
lines changed

5 files changed

+55
-6
lines changed

fgd/bases/WeaponSpawnSingle.fgd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@
2424

2525

2626
// Outputs
27-
output OnItemSpawn[L4D1](void) : "Fired if this object is spawned on the map. If the weapon is removed during the weapon spawn pass, this will not fire."
27+
output OnItemSpawn[L4D](void) : "Fired if this object is spawned on the map. If the weapon is removed during the weapon spawn pass, this will not fire."
2828
]

fgd/brush/func/func_healthcharger.fgd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@SolidClass base(BaseEntityVisBrush, EnableDisable)
2-
appliesto(HL1, EP1, EP2, P1, MBase)
2+
appliesto(HLS, EP1, EP2, P1, MBase)
33
= func_healthcharger: "Original brush-based health recharger."
44
[
55
// Outputs

fgd/point/info/info_map_parameters_versus.fgd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
molotovdensity(float) : "Molotov density" : "6.48" : "Molotov density per sq 100 yards"
99
pipebombdensity(float) : "Pipe Bomb density" : "6.48" : "Pipe Bomb density per sq 100 yards"
1010
pistoldensity(float) : "Pistol density" : "6.48" : "Pistol density per sq 100 yards"
11-
weapondensity[L4D1](float) : "Weapon density" : "6.48" : "Weapon (non-pistol) density per sq 100 yards"
11+
weapondensity[L4D](float) : "Weapon density" : "6.48" : "Weapon (non-pistol) density per sq 100 yards"
1212
gascandensity(float) : "Gas Can density" : "6.48" : "Gas Can density per sq 100 yards"
1313
oxygentankdensity(float) : "Oxygen Tank density" : "6.48" : "Oxygen Tank density per sq 100 yards"
1414
propanetankdensity(float) : "Propane Tank density" : "6.48" : "Propane Tank density per sq 100 yards"

fgd/point/multisource.fgd

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
@PointClass base(BaseEntityPoint)
2-
autovis(HL1)
32
iconsprite("editor/multisource")
4-
appliesto(complete, -Strata)
3+
appliesto(complete)
54
= multisource: "Goldsource-era entity for combining multiple inputs. Superceded by the I/O system, and logic_branch_listener." +
65
"Entities with their 'trigger' keyvalue set to the name of this will be detected, Then once they all have Use-ed this, it will fire the output."
76
[

src/hammeraddons/unify_fgd.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from __future__ import annotations
66

77
from typing import Any
8-
from collections.abc import Callable, MutableMapping
8+
from collections.abc import Callable, MutableMapping, Iterator
99
from collections import Counter, defaultdict, ChainMap, deque
1010
from pathlib import Path
1111
import argparse
@@ -49,6 +49,7 @@
4949
('HLS', 'Half-Life: Source'),
5050
('DODS', 'Day of Defeat: Source'),
5151
('CSS', 'Counter-Strike: Source'),
52+
('HL2DM', 'Half-Life 2: Deathmatch'),
5253
],
5354
'EP2': [
5455
('MESA', 'Black Mesa'),
@@ -714,6 +715,22 @@ def check_ent_sprites(ent: EntityDef, used: dict[str, list[str]]) -> None:
714715
used[display].append(ent.classname)
715716

716717

718+
def iter_tags(fgd: FGD) -> Iterator[str]:
719+
"""Iterate over all tags defined in the FGD."""
720+
for ent in fgd:
721+
for helper in ent.get_helpers(HelperExtAppliesTo):
722+
yield from helper.applies
723+
for kv_map in ent.keyvalues.values():
724+
for tags, kv in kv_map.items():
725+
yield from tags
726+
if kv.val_list is not None:
727+
for tup in kv.val_list:
728+
yield from tup[-1]
729+
for io_map in itertools.chain(ent.inputs.values(), ent.outputs.values()):
730+
for tags in io_map:
731+
yield from tags
732+
733+
717734
def action_count(
718735
dbase: Path,
719736
extra_db: Path | None,
@@ -957,6 +974,26 @@ def report_missing_res(msg: str) -> None:
957974
continue
958975
print(f'{len(info):02}: {key[:64]!r} -> {info}')
959976

977+
def check_parents(done: set[EntityDef], repeat: set[EntityDef], ent: EntityDef) -> None:
978+
if ent in done:
979+
repeat.add(ent)
980+
else:
981+
done.add(ent)
982+
for base in ent.bases:
983+
assert isinstance(base, EntityDef), (ent, ent.bases)
984+
check_parents(done, repeat, base)
985+
986+
for ent in fgd:
987+
done: set[EntityDef] = set()
988+
repeat: set[EntityDef] = set()
989+
check_parents(done, repeat, ent)
990+
if repeat:
991+
print(
992+
f'Repeated bases: {ent.classname} = '
993+
f'{[ent.classname for ent in repeat]}, '
994+
f'all={[ent.classname for ent in done]}'
995+
)
996+
960997

961998
def action_import(
962999
dbase: Path,
@@ -1092,6 +1129,16 @@ def action_export(
10921129

10931130
print(f'Map size: ({fgd.map_size_min}, {fgd.map_size_max})')
10941131

1132+
# Gather all the tags used by entities, make sure there aren't unrecognised ones - typos etc.
1133+
used_tags = {
1134+
tag.lstrip('!-+').upper()
1135+
for tag in iter_tags(fgd)
1136+
}
1137+
print(f'{len(used_tags)}/{len(ALL_TAGS)} tags used in DB.')
1138+
extra_tags = used_tags - ALL_TAGS
1139+
if extra_tags:
1140+
raise ValueError(f'Unknown tags: {extra_tags}')
1141+
10951142
aliases: dict[EntityDef, str | EntityDef] = {}
10961143
if engine_mode or collapse_bases:
10971144
# In engine mode, we don't care about specific games.
@@ -1153,6 +1200,8 @@ def action_export(
11531200
break
11541201
elif '-ENGINE' not in tags and '!ENGINE' not in tags:
11551202
tag_map[tags] = value
1203+
elif isinstance(value, KVDef) and value.editor_only:
1204+
tag_map[tags - {'-ENGINE', '!ENGINE'}] = value
11561205

11571206
if not tag_map:
11581207
# All were set as non-engine, so it's not present.
@@ -1418,6 +1467,7 @@ def action_export(
14181467
fgd.export(
14191468
txt_f,
14201469
custom_syntax=False,
1470+
escape_quotes='SINCE_STRATA' in tags,
14211471
# HL2/episodes require the old syntax.
14221472
old_report='UNTIL_L4D' in tags,
14231473
)

0 commit comments

Comments
 (0)