panel v0.9.2 — open-source game server manager

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 01:06:16 -07:00
commit 0f6aea796c
2164 changed files with 301480 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
package module
import (
"fmt"
"sort"
"sync"
)
// Registry is a concurrency-safe in-memory index of loaded manifests.
// It's held as a shared component by both Controller and Target.
type Registry struct {
mu sync.RWMutex
modules map[string]*Manifest
}
// NewRegistry returns an empty registry.
func NewRegistry() *Registry {
return &Registry{modules: make(map[string]*Manifest)}
}
// LoadDir scans dir for modules and inserts them. Duplicate IDs are rejected.
func (r *Registry) LoadDir(dir string) error {
ms, err := LoadDir(dir)
if err != nil {
return err
}
r.mu.Lock()
defer r.mu.Unlock()
for _, m := range ms {
if _, exists := r.modules[m.ID]; exists {
return fmt.Errorf("duplicate module id %q in %s", m.ID, dir)
}
r.modules[m.ID] = m
}
return nil
}
// Put inserts or replaces a manifest.
func (r *Registry) Put(m *Manifest) {
r.mu.Lock()
defer r.mu.Unlock()
r.modules[m.ID] = m
}
// Get returns the manifest for id, or (nil, false) if unknown.
func (r *Registry) Get(id string) (*Manifest, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
m, ok := r.modules[id]
return m, ok
}
// List returns all manifests sorted by id.
func (r *Registry) List() []*Manifest {
r.mu.RLock()
defer r.mu.RUnlock()
out := make([]*Manifest, 0, len(r.modules))
for _, m := range r.modules {
out = append(out, m)
}
sort.Slice(out, func(i, j int) bool { return out[i].ID < out[j].ID })
return out
}
// Len returns the number of modules currently registered.
func (r *Registry) Len() int {
r.mu.RLock()
defer r.mu.RUnlock()
return len(r.modules)
}