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]()) bm.RegisterExecNode(NewExecNode[AppendIntReturn]()) bm.RegisterExecNode(NewExecNode[AppendStringReturn]()) } 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 }