Files
ichni_Official/Assets/ThemeBundles/DepartureToMultiverse/Scripts/split_bm.py
SoulliesOfficial 7580c4d87c 大更
2026-03-14 03:13:10 -04:00

108 lines
4.2 KiB
Python

import os
import re
game_dir = r"d:\Projects\ichni Official\Assets\ThemeBundles\DepartureToMultiverse\Scripts\Game"
datacore_dir = r"d:\Projects\ichni Official\Assets\ThemeBundles\DepartureToMultiverse\Scripts\DataCore"
def extract_beatmap_namespace(filepath):
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
except Exception as e:
print("Error reading", filepath, e)
return
# Find the start of namespace Beatmap
match = re.search(r'^\s*namespace\s+Beatmap\s*\{', content, re.MULTILINE)
if not match:
print("No Beatmap namespace in", filepath)
return
start_idx = match.start()
# We need to find the matching closing brace
brace_depth = 0
end_idx = -1
for i in range(start_idx, len(content)):
if content[i] == '{':
brace_depth += 1
elif content[i] == '}':
brace_depth -= 1
if brace_depth == 0:
end_idx = i + 1
break
if end_idx == -1:
print("Mismatched braces in", filepath)
return
bm_namespace_content = content[start_idx:end_idx]
# Find the name of the _BM class to name the new file
class_match = re.search(r'public\s+(?:partial\s+)?class\s+(\w+_BM)', bm_namespace_content)
if not class_match:
print("No _BM class found in namespace Beatmap for", filepath)
return
bm_class_name = class_match.group(1)
# Make the original file clean
new_game_content = content[:start_idx] + content[end_idx:]
new_game_content = new_game_content.rstrip()
# close the namespace of the original file if needed, actually it's usually inside the original namespace!
# Let's check if "namespace Beatmap" is inside another namespace.
# Yes, typically "namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse" wraps everything.
# The new_game_content currently might have a trailing `}` because the outer namespace is closed at the end.
# E.g.
# namespace Outer {
# class OuterClass { }
# namespace Beatmap { ... }
# }
# If we remove "namespace Beatmap { ... }", we still need the trailing "}".
new_game_content = re.sub(r'[\r\n\s]*namespace\s+Beatmap[\s\S]*\}\s*\}\s*$', '\n}', content) # A quick hacky way but relies on structure.
# Better way: just remove the exact substring, then it leaves the outer closing brace intact.
# wait, if namespace Beatmap { ... } is inside namespace Outer { ... }
# start_idx to end_idx is exactly "namespace Beatmap { ... }"
# So content[:start_idx] + content[end_idx:] will leave the outer } perfectly.
new_content = content[:start_idx] + content[end_idx:]
# Clean up excess newlines
new_content = re.sub(r'\n\s*\n\s*\n', '\n\n', new_content)
# Ensure it ends with a newline
new_content = new_content.strip() + '\n'
with open(filepath, 'w', encoding='utf-8') as f:
f.write(new_content)
# Now create the DataCore file
rel_path = os.path.relpath(filepath, game_dir)
datacore_file_dir = os.path.dirname(os.path.join(datacore_dir, rel_path))
os.makedirs(datacore_file_dir, exist_ok=True)
datacore_filepath = os.path.join(datacore_file_dir, bm_class_name + ".cs")
# We need usings. Extract original usings
usings = "".join(re.findall(r'^(?:using\s+[\w\.]+;\s*)+', content, re.MULTILINE))
# Format the new DataCore file
datacore_content = usings + "\n"
# Wrap in outer namespace
datacore_content += "namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap\n{\n"
# Extract the classes inside "namespace Beatmap"
inner_classes = re.search(r'namespace\s+Beatmap\s*\{([\s\S]*)\}', bm_namespace_content).group(1)
datacore_content += inner_classes + "}\n"
with open(datacore_filepath, 'w', encoding='utf-8') as f:
f.write(datacore_content)
print(f"Split {os.path.basename(filepath)} -> {bm_class_name}.cs")
for root, dirs, files in os.walk(game_dir):
for file in files:
if file.endswith('.cs'):
filepath = os.path.join(root, file)
extract_beatmap_namespace(filepath)