创建房间逻辑前的概念梳理及代码实现
在编写创建房间的逻辑之前,我们需要先创建几个关键概念。
第一个概念是“联盟”。联盟可以理解为一个组织,它持有多个房间。一个联盟下可能挂载多个房间,这是我们的第一个概念。
第二个概念是“管理”。我们需要创建一个名为“Union”的管理类,用来管理联盟。联盟本身也有多种类型,因此需要一个管理机制来对它们进行统一管理。
第三个概念是“房间”。房间关联一个具体的游戏。在这个基础上,我们可以创建一个接口,通过这个接口实现多种不同的游戏。这就是这三个概念的基本架构。
在创建这些概念时,我们可以将它们分别放在不同的目录中。例如,联盟相关的概念可以放在一个名为“union”的目录下;管理类可以放在“manage”目录下;房间相关的概念则放在“room”目录下。
联盟(Union)的实现
在联盟中,我们以unionID
为键,以联盟的代理为值,构建一个联盟信息的映射。一个联盟下可能有多个房间,每个房间有一个房间号作为标识。以下是联盟管理类UnionManager
的实现:
package logic
import (
"sync"
"time"
"math/rand"
"fmt"
"game/component/room"
"core/services"
"framework/msError"
"framework/remote"
"core/models/entity"
"common/biz"
"game/component/proto"
)
type UnionManager struct {
sync.RWMutex
unionList map[int64]*Union
}
func NewUnionManager() *UnionManager {
return &UnionManager{
unionList: make(map[int64]*Union),
}
}
func (u *UnionManager) GetUnion(unionId int64) *Union {
u.Lock()
defer u.Unlock()
union, ok := u.unionList[unionId]
if ok {
return union
}
union = NewUnion(unionId, u)
union.Init()
u.unionList[unionId] = union
return union
}
func (u *UnionManager) CreateNewRoomID() string {
roomId := u.genRoomId()
for _, v := range u.unionList {
if v.RoomList[roomId] != nil {
return u.CreateNewRoomID()
}
}
return roomId
}
func (u *UnionManager) genRoomId() string {
rand.New(rand.NewSource(time.Now().UnixNano()))
one := rand.Int63n(999999) + 100000
roomId := fmt.Sprintf("%d", one)
return roomId
}
func (u *UnionManager) GetRoomById(roomId string) *room.Room {
for _, v := range u.unionList {
rm, ok := v.RoomList[roomId]
if ok {
return rm
}
}
return nil
}
func (u *UnionManager) JoinRoom(session *remote.Session, roomID string, userData *entity.User) *msError.Error {
union := u.getUnionByRoomId(roomID)
if union == nil {
return biz.RoomNotExist
}
return union.JoinRoom(session, roomID, userData)
}
func (u *UnionManager) getUnionByRoomId(roomID string) *Union {
for _, v := range u.unionList {
_, ok := v.RoomList[roomID]
if ok {
return v
}
}
return nil
}
联盟(Union)的具体实现
type Union struct {
Id int64
m *UnionManager
RoomList map[string]*room.Room
activeTime int64
}
func (u *Union) Init() {
// 初始化操作
}
func (u *Union) CloseRoom(roomId string) {
r, ok := u.RoomList[roomId]
if ok {
r.Close()
delete(u.RoomList, roomId)
}
}
func (u *Union) CreateRoom(service *services.UserInfoService, session *remote.Session, gameRuleId string, unionID int64, gameRule proto.GameRule, userData *entity.User) *msError.Error {
roomId := u.m.CreateNewRoomID()
creator := proto.BuildRoomUserInfo(userData)
if unionID == 1 {
creator.CreatorType = proto.UserCreate
} else {
creator.CreatorType = proto.UnionCreate
creator.UnionID = unionID
}
newRoom := room.NewRoom(service, roomId, creator, gameRule)
u.RoomList[roomId] = newRoom
return newRoom.UserEntryRoom(session, userData)
}
func (u *Union) JoinRoom(session *remote.Session, roomID string, userData *entity.User) *msError.Error {
u.activeTime = time.Now().UnixMilli()
r, ok := u.RoomList[roomID]
if !ok {
return biz.Fail
}
return r.UserEntryRoom(session, userData)
}
func NewUnion(id int64, m *UnionManager) *Union {
return &Union{
Id: id,
m: m,
RoomList: make(map[string]*room.Room),
}
}
创建房间逻辑的实现
在实现创建房间逻辑之前,我们需要完成以下步骤:
接收参数:从请求中解析出必要的参数,如联盟ID、游戏规则ID等。
查询用户信息:根据用户ID查询用户信息,确保用户存在。
创建房间:根据解析出的参数和用户信息,创建房间并生成房间号。
推送房间号和游戏类型:将房间号和游戏类型推送给客户端,告知客户端可以进入房间。
以下是创建房间逻辑的代码实现:
package handler
import (
"common/biz"
"core/models/entity"
"core/services"
"framework/msError"
"framework/remote"
"game/component/proto"
"game/logic"
"time"
)
func CreateRoomHandler(session *remote.Session, request *proto.CreateRoomRequest) *msError.Error {
// 1. 接收参数
unionID := request.UnionID
gameRuleID := request.GameRuleID
userID := session.GetUid()
// 2. 查询用户信息
userService := services.GetUserInfoService()
userData, err := userService.FindUserByUid(userID)
if err != nil || userData == nil {
return msError.NewError(msError.UserNotFound, "User not found")
}
// 3. 获取联盟管理器
unionManager := logic.NewUnionManager()
// 4. 获取联盟
union := unionManager.GetUnion(unionID)
// 5. 创建房间
gameRule := proto.GameRule{
GameType: request.GameType,
// 其他游戏规则参数
}
err = union.CreateRoom(services.GetUserInfoService(), session, gameRuleID, unionID, gameRule, userData)
if err != nil {
return err
}
// 6. 推送房间号和游戏类型
roomId := union.CreateNewRoomID()
pushMsg := &proto.CreateRoomResponse{
RoomID: roomId,
GameType: request.GameType,
}
session.Push([]string{userID}, pushMsg, "CreateRoomResponse")
return nil
}
通过上述代码实现,我们完成了创建房间逻辑的开发。主要步骤包括接收参数、查询用户信息、创建房间、生成房间号以及将房间号和游戏类型推送给客户端。