package logic import ( "crypto/md5" "encoding/hex" "encoding/json" "fmt" "fusenapi/server/websocket/internal/config" "github.com/zeromicro/go-zero/core/logx" "net" "time" ) var ( //取消unity僵尸任务控制通道 cancelUnityCtlChan = make(chan cancelUnityCtlChanItem, 1000) cancelRenderContextPanicMsg any = "cancel_render_context_panic_msg" ) // 控制通道元素 type cancelUnityCtlChanItem struct { Wid string `json:"wid"` //ws的唯一id DeadlineTime int64 `json:"deadline_time"` //截断时间 Sign string `json:"sign"` //有效签名 } // 取消渲染抛出的异常 func cancelRenderPanic() { panic(cancelRenderContextPanicMsg) } // 判断是否是取消渲染的异常 func isCancelRenderPanic(err any) bool { return err == cancelRenderContextPanicMsg } // 发送取消上下文消息给unity func sendCancelRenderMsgToUnity(wid string, deadlineTime int64) { data := cancelUnityCtlChanItem{ Wid: wid, DeadlineTime: deadlineTime, Sign: signMessage(wid, deadlineTime), } select { case cancelUnityCtlChan <- data: case <-time.After(time.Millisecond * 200): logx.Error("sendCancelRenderMsgToUnity数据超时丢弃") } } // 拨号udp func DialUdp(config config.Config) error { localAddr := &net.UDPAddr{IP: net.ParseIP(config.Unity.Udp.LocalAddr), Port: config.Unity.Udp.LocalPort} remoteAddr := &net.UDPAddr{IP: net.ParseIP(config.Unity.Udp.RemoteAddr), Port: config.Unity.Udp.RemotePort} conn, err := net.DialUDP("udp", localAddr, remoteAddr) if err != nil { return err } go ConsumeCancelUnityChanMessage(conn) return nil } // 签名消息 func signMessage(wid string, deadlineTime int64) string { h := md5.New() h.Write([]byte(fmt.Sprintf("%s_fusen_control_unity_%d", wid, deadlineTime))) return hex.EncodeToString(h.Sum(nil)) } // 消费数据 func ConsumeCancelUnityChanMessage(conn *net.UDPConn) { defer func() { if err := recover(); err != nil { logx.Error("ConsumeCancelUnityChanMessage 异常:", err) } }() defer conn.Close() for { select { case data := <-cancelUnityCtlChan: d, _ := json.Marshal(data) _, err := conn.Write(d) if err != nil { logx.Error("发送udp包通知Unity失败:", err) continue } } } }