first commit
This commit is contained in:
204
server/chatserver/controller/chat.go
Normal file
204
server/chatserver/controller/chat.go
Normal file
@@ -0,0 +1,204 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
20
server/chatserver/init.go
Normal file
20
server/chatserver/init.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package chatserver
|
||||
|
||||
import (
|
||||
"slgserver/db"
|
||||
"slgserver/net"
|
||||
"slgserver/server/chatserver/controller"
|
||||
)
|
||||
|
||||
var MyRouter = &net.Router{}
|
||||
|
||||
func Init() {
|
||||
db.TestDB()
|
||||
|
||||
//全部初始化完才注册路由,防止服务器还没启动就绪收到请求
|
||||
initRouter()
|
||||
}
|
||||
|
||||
func initRouter() {
|
||||
controller.DefaultChat.InitRouter(MyRouter)
|
||||
}
|
||||
22
server/chatserver/logic/entity.go
Normal file
22
server/chatserver/logic/entity.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package logic
|
||||
|
||||
import "time"
|
||||
|
||||
type User struct {
|
||||
rid int
|
||||
nickName string
|
||||
}
|
||||
|
||||
func NewUser(rid int, nickName string) *User {
|
||||
return &User{
|
||||
rid: rid,
|
||||
nickName: nickName,
|
||||
}
|
||||
}
|
||||
|
||||
type Msg struct {
|
||||
RId int `json:"rid"`
|
||||
NickName string `json:"nickName"`
|
||||
Msg string `json:"msg"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
79
server/chatserver/logic/group.go
Normal file
79
server/chatserver/logic/group.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"slgserver/net"
|
||||
"slgserver/server/chatserver/proto"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Group struct {
|
||||
userMutex sync.RWMutex
|
||||
msgMutex sync.RWMutex
|
||||
users map[int]*User
|
||||
msgs ItemQueue
|
||||
}
|
||||
|
||||
func NewGroup() *Group {
|
||||
return &Group{users: map[int]*User{}}
|
||||
}
|
||||
|
||||
func (this*Group) Enter(u *User) {
|
||||
this.userMutex.Lock()
|
||||
defer this.userMutex.Unlock()
|
||||
this.users[u.rid] = u
|
||||
}
|
||||
|
||||
func (this*Group) Exit(rid int) {
|
||||
this.userMutex.Lock()
|
||||
defer this.userMutex.Unlock()
|
||||
delete(this.users, rid)
|
||||
}
|
||||
|
||||
func (this*Group) GetUser(rid int) *User {
|
||||
this.userMutex.Lock()
|
||||
defer this.userMutex.Unlock()
|
||||
return this.users[rid]
|
||||
}
|
||||
|
||||
func (this*Group) PutMsg(text string, rid int, t int8) *proto.ChatMsg {
|
||||
|
||||
this.userMutex.RLock()
|
||||
u, ok := this.users[rid]
|
||||
this.userMutex.RUnlock()
|
||||
if ok == false{
|
||||
return nil
|
||||
}
|
||||
|
||||
msg := &Msg{Msg: text, RId: rid, Time: time.Now(), NickName: u.nickName}
|
||||
this.msgMutex.Lock()
|
||||
size := this.msgs.Size()
|
||||
if size > 100 {
|
||||
this.msgs.Dequeue()
|
||||
}
|
||||
this.msgs.Enqueue(msg)
|
||||
this.msgMutex.Unlock()
|
||||
|
||||
//广播
|
||||
this.userMutex.RLock()
|
||||
c := &proto.ChatMsg{RId: msg.RId, NickName: msg.NickName, Time: msg.Time.Unix(), Msg: msg.Msg, Type: t}
|
||||
for _, user := range this.users {
|
||||
net.ConnMgr.PushByRoleId(user.rid, "chat.push", c)
|
||||
}
|
||||
this.userMutex.RUnlock()
|
||||
return c
|
||||
}
|
||||
|
||||
func (this*Group) History() []proto.ChatMsg {
|
||||
r := make([]proto.ChatMsg, 0)
|
||||
this.msgMutex.RLock()
|
||||
items := this.msgs.items
|
||||
for _, item := range items {
|
||||
msg := item.(*Msg)
|
||||
c := proto.ChatMsg{RId: msg.RId, NickName: msg.NickName, Time: msg.Time.Unix(), Msg: msg.Msg}
|
||||
r = append(r, c)
|
||||
}
|
||||
this.msgMutex.RUnlock()
|
||||
|
||||
return r
|
||||
}
|
||||
45
server/chatserver/logic/queue.go
Normal file
45
server/chatserver/logic/queue.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package logic
|
||||
|
||||
type Item interface {
|
||||
}
|
||||
|
||||
// Item the type of the queue
|
||||
type ItemQueue struct {
|
||||
items []Item
|
||||
}
|
||||
|
||||
type ItemQueuer interface {
|
||||
New() ItemQueue
|
||||
Enqueue(t Item)
|
||||
Dequeue() *Item
|
||||
IsEmpty() bool
|
||||
Size() int
|
||||
}
|
||||
|
||||
// New creates a new ItemQueue
|
||||
func (s *ItemQueue) New() *ItemQueue {
|
||||
s.items = []Item{}
|
||||
return s
|
||||
}
|
||||
|
||||
// Enqueue adds an Item to the end of the queue
|
||||
func (s *ItemQueue) Enqueue(t Item) {
|
||||
s.items = append(s.items, t)
|
||||
}
|
||||
|
||||
// dequeue
|
||||
func (s *ItemQueue) Dequeue() *Item {
|
||||
item := s.items[0] // 先进先出
|
||||
s.items = s.items[1:len(s.items)]
|
||||
|
||||
return &item
|
||||
}
|
||||
|
||||
func (s *ItemQueue) IsEmpty() bool {
|
||||
return len(s.items) == 0
|
||||
}
|
||||
|
||||
// Size returns the number of Items in the queue
|
||||
func (s *ItemQueue) Size() int {
|
||||
return len(s.items)
|
||||
}
|
||||
64
server/chatserver/proto/chat.go
Normal file
64
server/chatserver/proto/chat.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package proto
|
||||
|
||||
type LoginReq struct {
|
||||
RId int `json:"rid"`
|
||||
NickName string `json:"nickName"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type LoginRsp struct {
|
||||
RId int `json:"rid"`
|
||||
NickName string `json:"nickName"`
|
||||
}
|
||||
|
||||
type LogoutReq struct {
|
||||
RId int `json:"RId"`
|
||||
}
|
||||
|
||||
type LogoutRsp struct {
|
||||
RId int `json:"RId"`
|
||||
}
|
||||
|
||||
type ChatReq struct {
|
||||
Type int8 `json:"type"` //0世界聊天、1联盟聊天
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
|
||||
type ChatMsg struct {
|
||||
RId int `json:"rid"`
|
||||
NickName string `json:"nickName"`
|
||||
Type int8 `json:"type"` //0世界聊天、1联盟聊天
|
||||
Msg string `json:"msg"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
|
||||
type HistoryReq struct {
|
||||
Type int8 `json:"type"` //0世界聊天、1联盟聊天
|
||||
}
|
||||
|
||||
type HistoryRsp struct {
|
||||
Type int8 `json:"type"` //0世界聊天、1联盟聊天
|
||||
Msgs []ChatMsg `json:"msgs"`
|
||||
}
|
||||
|
||||
type JoinReq struct {
|
||||
Type int8 `json:"type"` //0世界聊天、1联盟聊天
|
||||
Id int `json:"id"`
|
||||
}
|
||||
|
||||
type JoinRsp struct {
|
||||
Type int8 `json:"type"` //0世界聊天、1联盟聊天
|
||||
Id int `json:"id"`
|
||||
}
|
||||
|
||||
type ExitReq struct {
|
||||
Type int8 `json:"type"` //0世界聊天、1联盟聊天
|
||||
Id int `json:"id"`
|
||||
}
|
||||
|
||||
type ExitRsp struct {
|
||||
Type int8 `json:"type"` //0世界聊天、1联盟聊天
|
||||
Id int `json:"id"`
|
||||
}
|
||||
Reference in New Issue
Block a user