// Package mods Mod 运行时:generation 版本化注册表、Lua 沙箱、注册 API 与热重载(热更新.md §4、Mod开发指南.md)。 package mods import ( "fmt" "sync" ) // Entry 一个注册条目。 type Entry struct { Key string // 注册键(如 "block:ruby_ore") Kind string // block / item / recipe / event / command Gen uint64 // 注册代数(热更新.md §4.1) Source string // 来源 Mod ID Data any // 条目数据(结构由注册方定义) } // Registry 注册表(generation 版本化)。 type Registry struct { mu sync.RWMutex entries map[string]Entry gen map[string]uint64 // 来源 → 当前代数 } // NewRegistry 创建注册表。 func NewRegistry() *Registry { return &Registry{entries: make(map[string]Entry), gen: make(map[string]uint64)} } // Reload 重载一个来源的注册(热更新.md §4.1–§4.2 两阶段 + 提交): // 先以新代数执行 register;成功才回收旧代条目;失败保留旧版并返回错误。 func (r *Registry) Reload(source string, register func(gen uint64) error) error { r.mu.Lock() next := r.gen[source] + 1 r.mu.Unlock() if err := register(next); err != nil { return fmt.Errorf("mods.Registry.Reload %s: %w(保留旧版本)", source, err) } // 提交:回收旧代 r.mu.Lock() defer r.mu.Unlock() for k, e := range r.entries { if e.Source == source && e.Gen != next { delete(r.entries, k) } } r.gen[source] = next return nil } // Register 写入条目(register 回调内调用)。 func (r *Registry) Register(source string, gen uint64, kind, key string, data any) error { r.mu.Lock() defer r.mu.Unlock() k := kind + ":" + key if old, dup := r.entries[k]; dup && old.Source != source { return fmt.Errorf("mods.Register: 注册键 %q 与 %q 冲突", k, old.Source) } r.entries[k] = Entry{Key: k, Kind: kind, Gen: gen, Source: source, Data: data} return nil } // Entries 导出全部条目(只读副本)。 func (r *Registry) Entries() []Entry { r.mu.RLock() defer r.mu.RUnlock() out := make([]Entry, 0, len(r.entries)) for _, e := range r.entries { out = append(out, e) } return out } // Gen 返回来源的当前代数。 func (r *Registry) Gen(source string) uint64 { r.mu.RLock() defer r.mu.RUnlock() return r.gen[source] }