Rebuild SCUM plugin data ownership

This commit is contained in:
npc0-hue
2026-08-14 10:03:58 +08:00
parent c8b49c711c
commit a6c4cdac5d
79 changed files with 532 additions and 1842 deletions
-16
View File
@@ -69,18 +69,8 @@ type GameClientBridgeQueryTemplateDeclaration struct {
TargetKey string
ParameterSchemaRef string
ResultSchemaRef string
SQLRef string
MaxRows int
TimeoutSeconds int
RowTarget *SCUMRowTargetDeclaration
}
// SCUMRowTargetDeclaration is plugin-owned data-shaping metadata. The platform
// only applies this declaration; it does not infer a destination from a query key.
type SCUMRowTargetDeclaration struct {
TargetTable string
UpsertKeys []string
ColumnMappings map[string]string
}
type GameClientBridgeOperationKind string
@@ -463,12 +453,6 @@ func CopyGameClientBridgeManifest(value GameClientBridgeManifest) GameClientBrid
}
value.Snapshots = append([]GameClientBridgeSnapshotDeclaration(nil), value.Snapshots...)
value.QueryTemplates = append([]GameClientBridgeQueryTemplateDeclaration(nil), value.QueryTemplates...)
for index := range value.QueryTemplates {
if value.QueryTemplates[index].RowTarget != nil {
copy := CopySCUMRowTargetDeclaration(*value.QueryTemplates[index].RowTarget)
value.QueryTemplates[index].RowTarget = &copy
}
}
value.OperationTemplates = append([]GameClientBridgeOperationTemplateDeclaration(nil), value.OperationTemplates...)
value.Pages = append([]GameClientBridgePageContract(nil), value.Pages...)
value.Features = append([]GameClientBridgeFeatureDeclaration(nil), value.Features...)
+22 -31
View File
@@ -1,10 +1,6 @@
package domain
import (
"encoding/json"
"strings"
"time"
)
import "time"
const SCUMRewardDeliverCommandType = "reward.deliver"
const SCUMGiftNotificationCommandType = "player.notify"
@@ -19,32 +15,7 @@ type SCUMGiftItemCatalog struct {
Items []SCUMGiftItemDefinition
}
func ParseSCUMGiftItemCatalog(content string) (SCUMGiftItemCatalog, bool) {
var catalog struct {
GameVersion string `json:"gameVersion"`
Items []struct {
Key string `json:"key"`
Label string `json:"label"`
MaximumQuantity int `json:"maximumQuantity"`
} `json:"items"`
}
if json.Unmarshal([]byte(content), &catalog) != nil || strings.TrimSpace(catalog.GameVersion) == "" || len(catalog.Items) == 0 {
return SCUMGiftItemCatalog{}, false
}
result := SCUMGiftItemCatalog{GameVersion: catalog.GameVersion, Items: make([]SCUMGiftItemDefinition, 0, len(catalog.Items))}
seen := map[string]struct{}{}
for _, item := range catalog.Items {
if strings.TrimSpace(item.Key) == "" || strings.TrimSpace(item.Label) == "" || item.MaximumQuantity < 1 {
return SCUMGiftItemCatalog{}, false
}
if _, ok := seen[item.Key]; ok {
return SCUMGiftItemCatalog{}, false
}
seen[item.Key] = struct{}{}
result.Items = append(result.Items, SCUMGiftItemDefinition{Key: item.Key, Label: item.Label, MaximumQuantity: item.MaximumQuantity})
}
return result, true
}
var SCUMGiftItemCatalogs = []SCUMGiftItemCatalog{{GameVersion: "0.9.700.90357", Items: []SCUMGiftItemDefinition{{Key: "bandage", Label: "绷带", MaximumQuantity: 20}, {Key: "water-bottle", Label: "饮用水", MaximumQuantity: 10}, {Key: "improvised-spear", Label: "简易长矛", MaximumQuantity: 2}}}}
type GameGiftItem struct {
CatalogItemKey string
@@ -151,3 +122,23 @@ func CopyGameGiftGrant(value GameGiftGrant) GameGiftGrant {
value.Items = CopyGameGiftItems(value.Items)
return value
}
func SCUMGiftCatalogForVersion(version string) (SCUMGiftItemCatalog, bool) {
for _, catalog := range SCUMGiftItemCatalogs {
if catalog.GameVersion == version {
return catalog, true
}
}
return SCUMGiftItemCatalog{}, false
}
func SCUMGiftItemForVersion(version, key string) (SCUMGiftItemDefinition, bool) {
catalog, ok := SCUMGiftCatalogForVersion(version)
if !ok {
return SCUMGiftItemDefinition{}, false
}
for _, item := range catalog.Items {
if item.Key == key {
return item, true
}
}
return SCUMGiftItemDefinition{}, false
}
+29
View File
@@ -0,0 +1,29 @@
package domain
import "time"
// PluginDataRecord is an opaque plugin-owned platform record. Platform scopes
// it but does not interpret the collection name or payload fields.
type PluginDataRecord struct {
ID string
PluginID string
ServerInstanceID string
Collection string
Key string
Value map[string]any
CreatedAt time.Time
UpdatedAt time.Time
}
type PluginDataFilter struct {
PluginID string
ServerInstanceID string
Collection string
Key string
Limit int
}
func CopyPluginDataRecord(value PluginDataRecord) PluginDataRecord {
value.Value = CopyGameClientBridgePayload(value.Value)
return value
}
-1
View File
@@ -25,7 +25,6 @@ type SCUMProjectionFilter struct {
FlagID string
SubjectType SCUMProjectionSubject
QueryKey string
TargetTable SCUMDataSet
Freshness SCUMProjectionFreshness
Search string
Limit int
-42
View File
@@ -85,35 +85,6 @@ type SCUMObservationResult struct {
Rows []map[string]any
}
type SCUMDataSet string
const (
SCUMDataSetUsers SCUMDataSet = "scum_users"
SCUMDataSetSquads SCUMDataSet = "scum_squads"
SCUMDataSetMembers SCUMDataSet = "scum_squad_members"
SCUMDataSetVehicles SCUMDataSet = "scum_vehicles"
SCUMDataSetFlags SCUMDataSet = "scum_flags"
SCUMDataSetActivity SCUMDataSet = "scum_activity_events"
// Gift events are facts observed in SCUM's finished_timed_gift_spawner table.
// Platform-owned gift catalogs, revisions, and grants use their own repositories.
SCUMDataSetGiftEvents SCUMDataSet = "scum_gift_events"
SCUMDataSetMapPoints SCUMDataSet = "scum_map_points"
)
type SCUMDataRow struct {
ID string
ServerInstanceID string
TargetTable SCUMDataSet
UpsertKey string
Fields map[string]any
Payload map[string]any
PluginID string
QueryKey string
Freshness SCUMProjectionFreshnessState
CreatedAt time.Time
UpdatedAt time.Time
}
type SCUMProjectionFreshnessState struct {
Status SCUMProjectionFreshness
ObservationID string
@@ -261,19 +232,6 @@ func CopySCUMObservationResult(value SCUMObservationResult) SCUMObservationResul
return value
}
func CopySCUMRowTargetDeclaration(value SCUMRowTargetDeclaration) SCUMRowTargetDeclaration {
value.UpsertKeys = CopyStringSlice(value.UpsertKeys)
value.ColumnMappings = CopyStringMap(value.ColumnMappings)
return value
}
func CopySCUMDataRow(value SCUMDataRow) SCUMDataRow {
value.Fields = CopyGameClientBridgePayload(value.Fields)
value.Payload = CopyGameClientBridgePayload(value.Payload)
value.Freshness = CopySCUMProjectionFreshnessState(value.Freshness)
return value
}
func CopyGameClientBridgeRows(values []map[string]any) []map[string]any {
if values == nil {
return nil