133 lines
4.9 KiB
Python
133 lines
4.9 KiB
Python
import os
|
|
import yaml
|
|
import json
|
|
|
|
def parse_prototypes(root_dir):
|
|
all_entities = {}
|
|
|
|
# Recursively find all .yml files
|
|
for root, dirs, files in os.walk(root_dir):
|
|
for file in files:
|
|
if file.endswith(".yml"):
|
|
file_path = os.path.join(root, file)
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
# Define a loader that ignores custom !type tags
|
|
class IgnoreTagsLoader(yaml.SafeLoader):
|
|
pass
|
|
|
|
def ignore_tag(loader, tag_suffix, node):
|
|
if isinstance(node, yaml.MappingNode):
|
|
return loader.construct_mapping(node)
|
|
elif isinstance(node, yaml.SequenceNode):
|
|
return loader.construct_sequence(node)
|
|
return loader.construct_scalar(node)
|
|
|
|
IgnoreTagsLoader.add_multi_constructor('!', ignore_tag)
|
|
|
|
# Some files have multiple YAML documents separated by ---
|
|
docs = yaml.load_all(f, Loader=IgnoreTagsLoader)
|
|
for doc in docs:
|
|
if not doc or not isinstance(doc, list):
|
|
continue
|
|
for entry in doc:
|
|
if entry.get('type') == 'entity' and 'id' in entry:
|
|
all_entities[entry['id']] = entry
|
|
except Exception as e:
|
|
print(f"Error parsing {file_path}: {e}")
|
|
|
|
# Helper to get components including from parents
|
|
def get_components(entity_id, seen=None):
|
|
if seen is None:
|
|
seen = set()
|
|
if entity_id in seen:
|
|
return {}
|
|
seen.add(entity_id)
|
|
|
|
entity = all_entities.get(entity_id)
|
|
if not entity:
|
|
return {}
|
|
|
|
merged_components = {}
|
|
|
|
parent = entity.get('parent')
|
|
if parent:
|
|
parents = [parent] if isinstance(parent, str) else parent
|
|
for p in parents:
|
|
parent_comps = get_components(p, seen)
|
|
# Merge parent components into our current set
|
|
for ctype, cdata in parent_comps.items():
|
|
if ctype not in merged_components:
|
|
merged_components[ctype] = cdata.copy()
|
|
else:
|
|
merged_components[ctype].update(cdata)
|
|
|
|
# Now add/override with local components
|
|
local_components = entity.get('components', [])
|
|
for comp in local_components:
|
|
ctype = comp.get('type')
|
|
if not ctype:
|
|
continue
|
|
if ctype not in merged_components:
|
|
merged_components[ctype] = comp.copy()
|
|
else:
|
|
merged_components[ctype].update(comp)
|
|
|
|
return merged_components
|
|
|
|
extractables = {}
|
|
|
|
for eid, entity in all_entities.items():
|
|
if entity.get('abstract'):
|
|
continue
|
|
|
|
components = get_components(eid)
|
|
|
|
extractable = components.get('Extractable')
|
|
solution_manager = components.get('SolutionContainerManager')
|
|
name = entity.get('name', eid)
|
|
|
|
if extractable:
|
|
data = {
|
|
"id": eid,
|
|
"name": name,
|
|
"grind": [],
|
|
"juice": []
|
|
}
|
|
|
|
# Grinding
|
|
grind_sol_name = extractable.get('grindableSolutionName')
|
|
if grind_sol_name and solution_manager:
|
|
sols = solution_manager.get('solutions', {})
|
|
target_sol = sols.get(grind_sol_name, {})
|
|
reagents = target_sol.get('reagents', [])
|
|
for r in reagents:
|
|
data['grind'].append({
|
|
"id": r['ReagentId'],
|
|
"amount": r['Quantity']
|
|
})
|
|
|
|
# Juicing
|
|
juice_sol = extractable.get('juiceSolution')
|
|
if juice_sol:
|
|
reagents = juice_sol.get('reagents', [])
|
|
for r in reagents:
|
|
data['juice'].append({
|
|
"id": r['ReagentId'],
|
|
"amount": r['Quantity']
|
|
})
|
|
|
|
if data['grind'] or data['juice']:
|
|
extractables[eid] = data
|
|
|
|
return extractables
|
|
|
|
if __name__ == "__main__":
|
|
root = "/home/laythe/Documents/ss14reagent/Prototypes"
|
|
results = parse_prototypes(root)
|
|
|
|
with open("extractables.json", "w", encoding="utf-8") as f:
|
|
json.dump(results, f, indent=2)
|
|
|
|
print(f"Successfully extracted {len(results)} items to extractables.json")
|