package machinedoll import ( "encoding/json" "fmt" "mongo.games.com/goserver/core/timer" "os/signal" "syscall" "mongo.games.com/game/protocol/machine" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/netlib" "mongo.games.com/goserver/srvlib" "net" "os" "path/filepath" "time" ) var GameConn *netlib.Session var ConnMap = make(map[int]net.Conn) type MachineManager struct { DelConnMap map[int]string } var MachineMgr = &MachineManager{ DelConnMap: make(map[int]string), } func (this *MachineManager) ModuleName() string { return "MachineManager" } // 心跳间隔时间(秒) const heartbeatInterval = 1 func (this *MachineManager) Init() { var serverAddrs []string programDir, err := os.Getwd() if err != nil { fmt.Println("Error getting working directory:", err) return } configFile := filepath.Join(programDir, "machineIPConfig.json") fmt.Println("构建配置文件的路径", configFile) fileData, err := os.ReadFile(configFile) if err != nil { logger.Logger.Error("Read robot account file error:", err) return } else { if err = json.Unmarshal(fileData, &serverAddrs); err != nil { logger.Logger.Error("Unmarshal robot account data error:", err) return } } //与娃娃机创建连接 // 遍历每个服务器地址,建立连接 for i, addr := range serverAddrs { conn, err := net.DialTimeout("tcp", addr, 5*time.Second) if err != nil { fmt.Println("Failed to connect to server:", err) continue } ConnMap[i+1] = conn go this.StartHeartbeat(i+1, &conn, addr) } fmt.Println("Connected to server:\n", ConnMap[1].RemoteAddr()) fmt.Println("投币请按Q!!!!") fmt.Println("w向前s向后a向左d向右 j强力抓取k弱力抓取!") // 监听 WASD 按键事件 /* go listenKeyboardEvents(ConnMap[1]) // 监听中断信号,等待用户退出 waitForUserExit()*/ } func (this *MachineManager) StartHeartbeat(id int, conn *net.Conn, addr string) { // 定期发送心跳包 ticker := time.NewTicker(heartbeatInterval * time.Second) defer ticker.Stop() for { select { case <-ticker.C: // 发送心跳包 _, err := (*conn).Write([]byte("heartbeat")) if err != nil { fmt.Println("Failed to send heartbeat:", err) delete(ConnMap, id) this.DelConnMap[id] = addr //通知游戏服 this.UpdateToGameServer() fmt.Println("删除链接!!!!!!addr = ", addr) go timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool { this.ReConnect() return true }), nil, time.Duration(5)*time.Second, 100) return } } } } // 重连 func (this *MachineManager) ReConnect() bool { fmt.Println("================重连============") delIds := []int{} status := false for id, addr := range this.DelConnMap { conn, err := net.DialTimeout("tcp", addr, 5*time.Second) if err != nil { continue } ConnMap[id] = conn delIds = append(delIds, id) status = true } for _, id := range delIds { delete(this.DelConnMap, id) fmt.Println("重新链接成功!!!!!!id = ", id) } if status { this.UpdateToGameServer() return true } return false } func (this *MachineManager) UpdateToGameServer() { msg := &machine.MSDollMachineList{} for i, _ := range ConnMap { info := &machine.DollMachine{} info.Id = int32(i) info.VideoAddr = "www.baidu.com" msg.Data = append(msg.Data, info) } SendToGameServer(int(machine.DollMachinePacketID_PACKET_MSDollMachineList), msg) } func SendToGameServer(pid int, msg interface{}) { if GameConn == nil { GameConn = srvlib.ServerSessionMgrSington.GetSession(1, 7, 701) } if GameConn != nil { GameConn.Send(pid, msg) } else { logger.Logger.Error("GameConn is nil !") } } func init() { MachineMgr.Init() } func listenKeyboardEvents(conn net.Conn) { for { // 读取键盘事件 key := readKeyboardEvent() switch key { case "w": Backward(conn) time.Sleep(200 * time.Millisecond) BackwardStop(conn) case "W": Backward(conn) time.Sleep(200 * time.Millisecond) BackwardStop(conn) case "a": Left(conn) time.Sleep(200 * time.Millisecond) LeftStop(conn) case "A": Left(conn) time.Sleep(200 * time.Millisecond) LeftStop(conn) case "s": Forward(conn) time.Sleep(200 * time.Millisecond) ForwardStop(conn) case "S": Forward(conn) time.Sleep(200 * time.Millisecond) ForwardStop(conn) case "d": Right(conn) time.Sleep(200 * time.Millisecond) RightStop(conn) case "D": Right(conn) time.Sleep(200 * time.Millisecond) RightStop(conn) case "j": Grab(conn) case "J": SetPower(conn) time.Sleep(200 * time.Millisecond) Grab(conn) case "k": WeakGrab(conn) case "K": WeakGrab(conn) case "q": Coin(conn) Backward(conn) time.Sleep(200 * time.Millisecond) BackwardStop(conn) case "Q": Coin(conn) Backward(conn) time.Sleep(150 * time.Millisecond) BackwardStop(conn) case "1": RestoreFactorySettings(conn) case "2": OpenMusic(conn) case "3": Reboot(conn) case "4": StopServer(conn) case "5": StartServer(conn) case "6": ClearRemainingGames(conn) case "7": SetPower(conn) case "8": CloseMusic(conn) } } } func readKeyboardEvent() string { var b [1]byte var done uint32 err := syscall.ReadFile(syscall.Stdin, b[:], &done, nil) if err != nil { panic(err) } return string(b[:]) } func waitForUserExit() { // 创建一个信号通道 signalChan := make(chan os.Signal, 1) // 监听中断信号 signal.Notify(signalChan, os.Interrupt) // 等待用户按下 Ctrl+C 退出 <-signalChan fmt.Println("退出程序...") }