Panel — public source drop (v0.9.0)
Self-hostable game-server control panel: controller + agent + 26 game modules. One-line install (prebuilt release, no Go required): curl -fsSL https://git.pdxtechs.com/dbledeez/panel/raw/branch/main/install.sh | sudo bash Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
package empyrionitems
|
||||
|
||||
// Loot group parser for Empyrion's `LootGroups.ecf`.
|
||||
// Format:
|
||||
//
|
||||
// { +LootGroup Name: EscapePodEasy
|
||||
// Count: all
|
||||
// Item_0: EmergencyRations, param1: 1
|
||||
// Item_1: WaterBottle, param1: 5
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// param1 = count (or "low-high" range), param2 = optional probability.
|
||||
// Item names are canonical Item.Name tokens.
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LootEntry struct {
|
||||
Item string `json:"item"`
|
||||
Count string `json:"count,omitempty"`
|
||||
Probability string `json:"probability,omitempty"`
|
||||
}
|
||||
|
||||
type LootGroup struct {
|
||||
Name string `json:"name"`
|
||||
Count string `json:"count,omitempty"`
|
||||
Items []LootEntry `json:"items"`
|
||||
}
|
||||
|
||||
type LootIndex struct {
|
||||
Groups []LootGroup
|
||||
byName map[string]*LootGroup
|
||||
byItem map[string][]string // ingredientLower → group names
|
||||
}
|
||||
|
||||
func LoadLootFromFile(path string) (*LootIndex, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
return LoadLootFromReader(f)
|
||||
}
|
||||
|
||||
func LoadLootFromReader(r io.Reader) (*LootIndex, error) {
|
||||
idx := &LootIndex{byName: map[string]*LootGroup{}, byItem: map[string][]string{}}
|
||||
sc := bufio.NewScanner(r)
|
||||
sc.Buffer(make([]byte, 1024*1024), 1024*1024)
|
||||
|
||||
var current *LootGroup
|
||||
var depth int
|
||||
|
||||
for sc.Scan() {
|
||||
line := stripComment(sc.Text())
|
||||
trim := strings.TrimSpace(line)
|
||||
if trim == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if current == nil {
|
||||
if strings.HasPrefix(trim, "{ +LootGroup ") || strings.HasPrefix(trim, "{+LootGroup ") || strings.HasPrefix(trim, "{ LootGroup ") {
|
||||
body := strings.TrimPrefix(trim, "{ +LootGroup ")
|
||||
body = strings.TrimPrefix(body, "{+LootGroup ")
|
||||
body = strings.TrimPrefix(body, "{ LootGroup ")
|
||||
current = &LootGroup{}
|
||||
for _, kv := range splitTopLevel(body, ',') {
|
||||
parts := strings.SplitN(strings.TrimSpace(kv), ":", 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
k := strings.TrimSpace(parts[0])
|
||||
v := stripQuotes(strings.TrimSpace(parts[1]))
|
||||
if strings.EqualFold(k, "name") {
|
||||
current.Name = v
|
||||
}
|
||||
}
|
||||
depth = 1
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
opens := strings.Count(trim, "{")
|
||||
closes := strings.Count(trim, "}")
|
||||
depth += opens - closes
|
||||
if depth <= 0 {
|
||||
if current.Name != "" {
|
||||
cp := *current
|
||||
idx.Groups = append(idx.Groups, cp)
|
||||
gp := &idx.Groups[len(idx.Groups)-1]
|
||||
idx.byName[strings.ToLower(cp.Name)] = gp
|
||||
for _, it := range cp.Items {
|
||||
low := strings.ToLower(it.Item)
|
||||
idx.byItem[low] = append(idx.byItem[low], cp.Name)
|
||||
}
|
||||
}
|
||||
current = nil
|
||||
depth = 0
|
||||
continue
|
||||
}
|
||||
|
||||
parts := strings.SplitN(trim, ":", 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(parts[0])
|
||||
val := stripComment(strings.TrimSpace(parts[1]))
|
||||
|
||||
if strings.HasPrefix(strings.ToLower(key), "item_") {
|
||||
// Item_N: Name, param1: count, param2: probability
|
||||
le := LootEntry{}
|
||||
pieces := splitTopLevel(val, ',')
|
||||
for i, p := range pieces {
|
||||
p = strings.TrimSpace(p)
|
||||
if i == 0 {
|
||||
le.Item = stripQuotes(p)
|
||||
continue
|
||||
}
|
||||
kv := strings.SplitN(p, ":", 2)
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
kk := strings.ToLower(strings.TrimSpace(kv[0]))
|
||||
vv := strings.TrimSpace(kv[1])
|
||||
switch kk {
|
||||
case "param1", "param":
|
||||
le.Count = vv
|
||||
case "param2", "xdata":
|
||||
le.Probability = vv
|
||||
}
|
||||
}
|
||||
if le.Item != "" {
|
||||
current.Items = append(current.Items, le)
|
||||
}
|
||||
} else if strings.EqualFold(key, "Count") {
|
||||
current.Count = strings.TrimSpace(val)
|
||||
}
|
||||
}
|
||||
if err := sc.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
func (idx *LootIndex) ByName(name string) *LootGroup {
|
||||
if g, ok := idx.byName[strings.ToLower(name)]; ok {
|
||||
c := *g
|
||||
return &c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (idx *LootIndex) DroppedBy(itemName string) []string {
|
||||
return append([]string{}, idx.byItem[strings.ToLower(itemName)]...)
|
||||
}
|
||||
Reference in New Issue
Block a user