Explorar el Código

websocket调整

sunkean hace 3 años
padre
commit
52b1d87907

+ 61 - 5
src/main/java/com/izouma/nineth/domain/MetaMMOLoginInfo.java

@@ -11,6 +11,7 @@ import lombok.NoArgsConstructor;
 import javax.persistence.Entity;
 import javax.persistence.Table;
 import java.time.LocalDateTime;
+import java.util.Objects;
 
 @Data
 @AllArgsConstructor
@@ -25,13 +26,13 @@ public class MetaMMOLoginInfo extends BaseEntity {
     private String nickname;
 
     @ApiModelProperty("用户id")
-    private Long  userId;
+    private Long userId;
 
     @ApiModelProperty("区域id")
-    private Long  regionId;
+    private Long regionId;
 
     @ApiModelProperty("城市id")
-    private Long  cityId;
+    private Long cityId;
 
     @ApiModelProperty("上线时间")
     private LocalDateTime onLineTime;
@@ -39,8 +40,8 @@ public class MetaMMOLoginInfo extends BaseEntity {
     @ApiModelProperty("离线时间")
     private LocalDateTime offLineTime;
 
-    @ApiModelProperty("UUID")
-    private String UUID;
+    @ApiModelProperty("sessionId")
+    private String sessionId;
 
     @ApiModelProperty("角色")
     private String role;
@@ -57,4 +58,59 @@ public class MetaMMOLoginInfo extends BaseEntity {
 
     private Float eulerZ;
 
+    private int top;
+
+    private int hat;
+
+    private int down;
+
+    private int shoes;
+
+    private int anim;
+
+    private int emoji;
+
+    /**
+     * 根据玩家历史登陆信息初始化本次登陆信息
+     *
+     * @param metaMMOLoginInfo 历史登陆信息
+     * @return 本次登陆默认信息
+     */
+    public static MetaMMOLoginInfo initMetaMMOLoginInfo(MetaMMOLoginInfo metaMMOLoginInfo) {
+        MetaMMOLoginInfo newMetaMMOLoginInfo = new MetaMMOLoginInfo();
+        if (Objects.isNull(metaMMOLoginInfo)) {
+            newMetaMMOLoginInfo.setRegionId(0L);
+            newMetaMMOLoginInfo.setCityId(0L);
+            newMetaMMOLoginInfo.setAxisX(0F);
+            newMetaMMOLoginInfo.setAxisY(0F);
+            newMetaMMOLoginInfo.setAxisZ(0F);
+            newMetaMMOLoginInfo.setEulerX(0F);
+            newMetaMMOLoginInfo.setEulerY(0F);
+            newMetaMMOLoginInfo.setEulerZ(0F);
+            newMetaMMOLoginInfo.setTop(0);
+            newMetaMMOLoginInfo.setHat(0);
+            newMetaMMOLoginInfo.setDown(0);
+            newMetaMMOLoginInfo.setShoes(0);
+            newMetaMMOLoginInfo.setAnim(0);
+            newMetaMMOLoginInfo.setEmoji(0);
+            return newMetaMMOLoginInfo;
+        }
+        newMetaMMOLoginInfo.setCityId(metaMMOLoginInfo.getCityId());
+        newMetaMMOLoginInfo.setRegionId(metaMMOLoginInfo.getRegionId());
+        newMetaMMOLoginInfo.setAxisX(metaMMOLoginInfo.getAxisX());
+        newMetaMMOLoginInfo.setAxisY(metaMMOLoginInfo.getAxisY());
+        newMetaMMOLoginInfo.setAxisZ(metaMMOLoginInfo.getAxisZ());
+        newMetaMMOLoginInfo.setEulerX(metaMMOLoginInfo.getEulerX());
+        newMetaMMOLoginInfo.setEulerY(metaMMOLoginInfo.getEulerY());
+        newMetaMMOLoginInfo.setEulerZ(metaMMOLoginInfo.getEulerZ());
+        newMetaMMOLoginInfo.setTop(metaMMOLoginInfo.getTop());
+        newMetaMMOLoginInfo.setHat(metaMMOLoginInfo.getHat());
+        newMetaMMOLoginInfo.setDown(metaMMOLoginInfo.getDown());
+        newMetaMMOLoginInfo.setShoes(metaMMOLoginInfo.getShoes());
+        newMetaMMOLoginInfo.setAnim(metaMMOLoginInfo.getAnim());
+        newMetaMMOLoginInfo.setEmoji(metaMMOLoginInfo.getEmoji());
+        newMetaMMOLoginInfo.setRole(metaMMOLoginInfo.getRole());
+        return newMetaMMOLoginInfo;
+    }
+
 }

+ 41 - 0
src/main/java/com/izouma/nineth/dto/MetaServiceResult.java

@@ -0,0 +1,41 @@
+package com.izouma.nineth.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MetaServiceResult {
+
+    @ApiModelProperty("返回消息")
+    private String message;
+
+    @ApiModelProperty("是否成功")
+    private boolean success;
+
+    public static MetaServiceResult returnSuccess() {
+        return returnSuccess("success");
+    }
+
+    public static MetaServiceResult returnSuccess(String message) {
+        MetaServiceResult result = new MetaServiceResult();
+        result.setMessage(message);
+        result.setSuccess(true);
+        return result;
+    }
+
+    public static MetaServiceResult returnError() {
+        return returnError("error");
+    }
+
+    public static MetaServiceResult returnError(String message) {
+        MetaServiceResult result = new MetaServiceResult();
+        result.setMessage(message);
+        result.setSuccess(false);
+        return result;
+    }
+
+}

+ 1 - 1
src/main/java/com/izouma/nineth/repo/MetaMMOLoginInfoRepo.java

@@ -10,5 +10,5 @@ public interface MetaMMOLoginInfoRepo extends JpaRepository<MetaMMOLoginInfo, Lo
     @Query(value = "select * from meta_mmo_login_info a where a.user_id = ?1 order by a.created_at desc limit 1",nativeQuery = true)
     MetaMMOLoginInfo findLastByUserId(Long userId);
 
-    MetaMMOLoginInfo findByUUID(String UUID);
+    MetaMMOLoginInfo findByUserIdAndSessionIdAndDel(Long userId, String sessionId, boolean del);
 }

+ 237 - 285
src/main/java/com/izouma/nineth/websocket/WebSocket.java

@@ -5,9 +5,11 @@ import com.alibaba.fastjson.JSONObject;
 import com.izouma.nineth.domain.MetaMMOLoginInfo;
 import com.izouma.nineth.dto.MMOMessage;
 import com.izouma.nineth.dto.MMOSingleMessage;
+import com.izouma.nineth.dto.MetaServiceResult;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.MetaMMOLoginInfoRepo;
 import com.izouma.nineth.utils.ApplicationContextUtil;
+import com.izouma.nineth.utils.ObjUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -19,7 +21,10 @@ import javax.websocket.server.PathParam;
 import javax.websocket.server.ServerEndpoint;
 import java.io.IOException;
 import java.time.LocalDateTime;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 
@@ -31,118 +36,45 @@ public class WebSocket {
     /**
      * 当前在线的客户端map
      */
-    private static Map<String, WebSocket> clients = new ConcurrentHashMap();
+    private static final Map<String, Session> clients = new ConcurrentHashMap();
 
-    /**
-     * session
-     */
-    private Session session;
-
-    /**
-     * 用户id
-     */
-    private String userId;
-
-    /**
-     * uuid
-     */
-    private String uuid;
-
-    /**
-     * key
-     */
-    private String key;
-
-    /**
-     * cityId
-     */
-    private Long cityId;
-
-    /**
-     * 区域id
-     */
-    private Long regionId;
-
-    private RedisTemplate redisTemplate;
-
-    Session getSession() {
-        return this.session;
-    }
+    private final String REDIS_PREFIX = "meta:";
 
-    private MetaMMOLoginInfoRepo metaMMOLoginInfoRepo;
+    private final RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");
 
-    public void init() {
-        if (this.metaMMOLoginInfoRepo == null) {
-            metaMMOLoginInfoRepo = (MetaMMOLoginInfoRepo) ApplicationContextUtil.getBean("metaMMOLoginInfoRepo");
-        }
-        if (this.redisTemplate == null) {
-            redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");
-        }
-    }
+    private final MetaMMOLoginInfoRepo metaMMOLoginInfoRepo = (MetaMMOLoginInfoRepo) ApplicationContextUtil.getBean("metaMMOLoginInfoRepo");
 
     @OnOpen
     public void onOpen(@PathParam("nickName") String nickName, @PathParam("userId") String userId, Session session) {
-        init();
         try {
-            // 判断当前玩家是否在线
-            if (clients.containsKey(userId)) {
-                WebSocket webSocket = clients.get(userId);
-                // 关闭当前的链接
+            // 判断当前玩家是否在其他地方登陆
+            if (clients.containsKey(REDIS_PREFIX.concat(userId))) {
+                log.info(String.format("当前玩家[%S]已经在别处登陆,sessionId为[%S]", userId, session.getId()));
+                WebSocket webSocket = new WebSocket();
+                // 关闭连接
                 MMOSingleMessage mmoSingleMessage = new MMOSingleMessage();
                 mmoSingleMessage.setMessageType(6);
                 mmoSingleMessage.setMessage("您已在其他地方登录");
-                webSocket.sendMessageTo(JSON.toJSONString(mmoSingleMessage), userId);
-                try {
-                    webSocket.getSession().close();
-                } catch (Exception e) {
-                    log.error("close session error", e);
-                }
-            }
-            // 获取上次登录的信息
-            MetaMMOLoginInfo metaMMOLoginInfo = metaMMOLoginInfoRepo.findLastByUserId(Long.parseLong(userId));
-            if (Objects.isNull(metaMMOLoginInfo)) {
-                // 首次登陆 初始化玩家信息
-                metaMMOLoginInfo = new MetaMMOLoginInfo();
-                metaMMOLoginInfo.setUserId(Long.parseLong(userId));
-                metaMMOLoginInfo.setNickname(nickName);
-                metaMMOLoginInfo.setRegionId(0L);
-                metaMMOLoginInfo.setCityId(0L);
-                metaMMOLoginInfo.setAxisX(0F);
-                metaMMOLoginInfo.setAxisY(0F);
-                metaMMOLoginInfo.setAxisZ(0F);
-                metaMMOLoginInfo.setEulerX(0F);
-                metaMMOLoginInfo.setEulerY(0F);
-                metaMMOLoginInfo.setEulerZ(0F);
+                webSocket.sendMessageTo(JSON.toJSONString(mmoSingleMessage), REDIS_PREFIX.concat(userId));
+                log.info("关闭当前session连接");
+                session.close();
             }
             log.info("现在来连接的sessionId:" + session.getId() + "玩家id:" + userId + "玩家昵称" + nickName);
-            this.userId = userId;
-            this.session = session;
-            // 生成缓存key 规则 --> cityId:regionId
-            this.key = String.valueOf(metaMMOLoginInfo.getCityId()).concat(":").concat(String.valueOf(metaMMOLoginInfo.getRegionId()));
-            this.cityId = metaMMOLoginInfo.getCityId();
-            this.regionId = metaMMOLoginInfo.getRegionId();
-            // 玩家信息存入websocket
-            clients.put(userId, this);
+            clients.put(REDIS_PREFIX.concat(userId), session);
+            // 获取上次登录的信息
+            MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findLastByUserId(Long.parseLong(userId));
+            // 玩家登陆信息入库
+            MetaMMOLoginInfo metaMMOLoginInfo = MetaMMOLoginInfo.initMetaMMOLoginInfo(dbMetaMMOLoginInfo);
+            metaMMOLoginInfo.setNickname(nickName);
+            metaMMOLoginInfo.setUserId(Long.parseLong(userId));
+            metaMMOLoginInfo.setOnLineTime(LocalDateTime.now());
+            metaMMOLoginInfo.setSessionId(session.getId());
+            MetaMMOLoginInfo save = metaMMOLoginInfoRepo.save(metaMMOLoginInfo);
             MMOMessage mmoMessage = new MMOMessage();
             mmoMessage.setMessageType(5);
-            mmoMessage.setMessage(metaMMOLoginInfo);
-            sendMessageTo(JSON.toJSONString(mmoMessage), userId);
-            this.uuid = UUID.randomUUID().toString();
-            // 玩家信息入库
-            MetaMMOLoginInfo newMetaMMOLoginInfo = new MetaMMOLoginInfo();
-            newMetaMMOLoginInfo.setNickname(metaMMOLoginInfo.getNickname());
-            newMetaMMOLoginInfo.setUserId(metaMMOLoginInfo.getUserId());
-            newMetaMMOLoginInfo.setCityId(metaMMOLoginInfo.getCityId());
-            newMetaMMOLoginInfo.setRegionId(metaMMOLoginInfo.getRegionId());
-            newMetaMMOLoginInfo.setAxisX(metaMMOLoginInfo.getAxisX());
-            newMetaMMOLoginInfo.setAxisY(metaMMOLoginInfo.getAxisY());
-            newMetaMMOLoginInfo.setAxisZ(metaMMOLoginInfo.getAxisZ());
-            newMetaMMOLoginInfo.setEulerX(metaMMOLoginInfo.getEulerX());
-            newMetaMMOLoginInfo.setEulerY(metaMMOLoginInfo.getEulerY());
-            newMetaMMOLoginInfo.setEulerZ(metaMMOLoginInfo.getEulerZ());
-            newMetaMMOLoginInfo.setOnLineTime(LocalDateTime.now());
-            newMetaMMOLoginInfo.setUUID(uuid);
-            metaMMOLoginInfoRepo.save(newMetaMMOLoginInfo);
+            mmoMessage.setMessage(save);
+            log.info(String.format("通知玩家[%S],本次登陆信息[%S]", userId, JSON.toJSONString(mmoMessage)));
+            sendMessageTo(JSON.toJSONString(mmoMessage), REDIS_PREFIX.concat(userId));
         } catch (Exception e) {
             String errMsg = String.format("[%S]上线的时候发生了错误,错误信息[%S]", userId, e.getMessage());
             log.error(errMsg, e);
@@ -153,164 +85,155 @@ public class WebSocket {
     @OnError
     public void onError(Session session, Throwable error) {
         // 异常处理
-        log.info(String.format("服务端发生了错误:[%S]", error.getMessage()));
+        log.error(String.format("sessionId[%S]的服务端发生了错误:[%S]", session.getId(), error.getMessage()));
     }
 
-
     @OnClose
-    public void onClose() {
-        init();
+    public void onClose(@PathParam("userId") String userId) {
         // 查询地图中玩家信息
-        MetaMMOLoginInfo metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(this.userId);
+        MetaMMOLoginInfo metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(REDIS_PREFIX.concat(userId));
         if (Objects.isNull(metaMMOLoginInfo)) {
-            // 如果缓存中玩家信息为空,根据UUID查询数据库
-            MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findByUUID(uuid);
+            // 如果缓存中玩家信息为空,根据userId和sessionId查询数据库
+            MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findByUserIdAndSessionIdAndDel(Long.parseLong(userId), clients.get(userId).getId(), false);
             dbMetaMMOLoginInfo.setOffLineTime(LocalDateTime.now());
             // 更新离线时间
             metaMMOLoginInfoRepo.save(dbMetaMMOLoginInfo);
-            clients.remove(userId);
+            clients.remove(REDIS_PREFIX.concat(userId));
             return;
         }
         String key = String.valueOf(metaMMOLoginInfo.getCityId()).concat(":").concat(String.valueOf(metaMMOLoginInfo.getRegionId()));
-        List<String> userIds = redisTemplate.opsForList().range(key, 0, -1);
-        // 分发下线消息给区域内其他玩家
-        buildMessageForSendingToAllOther(userIds, 3, metaMMOLoginInfo);
-        MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findLastByUserId(metaMMOLoginInfo.getUserId());
+        List<String> otherUserIds = remove(key, userId);
+        if(CollectionUtils.isNotEmpty(otherUserIds)) {
+            // 分发下线消息给区域内其他玩家
+            buildMessageForSendingToAllOther(otherUserIds, 3, metaMMOLoginInfo);
+        }
+        MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findById(metaMMOLoginInfo.getId()).orElseThrow(new BusinessException(String.format("数据库不存在id[%S]的记录", metaMMOLoginInfo.getId())));
+        ObjUtils.merge(dbMetaMMOLoginInfo, metaMMOLoginInfo);
         dbMetaMMOLoginInfo.setOffLineTime(LocalDateTime.now());
         metaMMOLoginInfoRepo.save(dbMetaMMOLoginInfo);
-        clients.remove(userId);
+        clients.remove(REDIS_PREFIX.concat(userId));
         // 删除redis中自己的信息
-        redisTemplate.delete(userId);
+        redisTemplate.delete(REDIS_PREFIX.concat(userId));
         // 移除地图中自己的信息
-        redisTemplate.opsForList().remove(key, 0, userId);
+        redisTemplate.opsForList().remove(REDIS_PREFIX.concat(key), 0, REDIS_PREFIX.concat(userId));
     }
 
-
     @OnMessage
-    public void onMessage(String message, Session session) {
-        init();
-        log.info("来自客户端消息:" + message + "客户端的id是:" + session.getId());
+    public void onMessage(@PathParam("nickName") String nickName, @PathParam("userId") String userId, String message, Session session) {
         if (StringUtils.isBlank(message)) {
-            log.info("message is null");
-            return;
-        }
-        JSONObject jsonObject = JSON.parseObject(message);
-        if (Objects.isNull(jsonObject.getString("type"))) {
-            String errMsg = "操作类型为空";
-            log.error(errMsg);
-            throw new BusinessException(errMsg);
-        }
-        if (Objects.isNull(jsonObject.getString("cityId"))) {
-            String errMsg = "cityId为空";
+            String errMsg = "Illegal parameter : message can not be null";
             log.error(errMsg);
             throw new BusinessException(errMsg);
         }
-        if (Objects.isNull(jsonObject.getString("regionId"))) {
-            String errMsg = "regionId为空";
-            log.error(errMsg);
-            throw new BusinessException(errMsg);
+        JSONObject jsonObject = JSON.parseObject(message);
+        MetaServiceResult result = checkParams(jsonObject);
+        if (!result.isSuccess()) {
+            log.error(result.getMessage());
+            throw new BusinessException(result.getMessage());
         }
+        log.info("来自客户端消息:" + message + "客户端的id是:" + session.getId());
         int type = Integer.parseInt(jsonObject.getString("type"));
         String cityId = jsonObject.getString("cityId");
         String regionId = jsonObject.getString("regionId");
         String key = cityId.concat(":").concat(regionId);
-        // 从当前地图中获取其他玩家信息
-        List<String> userIds = redisTemplate.opsForList().range(key, 0, -1);
-        // 进入地图 把自己位置信息通知别人,获取其他人的位置信息
-        if (type == 1) {
-            MetaMMOLoginInfo metaMMOLoginInfo = buildMetaMMOLoginInfo(jsonObject, Long.parseLong(cityId), Long.parseLong(regionId));
-            // 判断地图中是否存在玩家
-            if (CollectionUtils.isNotEmpty(userIds)) {
-                List<MetaMMOLoginInfo> metaMMOLoginInfos = redisTemplate.opsForValue().multiGet(userIds);
-                if (CollectionUtils.isNotEmpty(metaMMOLoginInfos)) {
-                    // 过滤自己
-                    metaMMOLoginInfos = remove(metaMMOLoginInfos);
+        List<String> otherUserIds = remove(key, userId);
+        MetaMMOLoginInfo metaMMOLoginInfo;
+        List<MetaMMOLoginInfo> metaMMOLoginInfos = redisTemplate.opsForValue().multiGet(otherUserIds);
+        switch (type) {
+            case 1:
+                log.info("当前操作类型为1 -> 玩家进入地图");
+                metaMMOLoginInfo = buildMetaMMOLoginInfo(jsonObject, Long.parseLong(cityId), Long.parseLong(regionId), nickName, userId);
+                if (CollectionUtils.isNotEmpty(otherUserIds)) {
                     if (CollectionUtils.isNotEmpty(metaMMOLoginInfos)) {
                         // 分发区域内其他玩家信息给自己
-                        buildMessageForSendingToUser(userId, 1, metaMMOLoginInfos);
+                        buildMessageForSendingToUser(REDIS_PREFIX.concat(userId), 1, metaMMOLoginInfos);
                         // 分发自己信息给区域内其他玩家
-                        buildMessageForSendingToAllOther(userIds, 4, metaMMOLoginInfo);
+                        buildMessageForSendingToAllOther(otherUserIds, 4, metaMMOLoginInfo);
                     }
                 }
-            }
-            // 将自己信息存到redis中
-            redisTemplate.opsForValue().set(userId, metaMMOLoginInfo);
-            redisTemplate.opsForList().leftPush(key, userId);
-        }
-        // 如果是区域直接切换区域
-        if (type == 2) {
-            MetaMMOLoginInfo metaMMOLoginInfo = buildMetaMMOLoginInfo(jsonObject, Long.parseLong(cityId), Long.parseLong(regionId));
-            if (CollectionUtils.isNotEmpty(userIds)) {
+                // 将自己信息存到redis中
+                redisTemplate.opsForValue().set(REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
+                redisTemplate.opsForList().leftPush(REDIS_PREFIX.concat(key), REDIS_PREFIX.concat(userId));
+                break;
+            case 2:
+                log.info(String.format("当前操作类型为[%S] -> 玩家切换区域", type));
+                metaMMOLoginInfo = buildMetaMMOLoginInfo(jsonObject, Long.parseLong(cityId), Long.parseLong(regionId), nickName, userId);
+                if (CollectionUtils.isNotEmpty(otherUserIds)) {
+                    // 分发自己信息给区域内其他玩家
+                    buildMessageForSendingToAllOther(otherUserIds, 4, metaMMOLoginInfo);
+                    // 分发区域内其他玩家信息给自己
+                    buildMessageForSendingToUser(REDIS_PREFIX.concat(userId), 1, metaMMOLoginInfos);
+                }
+                MetaMMOLoginInfo oldMetaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(REDIS_PREFIX.concat(userId));
+                if (Objects.isNull(oldMetaMMOLoginInfo)) {
+                    String errMsg = "缺失玩家上次区域的地图缓存信息";
+                    log.error(errMsg);
+                    throw new BusinessException(errMsg);
+                }
+                String oldKey = String.valueOf(oldMetaMMOLoginInfo.getCityId()).concat(":").concat(String.valueOf(oldMetaMMOLoginInfo.getRegionId()));
+                List<String> oldUserIds = redisTemplate.opsForList().range(REDIS_PREFIX.concat(oldKey), 0, -1);
+                if (CollectionUtils.isEmpty(oldUserIds)) {
+                    String errMsg = "查询不到上次所进入的区域的玩家信息";
+                    log.error(errMsg);
+                    throw new BusinessException(errMsg);
+                }
+                // 分发消息给之前区域的玩家
+                buildMessageForSendingToAllOther(oldUserIds, 3, oldMetaMMOLoginInfo);
+                // 清除玩家上次缓存的地图信息
+                redisTemplate.opsForList().remove(REDIS_PREFIX.concat(oldKey), 0, REDIS_PREFIX.concat(userId));
+                // 缓存玩家新的地图信息
+                redisTemplate.opsForValue().set(REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
+                redisTemplate.opsForList().leftPush(REDIS_PREFIX.concat(key), REDIS_PREFIX.concat(userId));
+                break;
+            case 3:
+                log.info(String.format("当前操作类型为[%S] -> 玩家在地图内移动", type));
+                metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(REDIS_PREFIX.concat(userId));
+                if (Objects.isNull(metaMMOLoginInfo)) {
+                    String errMsg = "缓存中不存在本玩家信息";
+                    log.error(errMsg);
+                    throw new BusinessException(errMsg);
+                }
+                // 更新玩家位置信息
+                buildCommonProperty(metaMMOLoginInfo, jsonObject);
                 // 分发玩家信息给区域内其他玩家
-                buildMessageForSendingToAllOther(userIds, 4, metaMMOLoginInfo);
-                // 分发区域内其他玩家信息给自己
-                List<MetaMMOLoginInfo> metaMMOLoginInfos = redisTemplate.opsForValue().multiGet(userIds);
-                if (CollectionUtils.isNotEmpty(metaMMOLoginInfos)) {
-                    // 过滤自己
-                    metaMMOLoginInfos = remove(metaMMOLoginInfos);
-                    if (CollectionUtils.isNotEmpty(metaMMOLoginInfos)) {
-                        buildMessageForSendingToUser(userId, 1, metaMMOLoginInfos);
-                    }
+                buildMessageForSendingToAllOther(otherUserIds, 2, metaMMOLoginInfo);
+                redisTemplate.opsForValue().set(REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
+                break;
+            case 4:
+                log.info(String.format("当前操作类型为[%S] -> 玩家进入大厅", type));
+                metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(REDIS_PREFIX.concat(userId));
+                if (Objects.isNull(metaMMOLoginInfo)) {
+                    String errMsg = "缓存中不存在本玩家信息";
+                    log.error(errMsg);
+                    throw new BusinessException(errMsg);
                 }
-            }
-            // 分发玩家信息给之前区域内其他玩家
-            MetaMMOLoginInfo oldMetaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(userId);
-            if (Objects.isNull(oldMetaMMOLoginInfo)) {
-                String errMsg = "缺失玩家上次区域的地图缓存信息";
-                log.error(errMsg);
-                throw new BusinessException(errMsg);
-            }
-            String oldKey = String.valueOf(oldMetaMMOLoginInfo.getCityId()).concat(":").concat(String.valueOf(oldMetaMMOLoginInfo.getRegionId()));
-            List<String> oldUserIds = redisTemplate.opsForList().range(oldKey, 0, -1);
-            if (CollectionUtils.isEmpty(oldUserIds)) {
-                String errMsg = "查询不到上次所进入的区域的玩家信息";
-                log.error(errMsg);
-                throw new BusinessException(errMsg);
-            }
-            // 分发消息给之前区域的玩家
-            buildMessageForSendingToAllOther(oldUserIds, 3, oldMetaMMOLoginInfo);
-            // 清除玩家上次缓存的地图信息
-            redisTemplate.opsForList().remove(oldKey, 0, userId);
-            // 缓存玩家新的地图信息
-            redisTemplate.opsForValue().set(userId, metaMMOLoginInfo);
-            redisTemplate.opsForList().leftPush(key, userId);
-        }
-        // 玩家在地图内移动
-        if (type == 3) {
-            MetaMMOLoginInfo metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(userId);
-            if (Objects.isNull(metaMMOLoginInfo)) {
-                String errMsg = "缓存中不存在本玩家信息";
-                log.error(errMsg);
-                throw new BusinessException(errMsg);
-            }
-            // 分发玩家信息给区域内其他玩家
-            buildMessageForSendingToAllOther(userIds, 2, metaMMOLoginInfo);
-            // 更新缓存中玩家位置信息
-            buildMetaMMOLoginInfo(metaMMOLoginInfo, jsonObject);
-            redisTemplate.opsForValue().set(userId, metaMMOLoginInfo);
-        }
-        // 进入大厅
-        if (type == 4) {
-            MetaMMOLoginInfo metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(userId);
-            if (Objects.isNull(metaMMOLoginInfo)) {
-                String errMsg = "缓存中不存在本玩家信息";
+                // 分发玩家信息给区域内其他玩家
+                buildMessageForSendingToAllOther(otherUserIds, 3, metaMMOLoginInfo);
+                // 更新库中玩家位置信息
+                MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findById(metaMMOLoginInfo.getId()).orElseThrow(new BusinessException(String.format("数据库不存在id[%S]的记录", metaMMOLoginInfo.getId())));
+                dbMetaMMOLoginInfo.setAxisX(metaMMOLoginInfo.getAxisX());
+                dbMetaMMOLoginInfo.setAxisY(metaMMOLoginInfo.getAxisY());
+                dbMetaMMOLoginInfo.setAxisZ(metaMMOLoginInfo.getAxisZ());
+                dbMetaMMOLoginInfo.setEulerX(metaMMOLoginInfo.getEulerX());
+                dbMetaMMOLoginInfo.setEulerY(metaMMOLoginInfo.getEulerY());
+                dbMetaMMOLoginInfo.setEulerZ(metaMMOLoginInfo.getEulerZ());
+                dbMetaMMOLoginInfo.setCityId(metaMMOLoginInfo.getCityId());
+                dbMetaMMOLoginInfo.setRegionId(metaMMOLoginInfo.getRegionId());
+                dbMetaMMOLoginInfo.setTop(metaMMOLoginInfo.getTop());
+                dbMetaMMOLoginInfo.setHat(metaMMOLoginInfo.getHat());
+                dbMetaMMOLoginInfo.setShoes(metaMMOLoginInfo.getShoes());
+                dbMetaMMOLoginInfo.setDown(metaMMOLoginInfo.getDown());
+                dbMetaMMOLoginInfo.setEmoji(metaMMOLoginInfo.getEmoji());
+                dbMetaMMOLoginInfo.setAnim(metaMMOLoginInfo.getAnim());
+                dbMetaMMOLoginInfo.setRole(metaMMOLoginInfo.getRole());
+                metaMMOLoginInfoRepo.save(dbMetaMMOLoginInfo);
+                break;
+            default:
+                String errMsg = String.format("不存在的操作类型[%S]", type);
                 log.error(errMsg);
                 throw new BusinessException(errMsg);
-            }
-            // 分发玩家信息给区域内其他玩家
-            buildMessageForSendingToAllOther(userIds, 3, metaMMOLoginInfo);
-            // 更新库中玩家位置信息
-            MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findByUUID(uuid);
-            dbMetaMMOLoginInfo.setAxisX(metaMMOLoginInfo.getAxisX());
-            dbMetaMMOLoginInfo.setAxisY(metaMMOLoginInfo.getAxisY());
-            dbMetaMMOLoginInfo.setAxisZ(metaMMOLoginInfo.getAxisZ());
-            dbMetaMMOLoginInfo.setEulerX(metaMMOLoginInfo.getEulerX());
-            dbMetaMMOLoginInfo.setEulerY(metaMMOLoginInfo.getEulerY());
-            dbMetaMMOLoginInfo.setEulerZ(metaMMOLoginInfo.getEulerZ());
-            dbMetaMMOLoginInfo.setCityId(metaMMOLoginInfo.getCityId());
-            dbMetaMMOLoginInfo.setRegionId(metaMMOLoginInfo.getRegionId());
-            metaMMOLoginInfoRepo.save(dbMetaMMOLoginInfo);
         }
+
     }
 
     /**
@@ -324,7 +247,17 @@ public class WebSocket {
         MMOMessage mmoMessage = new MMOMessage();
         mmoMessage.setMessageType(messageType);
         mmoMessage.setMessage(metaMMOLoginInfo);
-        sendMessageAllOther(userIds, JSON.toJSONString(mmoMessage));
+        if (!clients.containsKey(REDIS_PREFIX.concat(String.valueOf(metaMMOLoginInfo.getUserId())))) {
+            throw new BusinessException("session信息不存在");
+        }
+        userIds.forEach(id -> {
+            try {
+                log.info(String.format("服务器给所有当前区域内在线用户发送消息,当前在线人员为[%S]。消息:[%S]", id, JSON.toJSONString(mmoMessage)));
+                clients.get(id).getBasicRemote().sendText(JSON.toJSONString(mmoMessage));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        });
     }
 
     /**
@@ -341,17 +274,6 @@ public class WebSocket {
         sendMessageTo(JSON.toJSONString(mmoMessage), userId);
     }
 
-    /**
-     * 移除自己信息
-     *
-     * @param metaMMOLoginInfos 信息集合
-     * @return 非自己信息集合
-     */
-    private List<MetaMMOLoginInfo> remove(List<MetaMMOLoginInfo> metaMMOLoginInfos) {
-        return metaMMOLoginInfos.stream()
-                .filter(mmoLoginInfo -> !Objects.equals(mmoLoginInfo.getUserId(), userId)).collect(Collectors.toList());
-    }
-
     /**
      * 给指定用户分发消息
      *
@@ -359,70 +281,50 @@ public class WebSocket {
      * @param toUserId 用户id
      */
     public void sendMessageTo(String message, String toUserId) {
-        clients.values().forEach(webSocket -> {
-            if (webSocket.userId.equals(toUserId)) {
-                log.info(String.format("给指定的在线用户发送消息,当前在线人员为[%S]。消息:[%S]", webSocket.userId.toString(), message));
-                try {
-                    webSocket.session.getBasicRemote().sendText(message);
-                } catch (IOException e) {
-                    log.error("sendMessageTo error", e);
-                }
-            }
-        });
-    }
-
-
-    /**
-     * 分发下线消息给当前城市当前区域中其他玩家
-     *
-     * @param userIds 其他玩家id集合
-     * @param message 消息体
-     */
-    public void sendMessageAllOther(List<String> userIds, String message) {
-        clients.values().forEach(webSocket -> {
-            if (!Objects.equals(webSocket.userId, userId) && userIds.contains(webSocket.userId)) {
-                log.info(String.format("服务器给所有当前区域内在线用户发送消息,当前在线人员为[%S]。消息:[%S]", webSocket.userId.toString(), message));
-                try {
-                    webSocket.session.getBasicRemote().sendText(message);
-                } catch (IOException e) {
-                    log.error("sendMessageAllOther error", e);
-                }
-            }
-        });
+        if (!clients.containsKey(toUserId)) {
+            throw new BusinessException("session信息不存在");
+        }
+        log.info(String.format("给指定的在线用户发送消息,当前在线人员为[%S]。消息:[%S]", toUserId, message));
+        try {
+            clients.get(toUserId).getBasicRemote().sendText(message);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     /**
-     * 分发消息给所有玩家
+     * 构建玩家登陆信息
      *
-     * @param message 消息体
+     * @param jsonObject 玩家位置等信息json对象
+     * @param cityId     城市id
+     * @param regionId   区域id
+     * @return 玩家位置信息
      */
-    public void sendMessageAll(String message) {
-        clients.values().forEach(webSocket -> {
-            log.info(String.format("服务器给所有当前区域内在线用户发送消息,当前在线人员为[%S]。消息:[%S]", webSocket.userId.toString(), message));
-            try {
-                webSocket.session.getBasicRemote().sendText(message);
-            } catch (IOException e) {
-                log.error("sendMessageAll error", e);
-            }
-        });
-    }
-
-    private MetaMMOLoginInfo buildMetaMMOLoginInfo(JSONObject jsonObject, Long cityId, Long regionId) {
-        // 拿到自己进入地图市时的信息通知给其他人,获取当前区域内其他玩家信息
-        String role = jsonObject.getString("role");
+    private MetaMMOLoginInfo buildMetaMMOLoginInfo(JSONObject jsonObject, Long cityId, Long regionId, String nickName, String userId) {
         // 获取到进入地图时自己的信息
         MetaMMOLoginInfo metaMMOLoginInfo = new MetaMMOLoginInfo();
-        buildMetaMMOLoginInfo(metaMMOLoginInfo, jsonObject);
-        metaMMOLoginInfo.setUserId(Long.parseLong(userId));
+        buildCommonProperty(metaMMOLoginInfo, jsonObject);
         metaMMOLoginInfo.setCityId(cityId);
         metaMMOLoginInfo.setRegionId(regionId);
-        if (StringUtils.isNotBlank(role)) {
-            metaMMOLoginInfo.setRole(role);
+        metaMMOLoginInfo.setUserId(Long.parseLong(userId));
+        metaMMOLoginInfo.setNickname(nickName);
+        if (Objects.nonNull(jsonObject.getString("role"))) {
+            metaMMOLoginInfo.setRole(jsonObject.getString("role"));
+        }
+        if (Objects.nonNull(jsonObject.getString("id"))) {
+            metaMMOLoginInfo.setId(Long.parseLong(jsonObject.getString("id")));
         }
+        metaMMOLoginInfo.setCityId(cityId);
         return metaMMOLoginInfo;
     }
 
-    private void buildMetaMMOLoginInfo(MetaMMOLoginInfo metaMMOLoginInfo, JSONObject jsonObject) {
+    /**
+     * 根据jsonObject构建玩家位置信息
+     *
+     * @param metaMMOLoginInfo 玩家登陆信息
+     * @param jsonObject       玩家位置信息json对象
+     */
+    private void buildCommonProperty(MetaMMOLoginInfo metaMMOLoginInfo, JSONObject jsonObject) {
         if (Objects.nonNull(jsonObject.getString("axisX"))) {
             metaMMOLoginInfo.setAxisX(Float.parseFloat(jsonObject.getString("axisX")));
         }
@@ -441,8 +343,58 @@ public class WebSocket {
         if (Objects.nonNull(jsonObject.getString("eulerZ"))) {
             metaMMOLoginInfo.setEulerZ(Float.parseFloat(jsonObject.getString("eulerZ")));
         }
-        if (Objects.nonNull(jsonObject.getString("nickName"))) {
-            metaMMOLoginInfo.setNickname(jsonObject.getString("nickName"));
+        if (Objects.nonNull(jsonObject.getString("top"))) {
+            metaMMOLoginInfo.setTop(Integer.parseInt(jsonObject.getString("top")));
+        }
+        if (Objects.nonNull(jsonObject.getString("hat"))) {
+            metaMMOLoginInfo.setHat(Integer.parseInt(jsonObject.getString("hat")));
+        }
+        if (Objects.nonNull(jsonObject.getString("down"))) {
+            metaMMOLoginInfo.setDown(Integer.parseInt(jsonObject.getString("down")));
+        }
+        if (Objects.nonNull(jsonObject.getString("shoes"))) {
+            metaMMOLoginInfo.setShoes(Integer.parseInt(jsonObject.getString("shoes")));
+        }
+        if (Objects.nonNull(jsonObject.getString("anim"))) {
+            metaMMOLoginInfo.setAnim(Integer.parseInt(jsonObject.getString("anim")));
+        }
+        if (Objects.nonNull(jsonObject.getString("emoji"))) {
+            metaMMOLoginInfo.setEmoji(Integer.parseInt(jsonObject.getString("emoji")));
+        }
+    }
+
+    /**
+     * 校验参数
+     *
+     * @param jsonObject 参数
+     * @return 校验结果
+     */
+    private MetaServiceResult checkParams(JSONObject jsonObject) {
+        if (Objects.isNull(jsonObject)) {
+            return MetaServiceResult.returnError("Illegal parameter : jsonObject can not be null");
+        }
+        if (Objects.isNull(jsonObject.getString("type"))) {
+            return MetaServiceResult.returnError("Illegal parameter : type can not be null");
+        }
+        if (Objects.isNull(jsonObject.getString("cityId"))) {
+            return MetaServiceResult.returnError("Illegal parameter : cityId can not be null");
+        }
+        if (Objects.isNull(jsonObject.getString("regionId"))) {
+            return MetaServiceResult.returnError("Illegal parameter : regionId can not be null");
+        }
+        if (Objects.isNull(jsonObject.getString("id"))) {
+            return MetaServiceResult.returnError("Illegal parameter : id can not be null");
+        }
+        return MetaServiceResult.returnSuccess("check success");
+    }
+
+    private List<String> remove(String key, String userId) {
+        List<String> userIds = redisTemplate.opsForList().range(REDIS_PREFIX.concat(key), 0, -1);
+        //  去除当前玩家id
+        List<String> otherUserIds = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(userIds)) {
+            otherUserIds = userIds.stream().filter(id -> !Objects.equals(id, REDIS_PREFIX.concat(userId))).collect(Collectors.toList());
         }
+        return otherUserIds;
     }
 }