package user_m import ( "hilo-user/_const/enum/robot_e" "hilo-user/_const/enum/user_e" "hilo-user/domain" "hilo-user/domain/cache/robot_c" "hilo-user/resource/mysql" "math/rand" "time" ) // 游戏结构体 type GameTiny struct { GameUid mysql.ID GameType user_e.GameType GroupId string MgId int64 Diamond int64 NeedRobots int // 需要机器人数量 Status user_e.GameStatus // 游戏进行状态,1:进行中、0:结束, 心跳实时刷新 UpdatedTime time.Time } // 获取需要机器人的游戏 func GetNeedRobotGames(model *domain.Model) ([]GameTiny, error) { var resGames []GameTiny // 获取准备开始的游戏 var users []GameTiny sql := "SELECT user.id as user_uid,user.user_type,user.tx_group_id as group_id,mg_id,user.diamond,user.`status`,user.updated_time FROM user_info user,group_info g " + "WHERE user.tx_group_id = g.tx_group_id AND user. STATUS = 0 AND user.auto_match = 1 AND user.battle_start_at = 0 AND g.`password` = '' AND g.tourist_mic = 1" if err := model.DB().Raw(sql).Find(&users).Error; err != nil { return nil, err } now := time.Now() for _, user := range users { // 使用user.UpdatedTime(非CreatedTime)去判断8秒,兼容编辑游戏的情况 if now.Sub(user.UpdatedTime).Seconds() <= 8 { continue } // user players var players []GamePlayer if err := model.DB().Model(GamePlayer{}). Where("user_id = ?", user.GameUid).Find(&players).Error; err == nil { // 没有玩家,属于异常的user if len(players) <= 0 { model.Log.Errorf("GetNeedRobotGames no player exits,user:%v,players:%v", user, players) continue } // 玩家大于2个就不需要机器人 if len(players) > 1 { continue } // 机器人进群cd中 if robot_c.IsGroupInCd(model, user.GroupId) { model.Log.Warnf("IsGroupInCd in cd,user:%v", user) continue } var needRobots = 1 // 一个机器人 resGames = append(resGames, GameTiny{ GameUid: user.GameUid, GroupId: user.GroupId, MgId: user.MgId, NeedRobots: needRobots, Status: user.Status, GameType: user.GameType, Diamond: user.Diamond, }) } else if err != nil { model.Log.Errorf("GamePlayer fail:%v", err.Error()) } } return resGames, nil } // 获取正在使用中的机器人 func GetUsingRobots(model *domain.Model) ([]*GameRobot, error) { var robots []*GameRobot if err := model.DB().Model(GameRobot{}).Where("state = ?", robot_e.RobotStateUsing).Find(&robots).Error; err != nil { return nil, err } return robots, nil } // 获取房间中的机器人 func GetRoomRobots(model *domain.Model, txGroupId mysql.Str) ([]*GameRobot, error) { var robots []*GameRobot if err := model.DB().Model(GameRobot{}).Where("group_id = ?", txGroupId).Find(&robots).Error; err != nil { return nil, err } return robots, nil } // 获取异常的robot // state = 0,但是状态没清空 func GetAbnormalRobots(model *domain.Model) ([]*GameRobot, error) { var robots []*GameRobot if err := model.DB().Model(GameRobot{}).Where("state = ? AND op_step != 0", robot_e.RobotStateIdle).Find(&robots).Error; err != nil { return nil, err } return robots, nil } // 获取闲置中的机器人 // 并且设置为使用中 func GetSetIdleGameRobots(model *domain.Model, num int) ([]*GameRobot, error) { if num <= 0 { model.Log.Warnf("GetSetIdleGameRobots no need robot:%v", num) return nil, nil } var robots []*GameRobot var canUseRobots []*GameRobot err := model.Transaction(func(txModel *domain.Model) error { if err := txModel.Db.WithContext(txModel).Model(GameRobot{}).Where("state = ?", robot_e.RobotStateIdle).Limit(1000).Find(&robots).Error; err != nil { return err } // 打乱1000个空闲的机器人 rand.Shuffle(len(robots), func(i, j int) { robots[i], robots[j] = robots[j], robots[i] }) for i, robot := range robots { // 增加cd逻辑,60秒机器人不复用 if time.Now().Sub(robot.LastUseTime).Seconds() < 60 { model.Log.Warnf("robot cannot frequency use:%v", robot) continue } if err := robot.MarkUsing(txModel); err != nil { return err } canUseRobots = append(canUseRobots, robots[i]) num-- if num <= 0 { break } } return nil }) if err != nil { model.Log.Errorf("GetIdleGameRobots fail:%v", err) return nil, err } return canUseRobots, nil } // 游戏ai启动 func AddAi(model *domain.Model, robots []*GameRobot) { for _, robot := range robots { robot.Run() // 一个机器人一个协程 } }