These files were loaded only by their own test_*_parity.gd and never by the runtime (transitively checked, incl. client_phase_integration_system). Removes 76 manifest implementation/evidence references across 18 contracts; contract docs get a note that conclusions based on them are void. Live systems kept: chest, consumable, item_attr, metin_socket, whisper_chat. Full headless suite: no new failures (7 failing + 5 headless-hanging render tests are identical before the deletion). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
12 KiB
12 KiB
world.environment_weather —— 天空、环境、光照、昼夜、雪和天气
状态:PARTIAL
本合同检查 40250 的 .msenv 环境加载、背景/角色光照、线性雾、天空六面、云层、滤色、lens flare、风、雪粒子和地图环境生命周期。判断标准是同一份环境数据是否经过同一类调用链、在同一时序产生相同的可见状态和清理副作用;“字段已解析”或“测试能创建粒子”不能代替渲染与正式场景接入等价。
40250 参考调用链
GameLib/MapOutdoorRender.cpp/MapOutdoorRenderHTP.cpp/MapOutdoorRenderSTP.cppOnSetEnvironmentDataPtr将环境数据分派到 screen filter、SkyBox 和 lens flare;渲染顺序是天空、云、环境开始、地形/角色/水/雪/特效、环境结束和 lens flare。OnBeginEnvironment将.msenv的 fog near/far/color、背景方向光和角色方向光分别应用到 SpeedTree、terrain patch 和角色渲染;风强度进入森林渲染器。SetEnvironmentSkyBox使用 scale、gradient、texture render mode、六面纹理、云纹理、云高度/缩放/颜色/滚动速度,并通过 SkyBox transition 更新环境。
GameLib/SnowEnvironment.cpp/SnowParticle.cpp- 雪环境由专用粒子池、相机/世界范围、风/重力和粒子生命周期驱动,随 outdoor 渲染阶段更新和绘制,不是一次性创建的通用屏幕粒子节点。
Client/Eternexus/root/servercommandparser.py/game.py- 服务器
xmas_snow 0/1经ServerCommandParser进入__XMasSnow_Enable,先按__IsXMasMap过滤,再调用background.EnableSnow(0/1);该命令不是按地图名称自动推导天气。
- 服务器
EterLib/EnvironmentMap.cpp- 环境对象作为 outdoor 环境资源的生命周期边界参与加载/卸载;环境切换必须同步释放旧天空、雾、滤色、lens flare 和粒子状态。
当前端实现映射
formats/environment.*/extension/src/environment_builder.*- 已解析
.msenv的方向光、fog、sky gradient/六面/云、filter 和 lens flare 字段;apply_environment已创建背景Sun、角色CharacterLight和WorldEnvironment,texture-mode sky 已用 shader 采样六面和滚动云层。 - filter、lens flare、wind 目前主要保存在
WorldEnvironmentmetadata;没有对应运行时后处理、光晕节点或 SpeedTree 风更新。fog 使用 Godot depth fog,并主动 clamp/push begin/end、curve/density 与参考端 D3D 线性雾不相同。
- 已解析
extension/src/metin2_world.cpp/project/game_scene.gd.msenv在正式地图加载时接入Metin2World,世界卸载会移除环境节点;GameScene 会优先采用.msenv环境,避免兜底光照覆盖它。- 生产场景创建
fx/weather.gd,并由EntityStore::apply_server_command -> M2Client.weather_changed -> GameScene._on_weather_changed接收xmas_snow;场景按 40250 四张排除地图过滤,并在换图后重新应用当前开关。 WeatherDayNightSystem仍未实例化到正式场景;它的按地图自动天气/昼夜预设不作为 40250 生产行为。
project/fx/weather.gd- 使用跟随相机的单个
GPUParticles3D实现 snow/rain/none,粒子数量、重力、速度和颜色可切换;它没有 40250SnowEnvironment/SnowParticle的池、风向、范围、渲染阶段或资源失败回退链。
- 使用跟随相机的单个
project/weather_daynight_system.gd- 是当前端独立的昼夜/地图天气 helper,能计算 phase、天气和光照字典;但其地图预设与 40250
.msenv静态环境不是同一数据源,且正式 GameScene 未消费它。
- 是当前端独立的昼夜/地图天气 helper,能计算 phase、天气和光照字典;但其地图预设与 40250
分支等价矩阵
| 40250 判据/副作用 | 当前实现 | 结论 |
|---|---|---|
.msenv 解析、地图加载、环境节点创建和卸载 |
formats/environment + Metin2World::load_map + apply_environment |
基础链路通过;复杂地图/重入清理仍需扩展证据 |
| 背景/角色两套方向光和可见层 | Sun layer 1、CharacterLight layer 2 |
部分等价;光照色/能量和角色渲染消费仍需逐场景比对 |
| fog near/far/color、density/linear 分支、terrain/HTP/STP 使用 | Godot depth fog,begin/end 被 clamp,curve=0.5、density=0 | 不等价;参考的线性 D3D 雾公式和 LOD 分支没有 1:1 保持 |
| 六面天空、gradient、scale、texture mode、cloud plane/UV | Godot sky shader/ProceduralSkyMaterial,六面和云测试通过 | 部分等价;shader 采样与参考 quad/transition 仍需像素和边界比对 |
| screen filter alpha blend 和 lens flare | 字段只写 metadata,无运行时后处理/flare 渲染节点 | GAP |
| 风强度进入森林/树木更新 | 固定 msenv_wind_strength=0.2 metadata,无 SpeedTree/树节点风更新 |
GAP |
| SnowEnvironment/SnowParticle 池、范围、风/重力和 outdoor render 时序 | 单个相机跟随 GPUParticles3D | 部分等价;粒子可切换不代表池/时序/清理等价 |
服务器 xmas_snow 0/1、__IsXMasMap 过滤和雪开关 |
typed command -> weather_changed -> GameScene map filter -> Weather.set_weather |
部分等价;命令/过滤时序已对齐,但粒子池/渲染阶段不是 SnowEnvironment 1:1 |
.msenv 静态地图环境 vs 昼夜/天气切换 |
正式链消费服务器 xmas_snow;WeatherDayNightSystem helper 仍独立存在且不驱动生产地图 |
部分等价;40250 的 DayMode/PRESERVE_DayMode 和环境切换仍未接入 |
| 地图切换、暂停、重载和失败清理 | world 环境节点 queue_free;天气节点未按地图环境重置/验证 | 部分等价;缺少环境/粒子/云资源失败和快速切图组合证据 |
已执行测试
project/environment_test.gd:通过;A1.msenv、双方向光、WorldEnvironment、云纹理和 wind/filter metadata 可读取。project/skybox_test.gd:通过;CapeDragonHead/DawnMistWood texture-mode 六面天空、云层、scale 和 UV speed 断言通过。project/p9_test.gd:通过;通用 weather snow/rain/none 粒子开关路径通过,但不是参考雪环境池测试。project/test_weather_daynight_parity.gd:22 passed、0 failed;仅覆盖WeatherDayNightSystemhelper 的默认时相、时间推进、天气预设和信号,不覆盖正式 GameScene 接入或 40250.msenv渲染。extension/tests/net_entity_test.cpp/build/extension/net_entity_test:通过;覆盖GC_CHAT/COMMAND的xmas_snow 1/0typed event 顺序。project/gamescene_test.gd:通过;覆盖正式 GameScene 对 eligible map、四张 40250 排除地图和关闭命令的雪开关处理。project/netbridge_test.gd:通过;确认M2Client.weather_changed信号已注册。
Audit evidence round 2026-09-22T09:30Z
- 重新运行
environment_test.gd、skybox_test.gd、p9_test.gd和test_weather_daynight_parity.gd,结果分别通过、通过、通过、22/22 通过。 environment_test.gd实际加载 A1.msenv地图,skybox_test.gd实际加载 CapeDragonHead/DawnMistWood 六面天空;这些结果确认.msenv/天空基础链路仍可用,但不改变 filter、lens flare、wind、线性 fog 和 SnowEnvironment 池的差异结论。test_weather_daynight_parity.gd仍然只实例化独立WeatherDayNightSystem;对照GameScene::_build_world当前只创建fx/weather.gd,未发现正式地图加载时消费该 helper 的调用边沿,因此不能将 22/22 记为生产天气接入通过。- 本轮修复了服务器
xmas_snow的命令接入和正式场景地图过滤;合同继续保持PARTIAL,下一实现入口是DayMode/PRESERVE_DayMode、SnowEnvironment 池以及已确认的 filter/lens flare/wind GAP。
Deep audit round 2026-09-21
Fresh regression results
environment_test.gd、skybox_test.gd、p9_test.gd均退出码 0;真实 A1/CapeDragonHead/DawnMistWood 环境、六面天空、云参数和基础天气切换断言通过。test_weather_daynight_parity.gd22/22 通过,但它验证的是独立WeatherDayNightSystemhelper,不证明正式GameScene已实例化并消费天气系统。
Static parity conclusion
.msenv解析、背景/角色光、SkyBox 和地图环境节点的基础链路存在;filter、lens flare、wind 仍主要停留在 metadata,未形成 40250 的运行时后处理、光晕和树木风更新。- Godot depth fog 的 clamp/curve/density 与 40250 线性 D3D 雾不等价;六面天空/云 shader 有结构测试,但没有与参考 transition/render order 的像素 oracle。
- 生产场景已接入 40250 的服务器
xmas_snow命令和地图排除过滤,但没有接入DayMode/PRESERVE_DayMode;单个 GPUParticles3D 也不等价于 SnowEnvironment/SnowParticle 池和 outdoor render 时序。
本轮仍为 PARTIAL,完成服务器天气命令的实现和第三轮环境/天气证据登记。
Implementation fix round 2026-09-22T10:00Z
- 修复前
gamescene_test.gd的生产链回归无法让xmas_snow=1启用雪;native command-bus 也没有天气事件。 - 按 40250
ServerCommandParser.__XMasSnow_Enable -> game.__XMasSnow_Enable -> background.EnableSnow,新增EntityStore::WeatherChangedtyped event、M2Client.weather_changed(bool)信号,以及GameScene._on_weather_changed -> _apply_server_weather。 _apply_server_weather复刻__IsXMasMap的四张排除地图:metin2_map_n_flame_01、metin2_map_n_desert_01、metin2_map_spiderdungeon、metin2_map_deviltower1;地图切换后重新计算开关,避免服务器命令状态污染新地图。- 修复后 native
net_entity_test、gamescene_test.gd、netbridge_test.gd、p9_test.gd、environment_test.gd均通过。Godot 粒子仍只是平台适配,SnowEnvironment 池、DayMode、filter/lens flare/wind 和线性 fog 差异继续保留。
Active EterLib environment-render review
EterLib/SkyBox.cpp实际维护天空六面纹理、天空/云纹理、gradient、scale、scroll、天气/颜色过渡和 render 顺序;ScreenFilter.cpp、LensFlare.cpp是独立的屏幕滤镜与镜头光晕渲染对象,不只是环境字典字段。- 当前
WorldEnvironment/sky shader 能提供天空和雾的部分视觉结果,但filter、lens flare 和风更新主要停留在 metadata,没有对应运行时后处理/光晕对象;Godot depth fog 的 clamp、curve 和 density 也不等价于参考端的 D3D 线性雾分支。 - 因此本轮完成
SkyBox、ScreenFilter、LensFlare活跃源码静态核对;天空结构测试通过不能证明 transition/render order、滤镜、光晕和地图环境切换副作用一致,合同保持PARTIAL。
已确认差异和未验证项
- 保持 filter/lens flare/wind 的明确 GAP,或实现对应的后处理、光晕和树木风更新,并为每个资源失败/禁用分支补测试。
- 以 40250 的 fog near/far、天空 transition、云 plane、背景/角色光照和 render order 建立截图/参数 oracle,禁止只用 metadata 断言代替渲染证据。
- 补齐
DayMode/PRESERVE_DayMode的正式环境切换和场景生命周期;WeatherDayNightSystem的自动地图预设继续隔离,不能替代 40250 服务器命令。 - 建立真实地图快速切换、暂停恢复、环境资源缺失、重复加载/卸载和粒子/天空无悬挂节点的组合测试。
- 对 SnowEnvironment 的池化、世界范围、风/重力、相机边界和 outdoor render 时序补专门实现或明确平台适配合同。
下一轮验证入口
- 进入实现阶段后,优先修复正式 GameScene 的天气/地图环境接入和 fog/filter/lens flare/wind 中的已确认 GAP;修复后重新运行本合同四组测试并增加真实渲染证据。
2026-09-22 死代码删除
以下文件只被自身测试引用、运行时从不加载,已删除;本文中以它们为实现或证据的结论作废,相关行为需按 40250 源码单元重新移植:test_weather_daynight_parity.gd, weather_daynight_system.gd。