shenlei and Claude Sonnet 5
9732f2799e
40250 classic: increment 50 (W4) — map BGM selection + background volume save/restore
...
§9.1 map BGM selection (bgm_director.gd):
- server bgm_changed(name, volume): non-empty name plays it as field music;
empty name falls back to musicInfo.fieldMusic (METIN2THEMA = "M2BG.mp3")
- volume < 0 (server unspecified, GC_MAIN_CHARACTER3_BGM) -> default
1/5*0.1 = 0.02; otherwise server volume; volume applied before play_bgm()
fade-in (matches game.py:190 SetMusicVolume/SetSoundVolume then FadeInMusic)
- connect M2Client.world_reset -> re-run selection on map change
- new musicinfo.gd: METIN2THEMA/loginMusic/createMusic/selectMusic/fieldMusic
constants + save/load_last_play_field_music -> user://BGM/lastplay.inf
§9.2 background/foreground volume save-restore:
- audio.gd: save_volume()/restore_volume() (backup fields echo reference
m_fBackupMusicVolume / m_fBackupSoundVolume) + set_music_volume()
- app_lifecycle.gd: _enter_background() uses save_volume() + mute instead of
stop_bgm(); _exit_background() calls restore_volume(); _bgm_name never cleared
§9.3 lifecycle ownership: DOC ONLY — design confirmed, deferred to Phase 2 / W0
(AppFlow sole lifecycle owner; M2Client drops NOTIFICATION_* keeps suspend/resume).
game_scene.gd / app_flow.gd / m2_client.* left untouched per workflow constraints.
Tests: bgm_test.gd (new) PASS; gamescene_test / netplay_test / p9_test green.
Docs: CLIENT-GAP.md increment 50 bullet + W4 progress row; CLIENT-GAP-FIX.md
§9.1 §9.2 状态/改动/测试/验收, §9.3 deferred note, C.5 batch record.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_014yvAPqPivoY7vmBbzgqK4W
2026-09-02 15:31:58 +09:00
shenlei and Claude Sonnet 5
f32064c74a
40250 classic: parallel-dev checkpoint through increment 49 (W0 interface freeze)
...
Captures the uncommitted parallel-development work (increments 46-49) on the
40250 classic client port, folded into docs/CLIENT-GAP.md + CLIENT-GAP-FIX.md.
Increment 49 (W0 interface-freeze batch, Phase 1 prerequisite) lands the
cross-workflow shared-file scaffolding so the 4 Phase 1 workflows can run in
isolated worktrees without contention:
- entity_store.{h,cpp}: Entity gains empire/affect_flags/owner_vid/state_flags;
new mut_spawn_full() (single-shot two-packet merge, §2.3), mut_ownership()
(§2.5), mut_map_bgm() + take_bgm_dirty()/bgm_name()/bgm_volume() (§9.1),
drain_dirty() (§2.1/§2.5 bare-field-update queue); mut_char_info() now stores
empire; reset_for_map_change() clears m_dirty.
- m2_client.cpp: new bgm_changed(name, volume) signal; classic + m2dev pump
loops drain drain_dirty() -> entity_info and take_bgm_dirty() -> bgm_changed;
entity_dict() exposes the 4 new keys.
- classic/classic_parser.{h,cpp}: GC_MAIN_CHARACTER3_BGM /
GC_MAIN_CHARACTER4_BGM_VOL route bgm_name/bgm_volume to mut_map_bgm() (was
discarded); new m_pending_actor staging map (W1 fills §2.2 merge logic).
- project/bgm_director.gd (new) + game_scene.gd: BGM consumption split out of
net_world.gd so W2/W4 don't collide; §8.6/§4.8 keybind convergence (digits
1-4 -> quickslots 0-3, F1-F4 -> quickslots 4-7, Ctrl+1..9 -> _emote()).
Tests: cmake --build build clean; ctest 16/16; 15 GDScript regressions green
(netbridge, gamescene, netplay, p9, p10, p2b, p8, system_menu_ui, skill,
combat_fx, skill_fx, player_motion, char_status_ui, chat, inventory), no skips.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_014yvAPqPivoY7vmBbzgqK4W
2026-09-02 15:13:01 +09:00
shenand shen
44bdcb0781
Fix 40250 classic login and world loading
2026-09-02 07:03:25 +08:00
shenlei
8f61990a83
Implement 40250 classic client port
2026-09-01 18:49:28 +09:00
shen and Claude 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
Claude
f4917a2b3b
Fix cull mode + isolate head-collapse to a libgr2 curve bug
...
Rendering fixes (real):
- m2_material shaders: cull_disabled -> cull_back (inside-of-mesh faces were
z-winning and darkening/hiding the head under the ShaderMaterial path).
- drop `* COLOR` from the shader (meshes carry no ARRAY_COLOR).
Animation: convert gr2 global poses to Godot *local* bone poses and set via
set_bone_pose (was set_bone_global_pose). MTGODOT_VERIFY=1 confirms
get_bone_global_pose(i) == conv(world[i]) for all 75 bones (<=2.6e-5).
Head/upper-armor collapse on dance_1 is NOT a Godot-route bug:
- reproduced identically in xrender-poc's bgfx demo at the same anim/t
- reproduced by the new MTGODOT_CPUSKIN=1 reference path (same LBS math as
xrender's validated skin_mesh)
- `general/wait` / `run` render correctly in all three
=> upstream libgr2 Curve::eval (degree-2 quaternion B-spline) vs Granny.
Demo default animation switched to general/wait; documented in MIDREVIEW §4
and README. Debug scaffolding gated behind MTGODOT_VERIFY / MTGODOT_CPUSKIN.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01WaHYEY9rwLWt21PULiYjeJ
2026-08-29 10:47:01 +09:00
Claude
528a6390ea
Phase 1 mid-review + stress harness
...
- docs/MIDREVIEW.md: what M0'-M2.5 proved, bridge-layer LOC (~1100),
key technical conclusions (4x4 transpose, animation method B, no
handedness flip needed), remaining risks, recommendation = enter Phase 2
with a 3-item wrap-up (compare.py, dump_materials oracle, refocused perf).
- harness MTGODOT_STRESS=N: grid of N animated warriors, vsync off, dumps
test/godot-macos-stress.json. Frame times are throttle-capped in a
background window (~30fps to 50 chars, 52ms at 100); the reliable signals
are build cost ~165ms/char and the 100-char breakout.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01WaHYEY9rwLWt21PULiYjeJ
2026-08-29 09:46:54 +09:00
Claude
eeffa2a730
M2.5: ShaderMaterial + texture resolution + fog; multi-skeleton verified
...
- m2_material: Metin2-style ShaderMaterial. blend_mix shader (opaque /
alpha-blend / alpha-test-cutout via `mode` uniform) + blend_add shader
(additive glow). modulate(tex, COORD) * COLOR, diffuse_lambert.
- Metin2Model: material_mode prop ("metin2" ShaderMaterial | "standard");
_resolve_texture does filename-convention + case-insensitive dir scan of
*.dds (face/hair keyword slots, stem match, fallback); set_surface_texture
override; guess_blend heuristic (hair->cutout, cape->alpha, effect->add).
Texture cache. Fixed opaque path to NOT alpha-discard (was hiding bodies).
- harness: AABB-based camera framing, engine depth fog (MTGODOT_FOG=1),
MTGODOT_ANIM_T fixed-pose capture (needs explicit anim reload first),
MTGODOT_AUTOSHOT batch screenshot.
Verified: warrior 5/5 surfaces textured under the shader (t=9 dance pose,
lit, fogged). assassin 17/17 textured via dir scan. shaman_lord (gr2 v7)
renders. Screenshots test/golden/m25-*.png, m2c-t*.png.
Gap (M2.5 gate not closed): libgr2 POD API exposes no material/texture-name/
blend data, so multi-slot -> texture/blend mapping is heuristic only. Needs
a libgr2 material API (gr2_material.cpp walking the type tree) — same gap as
xrender-poc M1 T5. Documented in docs/GODOT-POC-PLAN.md §M2.5 T2.5.6.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01WaHYEY9rwLWt21PULiYjeJ
2026-08-29 09:35:01 +09:00
Claude
27e39993f7
M1+M2: gr2 -> Skeleton3D/ArrayMesh/Skin + libgr2-driven animation
...
- gr2_bridge: gr2 Mat4 (row-major) -> Godot Transform3D (4x4 transpose);
build_skeleton (rest from local_transform, initial_placement folded into
roots), build_skin (bind i -> bone i, pose = inverse_world), build_mesh
(surface per gr2 mesh, ARRAY_BONES = skeleton idx via bone_bindings,
rigid meshes bound to bone_bindings[0]).
- dxt: DDS DXT1/3/5 decoder ported from xrender-poc.
- Metin2Model: load_gr2 -> Skeleton3D + MeshInstance3D + StandardMaterial3D
(runtime DDS albedo, face/body split by surface name). Z-up cm -> Y-up m
conversion on the node transform (unit_scale, flip_z, flip_winding props).
- Metin2AnimPlayer: _process samples a (separate) anim .gr2 with
gr2::sample_pose(model.skeleton, anim, t) -> set_bone_global_pose per bone;
Godot GPU-skins via skin_matrix = global_pose(i) * bind_pose(i) == gr2
deformer matrix. selfcheck() NaN-scans all anims.
Verified: warrior_cheongrin renders (75 bones, 5 surfaces, 3324 verts,
textured, upright). dance01 (dur 28.3s, 74 tracks) plays, 0 NaN over 25
samples, distinct poses at t=2/9/16/23. Screenshots in test/golden/.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01WaHYEY9rwLWt21PULiYjeJ
2026-08-29 09:23:29 +09:00
Claude
c52b8657c4
M0' scaffold: Godot 4.7 + GDExtension + libgr2 wired up (macOS)
...
- extension/: godot-cpp submodule (master, API 4.7), Metin2Model node
registered, links xrender-poc/libgr2 via sibling-dir reference.
- project/: Godot 4.7 project — orbit camera + DirectionalLight3D (shadows)
+ WorldEnvironment/procedural sky + placeholder cube; main.gd probes the
extension and can run libgr2 on a real .gr2 (MTGODOT_PROBE_GR2).
- build.sh one-shot build into project/bin/.
- docs/GODOT-POC-PLAN.md (phased: Phase 1 macOS -> M0'/M1/M2/M2.5).
Verified on this machine:
[mtgodot] Metin2Model registered OK — libgr2 linked
probe_gr2(warrior_cheongrin.gr2) -> gr2 OK: format_version=6 sections=8
Metal Forward+ renders the scene (test/golden/m0-scaffold.png).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01WaHYEY9rwLWt21PULiYjeJ
2026-08-29 09:09:55 +09:00