added inventory, updated DB
This commit is contained in:
parent
f218350959
commit
10c51f6825
16528 changed files with 147743 additions and 79 deletions
294
inventory-service/extract_all_enums.py
Normal file
294
inventory-service/extract_all_enums.py
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Comprehensive enum extraction from Mag-Plugins/Shared/Constants directory.
|
||||
|
||||
This script extracts ALL enum definitions from the Mag-Plugins source code
|
||||
and creates structured JSON mappings for the inventory service.
|
||||
"""
|
||||
|
||||
import re
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any, Tuple, Optional
|
||||
|
||||
def extract_enum_from_file(file_path: Path) -> Tuple[str, Dict[str, Any]]:
|
||||
"""Extract enum definition from a C# file."""
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find enum declaration
|
||||
enum_match = re.search(r'public enum (\w+)(?:\s*:\s*(\w+))?\s*{', content)
|
||||
if not enum_match:
|
||||
return None, {}
|
||||
|
||||
enum_name = enum_match.group(1)
|
||||
enum_type = enum_match.group(2) or 'int'
|
||||
|
||||
print(f"Extracting {enum_name} from {file_path.name}")
|
||||
|
||||
# Extract enum entries
|
||||
entries = {}
|
||||
comments = {}
|
||||
attributes = {}
|
||||
|
||||
# Pattern to match enum entries with various formats
|
||||
# Supports: Name = Value, Name, Name = 0x12345, etc.
|
||||
pattern = r'^\s*(?:\[([^\]]+)\])?\s*(?:/// <summary>\s*([^<]*?)\s*/// </summary>\s*)?(?:\[([^\]]+)\])?\s*(\w+)(?:\s*=\s*([^,]+?))?\s*,?\s*(?://\s*(.*))?$'
|
||||
|
||||
lines = content.split('\n')
|
||||
in_enum = False
|
||||
current_value = 0
|
||||
|
||||
for line in lines:
|
||||
# Check if we're entering the enum
|
||||
if f'enum {enum_name}' in line:
|
||||
in_enum = True
|
||||
continue
|
||||
|
||||
# Check if we're exiting the enum
|
||||
if in_enum and '}' in line and not line.strip().startswith('//'):
|
||||
break
|
||||
|
||||
if in_enum:
|
||||
match = re.match(pattern, line)
|
||||
if match:
|
||||
attr1, summary, attr2, name, value, comment = match.groups()
|
||||
|
||||
# Parse value
|
||||
if value:
|
||||
value = value.strip()
|
||||
if value.startswith('0x') and ' ' not in value:
|
||||
# Simple hex value
|
||||
parsed_value = int(value, 16)
|
||||
elif value.isdigit():
|
||||
# Simple integer
|
||||
parsed_value = int(value)
|
||||
elif '|' in value or '<<' in value or '+' in value:
|
||||
# Complex expression - store as string for now
|
||||
parsed_value = f"EXPR:{value}"
|
||||
else:
|
||||
# Try simple conversion
|
||||
try:
|
||||
parsed_value = int(value)
|
||||
except ValueError:
|
||||
parsed_value = f"VALUE:{value}"
|
||||
else:
|
||||
parsed_value = current_value
|
||||
|
||||
entries[parsed_value] = name
|
||||
|
||||
# Update current_value for auto-increment
|
||||
if isinstance(parsed_value, int):
|
||||
current_value = parsed_value + 1
|
||||
else:
|
||||
# For non-numeric values, increment anyway for next entry
|
||||
current_value += 1
|
||||
|
||||
# Store metadata
|
||||
if summary:
|
||||
comments[name] = summary.strip()
|
||||
if comment:
|
||||
comments[name] = comment.strip()
|
||||
if attr1 or attr2:
|
||||
attributes[name] = (attr1 or '') + ' ' + (attr2 or '')
|
||||
|
||||
return enum_name, {
|
||||
'type': enum_type,
|
||||
'values': entries,
|
||||
'comments': comments,
|
||||
'attributes': attributes,
|
||||
'source_file': file_path.name
|
||||
}
|
||||
|
||||
def extract_skill_names():
|
||||
"""Extract skill names with their indices from Skill.cs"""
|
||||
skill_file = Path('/home/erik/MosswartOverlord/Mag-Plugins/Shared/Constants/Skill.cs')
|
||||
|
||||
with open(skill_file, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
skills = {}
|
||||
lines = content.split('\n')
|
||||
in_enum = False
|
||||
index = 0
|
||||
|
||||
for line in lines:
|
||||
if 'enum Skill' in line:
|
||||
in_enum = True
|
||||
continue
|
||||
|
||||
if in_enum and '}' in line:
|
||||
break
|
||||
|
||||
if in_enum:
|
||||
# Match skill entries like "None," or "Axe, /* Retired */"
|
||||
match = re.match(r'^\s*(\w+),?\s*(?:/\*\s*([^*]*)\s*\*/)?', line)
|
||||
if match:
|
||||
skill_name = match.group(1)
|
||||
status = match.group(2) or "Active"
|
||||
skills[index] = {
|
||||
'name': skill_name,
|
||||
'status': status.strip()
|
||||
}
|
||||
index += 1
|
||||
|
||||
return skills
|
||||
|
||||
def categorize_enums():
|
||||
"""Create logical categories for different enum types."""
|
||||
return {
|
||||
'item_properties': {
|
||||
'description': 'Item property value keys for different data types',
|
||||
'enums': ['IntValueKey', 'DoubleValueKey', 'StringValueKey', 'BoolValueKey', 'QuadValueKey']
|
||||
},
|
||||
'item_classification': {
|
||||
'description': 'Item type and material classification',
|
||||
'enums': ['ItemType', 'MaterialType', 'WeenieType']
|
||||
},
|
||||
'game_mechanics': {
|
||||
'description': 'Skills, spells, and game system enums',
|
||||
'enums': ['Skill', 'SpellCategory', 'WieldRequirement']
|
||||
},
|
||||
'technical': {
|
||||
'description': 'Technical flags and masks for game engine',
|
||||
'enums': ['CoverageMask', 'EquipMask']
|
||||
}
|
||||
}
|
||||
|
||||
def create_translation_mappings():
|
||||
"""Create user-friendly translations for important enum values."""
|
||||
|
||||
# Map IntValueKey values to more descriptive names
|
||||
int_value_translations = {
|
||||
5: 'Encumbrance',
|
||||
19: 'Value (Pyreals)',
|
||||
25: 'Level',
|
||||
28: 'Armor Level',
|
||||
44: 'Base Damage',
|
||||
45: 'Damage Type',
|
||||
48: 'Weapon Skill',
|
||||
158: 'Wield Requirements',
|
||||
160: 'Wield Difficulty',
|
||||
218103842: 'Maximum Damage',
|
||||
218103849: 'Icon Overlay',
|
||||
218103850: 'Icon Underlay'
|
||||
}
|
||||
|
||||
# Material type friendly names
|
||||
material_translations = {
|
||||
0: 'Unknown',
|
||||
1: 'Ceramic',
|
||||
20: 'Diamond',
|
||||
21: 'Emerald',
|
||||
31: 'Ruby',
|
||||
32: 'Sapphire'
|
||||
}
|
||||
|
||||
return {
|
||||
'int_values': int_value_translations,
|
||||
'materials': material_translations
|
||||
}
|
||||
|
||||
def main():
|
||||
"""Main extraction process."""
|
||||
|
||||
constants_dir = Path('/home/erik/MosswartOverlord/Mag-Plugins/Shared/Constants')
|
||||
output_dir = Path('/home/erik/MosswartOverlord/inventory-service')
|
||||
|
||||
# Ensure output directory exists
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
|
||||
print("Starting comprehensive enum extraction from Mag-Plugins/Shared/Constants...")
|
||||
|
||||
# Extract all enum files
|
||||
all_enums = {}
|
||||
enum_files = list(constants_dir.glob('*.cs'))
|
||||
|
||||
for enum_file in enum_files:
|
||||
if enum_file.name == 'Dictionaries.cs': # Skip non-enum files
|
||||
continue
|
||||
|
||||
enum_name, enum_data = extract_enum_from_file(enum_file)
|
||||
if enum_name and enum_data:
|
||||
all_enums[enum_name] = enum_data
|
||||
|
||||
# Special handling for Skills (has complex structure)
|
||||
skill_data = extract_skill_names()
|
||||
all_enums['Skill'] = {
|
||||
'type': 'indexed',
|
||||
'values': skill_data,
|
||||
'source_file': 'Skill.cs'
|
||||
}
|
||||
|
||||
# Create categorized structure
|
||||
categories = categorize_enums()
|
||||
translations = create_translation_mappings()
|
||||
|
||||
# Save complete enum database
|
||||
complete_data = {
|
||||
'metadata': {
|
||||
'extracted_at': '2025-06-10',
|
||||
'source': 'Mag-Plugins/Shared/Constants',
|
||||
'total_enums': len(all_enums),
|
||||
'version': '1.0.0'
|
||||
},
|
||||
'categories': categories,
|
||||
'translations': translations,
|
||||
'enums': all_enums
|
||||
}
|
||||
|
||||
# Save main database
|
||||
main_output = output_dir / 'complete_enum_database.json'
|
||||
with open(main_output, 'w') as f:
|
||||
json.dump(complete_data, f, indent=2)
|
||||
|
||||
print(f"Saved complete enum database to {main_output}")
|
||||
|
||||
# Save individual enum files for backward compatibility
|
||||
individual_dir = output_dir / 'enums'
|
||||
individual_dir.mkdir(exist_ok=True)
|
||||
|
||||
for enum_name, enum_data in all_enums.items():
|
||||
enum_file = individual_dir / f'{enum_name}.json'
|
||||
with open(enum_file, 'w') as f:
|
||||
json.dump({enum_name: enum_data}, f, indent=2)
|
||||
|
||||
# Update existing files for backward compatibility
|
||||
if 'IntValueKey' in all_enums:
|
||||
legacy_int_file = output_dir / 'int_value_enums.json'
|
||||
with open(legacy_int_file, 'w') as f:
|
||||
json.dump(all_enums['IntValueKey']['values'], f, indent=2)
|
||||
print(f"Updated legacy file: {legacy_int_file}")
|
||||
|
||||
# Create comprehensive summary
|
||||
print("\n" + "="*60)
|
||||
print("EXTRACTION SUMMARY")
|
||||
print("="*60)
|
||||
|
||||
for enum_name, enum_data in all_enums.items():
|
||||
value_count = len(enum_data.get('values', {}))
|
||||
enum_type = enum_data.get('type', 'unknown')
|
||||
print(f"{enum_name:20} | {value_count:4} values | Type: {enum_type}")
|
||||
|
||||
print(f"\nTotal enums extracted: {len(all_enums)}")
|
||||
print(f"Files created:")
|
||||
print(f" - {main_output}")
|
||||
print(f" - {len(all_enums)} individual enum files in {individual_dir}/")
|
||||
|
||||
# Show sample translations
|
||||
print("\nSample enum translations:")
|
||||
for enum_name in ['IntValueKey', 'MaterialType', 'ItemType', 'Skill']:
|
||||
if enum_name in all_enums:
|
||||
values = all_enums[enum_name]['values']
|
||||
if isinstance(values, dict):
|
||||
sample_keys = list(values.keys())[:3]
|
||||
for key in sample_keys:
|
||||
if isinstance(values[key], dict):
|
||||
print(f" {enum_name}[{key}] = {values[key].get('name', values[key])}")
|
||||
else:
|
||||
print(f" {enum_name}[{key}] = {values[key]}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue