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

【redis的使用、账号流程、游戏服Handler的反射调用】1.自增id 2.全局用户名这样子名字唯一 3.

一、web服

1)账号注册 // 用于唯一命名服务

com.xinyue.game.center.business.account.logic.AccountRegisterService#accountRegister

 public void accountRegister(AccountEntity account) {
        accountManager.checkUsername(account.getUsername());
        accountManager.checkPassword(account.getPassword());
        checkUsernameHaveRegister(account.getUsername());

        // 注册的用户名,立马用redis保存下
        boolean saveResult = accountRedisManager.saveUsername(account.getUsername());
        if (saveResult) {
            AccountEntity saveAccount = accountDao.save(account);
            account.setId(saveAccount.getId());
            logger.info("用户注册成功,username:{}", account.getUsername());
        } else {
            throw ServerErrorCode.ACCOUNT_1005.exception();
        }
    }

唯一性实现

 public boolean saveUsername(String username) {
        String value = String.valueOf(System.currentTimeMillis());
        return redisTemplate.opsForValue().setIfAbsent(username, value, Duration.ofHours(USERNAME_EXPIRE_HOURS));
    }

经过注册后,进行登录

2)角色注册 / redis自增

com.xinyue.game.center.business.role.RoleService#createRole

    public CreateRoleResponse createRole(CreateRoleRequest createRoleParam) throws Exception {
        AccountEntity accountEntity = accountService.getAndCheckAccount(createRoleParam.getUserId());
        createRoleManager.checkNicknameSensitive(createRoleParam.getNickname());
        createRoleManager.checkRoleExist(accountEntity, createRoleParam.getZoneId());
        // 创建角色,这一步是会使用redis的自增
        PlayerEntity roleEntity = createRoleManager.createRole(createRoleParam);
        ZoneRoleEntity zoneRoleEntity = createRoleManager.getZoneRole(roleEntity);
        accountEntity.getSectionPlayerMap().put(createRoleParam.getZoneId(), zoneRoleEntity);
        accountService.updateAccount(accountEntity);
        CreateRoleResponse createRoleResponse = new CreateRoleResponse();
        createRoleResponse.setPlayerId(zoneRoleEntity.getPlayerId());
        createRoleResponse.setNickname(roleEntity.getNickname());
        createRoleResponse.setCreateTime(roleEntity.getCreateTime());
        createRoleResponse.setLastLoginTime(roleEntity.getCreateTime());
        String token = this.createToken(roleEntity);
        createRoleResponse.setToken(token);
        return createRoleResponse;
    }

自增实现

  public String generateRoleId(String zoneId) {
        String key = getKey(zoneId);
        long roleId = redisTemplate.opsForValue().increment(key);
        return zoneId + "_" + roleId;
    }

二、游戏服

1.请求进入游戏 // 携带userId 和 playerId和token

com.xinyue.game.server.logic.player.PlayerHandler#enterGame

   @GameMapping(EnterGameRequest.class)
    public void enterGame(GameChannelContext ctx, EnterGameRequest request) {
        String userId = request.getUserId();
        userService.checkUserId(userId);
        userService.checkToken(userId, request.getToken());
        logger.debug("用户认证成功,userId: {},token:{}", userId, request.getToken());
        this.bindChannel(ctx.getNettyCtx(), request.getPlayerId());
        gameAsyncTaskService.execute(request.getPlayerId(), "获取玩家信息", () -> {
            PlayerEntity playerEntity = playerCacheService.getPlayerOrLoading(request.getPlayerId());
            if (playerEntity == null) {
                ctx.writeAndFlush(EnumGameError.ROLE_NOT_EXIST);
            } else {
                EnterGameResponse response = new EnterGameResponse();
                response.setRole(playerEntity);
                ctx.writeAndFlush(response);
            }
        });
    }

可见,核心是GameChannelContext!!!

这个上下文是如何构建的呢?

com.xinyue.server.framework.handler.GameRequestDispatcherHandler#channelRead

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof GameMessagePackage) {
            try {
                GameMessagePackage request = (GameMessagePackage) msg;
                IGameMessage gameMessage = request.getBody();
                GameMessageHeader header = request.getHeader();

                // 重点就是这一步了
                GameChannelContext gtx = new GameChannelContext(ctx, header);
                IGameMessage requestMessage = gameMessage;
                int messageId = header.getLogicMessageId();
                int messageType = GameMessageType.REQUEST.getType();
                MessageClassKey classKey = new MessageClassKey(messageId, messageType);
                GameHandlerMappingManager gameHandlerMappingManager = GameHandlerMappingManager.getInstance();

                // 进行反射调用。 这一步的消息其实可以包装到上下文中。
                gameHandlerMappingManager.callMethod(gtx, classKey, requestMessage);
            } catch (Throwable e) {
                logger.error("处理客户端请求异常", e);
            }
        } else {
            logger.warn("收到非游戏对象请求数据:{}", msg.getClass().getName());
            ctx.fireChannelRead(msg);
        }
    }


http://www.kler.cn/a/444177.html

相关文章:

  • Android详解——ConstraintLayout约束布局
  • 【STM32 Modbus编程】-作为主设备写入多个线圈和寄存器
  • 睡岗和玩手机数据集,4653张原始图,支持YOLO,VOC XML,COCO JSON格式的标注
  • 记录一下自己对网络安全法的笔记
  • Electron-Vue 开发下 dev/prod/webpack server各种路径设置汇总
  • 《类和对象:基础原理全解析(上篇)》
  • lshw学习——简单介绍
  • Java字符串的|分隔符转List实现方案
  • LLM大语言模型私有化部署-使用Dify与Qwen2.5打造专属知识库
  • Linux学习——9_Ubuntu Linux操作系统
  • js逆向基础-hook调试
  • Guava 提供了集合操作 `List`、`Set` 和 `Map` 三个工具类
  • HarmonyOS 输入框组件:TextInput 和 TextArea 深度解析
  • Oracle RAC最佳实践-优化私网连接
  • kubeadm安装K8s高可用集群之集群初始化及master/node节点加入calico网络插件安装
  • 系列1:基于Centos-8.6部署Kubernetes (1.24-1.30)
  • 深入浅出Flink CEP丨如何通过Flink SQL作业动态更新Flink CEP作业
  • git stash 的文件如何找回
  • 数据结构--插入排序
  • JAVA开发时获取用户信息失败,分析后端日志信息
  • spring @Mapper Converter转换泛型异常
  • Kafka Streams 在监控场景的应用与实践
  • 使用正则表达式提取PDF文件页数的实现方案
  • 观察者模式(sigslot in C++)
  • docker pull 报错Get “https://registry-1.docker.io/v2/“: net/http: request canceled while waiting for c
  • CSS学习-第三天