|  | @@ -10,20 +10,16 @@ import com.zanxiang.game.module.mybatis.entity.User;
 | 
	
		
			
				|  |  |  import com.zanxiang.game.module.mybatis.mapper.GameUserRoleMapper;
 | 
	
		
			
				|  |  |  import com.zanxiang.game.module.sdk.constant.RedisKeyConstant;
 | 
	
		
			
				|  |  |  import com.zanxiang.game.module.sdk.enums.DataTypeEnum;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.sdk.enums.KafkaEventTrackEnum;
 | 
	
		
			
				|  |  |  import com.zanxiang.game.module.sdk.enums.LoginTypeEnum;
 | 
	
		
			
				|  |  |  import com.zanxiang.game.module.sdk.pojo.param.GameRoleActiveCallParam;
 | 
	
		
			
				|  |  |  import com.zanxiang.game.module.sdk.pojo.param.GameUserRoleUpdateParam;
 | 
	
		
			
				|  |  |  import com.zanxiang.game.module.sdk.pojo.param.UserData;
 | 
	
		
			
				|  |  |  import com.zanxiang.game.module.sdk.service.*;
 | 
	
		
			
				|  |  |  import com.zanxiang.module.redis.service.IDistributedLockComponent;
 | 
	
		
			
				|  |  | -import com.zanxiang.module.util.DateUtil;
 | 
	
		
			
				|  |  |  import com.zanxiang.module.util.JsonUtil;
 | 
	
		
			
				|  |  |  import lombok.extern.slf4j.Slf4j;
 | 
	
		
			
				|  |  | -import org.apache.kafka.clients.producer.Producer;
 | 
	
		
			
				|  |  | -import org.apache.kafka.clients.producer.ProducerRecord;
 | 
	
		
			
				|  |  | -import org.apache.logging.log4j.util.Strings;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  | -import org.springframework.beans.factory.annotation.Qualifier;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Value;
 | 
	
		
			
				|  |  |  import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  |  import org.springframework.transaction.annotation.Transactional;
 | 
	
	
		
			
				|  | @@ -41,36 +37,32 @@ import java.util.concurrent.TimeUnit;
 | 
	
		
			
				|  |  |  @Service
 | 
	
		
			
				|  |  |  public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, GameUserRole> implements IGameUserRoleService {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    @Autowired
 | 
	
		
			
				|  |  | -    private RestTemplate restTemplate;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @Autowired
 | 
	
		
			
				|  |  | -    private IGameUserService gameUserService;
 | 
	
		
			
				|  |  | +    @Value("${server.domain}")
 | 
	
		
			
				|  |  | +    private String serverUrl;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private IUserService userService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  | -    private IUserLoginLogService userLoginLogService;
 | 
	
		
			
				|  |  | +    private IKafkaService kafkaService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  | -    private IDistributedLockComponent distributedLockComponent;
 | 
	
		
			
				|  |  | +    private RestTemplate restTemplate;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  | -    private IUserTokenService userTokenService;
 | 
	
		
			
				|  |  | +    private IGameUserService gameUserService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private ICallBackService callBackService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    @Value("${spring.kafka.game-sdk.gameRoleActiveTopic}")
 | 
	
		
			
				|  |  | -    private String gameRoleActiveTopic;
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private IUserTokenService userTokenService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    @Value("${server.domain}")
 | 
	
		
			
				|  |  | -    private String serverUrl;
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private IUserLoginLogService userLoginLogService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  | -    @Qualifier("gameSdkKafkaProducer")
 | 
	
		
			
				|  |  | -    private Producer<String, String> kafkaProducer;
 | 
	
		
			
				|  |  | +    private IDistributedLockComponent distributedLockComponent;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      @Transactional(rollbackFor = Exception.class)
 | 
	
	
		
			
				|  | @@ -84,7 +76,7 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
 | 
	
		
			
				|  |  |          //创建角色
 | 
	
		
			
				|  |  |          if (Objects.equals(dataType, DataTypeEnum.TYPE_CREATE_ROLE.getDateType())) {
 | 
	
		
			
				|  |  |              //新建游戏角色
 | 
	
		
			
				|  |  | -            this.createRoleUpdate(param, userData);
 | 
	
		
			
				|  |  | +            this.gameRoleCreate(param, userData);
 | 
	
		
			
				|  |  |              //插入用户登录记录
 | 
	
		
			
				|  |  |              return userLoginLogService.createRoleLoginLog(userData, param.getRoleId(), param.getRoleName(), LoginTypeEnum.LOGIN_IN.getLoginType());
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -96,7 +88,11 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
 | 
	
		
			
				|  |  |          //逻辑兜底, 万一角色未创建成功, 补充创建
 | 
	
		
			
				|  |  |          if (gameUserRole == null) {
 | 
	
		
			
				|  |  |              //新建游戏角色
 | 
	
		
			
				|  |  | -            this.createRoleUpdate(param, userData);
 | 
	
		
			
				|  |  | +            this.gameRoleCreate(param, userData);
 | 
	
		
			
				|  |  | +            //刚创建的角色, 如果是更新请求, 则不需要执行
 | 
	
		
			
				|  |  | +            if (Objects.equals(dataType, DataTypeEnum.TYPE_LEVEL_UP.getDateType())) {
 | 
	
		
			
				|  |  | +                return Boolean.TRUE;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          //进入游戏
 | 
	
		
			
				|  |  |          if (Objects.equals(dataType, DataTypeEnum.TYPE_ENTER_GAME.getDateType())) {
 | 
	
	
		
			
				|  | @@ -105,22 +101,7 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          //等级提升更新
 | 
	
		
			
				|  |  |          if (Objects.equals(dataType, DataTypeEnum.TYPE_LEVEL_UP.getDateType())) {
 | 
	
		
			
				|  |  | -            //更新频率限制, 20秒更新一次, 避免游戏实时战力高频上报
 | 
	
		
			
				|  |  | -            if (!distributedLockComponent.doLock(RedisKeyConstant.ROLE_LEVEL_UP + userData.getUserId(), 0L, 20L, TimeUnit.SECONDS)) {
 | 
	
		
			
				|  |  | -                return Boolean.TRUE;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            return super.update(new LambdaUpdateWrapper<GameUserRole>()
 | 
	
		
			
				|  |  | -                    .set(GameUserRole::getRoleName, param.getRoleName())
 | 
	
		
			
				|  |  | -                    .set(GameUserRole::getRoleLevel, param.getRoleLevel())
 | 
	
		
			
				|  |  | -                    .set(gameUserRole == null || Strings.isBlank(gameUserRole.getServerId()), GameUserRole::getServerId, param.getServerId())
 | 
	
		
			
				|  |  | -                    .set(GameUserRole::getServerName, param.getServerName())
 | 
	
		
			
				|  |  | -                    .set(param.getRoleVipLevel() != null, GameUserRole::getRoleVipLevel, param.getRoleVipLevel())
 | 
	
		
			
				|  |  | -                    .set(param.getRolePower() != null, GameUserRole::getRolePower, param.getRolePower())
 | 
	
		
			
				|  |  | -                    .set(GameUserRole::getUpdateTime, param.getRoleGradeUpdateTime() == null || param.getRoleGradeUpdateTime() <= 0 ? LocalDateTime.now() : DateUtil.secondToLocalDateTime(param.getRoleGradeUpdateTime()))
 | 
	
		
			
				|  |  | -                    .set(param.getExtra() != null, GameUserRole::getExtra, JsonUtil.toString(param.getExtra()))
 | 
	
		
			
				|  |  | -                    .eq(GameUserRole::getUserId, userData.getUserId())
 | 
	
		
			
				|  |  | -                    .eq(GameUserRole::getGameId, userData.getGameId())
 | 
	
		
			
				|  |  | -                    .eq(GameUserRole::getRoleId, param.getRoleId()));
 | 
	
		
			
				|  |  | +            return this.gameRoleUpdate(param, gameUserRole, userData);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          //退出游戏
 | 
	
		
			
				|  |  |          if (Objects.equals(dataType, DataTypeEnum.TYPE_EXIT_GAME.getDateType())) {
 | 
	
	
		
			
				|  | @@ -130,7 +111,35 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
 | 
	
		
			
				|  |  |          return Boolean.FALSE;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private void createRoleUpdate(GameUserRoleUpdateParam param, UserData userData) {
 | 
	
		
			
				|  |  | +    private boolean gameRoleUpdate(GameUserRoleUpdateParam param, GameUserRole gameUserRole, UserData userData) {
 | 
	
		
			
				|  |  | +        //更新频率限制, 20秒更新一次, 避免游戏实时战力高频上报
 | 
	
		
			
				|  |  | +        if (!distributedLockComponent.doLock(RedisKeyConstant.ROLE_LEVEL_UP + userData.getUserId(), 0L, 20L, TimeUnit.SECONDS)) {
 | 
	
		
			
				|  |  | +            return Boolean.TRUE;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //玩家角色信息更新
 | 
	
		
			
				|  |  | +        if (gameUserRole.getServerId() == null) {
 | 
	
		
			
				|  |  | +            gameUserRole.setServerId(param.getServerId());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (param.getRoleVipLevel() != null) {
 | 
	
		
			
				|  |  | +            gameUserRole.setRoleVipLevel(param.getRoleVipLevel());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (param.getRolePower() != null) {
 | 
	
		
			
				|  |  | +            gameUserRole.setRolePower(param.getRolePower());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (param.getExtra() != null) {
 | 
	
		
			
				|  |  | +            gameUserRole.setExtra(JsonUtil.toString(param.getExtra()));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        gameUserRole.setRoleName(param.getRoleName());
 | 
	
		
			
				|  |  | +        gameUserRole.setRoleLevel(param.getRoleLevel());
 | 
	
		
			
				|  |  | +        gameUserRole.setServerName(param.getServerName());
 | 
	
		
			
				|  |  | +        gameUserRole.setUpdateTime(LocalDateTime.now());
 | 
	
		
			
				|  |  | +        boolean result = super.updateById(gameUserRole);
 | 
	
		
			
				|  |  | +        //角色更新数据埋点发送到卡夫卡
 | 
	
		
			
				|  |  | +        kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_ROLE_UPDATE, JsonUtil.toString(gameUserRole));
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void gameRoleCreate(GameUserRoleUpdateParam param, UserData userData) {
 | 
	
		
			
				|  |  |          //上锁
 | 
	
		
			
				|  |  |          if (!distributedLockComponent.doLock(RedisKeyConstant.ROLE_UPDATE_KEY + "_" + userData.getUserId(), 0L, 1L, TimeUnit.MINUTES)) {
 | 
	
		
			
				|  |  |              return;
 | 
	
	
		
			
				|  | @@ -148,7 +157,28 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
 | 
	
		
			
				|  |  |              return;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          User user = userService.getById(userData.getUserId());
 | 
	
		
			
				|  |  | -        userRole = GameUserRole.builder()
 | 
	
		
			
				|  |  | +        userRole = this.transform(param, userData, gameUser, user);
 | 
	
		
			
				|  |  | +        super.save(userRole);
 | 
	
		
			
				|  |  | +        //更新玩家创角数
 | 
	
		
			
				|  |  | +        gameUserService.update(new LambdaUpdateWrapper<GameUser>()
 | 
	
		
			
				|  |  | +                .setSql("role_count=role_count+" + 1)
 | 
	
		
			
				|  |  | +                .set(GameUser::getUpdateTime, LocalDateTime.now())
 | 
	
		
			
				|  |  | +                .eq(GameUser::getId, gameUser.getId()));
 | 
	
		
			
				|  |  | +        //更新用户创角数
 | 
	
		
			
				|  |  | +        userService.update(new LambdaUpdateWrapper<User>()
 | 
	
		
			
				|  |  | +                .setSql("role_count=role_count+" + 1)
 | 
	
		
			
				|  |  | +                .set(User::getUpdateTime, LocalDateTime.now())
 | 
	
		
			
				|  |  | +                .eq(User::getId, gameUser.getUserId()));
 | 
	
		
			
				|  |  | +        //用户创角回传
 | 
	
		
			
				|  |  | +        callBackService.roleCallBack(userRole, userData);
 | 
	
		
			
				|  |  | +        //用户创角埋点数据发送到卡夫卡
 | 
	
		
			
				|  |  | +        kafkaService.eventTrack(KafkaEventTrackEnum.KAFKA_EVENT_TRACK_ROLE_CREATE, JsonUtil.toString(userRole));
 | 
	
		
			
				|  |  | +        //释放锁
 | 
	
		
			
				|  |  | +        distributedLockComponent.unlock(RedisKeyConstant.ROLE_UPDATE_KEY + "_" + userData.getUserId());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private GameUserRole transform(GameUserRoleUpdateParam param, UserData userData, GameUser gameUser, User user) {
 | 
	
		
			
				|  |  | +        return GameUserRole.builder()
 | 
	
		
			
				|  |  |                  .userId(userData.getUserId())
 | 
	
		
			
				|  |  |                  .gameUserId(gameUser.getId())
 | 
	
		
			
				|  |  |                  .gameId(userData.getGameId())
 | 
	
	
		
			
				|  | @@ -161,26 +191,11 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
 | 
	
		
			
				|  |  |                  .rolePower(param.getRolePower())
 | 
	
		
			
				|  |  |                  .os(userData.getDeviceSystem())
 | 
	
		
			
				|  |  |                  .regTime(user == null ? null : user.getCreateTime())
 | 
	
		
			
				|  |  | -                .createTime(param.getRoleGradeUpdateTime() == null || param.getRoleGradeUpdateTime() <= 0 ? LocalDateTime.now() : DateUtil.secondToLocalDateTime(param.getRoleGradeUpdateTime()))
 | 
	
		
			
				|  |  | +                .createTime(LocalDateTime.now())
 | 
	
		
			
				|  |  |                  .updateTime(LocalDateTime.now())
 | 
	
		
			
				|  |  |                  .lastLoginTime(LocalDateTime.now())
 | 
	
		
			
				|  |  |                  .extra(param.getExtra() == null ? null : JsonUtil.toString(param.getExtra()))
 | 
	
		
			
				|  |  |                  .build();
 | 
	
		
			
				|  |  | -        super.save(userRole);
 | 
	
		
			
				|  |  | -        //更新玩家创角数
 | 
	
		
			
				|  |  | -        gameUserService.update(new LambdaUpdateWrapper<GameUser>()
 | 
	
		
			
				|  |  | -                .setSql("role_count=role_count+" + 1)
 | 
	
		
			
				|  |  | -                .set(GameUser::getUpdateTime, LocalDateTime.now())
 | 
	
		
			
				|  |  | -                .eq(GameUser::getId, gameUser.getId()));
 | 
	
		
			
				|  |  | -        //更新用户创角数
 | 
	
		
			
				|  |  | -        userService.update(new LambdaUpdateWrapper<User>()
 | 
	
		
			
				|  |  | -                .setSql("role_count=role_count+" + 1)
 | 
	
		
			
				|  |  | -                .set(User::getUpdateTime, LocalDateTime.now())
 | 
	
		
			
				|  |  | -                .eq(User::getId, gameUser.getUserId()));
 | 
	
		
			
				|  |  | -        //用户创角回传
 | 
	
		
			
				|  |  | -        callBackService.roleCallBack(userRole, userData);
 | 
	
		
			
				|  |  | -        //释放锁
 | 
	
		
			
				|  |  | -        distributedLockComponent.unlock(RedisKeyConstant.ROLE_UPDATE_KEY + "_" + userData.getUserId());
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
	
		
			
				|  | @@ -255,29 +270,17 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public boolean gameRoleActiveCall(UserData userData, GameRoleActiveCallParam param) {
 | 
	
		
			
				|  |  | -        //token临期失效判断
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            userTokenService.userTokenUpdateCheck(userData);
 | 
	
		
			
				|  |  | -        } catch (Exception ignored) {
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        //测试环境不使用kafka
 | 
	
		
			
				|  |  | +        //测试不执行
 | 
	
		
			
				|  |  |          if (this.serverUrl.contains("test")) {
 | 
	
		
			
				|  |  |              return Boolean.TRUE;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        //活跃提交
 | 
	
		
			
				|  |  | -        Map<String, Object> activeParamMap = new HashMap<>(6);
 | 
	
		
			
				|  |  | -        activeParamMap.put("userId", userData.getUserId());
 | 
	
		
			
				|  |  | -        activeParamMap.put("gameId", userData.getGameId());
 | 
	
		
			
				|  |  | -        activeParamMap.put("serverId", param.getServerId());
 | 
	
		
			
				|  |  | -        activeParamMap.put("roleId", param.getRoleId());
 | 
	
		
			
				|  |  | -        activeParamMap.put("roleLevel", param.getRoleLevel());
 | 
	
		
			
				|  |  | -        activeParamMap.put("activeTime", System.currentTimeMillis());
 | 
	
		
			
				|  |  | +        //token临期失效判断
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  | -            kafkaProducer.send(new ProducerRecord<>(gameRoleActiveTopic, userData.getUserId().toString(), JsonUtil.toString(activeParamMap)));
 | 
	
		
			
				|  |  | -        } catch (Exception e) {
 | 
	
		
			
				|  |  | -            log.error("用户角色活跃信息发送到 Kafka 异常!, activeParamMap : {}, e : {}", JsonUtil.toString(activeParamMap), e.getMessage());
 | 
	
		
			
				|  |  | -            return Boolean.FALSE;
 | 
	
		
			
				|  |  | +            userTokenService.userTokenUpdateCheck(userData);
 | 
	
		
			
				|  |  | +        } catch (Exception ignored) {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        //活跃信息发送到卡夫卡
 | 
	
		
			
				|  |  | +        kafkaService.roleActiveTrack(userData, param);
 | 
	
		
			
				|  |  |          return Boolean.TRUE;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |