mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-03 22:45:13 +08:00
222 lines
5.5 KiB
Go
222 lines
5.5 KiB
Go
package blueprint
|
||
|
||
import (
|
||
"fmt"
|
||
"sync/atomic"
|
||
"github.com/duanhf2012/origin/v2/log"
|
||
)
|
||
|
||
type Blueprint struct {
|
||
execNodes []IExecNode // 注册的定义执行结点
|
||
execNodeList []func() IExecNode
|
||
execPool *ExecPool
|
||
graphPool *GraphPool
|
||
|
||
blueprintModule IBlueprintModule
|
||
mapGraph map[int64]IGraph
|
||
seedID int64
|
||
cancelTimer func(*uint64) bool
|
||
|
||
execDefFilePath string // 执行结点定义文件路径
|
||
graphFilePath string // 蓝图文件路径
|
||
}
|
||
|
||
func (bm *Blueprint) RegisterExecNode(execNodeFunc func() IExecNode) {
|
||
bm.execNodeList = append(bm.execNodeList, execNodeFunc)
|
||
}
|
||
|
||
type IExecNodeType[T any] interface {
|
||
*T
|
||
IExecNode
|
||
}
|
||
|
||
// 生成一个泛型函数,返回func() IExecNode类型
|
||
func NewExecNode[T any, P IExecNodeType[T]]() func() IExecNode {
|
||
return func() IExecNode {
|
||
var t T
|
||
return P(&t)
|
||
}
|
||
}
|
||
|
||
func (bm *Blueprint) regSysNodes() {
|
||
bm.RegisterExecNode(NewExecNode[AddInt]())
|
||
bm.RegisterExecNode(NewExecNode[SubInt]())
|
||
bm.RegisterExecNode(NewExecNode[MulInt]())
|
||
bm.RegisterExecNode(NewExecNode[DivInt]())
|
||
bm.RegisterExecNode(NewExecNode[ModInt]())
|
||
bm.RegisterExecNode(NewExecNode[RandNumber]())
|
||
|
||
bm.RegisterExecNode(NewExecNode[Entrance_ArrayParam]())
|
||
bm.RegisterExecNode(NewExecNode[Entrance_IntParam]())
|
||
bm.RegisterExecNode(NewExecNode[Entrance_Timer]())
|
||
bm.RegisterExecNode(NewExecNode[DebugOutput]())
|
||
bm.RegisterExecNode(NewExecNode[Sequence]())
|
||
bm.RegisterExecNode(NewExecNode[Foreach]())
|
||
bm.RegisterExecNode(NewExecNode[ForeachIntArray]())
|
||
|
||
bm.RegisterExecNode(NewExecNode[GetArrayInt]())
|
||
bm.RegisterExecNode(NewExecNode[GetArrayString]())
|
||
bm.RegisterExecNode(NewExecNode[GetArrayLen]())
|
||
bm.RegisterExecNode(NewExecNode[CreateIntArray]())
|
||
bm.RegisterExecNode(NewExecNode[CreateStringArray]())
|
||
bm.RegisterExecNode(NewExecNode[AppendIntegerToArray]())
|
||
bm.RegisterExecNode(NewExecNode[AppendStringToArray]())
|
||
bm.RegisterExecNode(NewExecNode[BoolIf]())
|
||
bm.RegisterExecNode(NewExecNode[GreaterThanInteger]())
|
||
bm.RegisterExecNode(NewExecNode[LessThanInteger]())
|
||
bm.RegisterExecNode(NewExecNode[EqualInteger]())
|
||
bm.RegisterExecNode(NewExecNode[RangeCompare]())
|
||
bm.RegisterExecNode(NewExecNode[EqualSwitch]())
|
||
bm.RegisterExecNode(NewExecNode[Probability]())
|
||
bm.RegisterExecNode(NewExecNode[CreateTimer]())
|
||
}
|
||
|
||
|
||
func (bm *Blueprint) StartHotReload() (func(),error) {
|
||
var execPool ExecPool
|
||
var graphPool GraphPool
|
||
|
||
// 加载配置结点生成名字对应的innerExecNode
|
||
err := execPool.Load(bm.execDefFilePath)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 将注册的实际执行结点与innerExecNode进行关联
|
||
for _, newExec := range bm.execNodeList {
|
||
e := newExec()
|
||
if !execPool.Register(e) {
|
||
return nil,fmt.Errorf("register exec failed,exec:%s", e.GetName())
|
||
}
|
||
}
|
||
|
||
// 加载所有的vgf蓝图文件
|
||
err = graphPool.Load(&execPool, bm.graphFilePath, bm.blueprintModule)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 返回配置加载后的刷新内存处理
|
||
return func() {
|
||
// 替换旧的执行池和图池
|
||
bm.execPool = &execPool
|
||
bm.graphPool = &graphPool
|
||
|
||
for _, gh := range bm.mapGraph {
|
||
gFileName := gh.GetGraphFileName()
|
||
bGraph := bm.graphPool.GetBaseGraph(gFileName)
|
||
if bGraph == nil {
|
||
log.Warn("GetBaseGraph fail", log.String("graph file name", gFileName))
|
||
bGraph = &baseGraph{entrance: map[int64]*execNode{}}
|
||
}
|
||
|
||
gh.HotReload(bGraph)
|
||
}
|
||
}, nil
|
||
|
||
}
|
||
|
||
func (bm *Blueprint) Init(execDefFilePath string, graphFilePath string, blueprintModule IBlueprintModule, cancelTimer func(*uint64) bool) error {
|
||
var execPool ExecPool
|
||
var graphPool GraphPool
|
||
|
||
// 加载配置结点生成名字对应的innerExecNode
|
||
err := execPool.Load(execDefFilePath)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 注册系统执行结点
|
||
bm.regSysNodes()
|
||
|
||
// 将注册的实际执行结点与innerExecNode进行关联
|
||
for _, newExec := range bm.execNodeList {
|
||
e := newExec()
|
||
if !execPool.Register(e) {
|
||
return fmt.Errorf("register exec failed,exec:%s", e.GetName())
|
||
}
|
||
}
|
||
|
||
// 加载所有的vgf蓝图文件
|
||
err = graphPool.Load(&execPool, graphFilePath, blueprintModule)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
bm.execPool = &execPool
|
||
bm.graphPool = &graphPool
|
||
bm.cancelTimer = cancelTimer
|
||
bm.blueprintModule = blueprintModule
|
||
bm.mapGraph = make(map[int64]IGraph, 128)
|
||
bm.execDefFilePath = execDefFilePath
|
||
bm.graphFilePath = graphFilePath
|
||
|
||
return nil
|
||
}
|
||
|
||
func (bm *Blueprint) Create(graphName string) int64 {
|
||
if graphName == "" {
|
||
return 0
|
||
}
|
||
|
||
graphID := atomic.AddInt64(&bm.seedID, 1)
|
||
gr := bm.graphPool.Create(graphName, graphID)
|
||
if gr == nil {
|
||
return 0
|
||
}
|
||
|
||
bm.mapGraph[graphID] = gr
|
||
return graphID
|
||
}
|
||
|
||
func (bm *Blueprint) TriggerEvent(graphID int64, eventID int64, args ...any) error {
|
||
graph := bm.mapGraph[graphID]
|
||
if graph == nil {
|
||
return fmt.Errorf("can not find graph:%d", graphID)
|
||
}
|
||
|
||
_, err := graph.Do(eventID, args...)
|
||
return err
|
||
}
|
||
|
||
func (bm *Blueprint) Do(graphID int64, entranceID int64, args ...any) (Port_Array, error) {
|
||
graph := bm.mapGraph[graphID]
|
||
if graph == nil {
|
||
return nil, fmt.Errorf("can not find graph:%d", graphID)
|
||
}
|
||
|
||
return graph.Do(entranceID, args...)
|
||
}
|
||
|
||
func (bm *Blueprint) ReleaseGraph(graphID int64) {
|
||
if graphID == 0 {
|
||
return
|
||
}
|
||
|
||
defer delete(bm.mapGraph, graphID)
|
||
graph := bm.mapGraph[graphID]
|
||
if graph == nil {
|
||
return
|
||
}
|
||
|
||
graph.Release()
|
||
}
|
||
|
||
func (bm *Blueprint) CancelTimerId(graphID int64, timerId *uint64) bool {
|
||
tId := *timerId
|
||
bm.cancelTimer(timerId)
|
||
|
||
graph := bm.mapGraph[graphID]
|
||
if graph == nil {
|
||
return false
|
||
}
|
||
|
||
gr, ok := graph.(*Graph)
|
||
if !ok {
|
||
return false
|
||
}
|
||
|
||
delete(gr.mapTimerID, tId)
|
||
return true
|
||
}
|