refactor: merge FH4+FH5 into 'forza_horizon', add separate FH6 game plugin

This commit is contained in:
2026-07-25 16:40:03 +08:00
parent 7226d58a7a
commit cd08e793e1
9 changed files with 32 additions and 55 deletions
+10
View File
@@ -0,0 +1,10 @@
{
"id": "forza_horizon",
"name": "Forza Horizon 4/5",
"parser_type": "forza",
"telemetry_format": "fh5",
"description": "极限竞速:地平线4 & 5 UDP遥测数据 (FH6兼容格式)",
"author": "Yei.J. (AskaEth)",
"version": "1.0.0",
"default_port": 20777
}
+51
View File
@@ -0,0 +1,51 @@
import struct
import time
from server.telemetry.data import TelemetryData
def get_parser():
return ForzaHorizonParser()
class ForzaHorizonParser:
def game_id(self) -> str:
return "forza_horizon"
def parse(self, data: bytes, addr: tuple) -> TelemetryData:
td = TelemetryData(game_id="forza_horizon", timestamp=time.time())
td.raw = {"raw_hex": data.hex(), "length": len(data), "addr": f"{addr[0]}:{addr[1]}"}
if len(data) < 312:
return td
try:
td.raw["is_race_on"] = struct.unpack_from("<i", data, 0)[0]
td.max_rpm = struct.unpack_from("<f", data, 8)[0]
td.rpm = struct.unpack_from("<f", data, 16)[0]
td.acceleration_x = struct.unpack_from("<f", data, 20)[0]
td.acceleration_y = struct.unpack_from("<f", data, 24)[0]
td.acceleration_z = struct.unpack_from("<f", data, 28)[0]
td.position_x = struct.unpack_from("<f", data, 244)[0]
td.position_y = struct.unpack_from("<f", data, 248)[0]
td.position_z = struct.unpack_from("<f", data, 252)[0]
td.speed_kmh = struct.unpack_from("<f", data, 256)[0] * 3.6
td.speed_mph = td.speed_kmh * 0.621371
td.horsepower = struct.unpack_from("<f", data, 260)[0] / 745.7
td.torque = struct.unpack_from("<f", data, 264)[0]
td.boost = struct.unpack_from("<f", data, 284)[0]
td.fuel = struct.unpack_from("<f", data, 288)[0]
td.best_lap = struct.unpack_from("<f", data, 296)[0]
td.last_lap = struct.unpack_from("<f", data, 300)[0]
td.lap_time = struct.unpack_from("<f", data, 304)[0]
td.lap_number = struct.unpack_from("<H", data, 312)[0]
td.raw["race_position"] = struct.unpack_from("<B", data, 314)[0]
td.throttle = struct.unpack_from("<B", data, 315)[0] / 255.0
td.brake = struct.unpack_from("<B", data, 316)[0] / 255.0
td.clutch = struct.unpack_from("<B", data, 317)[0] / 255.0
td.handbrake = struct.unpack_from("<B", data, 318)[0] / 255.0
td.gear = struct.unpack_from("<B", data, 319)[0]
td.steering = max(-1.0, min(1.0, struct.unpack_from("<b", data, 320)[0] / 127.0))
except struct.error:
pass
return td