feat: surface SCUM vehicle functional state
This commit is contained in:
@@ -708,7 +708,7 @@ function mapHoverCard(e: ReactLike["createElement"], point: RecordMap, data: SCU
|
||||
} else if (layer === "vehicles") {
|
||||
push("载具", vehicleLabelFor(point));
|
||||
push("类名", textField(point, "className", "vehicleClass", "entityClass", "vehicleType"));
|
||||
push("状态", textField(point, "status", "state") || (boolField(point, "exists", "existsInGame") ? "存在" : ""));
|
||||
push("状态", textField(point, "status", "state") || vehicleFunctionalLabel(point) || (boolField(point, "exists", "existsInGame") ? "存在" : ""));
|
||||
push("耐久", vehicleDurabilityLabel(point));
|
||||
push("车锁", vehicleLockLabel(point, data));
|
||||
pushDate("最后观测", "vehicleObservedAt", "lastObservedAt", "observedAt", "updatedAt");
|
||||
@@ -760,6 +760,11 @@ function vehicleDurabilityLabel(point: RecordMap): string {
|
||||
return value ? `${value}${textField(point, "durabilityMax", "maxHealth") ? ` / ${textField(point, "durabilityMax", "maxHealth")}` : ""}` : "";
|
||||
}
|
||||
|
||||
function vehicleFunctionalLabel(point: RecordMap): string {
|
||||
if (field(point, "functional", "isFunctional") === undefined) return "";
|
||||
return boolField(point, "functional", "isFunctional") ? "可用" : "不可用";
|
||||
}
|
||||
|
||||
function mapUserMenu(e: ReactLike["createElement"], view: ViewState, users: Array<{ key: string; label: string; count: number }>, labels: Map<string, string>) {
|
||||
const selected = view.mapUsers;
|
||||
const rows = [...users, ...(selected ?? []).filter((key) => !users.some((user) => user.key === key)).map((key) => ({ key, label: labels.get(key) || key, count: 0 }))];
|
||||
@@ -1179,7 +1184,7 @@ function mapPointStrip(e: ReactLike["createElement"], point: RecordMap, trails:
|
||||
e("span", { className: "provider-id" }, `ID ${textField(point, "subjectId", "id", "_recordKey") || "unknown"}`),
|
||||
e("span", { className: "provider-id" }, `来源 ${textField(point, "source") || "平台表"}`),
|
||||
e("span", { className: "provider-id" }, freshness(point)),
|
||||
layerOf(point) === "vehicles" ? e("span", { className: "provider-id" }, `${textField(point, "className", "vehicleClass", "vehicleType") || "unknown"} · ${textField(point, "status", "state", "isFunctional") || "unknown"} · ${boolField(point, "locked") ? "已上锁" : "未上锁/未知"} · 访问 ${dateField(point, "lastAccessTime", "vehicleObservedAt", "sampledAt")}`) : null),
|
||||
layerOf(point) === "vehicles" ? e("span", { className: "provider-id" }, `${textField(point, "className", "vehicleClass", "vehicleType") || "unknown"} · ${textField(point, "status", "state") || vehicleFunctionalLabel(point) || "unknown"} · ${boolField(point, "locked") ? "已上锁" : "未上锁/未知"} · 访问 ${dateField(point, "lastAccessTime", "vehicleObservedAt", "sampledAt")}`) : null),
|
||||
locks.length ? e("div", { className: "console-row-list" }, locks.map((row, index) => e("div", { key: `selected-lock-${index}`, className: "console-row" }, e("span", null, dateField(row, "lockedAt", "createdAt")), e("strong", null, textField(row, "scumUserId") || "unknown"), e("strong", null, textField(row, "steamId") || "unknown")))) : null,
|
||||
trails.length ? e("div", { className: "console-row-list" }, trails.map((row, index) => e("div", { key: `selected-trail-${index}`, className: "console-row" }, e("span", null, dateField(row, "sampledAt", "observedAt")), e("strong", null, coords(row)), e("strong", null, textField(row, "source") || "平台轨迹表")))) : null
|
||||
);
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
},
|
||||
{
|
||||
"key": "scum.database.vehicles",
|
||||
"title": "Read SCUM vehicle positions and classes",
|
||||
"title": "Read SCUM vehicle positions, classes, and functional state",
|
||||
"permission": "server.game-client.read",
|
||||
"engine": "sqlite",
|
||||
"transportKey": "scum-database",
|
||||
@@ -392,6 +392,7 @@
|
||||
"gameVehicleId": "gameVehicleId",
|
||||
"vehicleClass": "vehicleClass",
|
||||
"displayName": "displayName",
|
||||
"functional": "functional",
|
||||
"exists": "existsInGame",
|
||||
"x": "x",
|
||||
"y": "y",
|
||||
|
||||
@@ -2,6 +2,7 @@ SELECT
|
||||
CAST(spawner.vehicle_entity_id AS TEXT) AS gameVehicleId,
|
||||
entity.class AS vehicleClass,
|
||||
spawner.vehicle_alias AS displayName,
|
||||
spawner.is_vehicle_functional AS functional,
|
||||
1 AS existsInGame,
|
||||
entity.location_x AS x,
|
||||
entity.location_y AS y,
|
||||
|
||||
@@ -39,7 +39,7 @@ const surfaceData: SCUMSurfaceData = {
|
||||
mapPoints: [{ id: "poi-1", name: "Airfield", layer: "other", x: 800, y: 900, z: 10, source: "plugin-map" }],
|
||||
mapRegions: [{ id: "region-1", name: "Safe Zone", x: 500, y: 600, z: 0, source: "server-config" }],
|
||||
mapSettings: [],
|
||||
vehicles: [{ id: "scum-vehicle-1", vehicleId: "scum-vehicle-1", gameVehicleId: "veh-1", label: "Laika", className: "BPC_Laika_C", locked: true, position: { x: 400, y: 200, z: 0 }, freshness: { status: "fresh" } }],
|
||||
vehicles: [{ id: "scum-vehicle-1", vehicleId: "scum-vehicle-1", gameVehicleId: "veh-1", label: "Laika", className: "BPC_Laika_C", functional: true, locked: true, position: { x: 400, y: 200, z: 0 }, freshness: { status: "fresh" } }],
|
||||
vehicleLocks: [{ id: "lock-1", scumVehicleId: "scum-vehicle-1", gameVehicleId: "veh-1", scumUserId: "scum-user-1", steamId: "76561198000000001", lockedAt: "2026-08-10T00:00:04Z", source: "platform.scum_vehicle_lock" }],
|
||||
trajectories: [
|
||||
{ subjectType: "player", subjectId: "76561198000000001", steamId: "76561198000000001", displayName: "Mira", x: 10, y: 20, z: 3, sampledAt: "2026-08-10T00:00:03Z", source: "platform.scum_user_trajectory" },
|
||||
@@ -297,7 +297,9 @@ describe("SCUM plugin feature module", () => {
|
||||
expect(view.elements.find((element) => element.label === "SCUM 地图图层")?.style?.backgroundImage).toContain("scum-map-terrain-4096.webp");
|
||||
expect(view.buttons.map((button) => button.label)).toEqual(expect.arrayContaining(["+", "-", "复位", "适应轨迹"]));
|
||||
const vehicleView = renderAndCollect({ pageKey: "live-map", pageTitle: "实时地图", data: { ...surfaceData, players: [], mapPoints: [], flags: [], mapRegions: [] } });
|
||||
expect(vehicleView.texts).toEqual(expect.arrayContaining(["BPC_Laika_C · unknown · 已上锁 · 访问 unknown", "scum-user-1", "76561198000000001"]));
|
||||
expect(vehicleView.texts).toEqual(expect.arrayContaining(["BPC_Laika_C · 可用 · 已上锁 · 访问 unknown", "scum-user-1", "76561198000000001"]));
|
||||
const unavailableVehicleView = renderAndCollect({ pageKey: "live-map", pageTitle: "实时地图", data: { ...surfaceData, vehicles: [{ ...surfaceData.vehicles[0], functional: false }], players: [], mapPoints: [], flags: [], mapRegions: [] } });
|
||||
expect(unavailableVehicleView.texts).toContain("BPC_Laika_C · 不可用 · 已上锁 · 访问 unknown");
|
||||
});
|
||||
|
||||
it("keeps the live map full width with one compact filter row and dropdown menus", () => {
|
||||
|
||||
Reference in New Issue
Block a user