import sys import struct import os import re def parse_map(file_path): with open(file_path, 'r') as f: lines = f.readlines() entities = [] stack = [] current_entity = None current_brush = None face_pattern = re.compile(r""" (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*) (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*) (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*) (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*) (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*) (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*) (\S+) """, re.VERBOSE) for line in lines: line = line.strip() if not line or line.startswith('//'): continue if line == '{': stack.append('{') if current_entity is None: current_entity = {'classname': None, 'keyvalues': {}, 'brushes': []} elif current_brush is None: current_brush = [] continue if line == '}': if current_brush is not None: current_entity['brushes'] = current_brush current_brush = None else: entities.append(current_entity) current_entity = None stack.pop() continue if current_brush is not None: m = face_pattern.match(line) if m: points = [ (float(m.group(1)), float(m.group(2)), float(m.group(3))), (float(m.group(4)), float(m.group(5)), float(m.group(6))), (float(m.group(7)), float(m.group(8)), float(m.group(9))), ] uvs = [ (float(m.group(10)), float(m.group(11))), (float(m.group(12)), float(m.group(13))), (float(m.group(14)), float(m.group(15))), ] texture = m.group(16) face = { 'points': points, 'uvs': uvs, 'texture': texture, } current_brush.append(face) else: print(f"Warning: Could not parse face line: {line}") continue if current_entity is not None: if line.startswith('"'): parts = re.findall(r'"([^"]*)"', line) if len(parts) == 2: key, value = parts if key == "classname": current_entity['classname'] = value else: current_entity['keyvalues'][key] = value else: print(f"Warning: Unexpected line in entity: {line}") return entities if (len(sys.argv)==1): print("mapcc.py is a rtt's .map to .fmap converter"); print("key changes:"); print("- uses triangles instead of brushes"); print("- uses uv coordinates instead of brushes"); print("use better map editor instead of this"); exit(0) entities = parse_map(sys.argv[1]) pakfilename = sys.argv[2] pakfile = open(pakfilename,"wb") pakfile.write(struct.Struct("<8sI").pack(b"rttfmapc",len(entities))) for i, e in enumerate(entities): pakfile.write(struct.Struct(f"<{len(e['classname'])+1}s").pack(str(e['classname']).encode("ascii"))) pakfile.write(struct.Struct("