Files
origin/util/blueprint/graph.go
boyce 593abd263e 优化websocket
优化蓝图
2025-12-08 15:30:44 +08:00

232 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package blueprint
import (
"fmt"
"time"
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/service"
"github.com/goccy/go-json"
)
const ReturnVarial = "g_Return"
var IsDebug = false
type IGraph interface {
Do(entranceID int64, args ...any) (Port_Array, error)
Release()
GetGraphFileName() string
HotReload(newBaseGraph *baseGraph)
}
type IBlueprintModule interface {
SafeAfterFunc(timerId *uint64, d time.Duration, AdditionData interface{}, cb func(uint64, interface{}))
TriggerEvent(graphID int64, eventID int64, args ...any) error
CancelTimerId(graphID int64, timerId *uint64) bool
GetGameService() service.IService
GetBattleService() service.IService
}
type baseGraph struct {
entrance map[int64]*execNode // 入口
}
type Graph struct {
graphFileName string
graphID int64
*baseGraph
graphContext
IBlueprintModule
mapTimerID map[uint64]struct{}
}
type graphContext struct {
context map[string]*ExecContext // 上下文
variables map[string]IPort // 变量
globalVariables map[string]IPort // 全局变量,g_Return,为执行返回值
}
type nodeConfig struct {
Id string `json:"id"`
Class string `json:"class"`
Module string `json:"module"`
//Pos []float64 `json:"pos"`
PortDefault map[string]interface{} `json:"port_defaultv"`
}
type edgeConfig struct {
EdgeID string `json:"edge_id"`
SourceNodeID string `json:"source_node_id"`
DesNodeId string `json:"des_node_id"`
SourcePortId int `json:"source_port_id"`
DesPortId int `json:"des_port_id"`
}
type MultiTypeValue struct {
Value any
}
// 实现json.Unmarshaler接口自定义解码逻辑
func (v *MultiTypeValue) UnmarshalJSON(data []byte) error {
// 尝试将数据解析为字符串
var strVal string
if err := json.Unmarshal(data, &strVal); err == nil {
v.Value = strVal
return nil
}
// 如果不是字符串,尝试解析为数字
var intVal int
if err := json.Unmarshal(data, &intVal); err == nil {
v.Value = intVal
return nil
}
// 如果不是字符串,尝试解析为数字
var boolVal bool
if err := json.Unmarshal(data, &boolVal); err == nil {
v.Value = boolVal
return nil
}
// 如果不是字符串,尝试解析为数字
var float64Val float64
if err := json.Unmarshal(data, &float64Val); err == nil {
v.Value = float64Val
return nil
}
var arrayVal []any
if err := json.Unmarshal(data, &arrayVal); err == nil {
v.Value = arrayVal
return nil
}
// 如果都失败,返回错误
return fmt.Errorf("cannot unmarshal JSON value: %s", string(data))
}
type variablesConfig struct {
Name string `json:"name"`
Type string `json:"type"`
Value MultiTypeValue `json:"value"`
}
type graphConfig struct {
GraphName string `json:"graph_name"`
Time string `json:"time"`
Nodes []nodeConfig `json:"nodes"`
Edges []edgeConfig `json:"edges"`
Variables []variablesConfig `json:"variables"`
}
func (gc *graphConfig) GetVariablesByName(varName string) *variablesConfig {
for _, varCfg := range gc.Variables {
if varCfg.Name == varName {
return &varCfg
}
}
return nil
}
func (gc *graphConfig) GetNodeByID(nodeID string) *nodeConfig {
for _, node := range gc.Nodes {
if node.Id == nodeID {
return &node
}
}
return nil
}
func (gr *Graph) GetAndCreateReturnPort() IPort {
p, ok := gr.globalVariables[ReturnVarial]
if ok && p != nil {
return p
}
p = NewPortArray()
gr.globalVariables[ReturnVarial] = p
return p
}
func (gr *Graph) Do(entranceID int64, args ...any) (Port_Array, error) {
if IsDebug {
log.Debug("Graph Do", log.String("graphName", gr.graphFileName), log.Int64("graphID", gr.graphID), log.Int64("entranceID", entranceID))
}
entranceNode := gr.entrance[entranceID]
if entranceNode == nil {
return nil, fmt.Errorf("entranceID:%d not found", entranceID)
}
gr.variables = map[string]IPort{}
gr.context = map[string]*ExecContext{}
if gr.globalVariables == nil {
gr.globalVariables = map[string]IPort{}
}else {
gr.globalVariables[ReturnVarial] = nil
}
err := entranceNode.Do(gr, args...)
if err != nil {
return nil, err
}
if gr.globalVariables != nil {
port := gr.globalVariables[ReturnVarial]
if port != nil {
array, ok := port.GetArray()
if ok {
return array, nil
}
}
}
return nil, nil
}
func (gr *Graph) GetNodeInPortValue(nodeID string, inPortIndex int) IPort {
if ctx, ok := gr.context[nodeID]; ok {
if inPortIndex >= len(ctx.InputPorts) || inPortIndex < 0 {
return nil
}
return ctx.InputPorts[inPortIndex]
}
return nil
}
func (gr *Graph) GetNodeOutPortValue(nodeID string, outPortIndex int) IPort {
if ctx, ok := gr.context[nodeID]; ok {
if outPortIndex >= len(ctx.OutputPorts) || outPortIndex < 0 {
return nil
}
return ctx.OutputPorts[outPortIndex]
}
return nil
}
func (gr *Graph) Release() {
// 有定时器关闭定时器
for timerID := range gr.mapTimerID {
gr.CancelTimerId(gr.graphID, &timerID)
}
gr.mapTimerID = nil
// 清理掉所有数据
*gr = Graph{}
}
func (gr *Graph) HotReload(newBaseGraph *baseGraph) {
gr.baseGraph = newBaseGraph
}
func (gr *Graph) GetGraphFileName() string{
return gr.graphFileName
}