2V2-e.5b: feed native map height and light into game render

This commit is contained in:
shenlei
2026-09-23 22:10:29 +09:00
parent 702fef7b47
commit 5a1df57e69
13 changed files with 678 additions and 76 deletions
+1
View File
@@ -425,6 +425,7 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次
| 2V2-d | `InstanceBase` + `ActorInstance` + `CGraphicThingInstance` adapter:`GC_CHARACTER_ADD` 创建主角实例(msm 模型 + 待机动作) | 完成。d.1:`ActorInstance*.cpp`(Attach/Battle/Blend/CollisionDetection/Event/Fly/Motion/MotionEvent/Position/Render/Rotation/Sync/WeaponTrace)、`InstanceBase*.cpp`(Battle/Effect/Event/Motion/Transform)、`GameUtil`、`FlyTarget`、`PhysicsObject`、`GameEventManager`、`WeaponTrace`、`MapUtil`、`lineintersect_utils` 原样移植,`pending/GameLib/{ActorInstance,FlyTarget,PhysicsObject,MapUtil}.cpp`、`pending/UserInterface/InstanceBase.cpp` 替身删除,`ActorInstance.cpp`/`InstanceBase.cpp` 随主角创建进入运行时(port-map 标 PORTED);`CGameEventManager` 与 `CPythonSystem`(最后一个成员)按 `CPythonApplication` 成员顺序在 `PythonBoot` 创建;`D3D8Types.h` 补全 `D3DTA`/`D3DTEXTUREOP`/`D3DCMPFUNC`/`D3DBLEND`/`D3DCULL`。假服 `CHARACTER_ADD` 的 `bType` 改为 `CHAR_TYPE_PC`(6,原 0 使 `RecvCharacterAppendPacket` 不记主角、`CHAR_ADDITIONAL_INFO` 报错)。2V2-c 的偶发 Loading 头 7 根因:`TPlayerSkill::tNextRead` 是 `time_t`,40250 用 `_USE_32BIT_TIME_T`,LP64 下 `TPacketGCSkillLevelNew` 变成 2551 字节(线上 1531),`CInputDB::PlayerLoad` 在 `PointsPacket` 后发的 `SKILL_LEVEL`(76)读多吞掉后续包;`Packet.h` 改 `LONG` 并 `static_assert` 1531,假服 Loading 阶段补发 `SKILL_LEVEL` 回归。`port.login_flow` 断言主角实例存在且种族 0、无 `TPacketGCCharacterAdditionalInfo` 报错;`port.login_live` 2026-09-23 对 192.168.21.203 连跑 8 次通过,剩余 SYSERR 只有 gr2 `NOT SUPPORT FILE`。d.2:Granny SDK 2.11 运行时在 libgr2 上实现(`platform/EterGrnLib/GrannyRuntime.cpp`,`shim/sdk/granny.h` 按 SDK 头声明所用类型与函数:文件/段、按类型定义的顶点转换含 half、材质贴图按 Usage 查找、网格绑定、变形器、控制器时钟/循环/缓入缓出、加权 SRT 采样与复合矩阵),`EterGrnLib/*.cpp`(LODController/Material/Mesh/Model/ModelInstance*/Motion/Thing/ThingInstance/Util)与 `EterLib/{GrpObjectInstance,GrpCollisionObject,CollisionData}.cpp` 原样移植,对应 platform 骨架与 pending 替身删除(port-map 标 PORTED);`Resource.cpp` 注册 gr2 工厂(mdatr 等 `CAttributeData` 资源化时再注册);VB/IB 为 CPU 缓冲(`platform/EterLib/CpuBuffer.h`),渲染 adapter 属 2V2-e。`app.UpdateGame`/`RenderGame`(40250 `PythonApplication.cpp:321/168`)接入,成员经单例访问(平台没有 `CPythonApplication` 对象),`CPythonGraphic`(含 `CCullingManager`)按成员顺序进 `GameSingletons`;`GetMousePosition` 读 host 光标。`port.login_flow` 断言主角 PART_MAIN 模型有网格、材质漫反射贴图已加载、WAIT 动作使骨骼矩阵逐帧变化;离线与 `port.login_live`(192.168.21.203)2026-09-23 通过 |
| 2V2-e | Godot 显示主角(渲染 adapter),离线 + 真服 smoke:进游戏看到可辨认的静止角色 | 完成。e.1 完成:3D 绘制命令通道。`EterLib/StateManager.cpp`、`EterLib/GrpBase.cpp` 原样移植(platform 骨架删除,port-map 标 PORTED);`CGraphicDevice::Create` 建平台 `IDirect3DDevice8`(`platform/EterLib/RecordingDevice.cpp`:记住 transform/渲染状态/贴图阶段/材质/灯光/FVF/流/索引,按 FVF 解码顶点、展开 strip/fan,每次 Draw* 记成一条 `Render3DDraw`,`RenderCommands3D.h`),默认 IB/PDT VB 为 CPU 缓冲;`D3DXMath` 补 `PerspectiveFovRH`/`OrthoRH`/`OrthoOffCenterRH` 与 `ID3DXMatrixStack`。相机:`PythonApplicationCamera.cpp` 原样移植 `__UpdateCamera`/`SetCamera`/`SetCenterPosition`/`GetCenterPosition` 等(成员放文件内静态结构,平台没有 `CPythonApplication` 对象),`Process` 按 40250 顺序调 `__UpdateCamera`→`OnCameraUpdate`→`OnUIUpdate`→`Begin`/`SetInterfaceRenderState`/`OnUIRender`/`End`;`CScreen::Begin/End/Set*Operation`、`CPythonGraphic::Set{Game,Interface}RenderState/PushState/PopState/GetOrthoDepth`、`CCullingManager::Process` 的 view/proj 更新(视锥剔除等 SphereLib)原样;`pending` 补 `CPythonPlayer::NEW_GetMainActorPosition/NEW_GetMainActorPtr/NEW_FindActorPtr/SetMainCharacterIndex`(事件处理器留待 `PythonPlayerEventHandler`)、`CMapManager::IsMapReady`。`port.login_flow` 断言某帧有贴图、带法线/UV 的三角形绘制,投影为 `SetPerspective` 的 RH 透视(_34=-1),且顶点全部落在屏幕内(相机对准主角);离线与 `port.login_live`(192.168.21.203)2026-09-23 通过。e.2 完成:Godot 消费端 `project/python_3d_surface.gd`(`Metin2PythonHost.render3d_draws` 绑定):每条透视绘制成一个 `MeshInstance3D`,变换为 world·view(D3D 行向量矩阵的行即基列),`Camera3D` 在原点,fov/near/far 从 `SetPerspective` 投影反推;材质按贴图/混合/alpha test/剔除/光照状态缓存,贴图只从 40250 包取(`UiAssets.load_pack_tex`,包名保留 `d:` 盘符)。`CPythonBackground::GetFarClip` 原样移植(`m_pkMap` 为空 → 50000),`CMapManager` 构造原样(`m_pkMap=NULL`)。PORT 替身:地图未移植前没有环境数据(`LoadMap`→`SetEnvironmentData`→`SetCharacterDirLight`),D3D 会把受光网格画成全黑;「开光照、无灯、环境光与自发光为 0」的绘制按无光照贴图显示并计入 `unlit_stand_in_count`,随环境移植删除。`script/python_game_render_test.sh`(离线起 `port_fake_login_server`,`--live` 读 `MT_LIVE_*`)跑 `python_game_render_test.gd`:system.py 登录→选人→进游戏,4 条绘制(脸、Object05、身体、头发)全部带贴图,截图中心有角色;2026-09-23 离线通过。e.3 完成:实服冒烟 `MT_LIVE_*` 指向 192.168.21.203,`--live` 进游戏后主角与周围狼群带正确贴图、HUD 在上(246 条绘制、10 张贴图);修 `python_3d_surface.gd` 材质缓存键把 bool 交给 `%d`(格式化失败使所有绘制共用第一个材质即脸部贴图),测试加「每个贴图名一张贴图」断言;2026-09-23 离线与实服通过 |
2V2-e.4(2026-09-23):Python 3D 表面接上 40250 包内真实 A1 地图。`Metin2World` 的高度图、tile/splat、地表 DDS、`.msenv` 和 `AtlasInfo.txt` 经 `pack://` 读取;相机逆矩阵选当前 3×3 区块,地表随 D3D view 进入同一相机空间。角色材质不再使用 `unlit_stand_in_count` 的无光照替身,方向光取地图 `.msenv` 的 Character 参数,地形由同一环境的 Background 参数照明。离线截图能看到脚下石砖/沙地,9/9 区块带 splat,角色受光;`python_game_render_test.sh` 检查真实地图、光和地表像素差异。`CMapManager::LoadMap`、`CPythonBackground::SetCharacterDirLight` 的 native 链仍待逐单元移植;当前平台适配将地形一次性对齐到角色初始海拔(native `GetHeight` 尚为替身),所以不把这一步记作该 native 单元的 PORTED。地图内流式更新已接,跨图 warp 的 3D 场景替换留后续地图生命周期批次。
2V2-e.5(2026-09-23):原生 `CPythonNetworkStream::Warp` → `CPythonBackground::Warp` → `CMapManager::LoadMap/GetHeight` 已在运行路径接上包内 AtlasInfo、Setting.txt、height.raw 和 `.msenv`。地形高度使用 40250 的三角插值;`RenderGame` 调 `SetCharacterDirLight` 后录制绘制的 light0 来自该环境。Godot 地表按 native map 名和地图本地坐标放置,移除初始海拔平移,换图时重建地表;离线角色脚底与地表高度差约 0.1 cm,4/4 绘制带 light0。地图后端仍是过渡适配:`CMapOutdoor`、放置物件高度/属性、雾与完整环境状态、迷你地图/传送门等未移植,port-map 保持 ADAPTED/TODO,不宣称整个 native 地图单元 PORTED。修正 `EterBase/Utils` 的 MIN/MAX/fMIN/fMAX 系列返回零桩:地图就绪后相机 `Update` 会调用 fMIN/fMAX,否则距离被压成 0、view 矩阵变 NaN。离线测试增加有限矩阵、native map 一致性、脚底高度和 light0 检查;实服凭据当前环境缺失,换图和实服截图尚待 live 验证。
4. **2V3 — 本地移动**:加入 `PythonPlayer`、`PythonPlayerInput*`、`PythonPlayerEventHandler`、
`InstanceBaseMovement`、`ActorInstance{Motion,Event,Position,Rotation,CollisionDetection}` 的实际依赖闭包。验收为输入经过新路径
改变位置/朝向、发送与 40250 相同的移动封包,并在离线边界测试和真服 smoke 中通过。接通时删除对应 legacy 玩法逻辑。