匹配

匹配.png

//请求匹配

message CM_Match {

int type; //匹配房间类型

String name; //玩家名称

long targetPlayerId; //加入他人比赛,目标玩家id

}

//匹配成功

message L2RM_MatchSucc {

int roomId;

int roomType;

boolean createRoomIfNotExist; //场景中的第一个玩家为true

RoomPlayerEnt ent; //房间服需要的玩家信息

}

//业务服收到此消息创建房间

message R2LM_AddRoom {

int id;

int sign; //房间签名

int type;

Date createTime;

}

//业务服收到此消息,在房间销毁前(R2LM_RemoveRoom),玩家都可以断线重连房间服

message R2LM_AddPlayer {

long playerId;

int roomId;

int roomSign;

int roomType;

int token; //登录令牌,断线重连时下发给客户端

}

//客户端收到此消息后连接房间服

message SM_RoomServerPermission {

String host;

int port;

String token; //本次登录的令牌

}

业务服房间管理

业务服维护了房间服的Room。房间服创建Room,业务服创建对应Room,房间服销毁Room,业务服销毁对应Room。其变化通过处理房间服的R2LM_AddRoom,R2LM_RemoveRoom等消息完成。

在匹配规则中另外维护了MatchRoom。匹配规则认为需要创建一个新的房间时,则马上创建MatchRoom,当一个玩家被匹配到某个MatchRoom中,MatchRoom中立即添加该玩家。新增过程不依赖房间服的消息。

Room的作用是用于统计房间服的信息,玩家的断线重连。MatchRoom用于完成匹配逻辑。两者的作用不同决定生命周期不同,Room的生命周期由房间服决定,MatchRoom在匹配时创建,在人满时销毁,在房间服的房间销毁时也会销毁。

class Room {

int id;

int sign;

RoomType type;

Date createTime;

int playerNum; //玩家数量

int watcherNum; //观战者数量

RoomServer server; //所属房间服

}

class MatchRoom {

int id;

List playerIds;

RoomServer server; //所属房间服

}

进入房间服

进入房间服.png

message CM_EnterRoom {

long playerId;

String token; //登录令牌

}

//业务服收到此消息,将玩家加入房间服玩家集合

message R2LM_PlayerEnterRoom {

long playerId;

int roomId;

int roomType;

int status; //状态 0.游戏 1.观战

}

//场景快照

message SM_SceneSnapshot {

}

离开房间服

离开房间服.png

//业务服收到此消息,将玩家从房间服玩家集合中移除

message R2LM_PlayerLeaveRoom {

long playerId;

int roomId;

String token; //登录令牌相同才能移除玩家

}

玩家结算

玩家结算.png

//结算消息分成两部分,第一部分在房间服计算,比如排行榜

message SM_RoomResult {

根据结算面板确定...

}

//通知客户端断开房间服连接,返回业务服

message SM_DisconnectRoomServer {

连接业务服的信息...

}

//将结算内容发到业务服,由业务服计算奖励等数据

message R2LM_PlayerResult {

}

//业务服收到此消息,清理玩家断线重连的相关信息。

//房间服再次收到R2LM_AddPlayer消息才允许玩家登陆。

message R2LM_RemovePlayer {

long playerId;

String token; //登录令牌相同才能移除玩家

}

房间结算

房间结算.png

//房间结算,包含了所有需要结算的玩家

message R2LM_RoomResult {

}

//业务服收到此消息,清理房间服

message R2LM_RemoveRemove {

long playerId;

String token; //登录令牌相同才能移除玩家

}

房间结算时,所有玩家必须结算。

房间服消息作用

房间服发给业务服的消息主要有6个

R2LM_AddRoom

R2LM_RemoveRoom

R2LM_AddPlayer

R2LM_RemovePlayer

R2LM_PlayerEnterRoom

R2LM_PlayerLeaveRoom

R2LM_AddRoom/R2LM_RemoveRoom用于维护业务服的房间的创建和销毁。

R2LM_AddPlayer/R2LM_RemovePlayer主要用于维护玩家能否断线重连房间服。

R2LM_PlayerEnterRoom/R2LM_PlayerLeaveRoom用于维护哪些玩家在房间服,以及相关状态的修改。

玩家离开房间服的行为会导致房间服发送R2LM_PlayerLeaveRoom给业务服,而玩家完成一局游戏才会导致房间服发送R2LM_RemovePlayer给业务服。

房间服线程模型

每个房间绑定到线程池中的一个线程,房间的所有业务都单线程处理。

房间支持消息队列,可以向其投递各种消息。玩家进入房间,玩家离开房间,玩家结算,房间结算等任务,都在房间线程中处理。

第一个玩家进入房间时,启动房间定时器,并处理房间消息。房间销毁后停止定时器,不再处理房间消息。

class Room {

ConcurrentLinkedQueue taskQueue;

}

问题:

当房间服收到L2RM_MatchSucc时,会创建新玩家,将玩家放入缓存,如果缓存中已存在玩家,则需要销毁已存在的玩家。销毁玩家的任务需要投递到房间线程中执行,可能会发生执行顺序错误问题。

代码顺序

Player oldPlayer = playerMap.put(playerId, player);

if(oldPlayer != null && oldPlayer.getScene() != null) {

oldPlayer.getScene().removePlayerAsync(oldPlayer);

...

}

send R2LM_AddPlayer message

执行顺序

thread 1: send R2LM_AddPlayer message

thread 2: send R2LM_RemovePlayer message //removePlayer是异步执行

解决方法:

并不纠正执行顺序,而是在R2LM_AddPlayer和R2LM_RemovePlayer消息中增加token字段。player和oldPlayer的玩家id相同,但是登录token不同。业务服通过对比token,可以知道本次R2LM_RemovePlayer是否有效,如果在R2LM_RemovePlayer之前已经收到了包含新的token的R2LM_AddPlayer消息,则忽略R2LM_RemovePlayer消息的处理。

由于执行顺序依然是异步的,在同一时间,房间服可能同时存在相同id的两个Player。所以除了在全局维护Player集合,每个房间还维护了自己的Player集合,房间中需要获取玩家通过内部的Player集合获取,不要通过全局的Player集合获取,因为获取到的可能是新的Player。

异常情况

L2RM_MatchSucc问题

1.玩家匹配到一个已经销毁的房间

解决方案

1.尽可能在房间销毁前停止匹配,比如持续12分钟的房间,可以在最后30s停止匹配。

2.提示错误。玩家手动重新匹配。

CM_EnterRoom问题

1.玩家不存在,或登录令牌错误

解决方案:报错。

2.房间不存在

解决方案:报错,重连业务服。

3.投递消息时房间存在,(在房间线程)执行消息时房间不存在

解决方案:报错,重连业务服。

只匹配,但不登录房间服的玩家如何清理

定时30分钟检查,Player关联的房间销毁则清理Player。

没有启动定时器的房间如何销毁

定时30分钟检查,30分钟都没有玩家进入则销毁房间。

java游戏房间匹配_游戏匹配和结算实现相关推荐

  1. java正则任意字符_正则表达式匹配任意字符(包括换行符)的写法

    今天在Java中想使用正则表达式来获取一段文本中的任意字符.于是很随意得就写出如下匹配规则: (.*) 结果运行之后才发现,无法获得换行之后的文本.于是查了一下手册,才发现正则表达式中,". ...

  2. python贪婪匹配和非贪婪匹配_贪婪匹配和非贪婪匹配

    1.什么是正则表达式的贪婪与非贪婪匹配 如:String str="abcaxc"; Patter p="ab*c"; 贪婪匹配:正则表达式一般趋向于最大长度匹 ...

  3. 买游戏来运营_游戏化思维帮你玩转社群运营

    传统的社群运营主要就是通过活动来进行运营的.但是如果只是单纯的通过各种活动,总是会造成只有过程,没有结果的情况,无法形成完整的运营体系. 今天,9妹跟大家来分享一下,怎么使用游戏化的思维,来更好的操作 ...

  4. 游戏开发论坛_游戏开发制作全流程介绍

    近日,根据<2020年1-6月中国游戏产业报告>显示,我国上半年网络游戏用户规模达到6.6亿人,游戏市场实际营收1394.93亿元,同比增长了22.34%,其中手游占比75.04%,达10 ...

  5. 古剑奇谭3服务器不稳定,古剑奇谭3设置游戏默认存档服务器方法_古剑奇谭3怎么修改游戏启动选项_游戏堡...

    < 修改启动选项: 一些玩家可能知道,Steam游戏可以自行设置游戏启动选项,已达到修改游戏设置.调整画面等目的. 本方法既通过设置游戏启动选项,来修改游戏默认连接服务器. 步骤: 在 Stea ...

  6. sword弹窗_刀剑神域夺命凶弹游戏问题解决方案汇总_刀剑神域夺命凶弹游戏出错怎么办_游戏堡...

    Hello,大家好!我是你们的老朋友Smile,<刀剑神域:夺命凶弹>已经在Steam平台发售一段日子了,但是很多玩家纷纷反映经常出现游戏错误,导致自己无法愉快的玩耍,那么这些问题如何才能 ...

  7. 3d游戏开发相关概念_游戏开发概念

    3d游戏开发相关概念 Game development is one of the most exciting fields of computer science and a major part ...

  8. java游戏房间匹配_游戏匹配实现

    设计思路 客户端向服务器发送匹配请求,服务端接收后将客户端Session放入匹配队列中,匹配完成时通知用户. 使用观察者设计模式可以实现这个功能. 代码 观察者代码: Java util 包拥有Obs ...

  9. 如何使用java编程算概率_游戏中概率的编程实现(转之别人)最简单的

    概率 听起来很玄 比如洗法宝 太一石 有一段说明 有一定概率 能改变法宝的技能阶数 那么 概率在编程中如何实现的呢 个人在大学里有学c++ java 以及vb 现以vb实现概率来说明 首先,要先说清楚 ...

最新文章

  1. iostext添加点击事件_iOS给UILabel添加点击事件
  2. 应用深度学习EEGNet来处理脑电信号
  3. java实现两个整数相除保留一位小数
  4. 成功解决启动SQLServer失败,根据错误信息判断错误故障
  5. 科大星云诗社动态20210501
  6. iOS开发(1)写在前面的话
  7. java 状态机_基于 RAFT 一致性算法的 Java 实现 SOFAJRaft
  8. crawler4j mysql_Nutch、heritrix、crawler4j优缺点
  9. JDK 14:CMS GC是OBE
  10. C语言 | typedef
  11. mysql免安装5.7.17_mysql免安装5.7.17数据库配置
  12. 实践单元测试(2) - 大话单元测试
  13. 实现Canvas2D绘图 使元素绕中心居中旋转
  14. H∞鲁棒控制问题的一般性描述
  15. python-常见的语法错误
  16. 传奇客户端小地图上的文字描述修改方法
  17. 微信公众号无法长按发送图片,长安反应慢
  18. 低成本、低功耗、小体积433MHz数字量无线控制器
  19. python数据分析师面试题选
  20. 计算机控制器cu的功能是,控制器cu的功能是

热门文章

  1. torch基本功能介绍
  2. 手机变php,poscms手机网站切换
  3. CF446D. DZY Loves Games
  4. 摩托罗拉Android系统,摩托罗拉官方Android 4.0系统正式到来
  5. 采集人物经历来佐证子平术
  6. 刚装修的房子多久能住?集成墙面真的好吗?
  7. 微信小程序开发手账从入门到部署【持续更新】
  8. 2022年安全员-C证及安全员-C证作业考试题库
  9. 安捷伦万用表--Agilent34401A数字万用表串口发送数据只上位机使用说明
  10. 深入理解Java虚拟机到底是什么