当前位置: 首页 > wzjs >正文

无锡新区做网站公司18款禁用软件黄app免费

无锡新区做网站公司,18款禁用软件黄app免费,建立网站内容,东营网站设计多少钱1.背景: 对于一款网络游戏来说,聊天是基础的交互功能。常见了聊天频道有私聊,世界,公会,队伍,甚至所有服都连接起来的全服聊天。 本文主要目的是,设计一套简单通用的聊天框架。 基本思想&…

1.背景:

对于一款网络游戏来说,聊天是基础的交互功能。常见了聊天频道有私聊,世界,公会,队伍,甚至所有服都连接起来的全服聊天。

本文主要目的是,设计一套简单通用的聊天框架。

基本思想:

使用统一的API处理所有的聊天频道。

并非所有聊天记录都需要存放到数据库,例如世界聊天,由于交互时效问题,重启丢失消息也可以接受。

2.聊天基础

基本流程是:

  1. 当玩家发送聊天的请求消息,先判断指定的频道能否发送,例如私聊的时候我方是否是对方的黑名单;
  2. 验证通过后,将消息保存到内存或者数据库,直接返回发送成功的返回值给客户端;
  3. 服务器收集指定频道的消息接收者列表,异步推送给所有玩家。
  4. 当玩家登录的时候,需要统一收集所有频道的离线消息,一次性推给客户端。

对一些基础的操作作抽象,如下:

/*** 聊天频道处理器*/
public interface ChatChannelHandler {/*** 发送消息之前的检查,例如等级要求,禁言等* @return 错误码*/int checkCanSend(PlayerEnt player, String target, String content);/*** 保存到内存或者数据库* @param message*/void cacheOrSave(ChatMessage message);/*** 角色登录的消息收集* @param player* @return*/List<ChatMessage> collectMessageOnLogin(PlayerEnt player);/*** 收到消息后,进行广播** @param message*/default void broadcast(ChatMessage message) {// 过滤不在线的玩家Collection<String> receivers = receivers(message).stream().filter(p -> SpringContext.getSessionManager().getSessionBy(p) != null).collect(Collectors.toSet());if (CollectionUtils.isEmpty(receivers)) {return;}PushChatNewMessage pushChatNewMessage = new PushChatNewMessage();pushChatNewMessage.setMessages(Collections.singletonList(message));for (String receiver : receivers) {MessageUtil.pushMessage(receiver, pushChatNewMessage);}}/*** 消息接收者列表, 可以不考虑玩家是否在线,底层会自动过滤** @param message* @return*/Collection<String> receivers(ChatMessage message);/*** 频道类型* @return*/byte channelType();}

3.私聊频道

对于私聊,有一个比较有争议的问题是,聊天记录只存一份,还是发送方/接收方独立存一份拷贝这个问题的本质是聊天软件对消息内容的存储方式,一种是扩散读,也就是消息只存一份;另外一种是扩散写,每个接收者独立存储一份副本。

对于游戏的聊天系统,远没有聊天软件那般复杂。

如果聊天记录不允许手动删除,而是由系统过期自动清除。考虑只存一份即可。类似下面的表定义。

这种方式,数据不会冗余,但有一个问题,如果程序使用了缓存,就稍微有点麻烦。当发送方或者接收方独立上线的时候,需要先查询发送方id或者接收方id是当前玩家的所有聊天记录的id,再通过这个id去查询缓存。

当然,如果聊天记录支持手动删除,为了不影响对方的聊天记录,只能双方各存一份拷贝了。 

比较直接的是,玩家身上存一个map,记录该玩家发送的,以及接收的所有消息记录。示例如下:

    /*** 私人聊天记录* key: 对方id* value: 消息列表*/private Map<String, List<ChatMessage>> privateChat = new HashMap<>();public void addNewMessage(String targetId, ChatMessage message) {privateChat.putIfAbsent(targetId, new LinkedList<>());List<ChatMessage> messages = privateChat.get(targetId);if (messages.size() >= 50) {messages.remove(0);}messages.add(message);}

 这种方式也有一个问题,就是如果发送消息的目标玩家是离线状态,为了把新消息发送给接收方,业务需要把离线用户从数据库捞取上来,有造成离线玩家缓存内存过大的风险。针对这种情况 ,可以把聊天记录作为一个单独的表设计,表结构只需要一个玩家id,以及一个保存聊天记录json数据的字段,以此减少程序内存。

本文为了方便,将聊天记录作为玩家表的一个字段,并非推荐方式。

代码如下:

/*** 私人聊天频道*/
public class PrivateChannelHandler implements ChatChannelHandler {@Overridepublic int checkCanSend(PlayerEnt player, String target, String content) {// 对方是否我的好友return 0;}@Overridepublic void cacheOrSave(ChatMessage message) {// 发送方,接收方,各存储一份拷贝PlayerEnt from = GameContext.playerService.getPlayer(message.getSenderId());from.getExtendBox().addNewMessage(message.getReceiverId(), message);GameContext.playerService.savePlayer(from);// 把消息存储到接收者的私聊列表中,如果离线,也要捞起来PlayerEnt target = GameContext.playerService.getPlayer(message.getReceiverId());// 丢到对方线程跑ThreadSafeUtil.addPlayerTask(target, () -> target.getExtendBox().addNewMessage(message.getSenderId(), message));}@Overridepublic List<ChatMessage> collectMessageOnLogin(PlayerEnt player) {return player.getExtendBox().getPrivateChat().values().stream().flatMap(List::stream).collect(Collectors.toList());}@Overridepublic Collection<String> receivers(ChatMessage message) {List<String> receivers = new LinkedList<>();// 发送方+接收方receivers.add(message.getReceiverId());receivers.add(message.getReceiverId());return receivers;}@Overridepublic byte channelType() {return Channels.PERSON;}
}

有一点需要注意的是,在投放接收者消息的时候,需要考虑线程安全问题。

4.世界频道

世界频道,即为单服的全服聊天。可能有些游戏,会定义为所有游戏服节点的全服聊天,这里只是概念的差异。

/*** 世界聊天频道*/
public class WorldChannelHandler implements ChatChannelHandler {// 世界聊天消息缓存// 最大100条消息,30分钟过期private LazyCacheMap<Long, ChatMessage> worldChatCache = new LazyCacheMap<>(100, 30 * TimeUtil.MILLIS_PER_MINUTE);@Overridepublic int checkCanSend(PlayerEnt player, String target, String content) {return 0;}@Overridepublic void cacheOrSave(ChatMessage message) {//世界聊天消息不需要存储到数据库, 只存储在内存中worldChatCache.put(message.getId(), message);}@Overridepublic List<ChatMessage> collectMessageOnLogin(PlayerEnt player) {return worldChatCache.getAllRecords();}@Overridepublic Collection<String> receivers(ChatMessage message) {return GameContext.playerService.getOnlinePlayers().keySet();}@Overridepublic byte channelType() {return Channels.WORLD;}
}

5.业务代码

处理聊天消息发送

/*** 消息发送* @param player 发送者* @param channel* @param content 聊天内容* @param target 发送目标,若为私聊频道,代表接收者id。若为世界频道,该参数为空。*/
public int sendMessage(PlayerEnt player, byte channel, String content, String target) {ChatChannelHandler handler = handlers.get(channel);AssertPlus.isFalse(handler == null);int errCode = handler.checkCanSend(player, target, content);if (errCode > 0) {return errCode;}// 这里要用异步广播ChatMessage message = new ChatMessage();message.setChannel(channel);message.setSenderId(player.getId());message.setReceiverId(target);message.setContent(content);handler.cacheOrSave(message);handler.broadcast(message);return 0;
}

处理登录下发离线消息

/*** 登录的时候,收集所有频道的离线聊天,统一下发* @param player*/
public void notifyNewMessageOnLogin(PlayerEnt player) {PushChatNewMessage push = new PushChatNewMessage();List<ChatMessage> messages = new LinkedList<>();handlers.values().forEach(handler->{messages.addAll(handler.collectMessageOnLogin(player));});push.setMessages(messages);MessageUtil.pushMessage(player, push);
}

http://www.dtcms.com/wzjs/327496.html

相关文章:

  • 网站建设制作设计营销公司杭州google play官网入口
  • 字体网站奉化seo页面优化外包
  • 个人做电商网站icp百度注册新账号
  • 工信部网站域名备案查询开网站需要什么流程
  • 做网站去哪个平台软文营销的写作技巧有哪些
  • 承接网站怎么做产品推广方案范例
  • 在线购物网站建设流程图网站优化推广方法
  • 网站pc端建设漯河网站推广公司
  • 移动互联网开发的心得体会300字网站seo关键词排名
  • 深圳做网站建设的哪家效果好又便宜seo专业术语
  • 公司做网站费用和人员配备浙江seo技术培训
  • 做网站名 注册那个商标营销手机系统安装
  • 网站建设与制作与维护最新新闻热点事件摘抄
  • wordpress后台怎么进的杭州哪家seo公司好
  • 马来西亚做网站html底部友情链接代码
  • 网站内容建设整改工作免费的自助建站
  • 网页制作下载链接泰安优化关键词排名哪家合适
  • 北滘网站建设软文推广渠道
  • 校园微网站建设方案ppt模板中国站长之家官网
  • 网站班级文化建设视频互联网广告平台代理
  • 公司外宣网站口碑营销案例简短
  • 哪些网站是用java做的在线外链
  • 内部劵淘网站怎么做苏州网站建设方案
  • 宣武富阳网站建设seo顾问阿亮博客
  • 呼伦贝尔网站设计郑州seo软件
  • 渭南网站建设公司电话网站排名优化公司
  • 用什么手机软件做网站数据交换平台
  • 怎样介绍自己做的网站新媒体培训
  • 网站建设公司排名百度seo是啥意思
  • 北海建设厅网站疫情最新资讯