diff --git a/.agents/skills/metin2-40250-parity-audit/SKILL.md b/.agents/skills/metin2-40250-parity-audit/SKILL.md index 3963b7dc..61e32041 100644 --- a/.agents/skills/metin2-40250-parity-audit/SKILL.md +++ b/.agents/skills/metin2-40250-parity-audit/SKILL.md @@ -32,9 +32,9 @@ one of three layers: | Layer | 40250 units | How to port | Where | | --- | --- | --- | --- | -| `logic` | `UserInterface/`, `GameLib/`, `EterLib` net/timer/text parsing, `EterPack`, `EterLocale` (everything not listed below) | Copy C++ -> C++. Same file name, class name, method names, member names and statement order; one reference file = one implementation file | `extension/src/port//.{h,cpp}` | +| `logic` | `UserInterface/`, `GameLib/`, `EterLib` net/timer/text parsing, `EterPack`, `EterLocale`, `EterBase` pure units (`tea`, `lzo`, `cipher`, `Random`, `Stl`, `Timer`, `Poly/`) (everything not listed below) | Copy C++ -> C++. Same file name, class name, method names, member names and statement order; one reference file = one implementation file | `extension/src/port//.{h,cpp}` | | `python` | `Client/Eternexus/root/*.py`, `uiscript/`, `UserInterface/*Module.cpp`, `EterPythonLib/`, `ScriptLib/` | Decided: embedded CPython 2.7.18 runs the scripts unchanged (`docs/PYTHON-EMBED-EVAL.md`, batch 2P); port only the C++ side. Never translate the scripts. Script functions get `RUN_AS_IS` once its evidence gate passes, never `N_A`. Reference is 40250 `Eternexus/root`, **not** `assets/root` | `extension/src/port//` (bindings), scripts from pack | -| `platform` | Direct3D/`Grp*`, Granny (`EterGrnLib`), Miles, SpeedTree, `EffectLib`/terrain rendering, Win32 window/input/IME, threads, anti-cheat | Adapter behind the interface the 40250 caller uses; equivalence by observable output | `extension/src/platform/` + existing render code (`metin2_model`, `metin2_anim`, `gr2_bridge`, ...) | +| `platform` | Direct3D/`Grp*`, Granny (`EterGrnLib`), Miles, SpeedTree, `EffectLib`/terrain rendering, Win32 window/input/IME, threads, anti-cheat, `EterBase` file/OS units (`_ETERBASE_PLATFORM` in `port_map.py`) | Adapter behind the interface the 40250 caller uses; equivalence by observable output | `extension/src/platform/` + existing render code (`metin2_model`, `metin2_anim`, `gr2_bridge`, ...) | Rules for the `logic` layer: diff --git a/.agents/skills/metin2-40250-parity-audit/scripts/port_map.py b/.agents/skills/metin2-40250-parity-audit/scripts/port_map.py index 500bd8a4..a586170b 100644 --- a/.agents/skills/metin2-40250-parity-audit/scripts/port_map.py +++ b/.agents/skills/metin2-40250-parity-audit/scripts/port_map.py @@ -37,6 +37,10 @@ PY_ROOT = "../../Client/Eternexus/root" UNIT_DIRS = REFERENCE_DIRS + ("EterBase", "EterPythonLib", "ScriptLib", "SpeedTreeLib", "SphereLib", "EterImageLib") PORT_DIR = "extension/src/port" LAYERS = ("logic", "python", "platform") +# EterBase units that wrap Win32 file/OS/UI resources. The rest (tea, lzo, cipher, Random, Stl, Timer, Poly/*) +# is plain logic and is ported into the mirror; CRC32 and Utils mix pure helpers with Win32 calls and stay here. +_ETERBASE_PLATFORM = ("CPostIt", "CRC32", "Debug", "FileBase", "FileDir", "FileLoader", "MappedFile", "TempFile", + "Utils", "error") # First matching pattern wins; anything unmatched is `logic`. LAYER_PATTERNS = [ ("python", [f"{PY_ROOT}/*.py", "EterPythonLib/*", "ScriptLib/*", "UserInterface/*Module.cpp", @@ -49,7 +53,7 @@ LAYER_PATTERNS = [ "EterLib/LensFlare.cpp", "EterLib/ScreenFilter.cpp", "EterLib/Decal.cpp", "EterLib/EnvironmentMap.cpp", "EterLib/JpegFile.cpp", "EterLib/TargaResource.cpp", "EterLib/DibBar.cpp", "EterLib/BlockTexture.cpp", "EterLib/CullingManager.cpp", "EterLib/Thread.cpp", "EterLib/Mutex.cpp", "EterLib/FileLoaderThread.cpp", - "EterLib/TextBar.cpp", "EterLib/Dimm.h", "EterBase/*", "GameLib/MapOutdoorRender*.cpp", "GameLib/MapOutdoorWater.cpp", + "EterLib/TextBar.cpp", "EterLib/Dimm.h", *[f"EterBase/{u}.cpp" for u in _ETERBASE_PLATFORM], "GameLib/MapOutdoorRender*.cpp", "GameLib/MapOutdoorWater.cpp", "GameLib/SnowParticle.cpp", "GameLib/SnowEnvironment.cpp", "GameLib/TerrainDecal.cpp", "GameLib/TerrainPatch.cpp", "UserInterface/PythonApplicationLogo.cpp", "UserInterface/MovieMan.cpp", "UserInterface/HackShield.cpp", "UserInterface/NProtectGameGuard.cpp", "UserInterface/ProcessCRC.cpp", @@ -81,6 +85,10 @@ DEFAULT_PRIORITY = "P4" # Column-0 definition: ` [Class::]name(` where the body `{` follows on this or the next line. _DEF = re.compile(r"^(?!return\b|else\b|if\b|while\b|for\b|switch\b|case\b|#|//|/\*|\s)" r"[^;(){}=]*?\b((?:[A-Za-z_]\w*::)*~?[A-Za-z_]\w*)\s*\(") +# Indented qualified definition inside a namespace block: `\t Class::name(...)` with a return type, +# or a constructor/destructor `\tClass::[~]Class(`, so calls in function bodies are not taken. +_INDENTED_DEF = re.compile(r"^[ \t]+(?:(?!return\b|else\b|delete\b|new\b|throw\b|case\b)[A-Za-z_][\w:<>,*& ]*[\s*&]+" + r"((?:[A-Za-z_]\w*::)+~?[A-Za-z_]\w*)|((?:[A-Za-z_]\w*::)*([A-Za-z_]\w*)::~?\3))\s*\(") _PY_CLASS = re.compile(r"^class\s+(\w+)") _PY_DEF = re.compile(r"^(\s*)def\s+(\w+)\s*\(") _TAG = re.compile(r"(?://|#)\s*40250:\s*([A-Za-z_][\w:.~]*)") @@ -90,17 +98,32 @@ def sha256(path: Path) -> str: return hashlib.sha256(path.read_bytes()).hexdigest() +_COMMENT_OR_LITERAL = re.compile(r'//[^\n]*|/\*.*?\*/|"(?:\\.|[^"\\\n])*"|\'(?:\\.|[^\'\\\n])*\'', re.S) + + +def _strip_comments(text: str) -> str: + """Blank out comments (keeping line breaks) so commented-out code and comment prose are not scanned.""" + def blank(m: re.Match) -> str: + s = m.group(0) + return s if s[0] in "\"'" else re.sub(r"[^\n]", " ", s) + return _COMMENT_OR_LITERAL.sub(blank, text) + + def cpp_functions(path: Path) -> list[str]: - lines = path.read_bytes().decode("latin-1").splitlines() + lines = _strip_comments(path.read_bytes().decode("latin-1")).splitlines() names: list[str] = [] for i, line in enumerate(lines): - m = _DEF.match(line) + m = _DEF.match(line) or _INDENTED_DEF.match(line) if not m or line.rstrip().endswith(";"): continue - name = m.group(1) - if name.isupper() or name.split("::")[-1].isupper(): # macros + prev = next((l.rstrip() for l in reversed(lines[:i]) if l.strip()), "") + if prev.endswith((",", ":")) and not prev.endswith("::") and "::" not in m.group(0): + continue # member initializer `m_x(NULL),` of a constructor above + name = next(g for g in m.groups() if g) + if "::" not in name and name.isupper(): # macros; CLZO::CLZO is a real constructor continue - rest = "\n".join(lines[i:i + 8]) + # The body `{` may follow a long parameter or initializer list; a `;` first means a declaration or call. + rest = "\n".join(lines[i:i + 40]) body = rest.find("{") semi = rest.find(";") if body < 0 or (0 <= semi < body): diff --git a/audit/history.jsonl b/audit/history.jsonl index d7ed09e9..4ee0c499 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -486,3 +486,4 @@ {"time": "2026-09-22T06:00:00Z", "event": "port_round", "unit": "UserInterface/PythonPlayerEventHandler.cpp", "ported": ["CPythonPlayerEventHandler::OnMove", "CPythonPlayerEventHandler::OnMoving", "CPythonPlayerEventHandler::OnStop"], "deleted": ["net_play.gd _tick_on_waiting idle FUNC_WAIT resend"], "divergent": ["CPythonPlayerEventHandler::OnWaiting (walking-but-stalled path not ported)"], "needs_live": [], "tests": ["project/netplay_test.gd PASS", "project/keyboard_motion_timeline_test.gd PASS", "project/movement_parity_test.gd PASS", "project/player_move_test.gd PASS"]} {"time":"2026-09-22T12:00:00Z","event":"dead_code_removal","deleted_system_files":106,"deleted_tests":106,"lines_removed":36221,"manifest_refs_removed":76,"contracts_touched":18,"reason":"project/*_system.gd reachable only from their own test_*_parity.gd; not implementations of 40250 behavior (SKILL.md: unreachable code is not evidence)","tests":["full headless Godot suite: 192 PASS, 7 FAIL and 5 render tests hanging in headless, all identical on the pre-deletion tree"]} {"time":"2026-09-22T13:00:00Z","event":"port_map_rebaseline","unit":"UserInterface/PythonPlayerEventHandler.cpp","reset_to_todo":["CPythonPlayerEventHandler::GetSingleton","CPythonPlayerEventHandler::~CPythonPlayerEventHandler","CPythonPlayerEventHandler::OnMoving","CPythonPlayerEventHandler::OnMove","CPythonPlayerEventHandler::OnStop","CPythonPlayerEventHandler::CPythonPlayerEventHandler"],"reason":"new mirror architecture owns the CPythonPlayerEventHandler singleton in native code; prior GDScript counterparts are migration sources, not final mirror implementations","tests":["port_map.py check"]} +{"time":"2026-09-22T15:00:00Z","event":"port_map_rebaseline","scope":"all units","totals":{"logic":3343,"python":5175,"platform":2091,"all":10609,"done":0,"divergent":1},"previous":{"logic":3285,"python":4890,"platform":2229,"all":10404},"changes":["cpp_functions: strip comments, accept indented qualified definitions inside namespace blocks, long parameter/initializer lists (40-line window), all-caps qualified ctors, skip constructor initializer entries","EterBase split by unit: tea/lzo/cipher/Random/Stl/Timer/Poly are logic, CPostIt/CRC32/Debug/FileBase/FileDir/FileLoader/MappedFile/TempFile/Utils/error stay platform; 8 obsolete platform stub files removed","audit/slices regenerated (layer fields; EterLib/Dimm.h now platform)"],"reason":"PORT-PLAN 2A step 6; inventory cross-checked against the clang-derived platform skeleton: every stub is inventoried except 22 declarations 40250 never defines and namespace/typedef spelling variants","tests":["port_map.py check","script/port_gate.sh (macos/android/ios/windows PASS, linux BLOCKED)"]} diff --git a/audit/slices/2V0.json b/audit/slices/2V0.json index cd619202..ffac2dd1 100644 --- a/audit/slices/2V0.json +++ b/audit/slices/2V0.json @@ -182,7 +182,7 @@ }, { "header": "EterBase/Filename.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, @@ -194,49 +194,49 @@ }, { "header": "EterBase/Poly/Poly.h", - "layer": "platform", + "layer": "logic", "reason": "include from UserInterface/PythonSkill.h", "owner_in_slice": false }, { "header": "EterBase/Poly/SymTable.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/Poly/Poly.h", "owner_in_slice": false }, { "header": "EterBase/Random.h", - "layer": "platform", + "layer": "logic", "reason": "include from EffectLib/EffectUpdateDecorator.h", "owner_in_slice": false }, { "header": "EterBase/ServiceDefs.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, { "header": "EterBase/Singleton.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterPack/EterPackManager.h", "owner_in_slice": false }, { "header": "EterBase/StdAfx.h", - "layer": "platform", + "layer": "logic", "reason": "implicit stricmp from EterPythonLib/PythonWindowManagerModule.cpp", "owner_in_slice": false }, { "header": "EterBase/Stl.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterPack/EterPackManager.h", "owner_in_slice": false }, { "header": "EterBase/Timer.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/Profiler.h", "owner_in_slice": false }, @@ -248,25 +248,25 @@ }, { "header": "EterBase/cipher.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/NetStream.h", "owner_in_slice": false }, { "header": "EterBase/lzo.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/MappedFile.h", "owner_in_slice": false }, { "header": "EterBase/tea.h", - "layer": "platform", + "layer": "logic", "reason": "include from UserInterface/PythonApplicationModule.cpp", "owner_in_slice": false }, { "header": "EterBase/vk.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, @@ -392,7 +392,7 @@ }, { "header": "EterLib/Dimm.h", - "layer": "logic", + "layer": "platform", "reason": "include from EterLib/IME.h", "owner_in_slice": false }, diff --git a/audit/slices/2V1.json b/audit/slices/2V1.json index 994a0255..c9bb9124 100644 --- a/audit/slices/2V1.json +++ b/audit/slices/2V1.json @@ -217,7 +217,7 @@ }, { "header": "EterBase/Filename.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, @@ -229,49 +229,49 @@ }, { "header": "EterBase/Poly/Poly.h", - "layer": "platform", + "layer": "logic", "reason": "include from UserInterface/PythonSkill.h", "owner_in_slice": false }, { "header": "EterBase/Poly/SymTable.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/Poly/Poly.h", "owner_in_slice": false }, { "header": "EterBase/Random.h", - "layer": "platform", + "layer": "logic", "reason": "include from EffectLib/EffectUpdateDecorator.h", "owner_in_slice": false }, { "header": "EterBase/ServiceDefs.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, { "header": "EterBase/Singleton.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterPack/EterPackManager.h", "owner_in_slice": false }, { "header": "EterBase/StdAfx.h", - "layer": "platform", + "layer": "logic", "reason": "implicit stricmp from EterPythonLib/PythonWindowManagerModule.cpp", "owner_in_slice": false }, { "header": "EterBase/Stl.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterPack/EterPackManager.h", "owner_in_slice": false }, { "header": "EterBase/Timer.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/Profiler.h", "owner_in_slice": false }, @@ -283,25 +283,25 @@ }, { "header": "EterBase/cipher.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/NetStream.h", "owner_in_slice": false }, { "header": "EterBase/lzo.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/MappedFile.h", "owner_in_slice": false }, { "header": "EterBase/tea.h", - "layer": "platform", + "layer": "logic", "reason": "include from UserInterface/AccountConnector.cpp", "owner_in_slice": false }, { "header": "EterBase/vk.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, @@ -427,7 +427,7 @@ }, { "header": "EterLib/Dimm.h", - "layer": "logic", + "layer": "platform", "reason": "include from EterLib/IME.h", "owner_in_slice": false }, diff --git a/audit/slices/2V2.json b/audit/slices/2V2.json index 3813944b..db63f6a3 100644 --- a/audit/slices/2V2.json +++ b/audit/slices/2V2.json @@ -237,7 +237,7 @@ }, { "header": "EterBase/Filename.h", - "layer": "platform", + "layer": "logic", "reason": "implicit CFileNameHelper from UserInterface/PythonNetworkStreamPhaseGame.cpp", "owner_in_slice": false }, @@ -249,49 +249,49 @@ }, { "header": "EterBase/Poly/Poly.h", - "layer": "platform", + "layer": "logic", "reason": "include from UserInterface/PythonSkill.h", "owner_in_slice": false }, { "header": "EterBase/Poly/SymTable.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/Poly/Poly.h", "owner_in_slice": false }, { "header": "EterBase/Random.h", - "layer": "platform", + "layer": "logic", "reason": "include from EffectLib/EffectUpdateDecorator.h", "owner_in_slice": false }, { "header": "EterBase/ServiceDefs.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, { "header": "EterBase/Singleton.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/CullingManager.h", "owner_in_slice": false }, { "header": "EterBase/StdAfx.h", - "layer": "platform", + "layer": "logic", "reason": "implicit stricmp from EterPythonLib/PythonWindowManagerModule.cpp", "owner_in_slice": false }, { "header": "EterBase/Stl.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterGrnLib/ThingInstance.h", "owner_in_slice": false }, { "header": "EterBase/Timer.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/Profiler.h", "owner_in_slice": false }, @@ -303,25 +303,25 @@ }, { "header": "EterBase/cipher.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/NetStream.h", "owner_in_slice": false }, { "header": "EterBase/lzo.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/MappedFile.h", "owner_in_slice": false }, { "header": "EterBase/tea.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/NetStream.h", "owner_in_slice": false }, { "header": "EterBase/vk.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, @@ -447,7 +447,7 @@ }, { "header": "EterLib/Dimm.h", - "layer": "logic", + "layer": "platform", "reason": "include from EterLib/IME.h", "owner_in_slice": false }, diff --git a/audit/slices/2V3.json b/audit/slices/2V3.json index 1e6e4a75..056f73a6 100644 --- a/audit/slices/2V3.json +++ b/audit/slices/2V3.json @@ -292,7 +292,7 @@ }, { "header": "EterBase/Filename.h", - "layer": "platform", + "layer": "logic", "reason": "implicit CFileNameHelper from UserInterface/PythonNetworkStreamPhaseGame.cpp", "owner_in_slice": false }, @@ -304,49 +304,49 @@ }, { "header": "EterBase/Poly/Poly.h", - "layer": "platform", + "layer": "logic", "reason": "include from UserInterface/PythonSkill.h", "owner_in_slice": false }, { "header": "EterBase/Poly/SymTable.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/Poly/Poly.h", "owner_in_slice": false }, { "header": "EterBase/Random.h", - "layer": "platform", + "layer": "logic", "reason": "include from EffectLib/EffectUpdateDecorator.h", "owner_in_slice": false }, { "header": "EterBase/ServiceDefs.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, { "header": "EterBase/Singleton.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/CullingManager.h", "owner_in_slice": false }, { "header": "EterBase/StdAfx.h", - "layer": "platform", + "layer": "logic", "reason": "implicit stricmp from EterPythonLib/PythonWindowManagerModule.cpp", "owner_in_slice": false }, { "header": "EterBase/Stl.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterGrnLib/ThingInstance.h", "owner_in_slice": false }, { "header": "EterBase/Timer.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/Profiler.h", "owner_in_slice": false }, @@ -358,25 +358,25 @@ }, { "header": "EterBase/cipher.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/NetStream.h", "owner_in_slice": false }, { "header": "EterBase/lzo.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/MappedFile.h", "owner_in_slice": false }, { "header": "EterBase/tea.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterLib/NetStream.h", "owner_in_slice": false }, { "header": "EterBase/vk.h", - "layer": "platform", + "layer": "logic", "reason": "include from EterBase/StdAfx.h", "owner_in_slice": false }, @@ -502,7 +502,7 @@ }, { "header": "EterLib/Dimm.h", - "layer": "logic", + "layer": "platform", "reason": "include from EterLib/IME.h", "owner_in_slice": false }, diff --git a/docs/PORT-PLAN.md b/docs/PORT-PLAN.md index b845e957..ed113673 100644 --- a/docs/PORT-PLAN.md +++ b/docs/PORT-PLAN.md @@ -33,9 +33,9 @@ metin2-client 是 40250 Windows 客户端的跨平台版本(macOS / Windows / | 层 | 40250 单元 | 做法 | 位置 | | --- | --- | --- | --- | -| `logic` | `UserInterface/`、`GameLib/`、`EterLib` 的网络/计时/文本解析、`EterPack`、`EterLocale` | 逐文件照抄 C++ | `extension/src/port//.{h,cpp}` | +| `logic` | `UserInterface/`、`GameLib/`、`EterLib` 的网络/计时/文本解析、`EterPack`、`EterLocale`、`EterBase` 的纯逻辑单元(`tea`、`lzo`、`cipher`、`Random`、`Stl`、`Timer`、`Poly/`) | 逐文件照抄 C++ | `extension/src/port//.{h,cpp}` | | `python` | `root/*.py`、`uiscript/`、`UserInterface/*Module.cpp`、`EterPythonLib/`、`ScriptLib/` | 脚本原样运行;`*Module.cpp`、窗口系统、`CPythonLauncher` 照抄 | `extension/src/port//` + `extension/third_party/cpython-2.7.18/` | -| `platform` | Direct3D/`Grp*`、Granny、Miles、SpeedTree、特效/地形渲染、Win32 窗口/输入/IME、线程、反作弊 | 适配层,接口与 40250 调用方看到的一致,按可观察输出核对 | `extension/src/platform/` + 现有渲染代码 | +| `platform` | Direct3D/`Grp*`、Granny、Miles、SpeedTree、特效/地形渲染、Win32 窗口/输入/IME、线程、反作弊、`EterBase` 的文件/OS 单元(`CPostIt`、`CRC32`、`Debug`、`FileBase`、`FileDir`、`FileLoader`、`MappedFile`、`TempFile`、`Utils`、`error`;`CRC32`、`Utils` 里的纯函数在 platform 实现里照抄) | 适配层,接口与 40250 调用方看到的一致,按可观察输出核对 | `extension/src/platform/` + 现有渲染代码 | ``` extension/src/port/UserInterface/InstanceBase.cpp # 40250 同名文件的照抄 @@ -80,7 +80,7 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 | 0 | 工具:参考根解析、`port_map.py`、构建/测试入口 | 完成(55f733fd、5afd5a4f) | | 1 | 删除运行时不加载的 106 个 `*_system.gd` 及其测试 | 完成(a989b8f1) | | — | 定下目录结构,评估内嵌 Python;Android 独立程序验证 | 完成(9d0e50de、b02c49bb) | -| **2A** | 基础:Win32 类型层、参考公共头的最小闭包、`port_logic` CMake 目标、platform 接口骨架、头文件可编译门禁、port-map 重新基线 | **进行中**(剩 Python 库闭包头、port-map 基线) | +| **2A** | 基础:Win32 类型层、参考公共头的最小闭包、`port_logic` CMake 目标、platform 接口骨架、头文件可编译门禁、port-map 重新基线 | **进行中**(剩 Python 库闭包头,等 2P) | | **2R** | 资源包能力盘点:EPK 类型/密钥/覆盖顺序/路径大小写/移动端交付 | **下一步**,可与 2A 并行(只读分析 + 独立工具) | | 2P | CPython 2.7.18 编进 libmtgodot,五个平台分别配置和验证 | 2A 之后 | | 2D | 数据源切到 40250(msm 路径、proto、资源根、严格资源测试) | proto 部分在 2A 之后;资源根在 2R 之后 | @@ -119,11 +119,11 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 4. `extension/src/platform/` 接口骨架:闭包里出现的平台类(`CGraphicThingInstance`、`CSoundManager` 等)只声明 40250 调用方用到的方法,先给空实现。 5. 门禁:`port/**` 下每个头文件单独编译通过(header self-containment),序列化结构的 `static_assert` 全部通过。 -6. port-map 重新基线(见第 6 节)。 +6. port-map 重新基线(见第 6 节)。**已完成**(2026-09-22)。 7. 用 `#include` 依赖图生成批次 2 的移植顺序(拓扑序),替换原来"互不共享实现文件即可并行"的假设:共享头文件的单元, 头文件由先做的那个单元负责,后面的单元只能在它合入后开始。 **已完成**:`port_deps.py`(显式 `#include` + 按符号解析的 StdAfx 隐式依赖)生成 `audit/slices/2V0–2V3.json` - 和 `audit/slices/batch2-order.json`。结论:每个切片的头文件闭包约 210 个(其中平台层约 110 个,来自 + 和 `audit/slices/batch2-order.json`。结论:每个切片的头文件闭包约 210–220 个(其中平台层约 100 个,来自 `ThingInstance.h`/`GrpBase.h` 等);P0 单元里 `InstanceBase`、`PythonCharacterManager`、`PythonPlayer`、 `PythonPlayerEventHandler` 的头文件互相包含,必须作为一组串行移植,`ActorInstance.cpp` 排在最前。 @@ -175,8 +175,11 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 - ScriptLib、EterPythonLib、UserInterface 的 StdAfx 会 include Python 头,要等 2P 把 CPython 加进来之后再照抄。 - 已完成(步骤 4):platform 骨架 `extension/src/platform/`,目标 `port_platform`(静态库,链接 `port_logic`, libmtgodot 改为链接它;从 `port/CMakeLists.txt` 加入以共用每个库的编译宏;`port_gate.sh` 构建它)。 - - 平台层头文件(同名 40250 `.cpp` 属于 platform 层,见 `port_map.py` 的 `LAYER_PATTERNS`)共 118 个,对应 - `platform//.cpp` 103 个(其余 15 个没有需要定义的东西),1917 个函数桩、146 个静态成员。 + - 平台层头文件(同名 40250 `.cpp` 属于 platform 层,见 `port_map.py` 的 `LAYER_PATTERNS`)对应 + `platform//.cpp` 95 个,1843 个函数桩(步骤 6 把 EterBase 的纯逻辑单元改为 logic 层后,删掉了 + `Random`、`Stl`、`cipher`、`lzo`、`tea`、`Timer`、`Poly/Poly`、`Poly/SymTable` 的 8 个桩文件)。 + - 其中 22 个桩对应 40250 只声明、从未定义的函数(如 `CEffectManager::GetRenderingEffectCount`、`Mutex::Trylock`), + 40250 里没有调用方,不算待移植函数。 - 由 `platform_stub.py gen` 生成:用 clang 对门禁编译单元按类名/函数名 `-ast-dump-filter` 导出声明,定义头文件里 声明了但没有定义的成员函数、构造/析构、自由函数和静态成员;返回类型写成尾置形式,使类内嵌套类型在类作用域里解析, 静态成员写成 `decltype(C::x) C::x{};`。已存在的文件不覆盖(除非 `--force`)。 @@ -185,7 +188,8 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 - 6 个构造函数手工补了与 40250 相同的初始化列表(基类 `CResource(c_szFileName)`、`CDecal` 的 const 成员)。 - 未覆盖:platform 层 `.cpp` 定义的**逻辑层头文件**成员(`GameLib/MapOutdoorRender*.cpp`、`MapOutdoorWater.cpp` 定义 `MapOutdoor.h` 的方法等)。这些在对应逻辑单元移植时手工补桩。 -- 未完成:依赖 Python 的三个库的闭包头(等 2P);port-map 重新基线(步骤 6)。 +- 已完成(步骤 6):port-map 重新基线,见第 6 节。 +- 未完成:依赖 Python 的三个库的闭包头(等 2P)。 | 平台 | port_gate | | --- | --- | @@ -290,7 +294,7 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 实时数字用 `port_map.py status` 查看。 -本次方案修订已经重置旧的 6 个完成状态;2A 完成工具和基础目标后再次确认基线: +本次方案修订重置了旧的 6 个完成状态;2A 完成工具和基础目标后,2026-09-22 重新确认了基线: - 之前"完成"的 6 个函数(`PythonPlayerEventHandler.cpp`)已作废并回退为 `TODO`:OnMove/OnMoving/OnStop 的实现在 `net_play.gd`,属于迁移来源;3 个 `N_A`(单例、构造、析构)与"单例归扩展所有"冲突。 @@ -298,7 +302,27 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 `impl` 指向随包运行的原脚本,`evidence` 要求目标平台的导入/运行证据;单元的 reference hash 与资源来源清单共同证明 运行的是完全相同的字节。`port_map.py`、SKILL 和 schema 已同步支持并把它计入 done。 -2026-09-22 基线前的数字(仅供参考):logic 3285 个函数、python 4890、platform 2229,完成数视为 0。 +基线(2026-09-22,`port_map.py status`): + +| 层 | 函数 | 完成 | 备注 | +| --- | --- | --- | --- | +| logic | 3343 | 0 | 1 个 `DIVERGENT`(`CPythonPlayerEventHandler::OnWaiting`) | +| python | 5175 | 0 | 其中 `root/*.py` 3350 | +| platform | 2091 | 0 | | +| 合计 | 10609 | 0 | | + +与基线前的数字(logic 3285、python 4890、platform 2229,共 10404)相比的变化: + +- 函数清单(`port_map.cpp_functions`)用 platform 骨架的 clang 声明逐个对照后修正: + - 新增 namespace 块内缩进的定义(`EterPythonLib` 的 `UI::CWindow` 等窗口类、`CWindowManager`、`NEffectUpdateDecorator`), + 这是 python 层 +285 的主要来源; + - 新增初始化列表或参数表超过 8 行的定义、类名全大写的构造/析构(`CLZO::CLZO`、`CIME::CIME`); + - 去掉 `/* */` 里注释掉的旧代码(如 `PythonNetworkDatagram.cpp` 整个文件、`GameUtil.cpp` 的碰撞函数)和被误当成函数的 + 构造函数初始化项(`m_hFM(NULL),`)。 + - 核对结果:platform 骨架里的每个函数桩都在清单里,只有 22 个 40250 未定义的声明,以及 namespace/typedef 写法不同的 + 同一函数(`NEffectUpdateDecorator::CAirResistanceDecorator::__Excute`、`CSkyObject::TSkyObjectFace` 与 `CSkyBox`)除外。 +- EterBase 按单元分层(见第 3 节),不再整个库算 platform。`audit/slices/*.json` 已重新生成(`EterLib/Dimm.h` 同时改为 + platform)。 ## 7. 换机器后的环境准备 diff --git a/extension/src/platform/EterBase/Poly/Poly.cpp b/extension/src/platform/EterBase/Poly/Poly.cpp deleted file mode 100644 index bc9feecd..00000000 --- a/extension/src/platform/EterBase/Poly/Poly.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// Platform skeleton for EterBase/Poly/Poly.h (40250 EterBase/Poly/Poly.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterBase/StdAfx.h" -#include "EterBase/Poly/Poly.h" - -#include "../../PlatformStub.h" - -CPoly::CPoly() -{ - MT_PLATFORM_STUB(); -} - -CPoly::~CPoly() -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::Analyze(const char *) -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::Eval() -> float -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::SetRandom(int) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::SetStr(const std::string &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::SetVar(const std::string &, double) -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::GetVarCount() -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::GetVarName(unsigned int) -> const char * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::Clear() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::my_irandom(double, double) -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::my_frandom(double, double) -> double -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::init() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::insert(const std::string &, int) -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::find(const std::string &) -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::emit(int, int) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::match(int) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::expo() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::factor() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::term() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::lexan() -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CPoly::error() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPoly::expr() -> void -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/EterBase/Poly/SymTable.cpp b/extension/src/platform/EterBase/Poly/SymTable.cpp deleted file mode 100644 index 6b27a5b2..00000000 --- a/extension/src/platform/EterBase/Poly/SymTable.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// Platform skeleton for EterBase/Poly/SymTable.h (40250 EterBase/Poly/SymTable.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterBase/StdAfx.h" -#include "EterBase/Poly/SymTable.h" - -#include "../../PlatformStub.h" - -CSymTable::CSymTable(int, std::string) -{ - MT_PLATFORM_STUB(); -} - -CSymTable::~CSymTable() -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/EterBase/Random.cpp b/extension/src/platform/EterBase/Random.cpp deleted file mode 100644 index e5cf26e6..00000000 --- a/extension/src/platform/EterBase/Random.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Platform skeleton for EterBase/Random.h (40250 EterBase/Random.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterBase/StdAfx.h" -#include "EterBase/Random.h" - -#include "../PlatformStub.h" - -auto frandom(float, float) -> float -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto random_range(long, long) -> long -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/EterBase/Stl.cpp b/extension/src/platform/EterBase/Stl.cpp deleted file mode 100644 index 176c1459..00000000 --- a/extension/src/platform/EterBase/Stl.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Platform skeleton for EterBase/Stl.h (40250 EterBase/Stl.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterBase/StdAfx.h" -#include "EterBase/Stl.h" - -#include "../PlatformStub.h" - -auto korean_tolower(const char) -> char -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto stl_static_string(const char *) -> std::string & -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto stl_lowers(std::string &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto split_string(const std::string &, const std::string &, std::vector &, bool) -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/EterBase/Timer.cpp b/extension/src/platform/EterBase/Timer.cpp deleted file mode 100644 index cf142ebb..00000000 --- a/extension/src/platform/EterBase/Timer.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Platform skeleton for EterBase/Timer.h (40250 EterBase/Timer.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterBase/StdAfx.h" -#include "EterBase/Timer.h" - -#include "../PlatformStub.h" - -CTimer::CTimer() -{ - MT_PLATFORM_STUB(); -} - -CTimer::~CTimer() -{ - MT_PLATFORM_STUB(); -} - -auto CTimer::Advance() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTimer::Adjust(int) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTimer::SetBaseTime() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTimer::GetCurrentSecond() -> float -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTimer::GetCurrentMillisecond() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTimer::GetElapsedSecond() -> float -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTimer::GetElapsedMilliecond() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTimer::UseCustomTime() -> void -{ - MT_PLATFORM_STUB(); -} - -auto ELTimer_Init() -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto ELTimer_GetMSec() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto ELTimer_SetServerMSec(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto ELTimer_GetServerMSec() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto ELTimer_SetFrameMSec() -> void -{ - MT_PLATFORM_STUB(); -} - -auto ELTimer_GetFrameMSec() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/EterBase/cipher.cpp b/extension/src/platform/EterBase/cipher.cpp deleted file mode 100644 index 43bce673..00000000 --- a/extension/src/platform/EterBase/cipher.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Platform skeleton for EterBase/cipher.h (40250 EterBase/cipher.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterBase/StdAfx.h" -#include "EterBase/cipher.h" - -#include "../PlatformStub.h" - -Cipher::Cipher() -{ - MT_PLATFORM_STUB(); -} - -Cipher::~Cipher() -{ - MT_PLATFORM_STUB(); -} - -auto Cipher::CleanUp() -> void -{ - MT_PLATFORM_STUB(); -} - -auto Cipher::Prepare(void *, size_t *) -> size_t -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto Cipher::Activate(bool, size_t, const void *, size_t) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto Cipher::SetUp(bool) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/EterBase/lzo.cpp b/extension/src/platform/EterBase/lzo.cpp deleted file mode 100644 index 669c6f77..00000000 --- a/extension/src/platform/EterBase/lzo.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Platform skeleton for EterBase/lzo.h (40250 EterBase/lzo.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterBase/StdAfx.h" -#include "EterBase/lzo.h" - -#include "../PlatformStub.h" - -CLZObject::CLZObject() -{ - MT_PLATFORM_STUB(); -} - -CLZObject::~CLZObject() -{ - MT_PLATFORM_STUB(); -} - -auto CLZObject::Clear() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CLZObject::BeginCompress(const void *, UINT) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CLZObject::BeginCompressInBuffer(const void *, UINT, void *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CLZObject::Compress() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZObject::BeginDecompress(const void *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZObject::Decompress(DWORD *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZObject::Encrypt(DWORD *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZObject::__Decrypt(DWORD *, BYTE *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZObject::GetSize() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZObject::AllocBuffer(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CLZObject::Initialize() -> void -{ - MT_PLATFORM_STUB(); -} - -decltype(CLZObject::ms_dwFourCC) CLZObject::ms_dwFourCC{}; - -CLZO::CLZO() -{ - MT_PLATFORM_STUB(); -} - -CLZO::~CLZO() -{ - MT_PLATFORM_STUB(); -} - -auto CLZO::CompressMemory(CLZObject &, const void *, UINT) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZO::CompressEncryptedMemory(CLZObject &, const void *, UINT, DWORD *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZO::Decompress(CLZObject &, const BYTE *, DWORD *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CLZO::GetWorkMemory() -> BYTE * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/EterBase/tea.cpp b/extension/src/platform/EterBase/tea.cpp deleted file mode 100644 index 722775c7..00000000 --- a/extension/src/platform/EterBase/tea.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Platform skeleton for EterBase/tea.h (40250 EterBase/tea.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterBase/StdAfx.h" -#include "EterBase/tea.h" - -#include "../PlatformStub.h" - -auto tea_encrypt(unsigned long *, const unsigned long *, const unsigned long *, int) -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto tea_decrypt(unsigned long *, const unsigned long *, const unsigned long *, int) -> int -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -}