go游戏后端开发20:房间消息推送处理

创建房间逻辑前的概念梳理及代码实现

在编写创建房间的逻辑之前,我们需要先创建几个关键概念。

第一个概念是"联盟"。联盟可以理解为一个组织,它持有多个房间。一个联盟下可能挂载多个房间,这是我们的第一个概念。

第二个概念是"管理"。我们需要创建一个名为"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),
	}
}
创建房间逻辑的实现

在实现创建房间逻辑之前,我们需要完成以下步骤:

  1. 接收参数:从请求中解析出必要的参数,如联盟ID、游戏规则ID等。

  2. 查询用户信息:根据用户ID查询用户信息,确保用户存在。

  3. 创建房间:根据解析出的参数和用户信息,创建房间并生成房间号。

  4. 推送房间号和游戏类型:将房间号和游戏类型推送给客户端,告知客户端可以进入房间。

以下是创建房间逻辑的代码实现:

复制代码
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
}

通过上述代码实现,我们完成了创建房间逻辑的开发。主要步骤包括接收参数、查询用户信息、创建房间、生成房间号以及将房间号和游戏类型推送给客户端。

相关推荐
海兰7 小时前
【文字三国志:第一篇】天命重构,大语言模型(LLM)动态生成文言风格的叙事文本的文字游戏
人工智能·游戏·语言模型
isyangli_blog8 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008118 小时前
FastAPI APIRouter
开发语言·python
Benszen8 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆8 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木8 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
杨充9 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~9 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
basketball6169 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
春生野草9 小时前
反射、Tomcat执行
java·开发语言