From a423cae411d75a0974c7c2d03e4162d2ecdb3059 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Tue, 28 Apr 2026 21:02:24 +0800 Subject: [PATCH] Update patch script --- iinkai.py | 103 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 9 deletions(-) diff --git a/iinkai.py b/iinkai.py index b0b6bfd..544a5b7 100644 --- a/iinkai.py +++ b/iinkai.py @@ -48,6 +48,18 @@ def extract_script(script_path: str, output_path: str): json.dump(result, f, ensure_ascii=False, indent=2) +def extract_dict_terms(script_path: str): + terms = {} + overrides = {} + with open(script_path, "r", encoding="utf-8-sig") as f: + for row in DictReader(f): + term = row['term'] + terms[term] = row + if ' ' in term: + overrides[term.split(' ')[0]] = term + return terms, overrides + + def extract_dict(script_path: str, output_path: str): with open(script_path, "r", encoding="utf-8") as f: script_text = f.read() @@ -133,13 +145,67 @@ def parse_message(message: str) -> List[ParsedLine]: return result -def patch_script(script_path: str, m3t_path: str, output_path: str, names): +def patch_dict(script_path: str, dict_path: str, output_path: str): + with open(script_path, "r", encoding="utf-8") as f: + script_text = f.read() + in_dict = False + dict_data = '\n' + start_line = None + end_line = None + for (i, line) in enumerate(script_text.splitlines()): + if line == "var text = '": + in_dict = True + start_line = i + 1 + elif line == "';": + in_dict = False + end_line = i - 1 + elif in_dict: + dict_data += line + "\n" + script = KAGScriptParser(dict_data).parse(True) + dicts = {} + with open(dict_path, "r", encoding="utf-8-sig") as f: + for row in DictReader(f): + dicts[row['term']] = row + new_script = [] + term = None + for line in script: + if isinstance(line, LabelNode): + term = line.name[1:] + new_script.append(LabelNode('.' + dicts[term]['translation'])) + elif isinstance(line, CommentNode): + new_script.append([TextNode(f";{line.text}")]) + elif isinstance(line, EmptyLineNode): + pass + elif isinstance(line, list): + pass + elif isinstance(line, CommandNode): + if line.name == "return": + data = dicts[term] + new_script.append([TextNode(data['translation'])]) + desc: str = data['description'] + for d in desc.splitlines(): + new_script.append([TextNode(d)]) + new_script.append(EmptyLineNode()) + new_script.append(line) + else: + raise ValueError("Unsupported command", line.name) + dict_data = KAGScriptParser.serialize(new_script) + origin_lines = script_text.splitlines(True) + with open(output_path, 'w', encoding='UTF-8') as f: + f.writelines(origin_lines[:start_line]) + f.write(dict_data) + f.write("\n") + f.writelines(origin_lines[end_line + 1:]) + + +def patch_script(script_path: str, m3t_path: str, output_path: str, names, term): with open(script_path, "r", encoding="utf-8") as f: script_text = f.read() script = KAGScriptParser(script_text).parse(True) new_script: ParsedScript = [] messages = [] name = None + terms, overrides = term with open(m3t_path, "r", encoding="utf-8") as f: for line in f: line = line.strip() @@ -151,6 +217,11 @@ def patch_script(script_path: str, m3t_path: str, output_path: str, names): if name is not None: d['name'] = name d['message'] = message.replace('\\n', '\n') + if name: + if not d['message'].startswith('「'): + d['message'] = '「' + d['message'] + if not d['message'].endswith('」'): + d['message'] += '」' messages.append(d) name = None i = 0 @@ -159,7 +230,19 @@ def patch_script(script_path: str, m3t_path: str, output_path: str, names): if line.name == "page": message = messages[i]['message'] i += 1 - new_script.extend(parse_message(message)) + nws = parse_message(message) + for nw in nws: + for node in nw: + if isinstance(node, TagNode): + if node.name == 'wd': + target = node.attributes['s'] + if target not in terms: + if target not in overrides: + print(message) + raise ValueError('unknown wd target', target) + node.attributes['s'] = overrides[target] + node.attributes['s'] = terms[node.attributes['s']]['translation'] + new_script.extend(nws) elif line.name.startswith("【") and line.name.endswith("】"): name = line.name[1:-1] if name in names: @@ -168,7 +251,7 @@ def patch_script(script_path: str, m3t_path: str, output_path: str, names): continue new_script.append(line) if i != len(messages): - print(f"WARNING: processed message not matched. expected {len(message)}, actual {i}") + print(f"WARNING: processed message not matched. expected {len(messages)}, actual {i}, {script_path}") script_data = KAGScriptParser.serialize(new_script) with open(output_path, 'w', encoding='utf-8') as f: f.write(script_data) @@ -211,8 +294,9 @@ def read_names(name_dict_path: str): return names -def patch_script_auto(script_path: str, m3t_path: str, output_path: str, name_dict_path: str): +def patch_script_auto(script_path: str, m3t_path: str, output_path: str, name_dict_path: str, dict_path: str): names = read_names(name_dict_path) + term = extract_dict_terms(dict_path) if isdir(script_path): for file in listdir(script_path): if not file.lower().endswith(".scn"): @@ -228,18 +312,18 @@ def patch_script_auto(script_path: str, m3t_path: str, output_path: str, name_di continue output_full_path = join(output_path, basename(file)) if file == "dict.scn": - pass + patch_dict(full_path, m3t_full_path, output_full_path) else: - patch_script(full_path, m3t_full_path, output_full_path, names) + patch_script(full_path, m3t_full_path, output_full_path, names, term) else: pdir = dirname(output_path) if pdir and not isdir(pdir): makedirs(pdir, exist_ok=True) base_name = basename(script_path) if base_name == "dict.scn": - pass + patch_dict(script_path, m3t_path, output_path) else: - patch_script(script_path, m3t_path, output_path, names) + patch_script(script_path, m3t_path, output_path, names, term) if __name__ == "__main__": @@ -254,8 +338,9 @@ if __name__ == "__main__": patch_parser.add_argument("m3t_path", help="Path to m3t file or directory") patch_parser.add_argument("output_path", help="Path to output KAG script file or directory") patch_parser.add_argument("name_dict_path", help="Path to name dict") + patch_parser.add_argument("dict_path", help="path to dict.csv") args = parser.parse_args() if args.command == "extract": extract_script_auto(args.script_path, args.output_path) elif args.command == "patch": - patch_script_auto(args.script_path, args.m3t_path, args.output_path, args.name_dict_path) + patch_script_auto(args.script_path, args.m3t_path, args.output_path, args.name_dict_path, args.dict_path)