Commit Graph
9 Commits
Author SHA1 Message Date
shenleiandClaude Opus 5 ffbb5d48d6 port(2P step 3c): stage python27.zip into the mobile sandbox
CPython opens the stdlib zip with its own stdio, so it needs a real path.
On the desktop res:// is a directory and globalize_path() is enough; in an
exported build res:// is inside the PCK, which nothing outside Godot reads.

  make_stdlib_zip.py now also writes <out>.sha256
  mtpython_stdlib_project copies python27.zip + .sha256 into project/
    (gitignored), and both export presets' include_filter lists them, so
    they enter the PCK — checked with --export-pack
  extension/src/python_stdlib.{h,cpp} (Metin2Python.stdlib_path in
    GDScript): reads the bytes out of the PCK, writes
    user://python27.zip.part, hashes the file as written against the
    shipped digest, then renames. A sandbox copy is reused only when it
    matches, so a first start killed mid-copy and a zip replaced by a new
    build both re-stage instead of feeding zipimport a torn file.
  PythonHost::SetDefaultStdLibPath / DefaultStdLibPath() answer with that
    path ($MT_PYTHON_STDLIB still wins). python_stdlib.cpp is the only unit
    that knows res:// / user://; port_platform stays godot-free.

Also fixes the Windows gate, which step 3b broke: without mtpython the
MinGW build compiled UserInterface/StdAfx.h (it includes ScriptLib/StdAfx.h,
as the original PCH does). port/CMakeLists.txt excludes that header and
PythonPackModule.cpp with ScriptLib, and platform/CMakeLists.txt excludes
platform/ScriptLib/ the same way.

Not done: on-device staging. The macOS test drives the mobile path with
force_stage=true, and nothing in the app boot calls it yet — the
interpreter only starts in the process with 2V0.

gates: python_stdlib_test.gd PASS (in-place path, staging, sha256, bytes
equal res://, no .part, ZIPReader finds encodings/__init__.py, no re-copy
on a second call, corrupted copy re-staged) · macOS ctest 27/27 ·
mingw + android + ios port_platform compile clean · port_map.py check 0
errors · key leak check 8/8 none.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 09:39:33 +09:00
shenleiandClaude Opus 5 2b873f190f port(2P step 3a/3b): stdlib on sys.path + the pack module
step 3a — 标准库:
  tools/py_embed/make_stdlib_zip.py packs the vendored Lib/ into
  <build>/python27.zip (397 modules, 6876547 bytes, ZIP_STORED — the zlib
  module is trimmed out of our CPython, so zipimport cannot inflate).
  The mtpython_stdlib target builds it; py_embed_test and the launcher test
  both run against it.
  platform/ScriptLib/PythonHost sets the embedding flags before
  Py_Initialize and, after it, puts the zip on sys.path and re-registers
  encodings.search_function with codecs — 2.7 builds the codec registry
  once, at startup, so replacing sys.path afterwards needs it back.

step 3b — pack 模块:
  UserInterface/PythonPackModule.cpp copied verbatim; packExist/packGet/
  initpack read root/ and uiscript/ through CEterPackManager, i.e. through
  asset_io. The CHINA_CRYPT_KEY block in that unit is CAccountConnector's
  and is kept #if 0 until the login slice (2V1). UserInterface/StdAfx.h is
  a documented partial mirror — the original is the whole client's PCH.

The launcher test now runs initpack() as RunMainScript does (its first
line), reads system.py / uiscript / locale text back out of the packs, and
confirms cp1252 decoding works off the zip. system.py still stops at
"No module named app" — the C++ modules are the 2V0 slice.

gates: port_map.py check 0 errors · key leak check 8/8 none · macOS ctest
27/27 · android + ios port_platform compile clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 09:16:37 +09:00
shenleiandClaude Opus 5 5fad769ee8 port 2P step 1: vendor CPython 2.7.18 as the mtpython static library
The embedded 40250 script layer needs its own interpreter on five platforms.
2.7 is end-of-life, so nothing can be fetched from the target SDKs and the
source is vendored (official 2.7.18 tarball, trimmed to 25MB; Lib/ stays for
step 3's python27.zip).

cpython-2.7.18/CMakeLists.txt builds one `mtpython` static library from exactly
the 133 objects the reference libpython2.7.a contains, off by default behind
-DMTGODOT_EMBED_PYTHON=ON. The source list and the built-in module table
(config/config.c, 39 entries) are shared; pyconfig.h is a probe result and is
not, so each platform keeps its own under config/<platform>/, regenerated by
tools/py_embed/gen_pyconfig.sh and checked against the shared table.

Three vendor patches, documented in docs/THIRD-PARTY.md: configure/configure.ac
learn arm64 on macOS, and posixmodule.c undefines the process-control calls it
hard-defines past pyconfig.h when building for iOS.

macOS (ctest python.embed: every builtin imports, codecs and pickle work off the
vendored Lib/), Android arm64 and iOS arm64 build. Linux needs a Linux host and
Windows needs a MinGW-vs-MSVC decision; both are noted for step 4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 08:27:35 +09:00
shenleiandClaude Opus 5 a9b31dec67 port 2D steps 3-4: strict 40250 asset gate with a provenance manifest
tools/asset_manifest.py records path/size/sha256 of pack/Index, every .eix/.epk
and Eternexus/root/*.msm (audit/assets/40250-client.json). The gate script sets
MT_ASSETS_STRICT=1, verifies the manifest, runs the native pack/proto tests and
four Godot tests, and fails on a missing client, a mismatch or a skip.
MT_40250_CLIENT now comes from the environment for the native tests too.
remote_player_test accepts both weighted WAIT variants (wait/wait_1).
PORT-PLAN §5 records the 2D status.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 01:41:38 +09:00
shenleiandClaude Opus 5 f210f47076 Batch 2R: 40250 pack inventory (epk_scan) and delivery decision
Read-only scanner for Client/pack following PackInitialize -> CEterPackManager
-> CEterPack::__BuildIndex/Get2. Keys are read from the reference EterPack.cpp
at run time; none are stored. Pure-Python TEA + LZO1X.

- 136 registered packs, 54,891 entries: NONE/COMPRESS/SECURITY only, no
  PANAMA/HybridCrypt, all entries decode
- first-registered pack wins; 2,282 shadowed entries (2,194 differ)
- metin2_patch_{sd,mineral,mundi} use a second packer layout; 4 SECURITY
  files fail 40250's CRC check and never load in the original
- no case collisions; paths are already lowercase
- PORT-PLAN: read EPK on device via ported EterPack, base install minus
  extra locales, rebuild dict in Index order on any pack change

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 23:59:18 +09:00
shenleiandClaude Opus 5 b02c49bb2f spike(python): CPython 2.7.18 runs the 40250 root scripts on Android arm64
libpython2.7.a cross-builds with NDK 27.2 (API 24) after disabling
HAVE_LANGINFO_H; 30 C modules built in. On a OnePlus 13 (API 36) the
harness runs system.py -> prototype.RunApp() and imports the root modules
with results identical to macOS (66/74; the 8 failures are stub values or
dev-only scripts). py_embed_spike.py now isolates __main__ like
CPythonLauncher and reports stdlib usage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 18:16:44 +09:00
shenandshen 66d217b313 feat(client): 完成40250客户端核心功能1:1对齐与桥梁高度采样修复
- 桥梁与静态物体高度采样修复:
  - 严格对齐 40250 CMapOutdoor::GetHeight 与 CAttributeInstance::GetHeight
  - 解析 .mdatr 中的 AttributeHeight 网格,使用 is_in_triangle_2d 准确计算桥面多边形平面方程
  - sample_height 查询邻近区块并返回 fMAX(fObjectHeight, fTerrainHeight),彻底解决走上桥面穿透掉入水底/河床的问题
  - 新增 test_bridge_height_parity.gd 自动化对拍测试
- 40250 怪物击杀经验动效:
  - 1:1 实现 FLY_EXP(0) / FLY_HP / FLY_SP 粒子轨迹与爆炸吸附
- 40250 客户端全系统功能对齐(Batches 1-31):
  - 包含公会、交易、骑乘、变身、钓鱼、采矿、商城、信件、结婚、地牢等 134 套对拍系统与自动化回归测试
- 文档沉淀:
  - 新增 docs/CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md 客户端对拍缺陷发现与修复工程指南
2026-09-19 08:51:25 -07:00
shenlei 8f61990a83 Implement 40250 classic client port 2026-09-01 18:49:28 +09:00
shenandClaude Sonnet 5 47baf6c0c6 Metin2 game client (P0–P11) + mobile asset pipeline
Networked client on the existing Godot 4.7 + libgr2 renderer:
- net: m2dev wire protocol (libsodium KX + XChaCha20), auth/select/game
  phases, EntityStore world model, ~all GC/CG headers. char create/delete,
  private shop / mall / cube, SHOP_GC_START_EX, guild, party (+ CG_PARTY_SET_STATE),
  quests, dragon soul, refine, safebox, exchange.
- UI: in-game windows migrated 1:1 from the reference uiscript/root .py —
  char status (/stat), inventory+equipment, select-item ([SELECT_ITEM] quest
  token), system-option + game-option + ESC system menu, private-shop 39-grid,
  party info board, shop tabs, atlas, minimap, quickbar, chat, …
- EterGrnLib polish: GR2 material blend/two-sided, LOD crossfade, motion-event
  dispatch, contact shadow, ray-AABB picking, weapon grip pre-transform.

Portable asset IO (A1) — all extension/libgr2/formats/mtproto reads routed
through godot::FileAccess (res:// PCK works on iOS/Android); standalone-lib
*_path() kept for the non-Godot CTests. AssetResolver + PropertyRegistry
switched to a baked index (bake_asset_index.gd) instead of std::filesystem.

Mobile builds: build-{android,ios}.sh, export-android.sh, pack-assets.sh,
gen-debug-keystore.sh. Assets ship as a zip mounted at runtime by
project/asset_pack.gd (adb push now; HTTP download is a drop-in later).

ctest 10/10, 34 GDScript suites, macOS/iOS/Android all build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EJxkHiNKS4kybHS3XKyAJ
2026-08-31 20:02:12 +09:00