113 lines
4.0 KiB
Python
113 lines
4.0 KiB
Python
|
|
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("<I").pack(len(e['brushes'])))
|
|
pakfile.write(struct.Struct("<I").pack(len(e['keyvalues'])))
|
|
for k, v in e['keyvalues'].items():
|
|
pakfile.write(struct.Struct(f"<{len(k)+1}s").pack(k.encode("ascii")))
|
|
pakfile.write(struct.Struct(f"<{len(v)+1}s").pack(v.encode("ascii")))
|
|
for k, face in enumerate(e['brushes']):
|
|
# the fuck
|
|
for i in range(9):
|
|
pakfile.write(struct.Struct(f"<f").pack(float(face['points'][int(i/3)][i%3])))
|
|
for i in range(6):
|
|
pakfile.write(struct.Struct(f"<f").pack(float(face['uvs'][int(i//2)][i%2])))
|
|
pakfile.write(struct.Struct(f"<{len(face['texture'])+1}s").pack(face['texture'].encode("ascii")))
|