81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
// 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]
|
||
}
|