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

news2025/4/8 23:04:39

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

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

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

第二个概念是“管理”。我们需要创建一个名为“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
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2329460.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Oracle数据库数据编程SQL<8 文本编辑器Notepad++和UltraEdit(UE)对比>

首先,用户界面方面。Notepad是开源的,界面看起来比较简洁,可能更适合喜欢轻量级工具的用户。而UltraEdit作为商业软件,界面可能更现代化,功能布局更复杂一些。不过,UltraEdit支持更多的主题和自定义选项&am…

Linux驱动开发练习案例

1 开发目标 1.1 架构图 操作系统:基于Linux5.10.10源码和STM32MP157开发板,完成tf-a(FSBL)、u-boot(SSBL)、uImage、dtbs的裁剪; 驱动层:为每个外设配置DTS并且单独封装外设驱动模块。其中电压ADC测试,采用linux内核…

Apache httpclient okhttp(1)

学习链接 Apache httpclient & okhttp(1) Apache httpclient & okhttp(2) httpcomponents-client github apache httpclient文档 apache httpclient文档详细使用 log4j日志官方文档 【Java基础】- HttpURLConnection…

微信小程序—路由

关于 app.json 中的配置 app.json 主要是对整个小程序进行一个全局的配置。 pages:在这个配置项目中,就可以配置小程序里面的页面,小程序默认显示 pages 数组中的第一个页面windows:主要配置和导航栏相关的 当然,在…

人工智能驱动的数据仓库优化:现状、挑战与未来趋势

1. 引言:数据仓库的演进与人工智能驱动优化的兴起 现代数据仓库的复杂性和规模正以前所未有的速度增长,这主要是由于数据量、种类和产生速度的急剧增加所致。传统的数据仓库技术在应对这些现代数据需求方面显得力不从心,这催生了对更先进解决…

LVS高可用负载均衡

一、项目图 二、主机规划 主机系统安装应用网络IPclientredhat 9.5无NAT192.168.72.115/24lvs-masterredhat 9.5ipvsadm,keepalivedNAT192.168.72.116/24 VIP 192.168.72.100/32lvs-backupredhat 9.5ipvsadm,keepalivedNAT192.168.72.117/24 VIP 192.168…

脑影像分析软件推荐 | JuSpace

目录 1. 软件界面 2.工具包功能简介 3.软件安装注意事项 参考文献: Dukart J, Holiga S, Rullmann M, Lanzenberger R, Hawkins PCT, Mehta MA, Hesse S, Barthel H, Sabri O, Jech R, Eickhoff SB. JuSpace: A tool for spatial correlation analyses of magne…

逛好公园的好处

逛公园和软件开发看似是两个不同的活动,但它们之间存在一些有趣的关联和相互促进的关系: 激发创造力:公园中的自然景观、多样的人群以及各种活动能为开发者带来新的灵感和创意。软件开发过程中,从公园中获得的创意可以帮助开发者设…

【网络安全】 防火墙技术

防火墙是网络安全防御的重要组成部分,它的主要任务是阻止或限制不安全的网络通信。在这篇文章中,我们将详细介绍防火墙的工作原理,类型以及如何配置和使用防火墙。我们将尽可能使用简单的语言和实例,以便于初学者理解。 一、什么…

文档的预解析

1. 预解析的核心目标 浏览器在正式解析(Parsing)HTML 前,会启动一个轻量级的 预解析器(Pre-Parser),快速扫描文档内容,实现: 提前发现并加载关键资源(如 CSS、JavaScrip…

记一次表格数据排序优化(一)--排序30000条数据有多卡

目录 需求 第一次尝试 运行环境 思路 存储 排序 触发排序操作 如何实现高效的排序 关键1 关键2 关键3 磨刀不误砍柴工 关键4 代码 效果 卡顿原因分析 原因1 原因2 第二次尝试 需求 1 我的qt程序通过表格显示30000条数据。数据来自udp,udp每隔10秒…

图形渲染中的定点数和浮点数

三种API的NDC区别 NDC全称,Normalized Device Coordinates Metal、Vulkan、OpenGL的区别如下: featureOpenGL NDCMetal NDCVulkan NDC坐标系右手左手右手z值范围[-1,1][0,1][0,1]xy视口范围[-1,1][-1,1][-1,1] GPU渲染的定点数和浮点数 定点数类型&a…

【深度学习】CNN简述

文章目录 一、卷积神经网络(CNN)二、CNN结构特性1. CNN 典型结构2. 局部连接3. 权重共享4.空间或时间上的次采样 三、理解层面 一、卷积神经网络(CNN) 卷积神经网络(Convolutional Neural Network,CNN)是一种用于处理…

强化学习课程:stanford_cs234 学习笔记(3)introduction to RL

文章目录 前言7 markov 实践7.1 markov 过程再叙7.2 markov 奖励过程 MRP(markov reward process)7.3 markov 价值函数与贝尔曼方程7.4 markov 决策过程MDP(markov decision process)的 状态价值函数7.4.1 状态价值函数7.4.2 状态…

紫檀博物馆一游与软件开发

今天去逛了中国紫檀博物馆,里边很多层展品,也有一些清代的古物,檀木,黄花梨木家具和各种摆件,馆主陈丽华女士也是发心复原、保留和弘扬中国的传统文化,和西游记唐僧扮演者迟成瑞先生一家。 每一件展品都精…

RocketMQ初认识

ProducerCustomerNameServer: Broker的注册服务发现中心BrokerServer:主要负责消息的存储、投递和查询以及服务高可用保证 RocketMQ的集群部署: 单个master的分支多个Master 模式:集群中有多个 Master 节点,彼此之间相互独立。生产者可以将消…

Chrome开发者工具实战:调试三剑客

在前端开发的世界里,Chrome开发者工具就是我们的瑞士军刀,它集成了各种强大的功能,帮助我们快速定位和解决代码中的问题。今天,就让我们一起来看看如何使用Chrome开发者工具中的“调试三剑客”:断点调试、调用栈跟踪和…

C++/Qt 模拟sensornetwork的工作

C/Qt 可视化模拟sensornetwork的工作 C/Qt 模拟sensornetwork的工作 C/Qt 可视化模拟sensornetwork的工作内容简介(一) 需求和规格说明(1)问题描述(2)设计目的(3)基本要求&#xff0…

ffmpeg音频分析

对一个16k 单声道音频,生成频谱图 ./ffmpeg -i input.wav -lavfi "showspectrumpics800x400:modecombined:scalelin:gain1.5" spectrum.png

【多线程】CAS机制

目录 一. CAS的概念 二. CAS的原理 三.标准库中的CAS 四. CAS的应用 (1)原子类的使用 (2) 自旋锁的实现 五. CAS的ABA问题 一. CAS的概念 CAS(Compare And Swap)机制是一种无锁的并发控制技术&#…