package controller import ( "github.com/mitchellh/mapstructure" "log/slog" "slgserver/constant" "slgserver/middleware" "slgserver/net" "slgserver/server/chatserver/logic" "slgserver/server/chatserver/proto" "slgserver/util" "sync" ) var DefaultChat = Chat{ worldGroup: logic.NewGroup(), unionGroups: make(map[int]*logic.Group), ridToUnionGroups: make(map[int]int), } type Chat struct { unionMutex sync.RWMutex worldGroup *logic.Group //世界频道 unionGroups map[int]*logic.Group //联盟频道 ridToUnionGroups map[int]int //rid对应的联盟频道 } func (this*Chat) InitRouter(r *net.Router) { g := r.Group("chat").Use(middleware.ElapsedTime(), middleware.Log()) g.AddRouter("login", this.login) g.AddRouter("logout", this.logout, middleware.CheckRId()) g.AddRouter("chat", this.chat, middleware.CheckRId()) g.AddRouter("history", this.history, middleware.CheckRId()) g.AddRouter("join", this.join, middleware.CheckRId()) g.AddRouter("exit", this.exit, middleware.CheckRId()) } func (this*Chat) login(req *net.WsMsgReq, rsp *net.WsMsgRsp) { reqObj := &proto.LoginReq{} rspObj := &proto.LoginRsp{} rsp.Body.Code = constant.OK rsp.Body.Msg = rspObj mapstructure.Decode(req.Body.Msg, reqObj) rspObj.RId = reqObj.RId rspObj.NickName = reqObj.NickName sess, err := util.ParseSession(reqObj.Token) if err != nil{ rsp.Body.Code = constant.InvalidParam return } if sess.IsValid() == false || sess.Id != reqObj.RId{ rsp.Body.Code = constant.InvalidParam return } net.ConnMgr.RoleEnter(req.Conn, reqObj.RId) this.worldGroup.Enter(logic.NewUser(reqObj.RId, reqObj.NickName)) } func (this*Chat) logout(req *net.WsMsgReq, rsp *net.WsMsgRsp) { reqObj := &proto.LogoutReq{} rspObj := &proto.LogoutRsp{} rsp.Body.Code = constant.OK rsp.Body.Msg = rspObj mapstructure.Decode(req.Body.Msg, reqObj) rspObj.RId = reqObj.RId net.ConnMgr.UserLogout(req.Conn) this.worldGroup.Exit(reqObj.RId) } func (this*Chat) chat(req *net.WsMsgReq, rsp *net.WsMsgRsp) { reqObj := &proto.ChatReq{} rspObj := &proto.ChatMsg{} rsp.Body.Code = constant.OK rsp.Body.Msg = rspObj mapstructure.Decode(req.Body.Msg, reqObj) p, _ := req.Conn.GetProperty("rid") rid := p.(int) if reqObj.Type == 0 { //世界聊天 rsp.Body.Msg = this.worldGroup.PutMsg(reqObj.Msg, rid, 0) }else if reqObj.Type == 1{ //联盟聊天 this.unionMutex.RLock() id, ok := this.ridToUnionGroups[rid] if ok { g, ok := this.unionGroups[id] if ok { g.PutMsg(reqObj.Msg, rid, 1) }else{ slog.Warn("chat not found rid in unionGroups", "rid", rid) } }else{ slog.Warn("chat not found rid in ridToUnionGroups", "rid", rid) } this.unionMutex.RUnlock() } } //历史记录 func (this*Chat) history(req *net.WsMsgReq, rsp *net.WsMsgRsp) { reqObj := &proto.HistoryReq{} rspObj := &proto.HistoryRsp{} rsp.Body.Code = constant.OK mapstructure.Decode(req.Body.Msg, reqObj) rspObj.Msgs = []proto.ChatMsg{} p, _ := req.Conn.GetProperty("rid") rid := p.(int) if reqObj.Type == 0 { r := this.worldGroup.History() rspObj.Msgs = r }else if reqObj.Type == 1 { this.unionMutex.RLock() id, ok := this.ridToUnionGroups[rid] if ok { g, ok := this.unionGroups[id] if ok { rspObj.Msgs = g.History() } } this.unionMutex.RUnlock() } rspObj.Type = reqObj.Type rsp.Body.Msg = rspObj } func (this*Chat) join(req *net.WsMsgReq, rsp *net.WsMsgRsp) { reqObj := &proto.JoinReq{} rspObj := &proto.JoinRsp{} rsp.Body.Code = constant.OK rsp.Body.Msg = rspObj rspObj.Type = reqObj.Type mapstructure.Decode(req.Body.Msg, reqObj) p, _ := req.Conn.GetProperty("rid") rid := p.(int) if reqObj.Type == 1 { u := this.worldGroup.GetUser(rid) if u == nil { rsp.Body.Code = constant.InvalidParam return } this.unionMutex.Lock() gId, ok := this.ridToUnionGroups[rid] if ok { if gId != reqObj.Id { //联盟聊天只能有一个,顶掉旧的 if g,ok := this.unionGroups[gId]; ok { g.Exit(rid) } _, ok = this.unionGroups[reqObj.Id] if ok == false { this.unionGroups[reqObj.Id] = logic.NewGroup() } this.ridToUnionGroups[rid] = reqObj.Id this.unionGroups[reqObj.Id].Enter(u) } }else{ //新加入 _, ok = this.unionGroups[reqObj.Id] if ok == false { this.unionGroups[reqObj.Id] = logic.NewGroup() } this.ridToUnionGroups[rid] = reqObj.Id this.unionGroups[reqObj.Id].Enter(u) } this.unionMutex.Unlock() } } func (this*Chat) exit(req *net.WsMsgReq, rsp *net.WsMsgRsp) { reqObj := &proto.ExitReq{} rspObj := &proto.ExitRsp{} rsp.Body.Code = constant.OK rsp.Body.Msg = rspObj rspObj.Type = reqObj.Type mapstructure.Decode(req.Body.Msg, reqObj) p, _ := req.Conn.GetProperty("rid") rid := p.(int) if reqObj.Type == 1 { this.unionMutex.Lock() id, ok := this.ridToUnionGroups[rid] if ok { g, ok := this.unionGroups[id] if ok { g.Exit(rid) } } delete(this.ridToUnionGroups, rid) this.unionMutex.Unlock() } }