共享雷达
概述
共享雷达用于将游戏内玩家/载具/空投等数据实时同步到接收端(显示端),实现多端数据共享。库内部负责同步发送,你只需在游戏循环里按 API 更新对局信息、自身地址与物品列表即可。
支持的游戏
| 枚举值 | 值 | 游戏 |
|---|---|---|
TXNET_RADAR_GAME_PUBGMHD | 0 | 和平精英 |
TXNET_RADAR_GAME_CODEV | 1 | 无畏契约 |
工作原理
- 调用
txnet_radar_init初始化并启动后台同步线程 - 游戏循环中调用
txnet_radar_set_game、txnet_radar_set_self、txnet_radar_add_item更新数据 - 自身数据:
txnet_radar_set_self仅上报自身 address;物品列表建议包含自身(与该 address 一致的那条),接收端可按 address 在 items 中匹配得到完整自身数据 - 后台线程按设定帧率将数据发送到接收端
- 超过 500ms 未更新的物品会被自动过滤
自动限速
以下情况自动降低同步频率至 0.5fps(每 2 秒一次):
- 物品列表为空(无有效数据)
map_id == 0(大厅状态)
数据正常后自动恢复用户设定的帧率。
函数
txnet_radar_init
cpp
void txnet_radar_init(bool* enabled_ptr, float* fps_ptr, txnet_radar_game_type game_type);初始化雷达模块并启动后台同步线程。
| 参数 | 类型 | 说明 |
|---|---|---|
enabled_ptr | bool* | 指向雷达开关变量的指针 |
fps_ptr | float* | 指向帧率变量的指针 |
game_type | txnet_radar_game_type | 游戏类型枚举 |
txnet_radar_set_game
cpp
void txnet_radar_set_game(unsigned long long world_address, int state, int map_id);设置当前对局信息。内部会检测 world_address 变化,变化时自动清空所有数据。
| 参数 | 类型 | 说明 |
|---|---|---|
world_address | unsigned long long | 游戏世界对象的内存地址 |
state | int | 游戏状态:0=大厅,1=对局中 |
map_id | int | 地图ID(0=未开局,-1=用户选图,>0=地图ID) |
txnet_radar_set_self
cpp
void txnet_radar_set_self(unsigned long long address);设置自身玩家地址(用于告诉接收端“哪条 address 是自身”)。昵称/队伍/坐标等信息不再由库单独维护,接收端可通过 self.address 在 items 中自行匹配得到完整自身数据。
| 参数 | 类型 | 说明 |
|---|---|---|
address | unsigned long long | 自身玩家对象的内存地址 |
txnet_radar_add_item
cpp
void txnet_radar_add_item(const void* item);添加或更新一个物品(玩家/载具/空投)。根据 address 判断是新增还是更新。
| 参数 | 类型 | 说明 |
|---|---|---|
item | const void* | 物品结构体指针(PUBGMHD 用 txnet_radar_item_pubgmhd*,CODEV 用 txnet_radar_item_codev*) |
必填字段与默认值
- 所有物品必填:
address、pos_x/pos_y/pos_z、name。其余字段在结构体中有默认值,主程序无需再填 0/NULL 或“无数据”常量。 - 无数据约定:库内使用
TXNET_RADAR_NO_VALUE(-999)表示可选数值无数据;接收端应将其视为“不可用/不绘制”。该常量由txnet.h提供,主程序只需包含头文件,不必自行定义;不赋值的可选字段即按默认“无数据”处理。 - 按 type 只填所需字段:例如
type=player时不必填载具相关字段,type=airdrop时只填 type、address、name、pos 即可。 - 字符串字段:
name、type、uid、weapon_name等为const char*时,可传nullptr或空指针,库会做安全拷贝(有界、遇\0停止),不会对野指针解引用。
数据结构
txnet_radar_item_pubgmhd
和平精英物品结构体,玩家、载具、空投通用。type 为 "player" | "vehicle" | "airdrop"。C++ 下各字段均有默认值(可选数值默认为无数据、指针为 nullptr),只需设置必填 + 当前 type 所需字段。坐标单位为游戏单位(1 单位 = 0.01 米)。
必填字段(按优先级)
| 字段 | 说明 |
|---|---|
address | 内存地址(唯一标识) |
name | 名称(玩家名/载具名/空投名) |
pos_x pos_y pos_z | 位置(游戏单位) |
可选字段(按优先级)
| 字段 | 说明 / 默认 |
|---|---|
type | "player" | "vehicle" | "airdrop",默认 "player" |
uid | 玩家 uid;可传 nullptr/空,库内存为空串 |
team | 队伍编号,默认 0 |
health | 血量;默认无数据(-999) |
signal | 信号;默认无数据(-999) |
rotator | 朝向角;默认无数据(-999) |
weapon_name | 武器名;可传 nullptr/空,库内存为空串 |
current_ammo max_ammo | 弹药;默认无数据(-999) |
distance | 距离;默认 0 |
fuel | 载具油量;默认无数据(-999) |
pitch | 俯仰;默认 0 |
state | 状态;默认 0 |
is_bot in_vehicle | 标记;默认 false |
weapon | 武器 id;默认 0 |
txnet_radar_item_codev
无畏契约物品结构体(仅玩家)。必填:address、name、pos_x/pos_y/pos_z;其余有默认值。
必填字段(按优先级)
| 字段 | 说明 |
|---|---|
address | 内存地址(唯一标识) |
name | 玩家名 |
pos_x pos_y pos_z | 位置(游戏单位) |
可选字段(按优先级)
| 字段 | 说明 / 默认 |
|---|---|
type | 默认 "player" |
uid | 可传 nullptr/空,库内存为空串 |
team | 默认 0 |
health | 默认无数据(-999) |
rotator | 默认无数据(-999) |
state | 默认 0 |
distance | 默认 0 |
weapon | 默认 0 |
weapon_name | 可传 nullptr/空,库内存为空串 |
示例
和平精英
cpp
#include "txnet.h"
static bool g_radarEnabled = true;
static float g_radarFps = 10.0f;
void initRadar() {
txnet_radar_init(&g_radarEnabled, &g_radarFps, TXNET_RADAR_GAME_PUBGMHD);
}
void gameLoop(GameData& game) {
txnet_radar_set_game(game.worldAddress, game.isInMatch ? 1 : 0, game.mapId);
txnet_radar_set_self(game.localPlayer.address);
// 建议物品列表包含自身(与 set_self 的 address 一致),接收端可据此在 items 中匹配 self
for (auto& player : game.players) {
txnet_radar_item_pubgmhd item = {};
item.type = "player";
item.address = player.address;
item.uid = player.uid;
item.name = player.name;
item.team = player.team;
item.pos_x = player.x; // 游戏单位(1 单位 = 0.01 米)
item.pos_y = player.y;
item.pos_z = player.z;
item.health = player.health;
item.signal = player.hasSignal ? player.signal : TXNET_RADAR_NO_VALUE;
item.rotator = player.hasRotator ? player.yaw : TXNET_RADAR_NO_VALUE;
item.current_ammo = player.currentAmmo >= 0 ? player.currentAmmo : TXNET_RADAR_NO_VALUE;
item.max_ammo = player.maxAmmo >= 0 ? player.maxAmmo : TXNET_RADAR_NO_VALUE;
item.distance = player.distance;
item.weapon_name = player.weaponName;
txnet_radar_add_item(&item);
}
for (auto& vehicle : game.vehicles) {
txnet_radar_item_pubgmhd item = {};
item.type = "vehicle";
item.address = vehicle.address;
item.name = vehicle.name;
item.pos_x = vehicle.x;
item.pos_y = vehicle.y;
item.pos_z = vehicle.z;
item.health = vehicle.hasDurability ? vehicle.durability : TXNET_RADAR_NO_VALUE;
item.fuel = vehicle.hasFuel ? vehicle.fuel : TXNET_RADAR_NO_VALUE;
item.rotator = vehicle.hasYaw ? vehicle.yaw : TXNET_RADAR_NO_VALUE;
txnet_radar_add_item(&item);
}
for (auto& airdrop : game.airdrops) {
txnet_radar_item_pubgmhd item = {};
item.type = "airdrop";
item.address = airdrop.id;
item.name = airdrop.name;
item.pos_x = airdrop.x;
item.pos_y = airdrop.y;
item.pos_z = airdrop.z;
txnet_radar_add_item(&item);
}
}无畏契约
cpp
#include "txnet.h"
static bool g_radarEnabled = true;
static float g_radarFps = 15.0f;
void initRadar() {
txnet_radar_init(&g_radarEnabled, &g_radarFps, TXNET_RADAR_GAME_CODEV);
}
void gameLoop(GameData& game) {
txnet_radar_set_game(game.worldAddress, game.state, game.mapId);
txnet_radar_set_self(game.localPlayer.address);
for (auto& player : game.players) {
txnet_radar_item_codev item = {};
item.type = "player";
item.address = player.address;
item.uid = player.uid;
item.name = player.name;
item.team = player.team;
item.pos_x = player.x;
item.pos_y = player.y;
item.pos_z = player.z;
item.health = player.health;
item.rotator = player.yaw;
item.state = player.isDead ? 1 : 0;
item.distance = player.distance;
item.weapon = player.weaponId;
item.weapon_name = player.weaponName;
txnet_radar_add_item(&item);
}
}数据字段(接收端渲染)
接收端用于渲染的数据本体包含以下字段(按常用程度):gameCode、mapId、self(仅 address)、items。
- mapId:0=未开局,-1=用户选图,>0=地图 ID
- self.address:接收端用它在
items中匹配自身(昵称/队伍/坐标等从 items 同 address 项获取) - 可选数值无数据:使用 -999(即
TXNET_RADAR_NO_VALUE)表示“不可用/不绘制”