diff --git a/server/hallserver/listener/handlermgr.go b/server/hallserver/listener/handlermgr.go index 6a104baf..d0b09256 100644 --- a/server/hallserver/listener/handlermgr.go +++ b/server/hallserver/listener/handlermgr.go @@ -22,6 +22,8 @@ func (this *HandlerMgr) Init() { cs.RegHandlerId(int(cs.CMMessageIdE__CMJoinRoom), constant.ROOM_MGR_HANDLER_ID) cs.RegHandlerId(int(cs.CMMessageIdE__CMSearchRoom), constant.ROOM_MGR_HANDLER_ID) cs.RegHandlerId(int(cs.CMMessageIdE__CMGetCurrentRoom), constant.ROOM_MGR_HANDLER_ID) + cs.RegHandlerId(int(cs.CMMessageIdE__CMEnterObserver), constant.ROOM_MGR_HANDLER_ID) + cs.RegHandlerId(int(cs.CMMessageIdE__CMLeaveObserver), constant.ROOM_MGR_HANDLER_ID) cs.RegHandlerId(int(cs.CMMessageIdE__CMDisbandRoom), constant.ROOM_HANDLER_ID) cs.RegHandlerId(int(cs.CMMessageIdE__CMLeaveRoom), constant.ROOM_HANDLER_ID) diff --git a/server/hallserver/room/room.go b/server/hallserver/room/room.go index 742a36e5..c15178d4 100644 --- a/server/hallserver/room/room.go +++ b/server/hallserver/room/room.go @@ -37,10 +37,7 @@ type room struct { gameStartNotifyMsg *cs.SMRoomGameStartNotify } -func (this *room) init(roomId string, - roomIdx int64, - owner common.Player, - msg *cs.CMCreateRoom) { +func (this *room) init(roomId string, roomIdx int64, owner common.Player, msg *cs.CMCreateRoom) { this.roomId = roomId this.roomIdx = roomIdx this.config.mapId = msg.GetMapId() @@ -123,7 +120,7 @@ func (this *room) canJoin(member common.Player, msg *cs.CMJoinRoom) bool { if t != nil && t.getMemberNum() >= constant.ROOM_MAX_TEAM_MEMBER_NUM { return false } - return false + return true } func (this *room) join(hum common.Player, msg *cs.CMJoinRoom) bool { @@ -138,7 +135,33 @@ func (this *room) join(hum common.Player, msg *cs.CMJoinRoom) bool { } else { t.addMember(m) } - return false + this.autoStartCountdown() + return true +} + +func (this *room) autoStartCountdown() { + if this.getTeamNum() != this.config.maxTeamNum { + return + } + var secondsRemaining int32 = 15 + timer := f5.GetTimer() + timer.SetInterval(1000, func(e int32, args *q5.Args) { + if e == q5.TIMER_EXEC_EVENT { + if this.getTeamNum() != this.config.maxTeamNum { + timer.DeleteRunningTimer() + return + } + if secondsRemaining > 0 { + this.AutoStartGameCountdownNotify(secondsRemaining) + } + if secondsRemaining == 0 { + this.notifyGameStart() + timer.DeleteRunningTimer() + return + } + secondsRemaining-- + } + }) } func (this *room) fillMFRoom(hum common.Player, pb *cs.MFRoom) { @@ -162,7 +185,7 @@ func (this *room) fillMFRoom(hum common.Player, pb *cs.MFRoom) { this.owner.fillMFMember(pb.Owner) } -func (this *room) fillMFCurrentRoom(hum common.Player, pb *cs.MFCurrentRoom) { +func (this *room) fillMFCurrentRoom(hum common.Player, pb *cs.MFCurrentRoom, observerTeam *team) { pb.RoomId = proto.String(this.roomId) pb.MapId = proto.Int32(this.config.mapId) pb.ZoneId = proto.Int32(this.config.zoneId) @@ -187,6 +210,12 @@ func (this *room) fillMFCurrentRoom(hum common.Player, pb *cs.MFCurrentRoom) { t.fillMFTeam(pbT) q5.AppendSlice(&pb.TeamList, pbT) } + + if observerTeam != nil && observerTeam.room != nil { + pbT2 := &cs.MFTeam{} + observerTeam.fillMFTeam(pbT2) + pb.ObserverTeam = pbT2 + } } func (this *room) OnPlayerOffline(hum common.Player) { @@ -214,23 +243,25 @@ func (this *room) CMLeaveRoom(hdr *f5.MsgHdr, msg *cs.CMLeaveRoom) { hum := hdr.Context.(common.Player) m := this.getMember(hum.GetAccountId()) if m != nil && this.roomState == ROOM_INIT_STATE { + var removeMemberAccountId string if this.isOwner(hum) { nextOwner := this.getNextOwner() if nextOwner == nil { this.doDisband(ROOM_DISBAND_NO_NEXT_OWNER_REASON) return } else { - this.removeMember(this.owner.hum.GetAccountId()) + removeMemberAccountId = this.owner.hum.GetAccountId() this.owner = nextOwner } } else { - this.removeMember(hum.GetAccountId()) + removeMemberAccountId = hum.GetAccountId() } notifyMsg := &cs.SMRoomLeaveNotify{} q5.NewSlice(¬ifyMsg.AccountIds, 0, 1) q5.AppendSlice(¬ifyMsg.AccountIds, m.hum.GetAccountId()) this.broadcastMsg(notifyMsg) this.notifyRoomInfo(hum) + this.removeMember(removeMemberAccountId) } } @@ -279,7 +310,18 @@ func (this *room) CMKickoutTeam(hdr *f5.MsgHdr, msg *cs.CMKickoutTeam) { m := this.getMember(hum.GetAccountId()) t := this.getTeamByUuid(msg.GetTeamUuid()) if m == this.owner && t != nil && t != m.team && this.roomState == ROOM_INIT_STATE { + membersPtr := make([]*member, 0, t.members.Size()) + t.members.ForEach( + func(data interface{}) bool { + if mPtr, ok := data.(*member); ok { + membersPtr = append(membersPtr, mPtr) + } + return true + }) notifyMsg := &cs.SMRoomKickoutNotify{} + for _, m2 := range membersPtr { + notifyMsg.AccountIds = append(notifyMsg.AccountIds, m2.hum.GetAccountId()) + } this.broadcastMsg(notifyMsg) t.unInit() this.notifyRoomInfo(hum) @@ -307,22 +349,6 @@ func (this *room) CMCloseNotify(hdr *f5.MsgHdr, msg *cs.CMCloseNotify) { } } -func (this *room) CMEnterObserver(hdr *f5.MsgHdr, msg *cs.CMEnterObserver) { - //hum := hdr.Context.(common.Player) - //m := this.getMember(hum.GetAccountId()) - // if this.isOwner(hum) { - // t := this.owner.team - // } -} - -func (this *room) CMLeaveObserver(hdr *f5.MsgHdr, msg *cs.CMLeaveObserver) { - //hum := hdr.Context.(common.Player) - //m := this.getMember(hum.GetAccountId()) - // if this.isOwner(hum) { - // t := this.owner.team - // } -} - func (this *room) broadcastMsg(msg proto.Message) { for _, m := range this.members { if m.hum.GetRoom() == this { @@ -386,13 +412,19 @@ func (this *room) GetRoomState() int32 { return this.roomState } +func (this *room) AutoStartGameCountdownNotify(seconds int32) { + notifyMsg := &cs.SMAutoStartGameCountdownNotify{} + notifyMsg.Seconds = proto.Int32(seconds) + this.broadcastMsg(notifyMsg) +} + func (this *room) notifyGameStart() { if this.gameStartNotifyMsg == nil { this.genGameStartNotifyMsg() } for _, m := range this.members { - if m.state == MEMBER_READY_STATE && - m.hum.GetRoom() == this && + // m.state == MEMBER_READY_STATE && + if m.hum.GetRoom() == this && !m.closeGameStartNotify { m.hum.SendMsg(this.gameStartNotifyMsg) } @@ -447,6 +479,7 @@ func (this *room) genGameStartNotifyMsg() { } func (this *room) canStart() bool { + return true alreadyNum := 0 for _, t := range this.teamUuidHash { if t.hasAlreadMember() { diff --git a/server/hallserver/room/roommgr.go b/server/hallserver/room/roommgr.go index c774642a..f10546a9 100644 --- a/server/hallserver/room/roommgr.go +++ b/server/hallserver/room/roommgr.go @@ -11,16 +11,12 @@ import ( "q5" ) -type TeamInfo struct { - TeamUUID string `json:"team_uuid"` - MemberList []memberInfo `json:"member_list"` -} - type roomMgr struct { cs.MsgHandlerImpl - currRoomId int32 - idHash map[string]*room - roomList q5.ListHead + currRoomId int32 + idHash map[string]*room + roomList q5.ListHead + observerTeam *team } func (this *roomMgr) Init() { @@ -81,12 +77,16 @@ func (this *roomMgr) CMCreateRoom(hdr *f5.MsgHdr, msg *cs.CMCreateRoom) { this.roomList.AddTail(&m.entry) rspMsg.RoomId = proto.String(m.roomId) + rspMsg.Room = new(cs.MFRoom) + m.fillMFRoom(hum, rspMsg.Room) + teamInfo := &TeamInfo{} err := json.Unmarshal([]byte(msg.GetTeamInfo()), teamInfo) - if err != nil { - f5.GetSysLog().Info(err.Error()) - } else { - this.SaveTeamLeader(m, msg.GetTeamUuid(), teamInfo) + if err == nil { + t := m.getTeamByUuid(msg.GetTeamUuid()) + if t != nil { + t.SaveTeamLeader(teamInfo) + } } hum.SendMsg(rspMsg) @@ -120,6 +120,21 @@ func (this *roomMgr) CMJoinRoom(hdr *f5.MsgHdr, msg *cs.CMJoinRoom) { hum.SendMsg(&rspMsg) return } + + r.join(hum, msg) + r.notifyRoomInfo(hum) + + if len(msg.GetTeamInfo()) > 0 { + teamInfo := &TeamInfo{} + err := json.Unmarshal([]byte(msg.GetTeamInfo()), teamInfo) + if err == nil { + t := r.getTeamByUuid(msg.GetTeamUuid()) + t.SaveTeamLeader(teamInfo) + } + } + + rspMsg.Room = new(cs.MFRoom) + r.fillMFRoom(hum, rspMsg.Room) hum.SendMsg(&rspMsg) } @@ -146,6 +161,7 @@ func (this *roomMgr) CMSearchRoom(hdr *f5.MsgHdr, msg *cs.CMSearchRoom) { } return true }) + rspMsg.SinceId = proto.Int64(sinceId) hum.SendMsg(&rspMsg) } @@ -154,8 +170,7 @@ func (this *roomMgr) CMGetCurrentRoom(hdr *f5.MsgHdr, msg *cs.CMGetCurrentRoom) rspMsg := &cs.SMGetCurrentRoom{} if hum.GetRoom() != nil && hum.GetRoom().GetRoomState() == ROOM_INIT_STATE { rspMsg.Room = new(cs.MFCurrentRoom) - - hum.GetRoom().(*room).fillMFCurrentRoom(hum, rspMsg.Room) + hum.GetRoom().(*room).fillMFCurrentRoom(hum, rspMsg.Room, this.observerTeam) hum.SendMsg(rspMsg) return } @@ -167,23 +182,80 @@ func (this *roomMgr) RemoveRoomMember(hdr *f5.MsgHdr) { if hum != nil { if roomPtr, ok := hum.GetRoom().(*room); ok { roomPtr.removeMember(hum.GetAccountId()) - } - } -} - -func (this *roomMgr) SaveTeamLeader(r *room, teamUUID string, teamInfo *TeamInfo) { - t := r.getTeamByUuid(teamUUID) - for _, mInfo := range teamInfo.MemberList { - if mInfo.IsLeader == 1 { - t.tmpTeamLeader = &memberInfo{ - AccountID: mInfo.AccountID, - Name: mInfo.Name, - Avatar: mInfo.Avatar, - AvatarFrame: mInfo.AvatarFrame, - HeroId: mInfo.HeroId, - IsLeader: mInfo.IsLeader, - State: mInfo.State, + if len(roomPtr.teamUuidHash) <= 0 { + roomPtr.unInit() } } } } + +func (this *roomMgr) CMEnterObserver(hdr *f5.MsgHdr, msg *cs.CMEnterObserver) { + hum := hdr.Context.(common.Player) + rspMsg := cs.SMEnterObserver{} + + roomPtr, ok := hum.GetRoom().(*room) + if !ok || roomPtr == nil { + rspMsg.Errcode = proto.Int32(1) + rspMsg.Errmsg = proto.String("room is empty") + hum.SendMsg(&rspMsg) + return + } + + if !roomPtr.isOwner(hum) { + rspMsg.Errcode = proto.Int32(2) + rspMsg.Errmsg = proto.String("not owner") + hum.SendMsg(&rspMsg) + return + } + + if this.observerTeam != nil && this.observerTeam.room != nil { + rspMsg.Errcode = proto.Int32(3) + rspMsg.Errmsg = proto.String("exists observer team") + hum.SendMsg(&rspMsg) + return + } + + t := roomPtr.owner.team + delete(roomPtr.teamUuidHash, t.teamUuid) + delete(roomPtr.teamIdHash, t.teamId) + this.observerTeam = roomPtr.owner.team + + hum.SendMsg(&rspMsg) + roomPtr.notifyRoomInfo(hum) +} + +func (this *roomMgr) CMLeaveObserver(hdr *f5.MsgHdr, msg *cs.CMLeaveObserver) { + hum := hdr.Context.(common.Player) + rspMsg := cs.SMLeaveObserver{} + + roomPtr, ok := hum.GetRoom().(*room) + if !ok { + rspMsg.Errcode = proto.Int32(1) + rspMsg.Errmsg = proto.String("room is empty") + hum.SendMsg(&rspMsg) + return + } + + if !roomPtr.isOwner(hum) { + rspMsg.Errcode = proto.Int32(2) + rspMsg.Errmsg = proto.String("not owner") + hum.SendMsg(&rspMsg) + return + } + + if roomPtr.getTeamNum() >= roomPtr.config.maxTeamNum { + rspMsg.Errcode = proto.Int32(3) + rspMsg.Errmsg = proto.String("teams is full") + hum.SendMsg(&rspMsg) + return + } + + t := roomPtr.owner.team + roomPtr.addTeam(t) + roomPtr.autoStartCountdown() + + this.observerTeam = nil + + hum.SendMsg(&rspMsg) + roomPtr.notifyRoomInfo(hum) +} diff --git a/server/hallserver/room/team.go b/server/hallserver/room/team.go index c7494c16..189de1a6 100644 --- a/server/hallserver/room/team.go +++ b/server/hallserver/room/team.go @@ -6,6 +6,12 @@ import ( "q5" ) +// TeamInfo from client data +type TeamInfo struct { + TeamUUID string `json:"team_uuid"` + MemberList []memberInfo `json:"member_list"` +} + type memberInfo struct { AccountID string `json:"account_id"` Name string `json:"name"` @@ -32,12 +38,17 @@ func (this *team) init(room *room, teamId int32, teamUuid string) { } func (this *team) unInit() { + deleteMembers := make([]*member, 0, this.members.Size()) this.members.ForEach( func(data interface{}) bool { - m := data.(*member) - m.unInit() + if mPtr, ok := data.(*member); ok { + deleteMembers = append(deleteMembers, mPtr) + } return true }) + for _, m := range deleteMembers { + m.unInit() + } delete(this.room.teamUuidHash, this.teamUuid) delete(this.room.teamIdHash, this.teamId) this.room = nil @@ -127,6 +138,25 @@ func (this *team) getOwnerCandidate() *member { return ownerCandidate } +func (this *team) SaveTeamLeader(teamInfo *TeamInfo) { + if this.tmpTeamLeader != nil { + return + } + for _, mInfo := range teamInfo.MemberList { + if mInfo.IsLeader == 1 { + this.tmpTeamLeader = &memberInfo{ + AccountID: mInfo.AccountID, + Name: mInfo.Name, + Avatar: mInfo.Avatar, + AvatarFrame: mInfo.AvatarFrame, + HeroId: mInfo.HeroId, + IsLeader: mInfo.IsLeader, + State: mInfo.State, + } + } + } +} + func newTeam(room *room, teamId int32, teamUuid string, leader *member) *team { t := new(team) t.init(room, teamId, teamUuid)