Parcourir la source

找服务接口

Administrator il y a 2 mois
Parent
commit
fbf2a4f4dc

+ 18 - 3
incubator-game/src/main/java/com/incubator/game/constant/RoomStatus.java

@@ -1,12 +1,27 @@
 package com.incubator.game.constant;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class RoomStatus {
     // 服务器IP或者域名地址
     private String name;
     // 在线用户数量
     private Long roomId;
     //房间比赛类型
-    private Long roomType;
+    private Integer roomType;
+
+    //玩家ID
+    private List<String> players = new ArrayList<>();
+
+
+    public List<String> getPlayers() {
+        return players;
+    }
+
+    public void setPlayers(List<String> players) {
+        this.players = players;
+    }
 
     public String getName() {
         return name;
@@ -24,11 +39,11 @@ public class RoomStatus {
         this.roomId = roomId;
     }
 
-    public Long getRoomType() {
+    public Integer getRoomType() {
         return roomType;
     }
 
-    public void setRoomType(Long roomType) {
+    public void setRoomType(Integer roomType) {
         this.roomType = roomType;
     }
 }

+ 29 - 1
incubator-game/src/main/java/com/incubator/game/contest/Contest.java

@@ -7,12 +7,17 @@ import com.incubator.common.log4j.Log;
 import com.incubator.common.util.DateUtils;
 import com.incubator.common.util.StringUtils;
 import com.incubator.game.GGame;
+import com.incubator.game.constant.RedisKeyConstant;
+import com.incubator.game.constant.RoomStatus;
+import com.incubator.game.constant.WkServerStatus;
 import com.incubator.game.data.data.GameData;
 import com.incubator.game.data.data.PromotionLvCO;
 import com.incubator.game.data.data.ext.ContestExt;
+import com.incubator.game.data.jedis.RedisUtil;
 import com.incubator.game.data.mq.RabbitMQUtil;
 import com.incubator.game.data.po.ContestPO;
 import com.incubator.game.handler.contest.GetContestListHandler;
+import com.incubator.game.handler.login.SubRoomHandler;
 import com.incubator.game.player.GPlayer;
 import com.incubator.game.player.Player;
 import com.incubator.game.room.GDRoom;
@@ -357,7 +362,29 @@ public class Contest {
 //            jsonData.put("team", rule.get("teamType")==null?0:rule.get("teamType"));
             jsonData.put("team",0);
             // 房间id
-            jsonData.put("roomId", RoomService.getInstance().randomRoomIdByContest());
+            //jsonData.put("roomId", RoomService.getInstance().randomRoomIdByContest());
+            HashMap<String, RoomStatus> wkToRedis = RedisUtil.getRoomToRedis(RedisKeyConstant.WK_ROOM_MAP);
+            jsonData.put("roomId", SubRoomHandler.randomRoomId7(wkToRedis));
+
+            //保存房间信息
+            RoomStatus roomStatus = new RoomStatus();
+            roomStatus.setRoomId(jsonData.getLong("roomId"));
+            roomStatus.setRoomType(1);
+            //查询服务器信息
+            HashMap<String, WkServerStatus> wkServes = RedisUtil.getWkToRedis(RedisKeyConstant.WK_SERVE);
+            ArrayList<WkServerStatus> wkServerStatuses = new ArrayList<>();
+            for (Map.Entry<String, WkServerStatus> entry : wkServes.entrySet()) {
+                String type1 = entry.getValue().getType();
+                if (type1.equals(String.valueOf(1))){
+                    wkServerStatuses.add(entry.getValue());
+                }
+            }
+            String name = SubRoomHandler.selectLeastPopulatedServer(wkServerStatuses).get().getName();
+            roomStatus.setName(name);
+            // 保存房间信息
+            RedisUtil.saveRoomToRedis(RedisKeyConstant.WK_ROOM_MAP, roomStatus);
+
+
             // 人数模式 2:2人 4:4人
             jsonData.put("playerNum", 4);
             Integer playingTypeOne = (Integer)rule.get("playingTypeOne");
@@ -424,6 +451,7 @@ public class Contest {
                     data.put("roomId", room.data.roomId);
                     data.put("roomType", room.data.type);
                     data.put("type", 1);
+                    data.put("wkIp", roomStatus.getName());
                     Log.debug("比赛开始 : 比赛 : {}, 玩家 : {}", this.data.contestId, this.actors);
                     tmPlayer.receive(CommonProto.Cmd.MatchOfficialStart_VALUE, data);
                 }

+ 35 - 1
incubator-game/src/main/java/com/incubator/game/data/jedis/RedisUtil.java

@@ -810,7 +810,24 @@ public final class RedisUtil {
 			}
 		}
 	}
-
+    /**
+     * 从 Redis 删除单个对象
+	 * @param redisKey Redis 键
+	 * @param key 哈希表中的字段名
+     */
+	public static void delHashToRedis(String redisKey, String key) {
+		Jedis jedis = null;
+		try {
+			jedis = JedisPoolUtil.getJedis();
+			jedis.hdel(redisKey, key);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			if (jedis != null) {
+				jedis.close();
+			}
+		}
+	}
 
 	/**
 	 * 缓存一个WkServerStatus到redis,成功返回1,失败返回0
@@ -891,6 +908,23 @@ public final class RedisUtil {
 		}
 	}
 
+	/**
+	 * 从 Redis 删除 RoomStatus 对象 String redisKey, String name
+	 */
+	public static void delRoomToRedis(String redisKey, String name) {
+		Jedis jedis = null;
+		try {
+			jedis = JedisPoolUtil.getJedis();
+			jedis.hdel(redisKey, name);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			if (jedis != null) {
+				jedis.close();
+			}
+		}
+	}
+
 	/**
 	 * 缓存一个WkServerStatus到redis,成功返回1,失败返回0
 	 * @param redisKey

+ 157 - 0
incubator-game/src/main/java/com/incubator/game/handler/login/SubRoomHandler.java

@@ -0,0 +1,157 @@
+package com.incubator.game.handler.login;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.incubator.common.MessageHandler;
+import com.incubator.common.log4j.Log;
+import com.incubator.common.net.Connection;
+import com.incubator.common.util.RandomUtil;
+import com.incubator.core.net.ws.NetHandler;
+import com.incubator.core.net.ws.WSRequest;
+import com.incubator.core.net.ws.WSResponse;
+import com.incubator.game.constant.RedisKeyConstant;
+import com.incubator.game.constant.RoomStatus;
+import com.incubator.game.constant.WkServerStatus;
+import com.incubator.game.data.jedis.RedisUtil;
+import com.incubator.game.player.Player;
+import com.incubator.game.room.Room;
+import com.incubator.game.room.RoomService;
+import com.incubator.game.util.PlayerUtil;
+import com.incubator.game.util.RoomUtil;
+import com.incubator.message.proto.CommonProto;
+
+import java.util.*;
+
+/**
+ * 创建房间或加入前分服请求
+ *
+ * @author johnc
+ */
+@MessageHandler(id = CommonProto.Cmd.SubRoomReq_VALUE)
+public class SubRoomHandler extends NetHandler {
+
+	@Override
+	public void onDate(Connection session, WSRequest request, WSResponse response) {
+		response.setCmd(CommonProto.Cmd.SubRoomRes_VALUE);
+
+		Player player = (Player) PlayerUtil.getOnlinePlayer(session.getPlayerId());
+		if (player == null) {
+			Log.info("创建房间失败,找不到玩家");
+			response.setCode(CommonProto.Code.SYSTEM_ERR_VALUE);
+			response.setMessage("操作失败");
+			return;
+		}
+		// 玩家是否存在房间
+		HashMap<String, RoomStatus> wkToRedis = RedisUtil.getRoomToRedis(RedisKeyConstant.WK_ROOM_MAP);
+		ArrayList<String> pls = new ArrayList<>();
+		for (Map.Entry<String, RoomStatus> entry : wkToRedis.entrySet()) {
+			String key = entry.getKey();
+			RoomStatus value = entry.getValue();
+			pls.addAll(value.getPlayers());
+		}
+
+		if (pls.contains(player.getId())) {
+			Log.info("玩家已在房间,不可创建房间");
+			response.setCode(CommonProto.Code.PLAYER_ROOM_EXIST_ERR_VALUE);
+			response.setMessage("操作失败");
+			return;
+		}
+		// 判断参数
+		long roomId = request.getDataValue("roomId", Long.class, 0L);
+		if (roomId > 0){
+			//加入房间
+			HashMap<String, WkServerStatus> wkServes = RedisUtil.getWkToRedis(RedisKeyConstant.WK_SERVE);
+			ArrayList<WkServerStatus> wkServerStatuses = new ArrayList<>();
+			for (Map.Entry<String, WkServerStatus> entry : wkServes.entrySet()) {
+				String type1 = entry.getValue().getType();
+				if (type1.equals(String.valueOf(0))){
+					wkServerStatuses.add(entry.getValue());
+				}
+			}
+			String name = selectLeastPopulatedServer(wkServerStatuses).get().getName();
+			JSONObject jsonData = new JSONObject();
+			jsonData.put("roomId", roomId);
+			jsonData.put("wkIp", name);
+			//修改房间信息
+			RoomStatus roomStatus = wkToRedis.get(String.valueOf(roomId));
+			List<String> players = roomStatus.getPlayers();
+			players.add(player.getId());
+			roomStatus.setPlayers(players);
+			RedisUtil.saveRoomToRedis(RedisKeyConstant.WK_ROOM_MAP, roomStatus);
+			// 正常返回
+			response.setData(jsonData);
+		}else {
+
+			// 房间规则
+			JSONObject jsonData = new JSONObject();
+			jsonData.put("roomId", randomRoomId(wkToRedis));
+			//保存房间信息
+			RoomStatus roomStatus = new RoomStatus();
+			roomStatus.setRoomId(jsonData.getLong("roomId"));
+			ArrayList<String> list = new ArrayList<>();
+			list.add(player.getId());
+			roomStatus.setPlayers(list);
+			roomStatus.setRoomType(0);
+			//查询服务器信息
+			HashMap<String, WkServerStatus> wkServes = RedisUtil.getWkToRedis(RedisKeyConstant.WK_SERVE);
+			ArrayList<WkServerStatus> wkServerStatuses = new ArrayList<>();
+			for (Map.Entry<String, WkServerStatus> entry : wkServes.entrySet()) {
+				String type1 = entry.getValue().getType();
+				if (type1.equals(String.valueOf(0))){
+					wkServerStatuses.add(entry.getValue());
+				}
+			}
+			String name = selectLeastPopulatedServer(wkServerStatuses).get().getName();
+			jsonData.put("wkIp", name);
+			roomStatus.setName(name);
+			// 保存房间信息
+			RedisUtil.saveRoomToRedis(RedisKeyConstant.WK_ROOM_MAP, roomStatus);
+			// 正常返回
+			response.setData(jsonData);
+		}
+
+
+	}
+	/**
+	 * 选择在线人数最少的服务器。
+	 *
+	 * @return 最少在线人数的服务器,如果不存在任何在线服务器,则返回 Optional.empty()。
+	 */
+	public  static Optional<WkServerStatus> selectLeastPopulatedServer(List<WkServerStatus> fetchOnlineServers){
+		// 使用流式 API 找到在线人数最少的服务器
+		return fetchOnlineServers.stream()
+				.min(Comparator.comparingInt(WkServerStatus::getNum));
+	}
+	/**
+	 * 生成唯一6位数房间号
+	 *
+	 * @return
+	 */
+	public static long randomRoomId(HashMap<String, RoomStatus> wkToRedis ) {
+		if (wkToRedis == null || wkToRedis.isEmpty()) {
+			return RandomUtil.randomSixDigits();
+		}
+		long roomNumber;
+		// 循环生成,直到找到一个唯一的房间号
+		do {
+			roomNumber = RandomUtil.randomSixDigits();
+		} while (wkToRedis.containsKey(roomNumber));
+		return roomNumber;
+	}
+
+	/**
+	 * 生成唯一7位数房间号
+	 *
+	 * @return
+	 */
+	public static long randomRoomId7(HashMap<String, RoomStatus> wkToRedis ) {
+		if (wkToRedis == null || wkToRedis.isEmpty()) {
+			return  RandomUtil.randomSevenDigits();
+		}
+		long roomNumber;
+		// 循环生成,直到找到一个唯一的房间号
+		do {
+			roomNumber = RandomUtil.randomSevenDigits();
+		} while (wkToRedis.containsKey(roomNumber));
+		return roomNumber;
+	}
+}

+ 9 - 0
incubator-game/src/main/java/com/incubator/game/room/GDRoom.java

@@ -4,9 +4,12 @@ import cn.hutool.json.JSONException;
 import com.alibaba.fastjson2.JSONObject;
 import com.incubator.common.log4j.Log;
 import com.incubator.common.util.RandomUtil;
+import com.incubator.game.constant.RedisKeyConstant;
+import com.incubator.game.constant.RoomStatus;
 import com.incubator.game.contest.Contest;
 import com.incubator.game.contest.ContestService;
 import com.incubator.game.data.entity.ZjUserInfolog;
+import com.incubator.game.data.jedis.RedisUtil;
 import com.incubator.game.data.po.RoomPO;
 import com.incubator.game.player.Player;
 import com.incubator.game.util.CardUtils;
@@ -128,6 +131,12 @@ public class GDRoom extends Room {
         try {
             // 清理房间数据
             this.actors.remove(player.getId());
+            RoomStatus roomToRedis = RedisUtil.getRoomToRedis(RedisKeyConstant.WK_ROOM_MAP, String.valueOf(this.data.roomId));
+            if (roomToRedis != null){
+                List<String> players = roomToRedis.getPlayers();
+                players.remove(player.getId());
+                roomToRedis.setPlayers(players);
+            }
             this.data.playerMap[player.data.pos] = null;
             // todo 房主退出
             if (player.getId().equals(this.data.ownerId)) {

+ 1 - 0
incubator-game/src/main/java/com/incubator/game/room/Room.java

@@ -123,6 +123,7 @@ public class Room implements GRoomInterface {
         this.scheduler = null;
         // 从缓存移除
         RoomService.getInstance().roomMap.remove(this.data.roomId);
+        RedisUtil.delRoomToRedis(RedisKeyConstant.WK_ROOM_MAP, String.valueOf(this.data.roomId));
         //RedisUtil.removeKeyFromRoomMap(RedisKeyConstant.WK_ROOM_MAP, this.data.roomId);
         // 重置房间数据
         this.resetRoom();

+ 9 - 0
incubator-game/src/main/java/com/incubator/game/room/ZDRoom.java

@@ -4,9 +4,12 @@ import cn.hutool.json.JSONException;
 import com.alibaba.fastjson2.JSONObject;
 import com.incubator.common.log4j.Log;
 import com.incubator.common.util.RandomUtil;
+import com.incubator.game.constant.RedisKeyConstant;
+import com.incubator.game.constant.RoomStatus;
 import com.incubator.game.contest.Contest;
 import com.incubator.game.contest.ContestService;
 import com.incubator.game.data.entity.ZjUserInfolog;
+import com.incubator.game.data.jedis.RedisUtil;
 import com.incubator.game.data.po.RoomPO;
 import com.incubator.game.player.Player;
 import com.incubator.game.util.CardUtils;
@@ -118,6 +121,12 @@ public class ZDRoom extends Room {
         try {
             // 清理房间数据
             this.actors.remove(player.getId());
+            RoomStatus roomToRedis = RedisUtil.getRoomToRedis(RedisKeyConstant.WK_ROOM_MAP, String.valueOf(this.data.roomId));
+            if (roomToRedis != null){
+                List<String> players = roomToRedis.getPlayers();
+                players.remove(player.getId());
+                roomToRedis.setPlayers(players);
+            }
             this.data.playerMap[player.data.pos] = null;
             // todo 房主退出
             if (player.getId().equals(this.data.ownerId)) {

+ 2 - 0
incubator-message/src/main/proto/CommonProto.proto

@@ -55,6 +55,8 @@ enum Cmd {
     LeaveRoomRes = 100026;             //玩家离开房间响应
     JoinCompetitionRoomReq = 100027;   // 加入比赛房间请求
     JoinCompetitionRoomRes = 100028;   // 加入比赛房间响应
+    SubRoomReq = 100029;           // 分组IP房间请求
+    SubRoomRes = 100030;           // 分组IP房间响应
 
     // 测试消息 200001-200100
     NormalMsgReq = 200001;     // 普通消息请求(客户端)