Files
hjha-server/GameModule/Manager/GameMessageManager.cs
xiaoou e9616125ce feat: initial commit - HJHA game server full source
6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) +
game logic (GameFix/GameDAL/ServerData) +
network layer (NetWorkMessage) +
data layer (ObjectModel) +
utilities (MrWu/Core/Config/CloudAPI/dll) +
adapters (zyxAdapter/base)

.NET 8.0 C# solution, 16 projects, 958 source files
2026-07-07 12:02:15 +08:00

593 lines
21 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Concurrent;
using System.Configuration;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using GameData;
using GameData;
using GameMessage;
using MessagePack;
using MrWu.Debug;
using MrWu.RabbitMQ;
using Newtonsoft.Json;
using Server.Core;
using Server.Data;
using Server.Data.Module;
using Server.MQ;
using Server.Net;
using Server.Pack;
using UnityGame;
namespace Server
{
public class GameMessageManager : SingleInstance<GameMessageManager>, IDisposable
{
private bool isStart = false;
/// <summary>
/// 等待处理的消息
/// </summary>
private readonly ConcurrentQueue<PackGroup> waitHandleMsg = new ConcurrentQueue<PackGroup>();
private readonly ConcurrentQueue<PackGroup> idlePackGroup = new ConcurrentQueue<PackGroup>();
private ModuleType _moduleType;
private int _moduleId;
private int Port;
public void Start(ModuleType moduleType,int port,int gameid)
{
if (isStart)
{
return;
}
this._moduleType = moduleType;
this._moduleId = (int)moduleType;
if (port > 0)
{
GameNetManager.Instance.ConnectedEvt += OnConnected;
GameNetManager.Instance.DisConnectedEvt += OnDisconnected;
GameNetManager.Instance.ReceiveEvt += OnReceived;
GameNetManager.Instance.Start($"/serid{gameid}/", port);
Port = port;
}
MessageDispatcher.Instance.AddListener(MessageCode.ClientPackRequest, OnClientPackRequest);
Debug.Info($"启动监听:{port} {gameid}");
isStart = true;
}
public void Update()
{
if (isStart)
{
if (Port > 0)
{
GameNetManager.Instance.Update();
}
while (true)
{
if (waitHandleMsg.TryDequeue(out PackGroup packGroup))
{
OnReceived(packGroup.Session,packGroup.HeadWrapper);
packGroup.HeadWrapper.Dispose();
ReleasePackGroup(packGroup);
}
else
{
break;
}
}
}
}
public void Dispose()
{
if (isStart)
{
if (Port > 0)
{
GameNetManager.Instance.ConnectedEvt -= OnConnected;
GameNetManager.Instance.DisConnectedEvt -= OnDisconnected;
GameNetManager.Instance.ReceiveEvt -= OnReceived;
GameNetManager.Instance.Dispose();
}
isStart = false;
}
}
private void OnConnected(Session session)
{
PackHead head = PackHead.Create();
head.packlx = ServerPackAgreement.connecOk;
session.SendPack(head);
head.Dispose();
}
private void OnDisconnected(Session session)
{
if (session.UserData == null)
{
return;
}
int userid = session.UserData.Userid;
if (!GameSessionManager.Instance.RemovePlayerSession(userid, session)) {
Debug.Error("玩家未移除链接!");
return;
}
GameDispatcher.Instance.DispatchNextFrame(GameMsgId.DisConnected, userid);
}
private void OnReceived(IUserSession session, byte[] data)
{
int packlx = 0;
try
{
string jsonData = Encoding.UTF8.GetString(data);
HeadWrapper headWrapper = JsonPack.GetData<HeadWrapper>(jsonData);
headWrapper.head.ip = session.RemoteIPAddress.ToString();
headWrapper.IsText = true;
if (headWrapper == null || headWrapper.head == null)
{
Debug.Error($"解包失败,收到的消息:{jsonData}");
session.DisConnected();
return;
}
if (session.UserData != null)
{
headWrapper.head.userid = session.UserData.Userid;
}
//输出毫秒值
//Debug.Info($"收包线程:{Thread.CurrentThread.ManagedThreadId},{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");
waitHandleMsg.Enqueue(GetPackGroup(session, headWrapper));
}
catch (Exception e)
{
Debug.Error($"收包处理错误 packlx:{packlx} {e.Message}");
}
}
private Task OnClientPackRequest(GamePacket gamePacket)
{
//Debug.Log("收到客户端来的包!");
if (gamePacket.MessageData is ClientPackRequest request)
{
Debug.Log($"head:{request.Head.Length}");
PackHead head = MessagePackSerializer.Deserialize<PackHead>(request.Head);
head.ip = gamePacket.Session.RemoteIPAddress.ToString();
if (gamePacket.Session.UserData != null)
{
head.userid = gamePacket.Session.UserData.Userid;
Debug.Log($"取服务器中绑定的数据:{head.userid}");
head.plat = gamePacket.Session.UserData.Plat.ToString();
head.platValue = gamePacket.Session.UserData.Plat;
head.clientVer = gamePacket.Session.UserData.ClientVer;
}
else
{
Debug.Log($"包内带的数据:{head.userid}");
}
HeadWrapper headWrapper = HeadWrapper.Create(head, request.Data);
if (gamePacket.Session is ProxySession temp)
{
waitHandleMsg.Enqueue(GetPackGroup(temp.SourceSession, headWrapper));
}
}
return Task.CompletedTask;
}
private void OnReceived(IUserSession session, HeadWrapper headWrapper)
{
PackHead head = headWrapper.head;
if (head.Util == null)
{
head.Util = GameBase.instance.myUtil;
}
switch (head.packlx)
{
case ServerPackAgreement.SocketPing: //测试用的
if (session.UserData != null)
Debug.Log("收到测试包了!");
session.SendPack(head,headWrapper.jsonMessage);
break;
case ServerPackAgreement.GetPlayerGameInfo: //获取玩家所有的游戏信息
GetPlayerGameInfo(head, session);
break;
case ServerPackAgreement.registeredSocket: //登录在本Socket中注册玩家
Debug.Log("来包绑定Socket!");
AddUser(head, (headWrapper.IsBinary ? headWrapper.Data2Text : headWrapper.jsonMessage), session);
break;
case ServerPackAgreement.closeSocket: //连接断开
session.DisConnected();
break;
case ServerPackAgreement.PushLogin: //强行登录
break;
case ServerPackAgreement.Heartbeat: //处理心跳
// if (head.otherInt != null)
// {
// Debug.Info($"处理心跳:{head.otherInt[0]} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");
// }
// else
// {
// Debug.Info("心跳包??");
// }
DoHeart(head,session);
break;
// case GamePackAgreement.EveryGame://任意游戏模块处理
// deliveyGame_(head,messagedata);
// break;
case GamePackAgreement.DoMessgae: //处理消息转发
break;
case GamePackAgreement.UpdateSocketCryptKey: //应客户端要求更新加密密钥
break;
default: //发送给指定游戏模块
if (session.UserData == null)
{
Debug.ImportantLog($"收到未知来历的包裹:{head.packlx}");
return;
}
Debug.Log("收到包裹:" + head.packlx);
//665000
if (head.packlx >= Game.Data.GameData.PackCardInt)
{
if ((head.packlx / Game.Data.GameData.PackCardInt) != _moduleId)
{
Debug.Warning("收到未解析的包裹!" + head.packlx);
return;
}
head.packlx = head.packlx % Game.Data.GameData.PackCardInt;
}
GamePack gamePack = null;
if (headWrapper.IsText)
{
gamePack = GamePack.Create(head, headWrapper.jsonMessage);
}
else
{
gamePack = GamePack.Create(head, headWrapper.Data);
}
GameManager.instance.DoPack(gamePack);
break;
}
}
/// <summary>
/// 处理心跳包
/// </summary>
private void DoHeart(PackHead head, IUserSession session) {
if (session.UserData == null) {
return;
}
session.SendPack(head);
}
private void AddUser(PackHead head, string jsonMessage, IUserSession session)
{
if (head.userid <= 0)
{
Debug.Log("userid is zero");
return;
}
//有uuid 处理uuid 没有 uuid 创建 uuid
BindSocket bindSocket = null;
if (!string.IsNullOrEmpty(jsonMessage))
{
bindSocket = JsonPack.GetData<BindSocket>(jsonMessage);
}
else
{
// 先临时生成uuid后续升级可以把这个删除,没有提供uuid的包提示升级
bindSocket = new BindSocket()
{
SeesionUUID = SessionUUIDManager.Instance.CreateSessionUUID(head.userid)
};
}
int userid = SessionUUIDManager.Instance.CheckSessionUUID(bindSocket.SeesionUUID);
if (userid != head.userid)
{
//登录过期,请重新登录
SendLoginResult(head, -1, session);
session.DisConnected();
return;
}
IUserSession beforeSession = GameSessionManager.Instance.FindSession(userid);
if (beforeSession != null) { //这个玩家已经有链接了
if (beforeSession == session)
{
Debug.Warning($"同一个链接发送过来的注册,已经注册过了! {userid}");
return;
}
Debug.Warning("--已经有这个链接了!" + head.userid + "," + beforeSession.IsDisConnected);
if (beforeSession.IsDisConnected)
{
Debug.Error($"已经有这个连接了:{head.userid}");
}
else
{
if(beforeSession.UserData != null)
{
Debug.Error($"--- ForceDisConnected UserId:{userid} beforeSession:{beforeSession.RemoteIPAddress} session:{session.RemoteIPAddress} {beforeSession.GetType().FullName} DeveiceInfoId:{beforeSession.UserData.DeviceInfo} {bindSocket.DeviceInfoId}");
}
else
{
Debug.Error($"beforeSession UserData is null userid:{userid}");
}
}
//断线,但是有可能还未发完包
// 先把断线逻辑处理完
if (beforeSession is Session)
{
SendLoginResult(head, -4, beforeSession);
GameNetManager.Instance.ForceDisconnected(beforeSession.Id);
}
else if (beforeSession is UserSession userSession)
{
userSession.ForceDiscConnect(ServerFin.FinCode_RemoteLogin,userid);
Debug.ImportantLog($"上一个强制下线:{userSession.Id} {ServerFin.FinCode_RemoteLogin}");
//要处理下线逻辑
}
SendLoginResult(head, -9, session);
} else
{
BindUser(session, userid, bindSocket, head);
}
}
private void BindUser(IUserSession session,int userid, BindSocket bindSocket,PackHead head)
{
object lockObj = null;
if (session is Session userSession)
{
lockObj = userSession.DisConnectLock;
}
else if (session is UserSession _userSession)
{
lockObj = new object();
}
lock (lockObj)
{
if (session.IsDisConnected)
{
Debug.Error("玩家链接已经断开,不处理!");
return;
}
session.BindUser(userid, bindSocket.SeesionUUID, head.clientVer,head.platValue,bindSocket.DeviceInfoId,false,bindSocket.StoreType);
//这个玩家正常
if (GameSessionManager.Instance.AddPlayerSession(head.userid, session))
{
Debug.Info("绑定完成!");
SendLoginResult(head, 1, session);
}
else
{
Debug.Error("玩家没有添加成功!");
}
}
}
/// <summary>
/// 发送登录结果包
/// </summary>
/// <param name="head"></param>
/// <param name="style"></param>
/// <param name="session"></param>
private void SendLoginResult(PackHead head, int style, IUserSession session, playerData pl = null) {
head.packlx = GamePackAgreement.registeredSocket;
SocketRegResult result = SocketRegResult.GetSocketRegResult(style);
result.pldata = pl;
session.SendPack(head, result);
}
/// <summary>
/// 获取玩家所在的游戏信息
/// </summary>
/// <param name="head">包头</param>
/// <param name="session">链接</param>
private async void GetPlayerGameInfo(PackHead head, IUserSession session) {
if (session.UserData == null) {
Debug.Error("897c570e-6571-4958-adaa-e8f2e48f2db1:用户未链接完成!" + head.userid);
return;
}
int clickGame = 0;
if (head.otherInt != null && head.otherInt.Length > 0) {
clickGame = head.otherInt[0];
}
PlayerLockInfo pllockinfo = await PlayerFun.GetPlayerLockInfoAsync(head.userid);
head = PackHead.Create(ServerPackAgreement.InGameInfo);
PlayerGameInfo pgi = null;
//这个包是给朋友房用的,朋友房先查询是不是在游戏中,如果在就提示玩家,不在才让进朋友房
if (pllockinfo != null) {
pgi = new PlayerGameInfo(pllockinfo.gameid, pllockinfo.isFriend ? 1 : 0,1, clickGame);
} else {
pgi = new PlayerGameInfo(0, 0, 2, clickGame);
}
session.SendPack(head,pgi);
head.Dispose();
}
private PackGroup GetPackGroup(IUserSession session,HeadWrapper headWrapper)
{
if (!idlePackGroup.TryDequeue(out PackGroup packGroup))
{
packGroup = new PackGroup();
}
packGroup.Session = session;
packGroup.HeadWrapper = headWrapper;
return packGroup;
}
private void ReleasePackGroup(PackGroup packGroup)
{
packGroup.Clear();
idlePackGroup.Enqueue(packGroup);
}
public bool ForceOffLine(int userid,bool isSendPack)
{
IUserSession session = GameSessionManager.Instance.FindSession(userid);
if (session == null)
{
Debug.Info("没找到玩家!" + userid);
return false;
}
else
{
if (isSendPack)
{
PackHead head = PackHead.Create(ServerPackAgreement.registeredSocket);
SocketRegResult plr = SocketRegResult.GetSocketRegResult(-4);
session.SendPack(head,plr);
head.Dispose();
}
session.DisConnected();
return true;
}
}
private class PackGroup
{
public IUserSession Session;
public HeadWrapper HeadWrapper;
public void Clear()
{
Session = null;
HeadWrapper = null;
}
}
}
public static class SessionExtend
{
public static void SendPack(this IUserSession session, PackHead head, byte[] data)
{
if (session == null)
{
return;
}
HeadWrapper headWrapper = HeadWrapper.Create(head, data);
session.SendPack(headWrapper);
headWrapper.Dispose();
}
public static void SendPack(this IUserSession session, PackHead head, object data) {
if (session == null)
{
return;
}
session.SendPack(head, data == null ? null : JsonPack.GetJson(data));
}
public static void SendPack(this IUserSession session, PackHead head, string jsonMessage = null)
{
if (session == null)
{
return;
}
//todo 这里可以用引用池
HeadWrapper headWrapper = HeadWrapper.Create(head, jsonMessage);
session.SendPack(headWrapper);
headWrapper.Dispose();
}
public static void SendPack(this IUserSession session, HeadWrapper value)
{
if (session == null)
{
return;
}
if (session.IsDisConnected)
{
return;
}
//Debug.Info($"发送包数据:{value.head.packlx}");
//这里只能按字符串发送TMD。之前的设计害死人
if (session is Session oldSession)
{
string jsonValue = JsonPack.GetJson(value);
oldSession.Send(jsonValue);
}
else
{
Debug.Log($"发包给客户端: 2122");
byte[] data = value.Data;
if (value.jsonMessage != null)
{
data = Encoding.UTF8.GetBytes(value.jsonMessage);
}
if (data != null)
{
Debug.Log($"发送的数据:{data.Length}");
}
ClientPackResponse response =
ClientPackResponse.Create(MessagePackSerializer.Serialize(value.head), data);
session.Send(response);
response.Dispose();
}
}
}
}