Files
browser/platform/domain/scum.go
T
npc0-hue 300390dc4d Fill the SCUM user and vehicle tables from the plugin-declared database read path
The SCUM 用户管理 list stayed empty because the typed scum_user and
scum_vehicle tables had no producer: the run ingest endpoint is signed-run
only, and the previously registered plugin templates asked for a Run
database capability the endpoint never advertises.

The plugin now declares bounded, read-only SQLite projections for players
and vehicles (sql/scum-db-v57/*.sql with query schemas), and the platform
dispatches those templates as durable remote.run.db.sqlite.query jobs on
run heartbeat and page open, then projects the returned rows into the typed
SCUM tables through the same shared ingest path used by signed run facts.
2026-09-16 18:01:33 +08:00

319 lines
7.2 KiB
Go

package domain
import "time"
const (
SCUMUserOfflineAfter = 15 * time.Minute
SCUMWelcomeMessageDelay = time.Minute
SCUMDefaultListLimit = 500
SCUMDefaultTrajectoryLimit = 500
SCUMFactBatchLimit = 1000
)
type SCUMPosition struct {
X float64
Y float64
Z float64
}
type SCUMUser struct {
ID string
ServerInstanceID string
SteamID string
DisplayName string
SquadID int64
RegisteredAt time.Time
LastLoginAt time.Time
LastActivityAt time.Time
LastLoginIP string
Online bool
X *float64
Y *float64
Z *float64
BankBalance *int64
GoldBars *int64
RiddenVehicleID string
GameVehicleID string
LastLoginAge time.Duration
WelcomeQueuedAt time.Time
WelcomeLastError string
CreatedAt time.Time
UpdatedAt time.Time
}
type SCUMUserFilter struct {
ServerInstanceID string
SteamID string
Online *bool
ChangedAfter time.Time
// StaleBefore matches users whose latest activity is older than the given
// instant. It backs the offline convergence query for stale online users.
StaleBefore time.Time
Limit int
}
type SCUMUserTrajectory struct {
ID string
ServerInstanceID string
SCUMUserID string
SteamID string
DisplayName string
X float64
Y float64
Z float64
RiddenVehicleID string
GameVehicleID string
ObservedAt time.Time
CreatedAt time.Time
}
type SCUMUserTrajectoryFilter struct {
ServerInstanceID string
SCUMUserID string
SteamID string
After time.Time
Limit int
}
type SCUMVehicle struct {
ID string
ServerInstanceID string
GameVehicleID string
VehicleClass string
DisplayName string
Exists bool
Locked bool
X *float64
Y *float64
Z *float64
LastObservedAt time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
type SCUMVehicleFilter struct {
ServerInstanceID string
GameVehicleID string
Exists *bool
ChangedAfter time.Time
Limit int
}
type SCUMVehicleTrajectory struct {
ID string
ServerInstanceID string
SCUMVehicleID string
GameVehicleID string
VehicleClass string
X float64
Y float64
Z float64
ObservedAt time.Time
CreatedAt time.Time
}
type SCUMVehicleTrajectoryFilter struct {
ServerInstanceID string
SCUMVehicleID string
GameVehicleID string
After time.Time
Limit int
}
type SCUMVehicleLock struct {
ID string
ServerInstanceID string
SCUMVehicleID string
GameVehicleID string
SCUMUserID string
SteamID string
LockedAt time.Time
CreatedAt time.Time
}
type SCUMVehicleLockFilter struct {
ServerInstanceID string
SCUMVehicleID string
GameVehicleID string
SCUMUserID string
SteamID string
After time.Time
Limit int
}
type SCUMSurface struct {
Users []SCUMUser
Vehicles []SCUMVehicle
UserTrajectories []SCUMUserTrajectory
VehicleTrajectories []SCUMVehicleTrajectory
VehicleLocks []SCUMVehicleLock
}
type SCUMFactIngest struct {
RunEndpointID string
SessionToken string
ServerInstanceID string
Users []SCUMUserFact
Vehicles []SCUMVehicleFact
}
type SCUMUserFact struct {
SteamID string
DisplayName string
SquadID *int64
LoginIP string
Online bool
Login bool
ObservedAt time.Time
LoginObservedAt time.Time
Position *SCUMPosition
BankBalance *int64
GoldBars *int64
RiddenGameVehicleID string
}
type SCUMVehicleFact struct {
GameVehicleID string
VehicleClass string
DisplayName string
Exists *bool
Locked *bool
LockedBySteamID string
LockedAt time.Time
ObservedAt time.Time
Position *SCUMPosition
}
type SCUMFactIngestResult struct {
Accepted bool
AcceptedUserCount int
AcceptedVehicleCount int
WelcomeQueuedCount int
ServerTime time.Time
}
func CopySCUMUser(value SCUMUser) SCUMUser {
value.X = copyFloatPtr(value.X)
value.Y = copyFloatPtr(value.Y)
value.Z = copyFloatPtr(value.Z)
value.BankBalance = copyInt64Ptr(value.BankBalance)
value.GoldBars = copyInt64Ptr(value.GoldBars)
return value
}
func CopySCUMUsers(values []SCUMUser) []SCUMUser {
if values == nil {
return nil
}
out := make([]SCUMUser, len(values))
for i, value := range values {
out[i] = CopySCUMUser(value)
}
return out
}
func CopySCUMUserTrajectory(value SCUMUserTrajectory) SCUMUserTrajectory { return value }
func CopySCUMUserTrajectories(values []SCUMUserTrajectory) []SCUMUserTrajectory {
if values == nil {
return nil
}
out := make([]SCUMUserTrajectory, len(values))
copy(out, values)
return out
}
func CopySCUMVehicle(value SCUMVehicle) SCUMVehicle {
value.X = copyFloatPtr(value.X)
value.Y = copyFloatPtr(value.Y)
value.Z = copyFloatPtr(value.Z)
return value
}
func CopySCUMVehicles(values []SCUMVehicle) []SCUMVehicle {
if values == nil {
return nil
}
out := make([]SCUMVehicle, len(values))
for i, value := range values {
out[i] = CopySCUMVehicle(value)
}
return out
}
func CopySCUMVehicleTrajectory(value SCUMVehicleTrajectory) SCUMVehicleTrajectory { return value }
func CopySCUMVehicleTrajectories(values []SCUMVehicleTrajectory) []SCUMVehicleTrajectory {
if values == nil {
return nil
}
out := make([]SCUMVehicleTrajectory, len(values))
copy(out, values)
return out
}
func CopySCUMVehicleLock(value SCUMVehicleLock) SCUMVehicleLock { return value }
func CopySCUMVehicleLocks(values []SCUMVehicleLock) []SCUMVehicleLock {
if values == nil {
return nil
}
out := make([]SCUMVehicleLock, len(values))
copy(out, values)
return out
}
func CopySCUMFactIngest(value SCUMFactIngest) SCUMFactIngest {
value.Users = CopySCUMUserFacts(value.Users)
value.Vehicles = CopySCUMVehicleFacts(value.Vehicles)
return value
}
func CopySCUMUserFacts(values []SCUMUserFact) []SCUMUserFact {
if values == nil {
return nil
}
out := make([]SCUMUserFact, len(values))
for i, value := range values {
out[i] = value
out[i].SquadID = copyInt64Ptr(value.SquadID)
out[i].BankBalance = copyInt64Ptr(value.BankBalance)
out[i].GoldBars = copyInt64Ptr(value.GoldBars)
if value.Position != nil {
position := *value.Position
out[i].Position = &position
}
}
return out
}
func CopySCUMVehicleFacts(values []SCUMVehicleFact) []SCUMVehicleFact {
if values == nil {
return nil
}
out := make([]SCUMVehicleFact, len(values))
for i, value := range values {
out[i] = value
out[i].Exists = copyBoolPtr(value.Exists)
out[i].Locked = copyBoolPtr(value.Locked)
if value.Position != nil {
position := *value.Position
out[i].Position = &position
}
}
return out
}
func copyInt64Ptr(value *int64) *int64 {
if value == nil {
return nil
}
copy := *value
return &copy
}
func copyBoolPtr(value *bool) *bool {
if value == nil {
return nil
}
copy := *value
return &copy
}