package baseroom import ( "fmt" "game/common/proto/pb" "github.com/fox/fox/log" "github.com/golang/protobuf/proto" "time" ) type BaseRoom[Seat ISeat] struct { id int roomType int // 房间配置id 初级,中级,高级 playType int // 玩法配置id color玩法id gameNo string Seats []Seat timeTypes map[TimerType]uint32 subRoom IRoom sTimer ITimer sender ISender } func NewBaseRoom[Seat ISeat](id, roomType, playType int, subRoom IRoom, sTimer ITimer, sender ISender) (*BaseRoom[Seat], pb.ErrCode) { room := &BaseRoom[Seat]{ id: id, roomType: roomType, playType: playType, gameNo: "", timeTypes: make(map[TimerType]uint32), subRoom: subRoom, sTimer: sTimer, sender: sender, } return room, pb.ErrCode_OK } func (r *BaseRoom[Seat]) Id() int { return r.id } func (r *BaseRoom[Seat]) RoomType() int { return r.roomType } func (r *BaseRoom[Seat]) SetTruthRoom(rm IRoom) { r.subRoom = rm } func (r *BaseRoom[Seat]) PlayType() int { return r.playType } // 入座玩家数量(包含机器人) func (r *BaseRoom[Seat]) SeatPlayerNum() int { num := 0 for _, seat := range r.Seats { if !seat.Empty() { num++ } } return num } // 真实玩家数量 func (r *BaseRoom[Seat]) RealPlayerNum() int { num := 0 for _, seat := range r.Seats { if !seat.Empty() && seat.Player().Robot() == nil { num++ } } return num } // 机器人数量 func (r *BaseRoom[Seat]) RobotPlayerNum() int { num := 0 for _, seat := range r.Seats { if !seat.Empty() && seat.Player().Robot() != nil { num++ } } return num } func (r *BaseRoom[Seat]) HasEmptySeat() bool { for _, seat := range r.Seats { if seat.Empty() { return true } } return false } func (r *BaseRoom[Seat]) HasPlayer(uid int64) bool { for _, seat := range r.Seats { if !seat.Empty() && seat.Player().Id() == uid { return true } } return false } func (r *BaseRoom[Seat]) AddPlayer(player IPlayer, seat int) { if seat < 0 || seat >= len(r.Seats) { log.Error(r.SeatLog(r.Seats[seat], "out of range")) return } r.Seats[seat].SetPlayer(player) return } func (r *BaseRoom[Seat]) RemovePlayer(player IPlayer) { for _, seat := range r.Seats { if !seat.Empty() && seat.Player().Id() == player.Id() { seat.SetPlayer(nil) break } } } func (r *BaseRoom[Seat]) OnMessage(cmd int32, params ...any) { if r.subRoom == nil { log.Error(r.Log("sub room is nil")) return } r.subRoom.OnMessage(cmd, params...) } func (r *BaseRoom[Seat]) DebugSendMsg(user IPlayer, msgId pb.MsgId, msg proto.Message) { log.Debug(r.UserLog(user.Id(), "send msg:%v %v", msgId, msg.String())) } func (r *BaseRoom[Seat]) SendMsg(user IPlayer, msgId pb.MsgId, msg proto.Message) { r.DebugSendMsg(user, msgId, msg) if user.Robot() != nil { user.Robot().OnMessage(msgId, msg) } else { for _, seat := range r.Seats { if !seat.Empty() && seat.Player().Id() == user.Id() { r.sender.SendMsg(user, msgId, msg) break } } } } func (r *BaseRoom[Seat]) Broadcast(msgId pb.MsgId, msg proto.Message, exclude ...IPlayer) { for _, seat := range r.Seats { if !seat.Empty() { exist := false for _, excludePlayer := range exclude { if excludePlayer.Id() == seat.Player().Id() { exist = true break } } if !exist { r.SendMsg(seat.Player(), msgId, msg) } } } } func (r *BaseRoom[Seat]) NewTimer(timerType TimerType, duration time.Duration, args ...interface{}) { if r.sTimer == nil { log.Error(r.Log("timer handler is nil")) return } if _, ok := r.timeTypes[timerType]; ok { log.Error(r.Log("timer type:%v is exist.can not new timer", timerType.String())) // if timerType == TtPlayerAct { // log.Debug(r.Log(log.StackTrace())) // } return } tid := r.sTimer.NewTimer(duration+time.Duration(10)*time.Millisecond, func() { r.sTimer.OnTimer(timerType, args...) }, true, r.Log("start type:%v timer", timerType.String())) r.timeTypes[timerType] = tid // log.Debug(r.Log("start type:%v timer", timerType.String())) } func (r *BaseRoom[Seat]) CancelTimer(timerType TimerType) { if tid, ok := r.timeTypes[timerType]; ok { r.sTimer.CancelTimer(tid) delete(r.timeTypes, timerType) // log.Debug(r.Log("stop type:%v timer, rest timer:%+v", timerType.String(), r.timeTypes)) } } func (r *BaseRoom[Seat]) CancelAllTimer() { for _, tid := range r.timeTypes { r.sTimer.CancelTimer(tid) // log.Debug(r.Log("start type:%v timer", timerType.String())) } r.timeTypes = make(map[TimerType]uint32) } func (r *BaseRoom[Seat]) Log(format string, a ...any) string { head := fmt.Sprintf("room:%v type:%v ", r.id, r.roomType) return head + fmt.Sprintf(format, a...) } func (r *BaseRoom[Seat]) SeatLog(seat Seat, format string, a ...any) string { head := "" if seat.Player() != nil { head = fmt.Sprintf("room:%v type:%v seat:%v user:%v robot:%v ", r.id, r.roomType, seat.No(), seat.Player().Id(), seat.Player().Robot() != nil) } else { head = fmt.Sprintf("room:%v type:%v seat:%v ", r.id, r.roomType, seat.No()) } return head + fmt.Sprintf(format, a...) } func (r *BaseRoom[Seat]) UserLog(uid int64, format string, a ...any) string { var seat Seat exist := false for _, st := range r.Seats { if !st.Empty() && st.Player().Id() == uid { seat = st exist = true break } } if exist { return r.SeatLog(seat, format, a...) } else { return r.Log(format, a...) } } // 玩家俱乐部房间玩游戏 func (r *BaseRoom[Seat]) GameStart() { } // 玩家俱乐部房间玩游戏 func (r *BaseRoom[Seat]) GameEnd() { }