Files
panel/pkg/sandbox/schema.go
T
2026-07-14 19:19:43 -07:00

95 lines
3.1 KiB
Go

package sandbox
import (
"sort"
"strconv"
)
// SchemaOption is one sandbox option as the UI needs it: identity, type, the
// selectable values (with display labels), and the default value.
type SchemaOption struct {
Name string `json:"name"` // SandboxOptions enum member (stable key + config_values suffix)
Display string `json:"display"` // human label
Category string `json:"category"` // raw category key (General/Entities/...)
Type string `json:"type"` // "float" | "int" | "bool"
Values []string `json:"values"` // selectable values in index order (the code stores the index)
Labels []string `json:"labels"` // optional UI labels parallel to Values (may be empty)
Default string `json:"default"` // default value (one of Values)
}
// SchemaCategory groups options under a UI-friendly title.
type SchemaCategory struct {
Key string `json:"key"` // raw category key
Title string `json:"title"` // UI title
Icon string `json:"icon"` // emoji for the section
Options []SchemaOption `json:"options"` // in registration order
}
// categoryMeta maps the decompile's raw category keys to UI titles + icons,
// in display order.
var categoryMeta = []struct{ Key, Title, Icon string }{
{"General", "Player", "🧍"},
{"Entities", "Entities & Zombies", "🧟"},
{"World", "World & Blood Moon", "🌍"},
{"Resources", "Loot & Resources", "💰"},
{"Crafting", "Crafting", "🔨"},
{"Traders", "Traders", "🪙"},
{"Tasks", "Quests & Tasks", "📋"},
{"Misc", "Miscellaneous", "🎛️"},
}
// Schema returns the full 150-option sandbox schema grouped into the 8 UI
// categories, in display order. The UI renders per-option controls from this and
// sends back a name→value map for Encode.
func Schema() []SchemaCategory {
byCat := map[string][]SchemaOption{}
for i := range options {
o := &options[i]
so := SchemaOption{
Name: o.Name,
Display: o.Display,
Category: o.Category,
Default: o.valueAtIndex(defaultIdx[o.Name]),
}
switch o.Type {
case optFloat:
so.Type = "float"
for _, f := range o.set.Floats {
so.Values = append(so.Values, strconv.FormatFloat(f, 'f', -1, 64))
}
case optInt:
so.Type = "int"
for _, n := range o.set.Ints {
so.Values = append(so.Values, strconv.Itoa(n))
}
case optBool:
so.Type = "bool"
for _, b := range o.set.Bools {
so.Values = append(so.Values, strconv.FormatBool(b))
}
}
so.Labels = append(so.Labels, o.set.Display...)
byCat[o.Category] = append(byCat[o.Category], so)
}
var out []SchemaCategory
for _, cm := range categoryMeta {
out = append(out, SchemaCategory{Key: cm.Key, Title: cm.Title, Icon: cm.Icon, Options: byCat[cm.Key]})
}
// Any category not in categoryMeta (forward-compat) appended at the end.
known := map[string]bool{}
for _, cm := range categoryMeta {
known[cm.Key] = true
}
var extra []string
for k := range byCat {
if !known[k] {
extra = append(extra, k)
}
}
sort.Strings(extra)
for _, k := range extra {
out = append(out, SchemaCategory{Key: k, Title: k, Icon: "⚙️", Options: byCat[k]})
}
return out
}