diff --git a/README.md b/README.md index 363409d..3018725 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,9 @@ python app.py ## 开发指南 -- [仪表盘开发指南](docs/DASHBOARD_DEV.md) — 创建自定义仪表盘主题 -- [游戏插件兼容开发指南](docs/PLUGIN_DEV.md) — 为任意赛车游戏编写遥测解析器 +- [仪表盘开发指南](docs/DASHBOARD_DEV.md) — 创建自定义仪表盘主题 (.tsd) +- [游戏插件兼容开发指南](docs/PLUGIN_DEV.md) — 为任意赛车游戏编写遥测解析器 (.tsp) +- [Forza 数据包格式参考](docs/FH_DATA_FORMAT.md) — 官方 UDP 包 324 字节完整字段定义 ## 项目结构 @@ -109,11 +110,12 @@ TurboSu/ │ │ ├── f1_24/ │ │ └── iracing/ │ └── user/ # 社区插件 (运行时安装) -├── dashboards/ # 内置仪表盘 (4 款) -│ ├── speedometer/ # manifest.json + index.html -│ ├── tachometer/ -│ ├── gear_indicator/ -│ └── lap_timer/ +├── dashboards/ # 内置仪表盘 (5 款) +│ ├── speedometer/ # 极速仪表 (auto 比例, 全兼容) +│ ├── tachometer/ # 转速表 (16:9, 全兼容) +│ ├── gear_indicator/ # 档位指示器 (1:1, R/N/1-8, 自适应映射) +│ ├── lap_timer/ # 圈速计时器 (4:3, Forza/F1) +│ └── forza_composite/ # Forza 复合仪表 (16:9, 仅Forza系列) ├── models/ │ ├── dashboard.py # 仪表盘模型 + 自动扫描 + zip导入导出 │ └── scene.py # 场景模型 + 画布/布局 + zip导入导出 diff --git a/docs/FH_DATA_FORMAT.md b/docs/FH_DATA_FORMAT.md new file mode 100644 index 0000000..2258a98 --- /dev/null +++ b/docs/FH_DATA_FORMAT.md @@ -0,0 +1,239 @@ + + +## 《极限竞速:地平线》系列 UDP 数据包完整定义 + +### 基础信息 + +| 属性 | 值 | +|------|-----| +| **协议** | UDP(单向发送,游戏不接收数据) | +| **包大小** | **324 字节(FH6)/ 约 311 字节(FH5)** | +| **发送频率** | 等于游戏帧率 | +| **字节序** | **Little Endian**(小端序) | +| **数据起始** | 玩家开始驾驶后发送,菜单/暂停/回放时不发送 | + +> FH6 和 FH5 的数据包基本兼容,主要差异是 FH6 新增了 `CarGroup`、`SmashableVelDiff`、`SmashableMass` 三个字段。 + +--- + +### 类型符号说明 + +| 符号 | 含义 | 示例 | +|------|------|------| +| `S8` / `S32` | 有符号整数(signed) | S8 范围 -128~127 | +| `U8` / `U16` / `U32` | 无符号整数(unsigned) | U8 范围 0~255 | +| `F32` | 32位浮点数(float) | 小端序 | + +--- + +### 完整数据包结构(按顺序) + +#### 第 1 部分:状态和时间(8 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 0 | 4 | S32 | `IsRaceOn` | 1=比赛中,0=菜单/停止 | +| 4 | 4 | U32 | `TimestampMS` | 时间戳(毫秒,会溢出归零) | + +#### 第 2 部分:引擎数据(12 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 8 | 4 | F32 | `EngineMaxRpm` | 引擎最大转速 | +| 12 | 4 | F32 | `EngineIdleRpm` | 引擎怠速转速 | +| 16 | 4 | F32 | `CurrentEngineRpm` | 当前引擎转速 | + +#### 第 3 部分:加速度与速度(24 字节,车身坐标系 X=右, Y=上, Z=前) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 20 | 4 | F32 | `AccelerationX` | +| 24 | 4 | F32 | `AccelerationY` | +| 28 | 4 | F32 | `AccelerationZ` | +| 32 | 4 | F32 | `VelocityX` | +| 36 | 4 | F32 | `VelocityY` | +| 40 | 4 | F32 | `VelocityZ` | + +#### 第 4 部分:角速度与方向(24 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 44 | 4 | F32 | `AngularVelocityX` | 俯仰(rad/s) | +| 48 | 4 | F32 | `AngularVelocityY` | 偏航(rad/s) | +| 52 | 4 | F32 | `AngularVelocityZ` | 侧倾(rad/s) | +| 56 | 4 | F32 | `Yaw` | 偏航角(弧度) | +| 60 | 4 | F32 | `Pitch` | 俯仰角(弧度) | +| 64 | 4 | F32 | `Roll` | 侧倾角(弧度) | + +#### 第 5 部分:悬挂行程(16 字节,归一化 0=最大拉伸, 1=最大压缩) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 68 | 4 | F32 | `NormalizedSuspensionTravelFrontLeft` | +| 72 | 4 | F32 | `NormalizedSuspensionTravelFrontRight` | +| 76 | 4 | F32 | `NormalizedSuspensionTravelRearLeft` | +| 80 | 4 | F32 | `NormalizedSuspensionTravelRearRight` | + +#### 第 6 部分:轮胎滑移比(16 字节,0=100%抓地力,|ratio|>1=失去抓地力) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 84 | 4 | F32 | `TireSlipRatioFrontLeft` | +| 88 | 4 | F32 | `TireSlipRatioFrontRight` | +| 92 | 4 | F32 | `TireSlipRatioRearLeft` | +| 96 | 4 | F32 | `TireSlipRatioRearRight` | + +#### 第 7 部分:车轮转速(16 字节,弧度/秒) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 100 | 4 | F32 | `WheelRotationSpeedFrontLeft` | +| 104 | 4 | F32 | `WheelRotationSpeedFrontRight` | +| 108 | 4 | F32 | `WheelRotationSpeedRearLeft` | +| 112 | 4 | F32 | `WheelRotationSpeedRearRight` | + +#### 第 8 部分:车轮状态(16 字节,0/1布尔值) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 116 | 4 | S32 | `WheelOnRumbleStripFrontLeft` | +| 120 | 4 | S32 | `WheelOnRumbleStripFrontRight` | +| 124 | 4 | S32 | `WheelOnRumbleStripRearLeft` | +| 128 | 4 | S32 | `WheelOnRumbleStripRearRight` | + +#### 第 9 部分:涉水深度(16 字节,FH5 为深度值,FH6 为 0/1) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 132 | 4 | S32/F32 | `WheelInPuddleFrontLeft` | +| 136 | 4 | S32/F32 | `WheelInPuddleFrontRight` | +| 140 | 4 | S32/F32 | `WheelInPuddleRearLeft` | +| 144 | 4 | S32/F32 | `WheelInPuddleRearRight` | + +> ⚠️ FH5 为 F32(水深值),FH6 为 S32(0/1布尔值) + +#### 第 10 部分:路面震动反馈(16 字节) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 148 | 4 | F32 | `SurfaceRumbleFrontLeft` | +| 152 | 4 | F32 | `SurfaceRumbleFrontRight` | +| 156 | 4 | F32 | `SurfaceRumbleRearLeft` | +| 160 | 4 | F32 | `SurfaceRumbleRearRight` | + +#### 第 11 部分:轮胎滑移角(16 字节) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 164 | 4 | F32 | `TireSlipAngleFrontLeft` | +| 168 | 4 | F32 | `TireSlipAngleFrontRight` | +| 172 | 4 | F32 | `TireSlipAngleRearLeft` | +| 176 | 4 | F32 | `TireSlipAngleRearRight` | + +#### 第 12 部分:轮胎复合滑移(16 字节) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 180 | 4 | F32 | `TireCombinedSlipFrontLeft` | +| 184 | 4 | F32 | `TireCombinedSlipFrontRight` | +| 188 | 4 | F32 | `TireCombinedSlipRearLeft` | +| 192 | 4 | F32 | `TireCombinedSlipRearRight` | + +#### 第 13 部分:实际悬挂行程(16 字节,单位:米) + +| 偏移 | 大小 | 类型 | 字段 | +|------|------|------|------| +| 196 | 4 | F32 | `SuspensionTravelMetersFrontLeft` | +| 200 | 4 | F32 | `SuspensionTravelMetersFrontRight` | +| 204 | 4 | F32 | `SuspensionTravelMetersRearLeft` | +| 208 | 4 | F32 | `SuspensionTravelMetersRearRight` | + +#### 第 14 部分:车辆信息(20 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 212 | 4 | S32 | `CarOrdinal` | 车辆唯一ID | +| 216 | 4 | S32 | `CarClass` | 等级 0(D) ~ 7(X) | +| 220 | 4 | S32 | `CarPerformanceIndex` | 性能指数 100~999 | +| 224 | 4 | S32 | `DrivetrainType` | 0=FWD, 1=RWD, 2=AWD | +| 228 | 4 | S32 | `NumCylinders` | 引擎气缸数 | + +#### 第 15 部分:FH6 新增字段(12 字节)⚠️ + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 232 | 4 | U32 | `CarGroup` | 车辆组标识(FH6新增) | +| 236 | 4 | F32 | `SmashableVelDiff` | 可破坏物体碰撞速度损失(m/s) | +| 240 | 4 | F32 | `SmashableMass` | 碰撞物体质量(kg) | + +> ⚠️ **FH5 没有这三个字段**,此位置为 12 字节的占位数据(`HorizonPlaceholder`) + +#### 第 16 部分:坐标与速度(16 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 244 | 4 | F32 | `PositionX` | 世界坐标 X(米) | +| 248 | 4 | F32 | `PositionY` | 世界坐标 Y(米) | +| 252 | 4 | F32 | `PositionZ` | 世界坐标 Z(米) | +| 256 | 4 | F32 | `Speed` | 速度(m/s) | + +#### 第 17 部分:动力与温度(24 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 260 | 4 | F32 | `Power` | 功率(瓦特) | +| 264 | 4 | F32 | `Torque` | 扭矩(牛·米) | +| 268 | 4 | F32 | `TireTempFrontLeft` | 轮胎温度 | +| 272 | 4 | F32 | `TireTempFrontRight` | 轮胎温度 | +| 276 | 4 | F32 | `TireTempRearLeft` | 轮胎温度 | +| 280 | 4 | F32 | `TireTempRearRight` | 轮胎温度 | + +#### 第 18 部分:增压与燃油(8 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 284 | 4 | F32 | `Boost` | 涡轮增压值(PSI,高于大气压) | +| 288 | 4 | F32 | `Fuel` | 燃油量(0.0~1.0) | + +#### 第 19 部分:里程与圈时(28 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 292 | 4 | F32 | `DistanceTraveled` | 总行驶距离(米) | +| 296 | 4 | F32 | `BestLap` | 最佳圈时(秒) | +| 300 | 4 | F32 | `LastLap` | 上一圈用时(秒) | +| 304 | 4 | F32 | `CurrentLap` | 当前圈用时(秒) | +| 308 | 4 | F32 | `CurrentRaceTime` | 总比赛时间(秒) | + +#### 第 20 部分:比赛信息(6 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 312 | 2 | U16 | `LapNumber` | 已完成圈数 | +| 314 | 1 | U8 | `RacePosition` | 当前排名位置 | + +#### 第 21 部分:玩家输入(6 字节,值范围 0~255) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 315 | 1 | U8 | `Accel` | 油门(0~255) | +| 316 | 1 | U8 | `Brake` | 刹车(0~255) | +| 317 | 1 | U8 | `Clutch` | 离合器(0~255) | +| 318 | 1 | U8 | `HandBrake` | 手刹(0~255) | +| 319 | 1 | U8 | `Gear` | 当前档位 | + +#### 第 22 部分:转向与AI(3 字节) + +| 偏移 | 大小 | 类型 | 字段 | 说明 | +|------|------|------|------|------| +| 320 | 1 | S8 | `Steer` | 转向(-127左 ~ 0中 ~ 127右) | +| 321 | 1 | S8 | `NormalizedDrivingLine` | 归一化赛道线(-127~127) | +| 322 | 1 | S8 | `NormalizedAIBrakeDifference` | AI刹车差异(-127~127) | + +--- + +### 快速参考:字段总数 + +- **FH6**:约 77 个字段,总计 **324 字节** +- **FH5**:约 74 个字段(比 FH6 少 CarGroup/SmashableVelDiff/SmashableMass),总计 **约 311 字节** +- **FH4**:和 FH5 基本一致