You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
8.6 KiB
269 lines
8.6 KiB
using System.Collections.Concurrent;
|
|
using ProtoCSStruct;
|
|
using Sog;
|
|
using Sog.Gate;
|
|
|
|
namespace FrameSync;
|
|
|
|
public class Room
|
|
{
|
|
public readonly int MatchTickInterval = 33;
|
|
public readonly ConcurrentQueue<CSPlayerOpInfo> playerOpInfos = new();
|
|
public uint currFrameIndex = 0;
|
|
public List<(uint, long)> playerSessionIDs = new(20);
|
|
public Dictionary<long, CSJoinRoomRes> playerInfos = new();
|
|
public CSMultFrapBootInfo cacheInfos = new CSMultFrapBootInfo();
|
|
public uint gateServerID;
|
|
public int refCount = 0;
|
|
public bool isFull = false;
|
|
public long matchTimeAcc = -1;
|
|
public RoomMode mode;
|
|
public bool isMatch = false;
|
|
|
|
public bool AddPlayer(ref CSJoinRoomRes joinRoom, uint gateId, long sessionID)
|
|
{
|
|
gateServerID = gateId;
|
|
playerSessionIDs.Add((gateId, sessionID));
|
|
playerInfos.Add(sessionID, joinRoom);
|
|
refCount++;
|
|
|
|
if (mode == RoomMode.None)
|
|
{
|
|
isFull = true;
|
|
}
|
|
else if (mode == RoomMode.Mode1v1)
|
|
{
|
|
isFull = refCount >= 2;
|
|
}
|
|
|
|
return isFull;
|
|
}
|
|
|
|
public void RemovePlayer(uint gateId, long sessionID)
|
|
{
|
|
for (int i = 0; i < playerSessionIDs.Count; i++)
|
|
{
|
|
if (playerSessionIDs[i].Item1 == gateId && playerSessionIDs[i].Item2 == sessionID)
|
|
{
|
|
playerSessionIDs.RemoveAt(i);
|
|
refCount--;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (refCount == 0)
|
|
{
|
|
isMatch = false;
|
|
}
|
|
}
|
|
public void BeginMatch(ServerApp app)
|
|
{
|
|
matchTimeAcc = -1;
|
|
isMatch = true;
|
|
|
|
// sync to all clients
|
|
CSRoomInfoSync infos = new CSRoomInfoSync();
|
|
infos.Mode = mode;
|
|
for (int i = 0; i < playerSessionIDs.Count; i++)
|
|
{
|
|
if (playerInfos.TryGetValue(playerSessionIDs[i].Item2, out CSJoinRoomRes joinRoom) == false)
|
|
{
|
|
TraceLog.Error("Room.BeginMatch playerInfos.TryGetValue failed");
|
|
continue;
|
|
}
|
|
|
|
infos.Poses.Add(joinRoom.Pos);
|
|
infos.Eids.Add(joinRoom.Eid);
|
|
}
|
|
for (int i = 0; i < playerSessionIDs.Count; i++)
|
|
{
|
|
uint gateServerID = playerSessionIDs[i].Item1;
|
|
long sessionID = playerSessionIDs[i].Item2;
|
|
infos.LocalEid = playerInfos[playerSessionIDs[i].Item2].Eid;
|
|
GateService.SendToGate(0, app.GetCluster(), gateServerID, sessionID, (int)CSGameMsgID.RoomInfoSync,
|
|
ref infos);
|
|
}
|
|
}
|
|
|
|
public void AddPlayerOpInfo(ref CSPlayerOpInfo playerOpInfo)
|
|
{
|
|
playerOpInfos.Enqueue(playerOpInfo);
|
|
}
|
|
public void Tick(long nowMs, ServerApp app)
|
|
{
|
|
if (isMatch == false) return; if (matchTimeAcc == -1)
|
|
{
|
|
matchTimeAcc = nowMs;
|
|
return;
|
|
}
|
|
|
|
if (nowMs - matchTimeAcc < MatchTickInterval * (currFrameIndex + 1))
|
|
return;
|
|
|
|
Broadcast(app);
|
|
}
|
|
public void Broadcast(ServerApp app)
|
|
{
|
|
CSFrapBootInfo frapBootInfo = new CSFrapBootInfo();
|
|
currFrameIndex++;
|
|
frapBootInfo.DwKFrapsNo = currFrameIndex;
|
|
|
|
var count = playerOpInfos.Count;
|
|
while (count > 0 && playerOpInfos.TryDequeue(out CSPlayerOpInfo playerOpInfo)) {
|
|
count--;
|
|
frapBootInfo.Ops.Add(playerOpInfo);
|
|
}
|
|
|
|
// 冗余4帧
|
|
// cacheInfos.SpareNum = currFrameIndex;
|
|
// if (cacheInfos.SpareNum >= 4) {
|
|
// cacheInfos.SpareNum = 4;
|
|
// }
|
|
// cacheInfos.SpareFraps.Add(frapBootInfo);
|
|
|
|
for (int i = 0; i < playerSessionIDs.Count; i++) {
|
|
TraceLog.TraceDetail("MatchSystem.Tick send to gateServerID {0}, sessionID {1} frapBootInfo {2}", playerSessionIDs[i].Item1, playerSessionIDs[i].Item2, cacheInfos.SpareFraps[0].DwKFrapsNo);
|
|
GateService.SendToGate(0, app.GetCluster(), playerSessionIDs[i].Item1, playerSessionIDs[i].Item2,
|
|
(int)CSGameMsgID.CsMultFrapBootInfoSync, ref cacheInfos);
|
|
}
|
|
|
|
// 满了
|
|
if (cacheInfos.SpareNum == 4)
|
|
{
|
|
for(int i = 1; i < 4; i++)
|
|
{
|
|
cacheInfos.SpareFraps[i - 1] = cacheInfos.SpareFraps[i];
|
|
}
|
|
cacheInfos.SpareFraps.RemoveAt(3);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static class MatchSystem
|
|
{
|
|
private static ServerApp m_app;
|
|
public static long MatchTickInterval = 33;
|
|
|
|
private static long lastMatchTickTime = 0;
|
|
public static List<Room> s_Rooms = new List<Room>(20);
|
|
private static Dictionary<long, Room> s_Player2Rooms = new Dictionary<long, Room>();
|
|
// private static List<CSPlayerOpInfo> playerOpInfos = new List<CSPlayerOpInfo>(20);
|
|
// private static List<(uint, long)> playerSessionIDs = new List<(uint, long)>(20);
|
|
// private static CSMultFrapBootInfo cacheInfos = new CSMultFrapBootInfo();
|
|
|
|
public static void JoinOrCreateRoom(ref CSJoinRoomReq joinRoom, uint gateServerID, long sessionID)
|
|
{
|
|
// 获取房间
|
|
if (s_Player2Rooms.TryGetValue(sessionID, out Room room))
|
|
{
|
|
CSJoinRoomRes joinRoomRes = new CSJoinRoomRes();
|
|
joinRoomRes.Mode = room.mode;
|
|
joinRoomRes.Pos = room.refCount;
|
|
joinRoomRes.Eid = 10 + room.refCount;
|
|
|
|
GateService.SendToGate(0, m_app.GetCluster(), gateServerID, sessionID, (int)CSGameMsgID.JoinRoomRes, ref joinRoomRes);
|
|
}
|
|
else
|
|
{
|
|
if (s_Rooms.Count > 0)
|
|
{
|
|
// 找没满的
|
|
Room targetRoom = null;
|
|
foreach (var r in s_Rooms)
|
|
{
|
|
if (r.mode == joinRoom.Mode && r.isFull == false)
|
|
{
|
|
targetRoom = r;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (targetRoom != null)
|
|
{
|
|
s_Player2Rooms.Add(sessionID, targetRoom);
|
|
|
|
CSJoinRoomRes joinRoomRes = new CSJoinRoomRes();
|
|
joinRoomRes.Mode = targetRoom.mode;
|
|
joinRoomRes.Pos = targetRoom.refCount;
|
|
joinRoomRes.Eid = 10 + targetRoom.refCount;
|
|
targetRoom.AddPlayer(ref joinRoomRes, gateServerID, sessionID);
|
|
GateService.SendToGate(0, m_app.GetCluster(), gateServerID, sessionID, (int)CSGameMsgID.JoinRoomRes,
|
|
ref joinRoomRes);
|
|
|
|
if (targetRoom.isFull)
|
|
{
|
|
targetRoom.BeginMatch(m_app);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
room = new Room();
|
|
room.mode = joinRoom.Mode;
|
|
// room.AddPlayer(ref joinRoom, gateServerID, sessionID);
|
|
s_Rooms.Add(room);
|
|
s_Player2Rooms.Add(sessionID, room);
|
|
|
|
CSJoinRoomRes joinRoomRes2 = new CSJoinRoomRes();
|
|
joinRoomRes2.Mode = room.mode;
|
|
joinRoomRes2.Pos = room.refCount;
|
|
joinRoomRes2.Eid = 10 + room.refCount;
|
|
|
|
room.AddPlayer(ref joinRoomRes2, gateServerID, sessionID);
|
|
GateService.SendToGate(0, m_app.GetCluster(), gateServerID, sessionID, (int)CSGameMsgID.JoinRoomRes,
|
|
ref joinRoomRes2);
|
|
|
|
if (room.isFull)
|
|
{
|
|
room.BeginMatch(m_app);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void LeaveRoom(uint gateServerID, long sessionID)
|
|
{
|
|
if (s_Player2Rooms.TryGetValue(sessionID, out Room room))
|
|
{
|
|
room.RemovePlayer(gateServerID, sessionID);
|
|
if (room.refCount == 0)
|
|
{
|
|
s_Rooms.Remove(room);
|
|
s_Player2Rooms.Remove(sessionID);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Init(ServerApp app)
|
|
{
|
|
m_app = app;
|
|
s_Player2Rooms.Clear();
|
|
s_Rooms.Clear();
|
|
}
|
|
|
|
public static void AddPlayerOpInfo(ref CSPlayerOpInfo playerOpInfo, uint gateServerID, long sessionID)
|
|
{
|
|
if (s_Player2Rooms.TryGetValue(sessionID, out Room room))
|
|
{
|
|
if (room.isMatch)
|
|
room.AddPlayerOpInfo(ref playerOpInfo);
|
|
}
|
|
}
|
|
|
|
public static void Tick(long nowMs, ServerApp app)
|
|
{
|
|
for (int i = 0; i < s_Rooms.Count; i++)
|
|
{
|
|
if (s_Rooms[i].refCount == 0)
|
|
{
|
|
s_Rooms.RemoveAt(i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < s_Rooms.Count; i++)
|
|
{
|
|
s_Rooms[i].Tick(nowMs, app);
|
|
}
|
|
}
|
|
}
|