|
|
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.izouma.meta.config.Constants;
|
|
|
import com.izouma.meta.domain.MetaMMOLoginInfo;
|
|
|
+import com.izouma.meta.domain.MetaObjectMoveCoordinate;
|
|
|
import com.izouma.meta.dto.MMOMessage;
|
|
|
import com.izouma.meta.dto.MMOSingleMessage;
|
|
|
import com.izouma.meta.dto.MetaRestResult;
|
|
|
@@ -39,13 +40,9 @@ public class MMOWebSocket {
|
|
|
*/
|
|
|
private static final Map<String, Session> clients = new ConcurrentHashMap();
|
|
|
|
|
|
- private final String REDIS_PREFIX = "meta:";
|
|
|
-
|
|
|
- private RedisTemplate redisTemplate;
|
|
|
-
|
|
|
+ private RedisTemplate redisTemplate;
|
|
|
private MetaMMOLoginInfoRepo metaMMOLoginInfoRepo;
|
|
|
-
|
|
|
- private WebsocketCommon websocketCommon;
|
|
|
+ private WebsocketCommon websocketCommon;
|
|
|
|
|
|
private void init() {
|
|
|
if (Objects.isNull(redisTemplate)) {
|
|
|
@@ -63,22 +60,22 @@ public class MMOWebSocket {
|
|
|
public void onOpen(@PathParam("nickName") String nickName, @PathParam("userId") String userId, Session session) {
|
|
|
init();
|
|
|
// 判断当前玩家是否在其他地方登陆
|
|
|
- if (clients.containsKey(REDIS_PREFIX.concat(userId))) {
|
|
|
+ if (clients.containsKey(Constants.REDIS_PREFIX.concat(userId))) {
|
|
|
log.info(String.format("当前玩家[%S]已经在别处登陆,sessionId为[%S]", userId, session.getId()));
|
|
|
// 关闭连接
|
|
|
MMOSingleMessage mmoSingleMessage = new MMOSingleMessage();
|
|
|
mmoSingleMessage.setMessageType(6);
|
|
|
mmoSingleMessage.setMessage("您已在其他地方登录,已为您关闭上次登陆信息");
|
|
|
- websocketCommon.sendMessageTo(clients, JSON.toJSONString(mmoSingleMessage), REDIS_PREFIX.concat(userId));
|
|
|
+ websocketCommon.sendMessageTo(clients, JSON.toJSONString(mmoSingleMessage), Constants.REDIS_PREFIX.concat(userId));
|
|
|
try {
|
|
|
log.info("关闭上次登陆的session连接");
|
|
|
- clients.get(REDIS_PREFIX.concat(userId)).close();
|
|
|
+ clients.get(Constants.REDIS_PREFIX.concat(userId)).close();
|
|
|
} catch (Exception e) {
|
|
|
log.error("session close throw exception:", e);
|
|
|
}
|
|
|
}
|
|
|
log.info("现在来连接的sessionId:" + session.getId() + "玩家id:" + userId + "玩家昵称" + nickName);
|
|
|
- clients.put(REDIS_PREFIX.concat(userId), session);
|
|
|
+ clients.put(Constants.REDIS_PREFIX.concat(userId), session);
|
|
|
// 获取上次登录的信息
|
|
|
MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findLastByUserId(Long.parseLong(userId));
|
|
|
// 玩家登陆信息入库
|
|
|
@@ -92,7 +89,7 @@ public class MMOWebSocket {
|
|
|
mmoMessage.setMessageType(5);
|
|
|
mmoMessage.setMessage(save);
|
|
|
log.info(String.format("通知玩家[%S],本次登陆信息[%S]", userId, JSON.toJSONString(mmoMessage)));
|
|
|
- websocketCommon.sendMessageTo(clients, JSON.toJSONString(mmoMessage), REDIS_PREFIX.concat(userId));
|
|
|
+ websocketCommon.sendMessageTo(clients, JSON.toJSONString(mmoMessage), Constants.REDIS_PREFIX.concat(userId));
|
|
|
}
|
|
|
|
|
|
@OnError
|
|
|
@@ -105,14 +102,14 @@ public class MMOWebSocket {
|
|
|
public void onClose(@PathParam("userId") String userId) {
|
|
|
init();
|
|
|
// 查询地图中玩家信息
|
|
|
- MetaMMOLoginInfo metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(REDIS_PREFIX.concat(userId));
|
|
|
+ MetaMMOLoginInfo metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(Constants.REDIS_PREFIX.concat(userId));
|
|
|
if (Objects.isNull(metaMMOLoginInfo)) {
|
|
|
// 如果缓存中玩家信息为空,根据userId和sessionId查询数据库
|
|
|
- MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findByUserIdAndSessionIdAndDel(Long.parseLong(userId), clients.get(REDIS_PREFIX.concat(userId)).getId(), false);
|
|
|
+ MetaMMOLoginInfo dbMetaMMOLoginInfo = metaMMOLoginInfoRepo.findByUserIdAndSessionIdAndDel(Long.parseLong(userId), clients.get(Constants.REDIS_PREFIX.concat(userId)).getId(), false);
|
|
|
dbMetaMMOLoginInfo.setOffLineTime(LocalDateTime.now());
|
|
|
// 更新离线时间
|
|
|
metaMMOLoginInfoRepo.save(dbMetaMMOLoginInfo);
|
|
|
- clients.remove(REDIS_PREFIX.concat(userId));
|
|
|
+ clients.remove(Constants.REDIS_PREFIX.concat(userId));
|
|
|
return;
|
|
|
}
|
|
|
String key = String.valueOf(metaMMOLoginInfo.getCityId()).concat(":").concat(String.valueOf(metaMMOLoginInfo.getRegionId()));
|
|
|
@@ -129,11 +126,11 @@ public class MMOWebSocket {
|
|
|
ObjUtils.merge(dbMetaMMOLoginInfo, metaMMOLoginInfo);
|
|
|
dbMetaMMOLoginInfo.setOffLineTime(LocalDateTime.now());
|
|
|
metaMMOLoginInfoRepo.save(dbMetaMMOLoginInfo);
|
|
|
- clients.remove(REDIS_PREFIX.concat(userId));
|
|
|
+ clients.remove(Constants.REDIS_PREFIX.concat(userId));
|
|
|
// 删除redis中自己的信息
|
|
|
- redisTemplate.delete(REDIS_PREFIX.concat(userId));
|
|
|
+ redisTemplate.delete(Constants.REDIS_PREFIX.concat(userId));
|
|
|
// 移除地图中自己的信息
|
|
|
- redisTemplate.opsForList().remove(REDIS_PREFIX.concat(key), 0, REDIS_PREFIX.concat(userId));
|
|
|
+ redisTemplate.opsForList().remove(Constants.REDIS_PREFIX.concat(key), 0, Constants.REDIS_PREFIX.concat(userId));
|
|
|
}
|
|
|
|
|
|
@OnMessage
|
|
|
@@ -145,7 +142,7 @@ public class MMOWebSocket {
|
|
|
}
|
|
|
if (Constants.HEART_RECEIVE.equals(message)) {
|
|
|
log.info(String.format("sessionId:[%S] userId:[%S] 连接正常", session.getId(), userId));
|
|
|
- websocketCommon.sendMessageTo(clients, Constants.HEART_RETURN, REDIS_PREFIX.concat(userId));
|
|
|
+ websocketCommon.sendMessageTo(clients, Constants.HEART_RETURN, Constants.REDIS_PREFIX.concat(userId));
|
|
|
return;
|
|
|
}
|
|
|
JSONObject jsonObject = JSON.parseObject(message);
|
|
|
@@ -160,6 +157,23 @@ public class MMOWebSocket {
|
|
|
String regionId = jsonObject.getString("regionId");
|
|
|
String key = cityId.concat(":").concat(regionId);
|
|
|
List<String> otherUserIds = remove(key, userId);
|
|
|
+ if (type == 9) {
|
|
|
+ String objectId = jsonObject.getString("objectId");
|
|
|
+ MetaObjectMoveCoordinate metaObjectMoveCoordinate = null;
|
|
|
+ try {
|
|
|
+ String str = websocketCommon.getRequest("/metaObjectMove/".concat(objectId).concat("/queryCoordinate"));
|
|
|
+ metaObjectMoveCoordinate = JSONObject.parseObject(str, MetaObjectMoveCoordinate.class);
|
|
|
+ } catch (Exception e) {
|
|
|
+ String errMsg = String.format("MetaObjectMoveCoordinate JSON parse throw exception:[%S]", e);
|
|
|
+ log.error(errMsg);
|
|
|
+ }
|
|
|
+ if (Objects.isNull(metaObjectMoveCoordinate)) {
|
|
|
+ log.error(String.format("物体[%S]坐标不存在", objectId));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ buildMessageForSendingToAllOther(otherUserIds, 9, metaObjectMoveCoordinate);
|
|
|
+ return;
|
|
|
+ }
|
|
|
MetaMMOLoginInfo metaMMOLoginInfo;
|
|
|
List<MetaMMOLoginInfo> metaMMOLoginInfos = redisTemplate.opsForValue().multiGet(otherUserIds);
|
|
|
switch (type) {
|
|
|
@@ -169,14 +183,14 @@ public class MMOWebSocket {
|
|
|
if (CollectionUtils.isNotEmpty(otherUserIds)) {
|
|
|
if (CollectionUtils.isNotEmpty(metaMMOLoginInfos)) {
|
|
|
// 分发区域内其他玩家信息给自己
|
|
|
- buildMessageForSendingToUser(REDIS_PREFIX.concat(userId), 1, metaMMOLoginInfos);
|
|
|
+ buildMessageForSendingToUser(Constants.REDIS_PREFIX.concat(userId), 1, metaMMOLoginInfos);
|
|
|
// 分发自己信息给区域内其他玩家
|
|
|
buildMessageForSendingToAllOther(otherUserIds, 4, metaMMOLoginInfo);
|
|
|
}
|
|
|
}
|
|
|
// 将自己信息存到redis中
|
|
|
- redisTemplate.opsForValue().set(REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
|
|
|
- redisTemplate.opsForList().leftPush(REDIS_PREFIX.concat(key), REDIS_PREFIX.concat(userId));
|
|
|
+ redisTemplate.opsForValue().set(Constants.REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
|
|
|
+ redisTemplate.opsForList().leftPush(Constants.REDIS_PREFIX.concat(key), Constants.REDIS_PREFIX.concat(userId));
|
|
|
break;
|
|
|
case 2:
|
|
|
log.info(String.format("当前操作类型为[%S] -> 玩家切换区域", type));
|
|
|
@@ -185,15 +199,15 @@ public class MMOWebSocket {
|
|
|
// 分发自己信息给区域内其他玩家
|
|
|
buildMessageForSendingToAllOther(otherUserIds, 4, metaMMOLoginInfo);
|
|
|
// 分发区域内其他玩家信息给自己
|
|
|
- buildMessageForSendingToUser(REDIS_PREFIX.concat(userId), 1, metaMMOLoginInfos);
|
|
|
+ buildMessageForSendingToUser(Constants.REDIS_PREFIX.concat(userId), 1, metaMMOLoginInfos);
|
|
|
}
|
|
|
- MetaMMOLoginInfo oldMetaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(REDIS_PREFIX.concat(userId));
|
|
|
+ MetaMMOLoginInfo oldMetaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(Constants.REDIS_PREFIX.concat(userId));
|
|
|
if (Objects.isNull(oldMetaMMOLoginInfo)) {
|
|
|
log.error("缺失玩家上次区域的地图缓存信息");
|
|
|
break;
|
|
|
}
|
|
|
String oldKey = String.valueOf(oldMetaMMOLoginInfo.getCityId()).concat(":").concat(String.valueOf(oldMetaMMOLoginInfo.getRegionId()));
|
|
|
- List<String> oldUserIds = redisTemplate.opsForList().range(REDIS_PREFIX.concat(oldKey), 0, -1);
|
|
|
+ List<String> oldUserIds = redisTemplate.opsForList().range(Constants.REDIS_PREFIX.concat(oldKey), 0, -1);
|
|
|
if (CollectionUtils.isEmpty(oldUserIds)) {
|
|
|
log.error("查询不到上次所进入的区域的玩家信息");
|
|
|
break;
|
|
|
@@ -201,14 +215,14 @@ public class MMOWebSocket {
|
|
|
// 分发消息给之前区域的玩家
|
|
|
buildMessageForSendingToAllOther(oldUserIds, 3, oldMetaMMOLoginInfo);
|
|
|
// 清除玩家上次缓存的地图信息
|
|
|
- redisTemplate.opsForList().remove(REDIS_PREFIX.concat(oldKey), 0, REDIS_PREFIX.concat(userId));
|
|
|
+ redisTemplate.opsForList().remove(Constants.REDIS_PREFIX.concat(oldKey), 0, Constants.REDIS_PREFIX.concat(userId));
|
|
|
// 缓存玩家新的地图信息
|
|
|
- redisTemplate.opsForValue().set(REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
|
|
|
- redisTemplate.opsForList().leftPush(REDIS_PREFIX.concat(key), REDIS_PREFIX.concat(userId));
|
|
|
+ redisTemplate.opsForValue().set(Constants.REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
|
|
|
+ redisTemplate.opsForList().leftPush(Constants.REDIS_PREFIX.concat(key), Constants.REDIS_PREFIX.concat(userId));
|
|
|
break;
|
|
|
case 3:
|
|
|
log.info(String.format("当前操作类型为[%S] -> 玩家在地图内移动", type));
|
|
|
- metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(REDIS_PREFIX.concat(userId));
|
|
|
+ metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(Constants.REDIS_PREFIX.concat(userId));
|
|
|
if (Objects.isNull(metaMMOLoginInfo)) {
|
|
|
log.error("缓存中不存在本玩家信息");
|
|
|
break;
|
|
|
@@ -217,11 +231,11 @@ public class MMOWebSocket {
|
|
|
buildCommonProperty(metaMMOLoginInfo, jsonObject);
|
|
|
// 分发玩家信息给区域内其他玩家
|
|
|
buildMessageForSendingToAllOther(otherUserIds, 2, metaMMOLoginInfo);
|
|
|
- redisTemplate.opsForValue().set(REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
|
|
|
+ redisTemplate.opsForValue().set(Constants.REDIS_PREFIX.concat(userId), metaMMOLoginInfo);
|
|
|
break;
|
|
|
case 4:
|
|
|
log.info(String.format("当前操作类型为[%S] -> 玩家进入大厅", type));
|
|
|
- metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(REDIS_PREFIX.concat(userId));
|
|
|
+ metaMMOLoginInfo = (MetaMMOLoginInfo) redisTemplate.opsForValue().get(Constants.REDIS_PREFIX.concat(userId));
|
|
|
if (Objects.isNull(metaMMOLoginInfo)) {
|
|
|
log.error("缓存中不存在本玩家信息");
|
|
|
break;
|
|
|
@@ -263,17 +277,21 @@ public class MMOWebSocket {
|
|
|
/**
|
|
|
* 分发玩家信息给区域内其他玩家
|
|
|
*
|
|
|
- * @param userIds 玩家id集合
|
|
|
- * @param messageType 消息类型
|
|
|
- * @param metaMMOLoginInfo 消息体
|
|
|
+ * @param userIds 玩家id集合
|
|
|
+ * @param messageType 消息类型
|
|
|
+ * @param data 消息体
|
|
|
*/
|
|
|
- private void buildMessageForSendingToAllOther(List<String> userIds, int messageType, MetaMMOLoginInfo metaMMOLoginInfo) {
|
|
|
+ private void buildMessageForSendingToAllOther(List<String> userIds, int messageType, Object data) {
|
|
|
MMOMessage mmoMessage = new MMOMessage();
|
|
|
mmoMessage.setMessageType(messageType);
|
|
|
- mmoMessage.setMessage(metaMMOLoginInfo);
|
|
|
- if (!clients.containsKey(REDIS_PREFIX.concat(String.valueOf(metaMMOLoginInfo.getUserId())))) {
|
|
|
- log.error("session信息不存在");
|
|
|
- return;
|
|
|
+ mmoMessage.setMessage(data);
|
|
|
+ // 进行类型转换和判断
|
|
|
+ if (data instanceof MetaMMOLoginInfo) {
|
|
|
+ MetaMMOLoginInfo metaMMOLoginInfo = (MetaMMOLoginInfo) data;
|
|
|
+ if (!clients.containsKey(Constants.REDIS_PREFIX.concat(String.valueOf(metaMMOLoginInfo.getUserId())))) {
|
|
|
+ log.error("session信息不存在");
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
userIds.forEach(id -> {
|
|
|
try {
|
|
|
@@ -398,6 +416,13 @@ public class MMOWebSocket {
|
|
|
if (Objects.isNull(jsonObject.getString("regionId"))) {
|
|
|
return MetaServiceResult.returnError("Illegal parameter : regionId can not be null");
|
|
|
}
|
|
|
+ int type = Integer.parseInt(jsonObject.getString("type"));
|
|
|
+ if (type == 9) {
|
|
|
+ if (Objects.isNull(jsonObject.getString("objectId"))) {
|
|
|
+ return MetaServiceResult.returnError("Illegal parameter : objectId can not be null");
|
|
|
+ }
|
|
|
+ return MetaServiceResult.returnSuccess("check success");
|
|
|
+ }
|
|
|
if (Objects.isNull(jsonObject.getString("id"))) {
|
|
|
return MetaServiceResult.returnError("Illegal parameter : id can not be null");
|
|
|
}
|
|
|
@@ -405,25 +430,25 @@ public class MMOWebSocket {
|
|
|
}
|
|
|
|
|
|
private List<String> remove(String key, String userId) {
|
|
|
- List<String> userIds = redisTemplate.opsForList().range(REDIS_PREFIX.concat(key), 0, -1);
|
|
|
+ List<String> userIds = redisTemplate.opsForList().range(Constants.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());
|
|
|
+ otherUserIds = userIds.stream().filter(id -> !Objects.equals(id, Constants.REDIS_PREFIX.concat(userId))).collect(Collectors.toList());
|
|
|
}
|
|
|
return otherUserIds;
|
|
|
}
|
|
|
|
|
|
public MetaRestResult<Void> clearMMO(String userId, String regionId, String cityId) {
|
|
|
init();
|
|
|
- if (clients.containsKey(REDIS_PREFIX.concat(userId))) {
|
|
|
+ if (clients.containsKey(Constants.REDIS_PREFIX.concat(userId))) {
|
|
|
String errMsg = String.format("userId[%S]用户mmo连接正常,无法清除缓存!", userId);
|
|
|
log.info(errMsg);
|
|
|
return MetaRestResult.returnError(errMsg);
|
|
|
}
|
|
|
String key = cityId.concat(":").concat(regionId);
|
|
|
- redisTemplate.delete(REDIS_PREFIX.concat(userId));
|
|
|
- redisTemplate.opsForList().remove(REDIS_PREFIX.concat(key), 0, REDIS_PREFIX.concat(userId));
|
|
|
+ redisTemplate.delete(Constants.REDIS_PREFIX.concat(userId));
|
|
|
+ redisTemplate.opsForList().remove(Constants.REDIS_PREFIX.concat(key), 0, Constants.REDIS_PREFIX.concat(userId));
|
|
|
return MetaRestResult.returnSuccess("清除成功");
|
|
|
}
|
|
|
}
|