forked from sin365/AxibugEmuOnline
归档
This commit is contained in:
parent
aab539afdd
commit
7485f016a3
@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Google.Protobuf">
|
||||||
|
<HintPath>..\..\Lib\Google.Protobuf.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="HaoYueNet.ServerNetwork">
|
||||||
|
<HintPath>..\..\Lib\HaoYueNet.ServerNetwork.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_LastSelectedProfileId>G:\Sin365\AxibugEmuOnline\AxibugEmuOnline.Server\AxibugEmuOnline.Server\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,20 @@
|
|||||||
|
namespace AxibugEmuOnline.Server.Common
|
||||||
|
{
|
||||||
|
public static class Helper
|
||||||
|
{
|
||||||
|
public static long GetNowTimeStamp()
|
||||||
|
{
|
||||||
|
return GetTimeStamp(DateTime.Now);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取时间戳
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static long GetTimeStamp(DateTime dt)
|
||||||
|
{
|
||||||
|
TimeSpan ts = dt - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||||
|
return Convert.ToInt64(ts.TotalSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
using Google.Protobuf;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server.Common
|
||||||
|
{
|
||||||
|
public static class ProtoBufHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
public static byte[] Serizlize(IMessage msg)
|
||||||
|
{
|
||||||
|
return msg.ToByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T DeSerizlize<T>(byte[] bytes)
|
||||||
|
{
|
||||||
|
var msgType = typeof(T);
|
||||||
|
object msg = Activator.CreateInstance(msgType);
|
||||||
|
((IMessage)msg).MergeFrom(bytes);
|
||||||
|
return (T)msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace AxibugEmuOnline.Server.Event
|
||||||
|
{
|
||||||
|
public enum EEvent
|
||||||
|
{
|
||||||
|
// 添加你自己需要的事件类型
|
||||||
|
OnUserJoin,
|
||||||
|
OnUserLeave
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,216 @@
|
|||||||
|
using AxibugEmuOnline.Server.Manager;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server.Event
|
||||||
|
{
|
||||||
|
|
||||||
|
public class EventSystem
|
||||||
|
{
|
||||||
|
private static EventSystem instance = new EventSystem();
|
||||||
|
public static EventSystem Instance { get { return instance; } }
|
||||||
|
|
||||||
|
private Dictionary<EEvent, List<Delegate>> eventDic = new Dictionary<EEvent, List<Delegate>>(128);
|
||||||
|
|
||||||
|
private EventSystem() { }
|
||||||
|
|
||||||
|
|
||||||
|
#region RegisterEvent
|
||||||
|
public void RegisterEvent(EEvent evt, Action callback)
|
||||||
|
{
|
||||||
|
InterRegisterEvent(evt, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterEvent<T1>(EEvent evt, Action<T1> callback)
|
||||||
|
{
|
||||||
|
InterRegisterEvent(evt, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterEvent<T1, T2>(EEvent evt, Action<T1, T2> callback)
|
||||||
|
{
|
||||||
|
InterRegisterEvent(evt, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterEvent<T1, T2, T3>(EEvent evt, Action<T1, T2, T3> callback)
|
||||||
|
{
|
||||||
|
InterRegisterEvent(evt, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterEvent<T1, T2, T3, T4>(EEvent evt, Action<T1, T2, T3, T4> callback)
|
||||||
|
{
|
||||||
|
InterRegisterEvent(evt, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InterRegisterEvent(EEvent evt, Delegate callback)
|
||||||
|
{
|
||||||
|
if (eventDic.ContainsKey(evt))
|
||||||
|
{
|
||||||
|
if (eventDic[evt].IndexOf(callback) < 0)
|
||||||
|
{
|
||||||
|
eventDic[evt].Add(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eventDic.Add(evt, new List<Delegate>() { callback });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UnregisterEvent
|
||||||
|
|
||||||
|
public void UnregisterEvent(EEvent evt, Action callback)
|
||||||
|
{
|
||||||
|
Delegate tempDelegate = callback;
|
||||||
|
InterUnregisterEvent(evt, tempDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnregisterEvent<T1>(EEvent evt, Action<T1> callback)
|
||||||
|
{
|
||||||
|
Delegate tempDelegate = callback;
|
||||||
|
InterUnregisterEvent(evt, tempDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnregisterEvent<T1, T2>(EEvent evt, Action<T1, T2> callback)
|
||||||
|
{
|
||||||
|
Delegate tempDelegate = callback;
|
||||||
|
InterUnregisterEvent(evt, tempDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnregisterEvent<T1, T2, T3>(EEvent evt, Action<T1, T2, T3> callback)
|
||||||
|
{
|
||||||
|
Delegate tempDelegate = callback;
|
||||||
|
InterUnregisterEvent(evt, tempDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnregisterEvent<T1, T2, T3, T4>(EEvent evt, Action<T1, T2, T3, T4> callback)
|
||||||
|
{
|
||||||
|
Delegate tempDelegate = callback;
|
||||||
|
InterUnregisterEvent(evt, tempDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InterUnregisterEvent(EEvent evt, Delegate callback)
|
||||||
|
{
|
||||||
|
if (eventDic.ContainsKey(evt))
|
||||||
|
{
|
||||||
|
eventDic[evt].Remove(callback);
|
||||||
|
if (eventDic[evt].Count == 0) eventDic.Remove(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region PostEvent
|
||||||
|
public void PostEvent<T1, T2, T3, T4>(EEvent evt, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
|
||||||
|
{
|
||||||
|
List<Delegate> eventList = GetEventList(evt);
|
||||||
|
if (eventList != null)
|
||||||
|
{
|
||||||
|
foreach (Delegate callback in eventList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((Action<T1, T2, T3, T4>)callback)(arg1, arg2, arg3, arg4);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Error(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostEvent<T1, T2, T3>(EEvent evt, T1 arg1, T2 arg2, T3 arg3)
|
||||||
|
{
|
||||||
|
List<Delegate> eventList = GetEventList(evt);
|
||||||
|
if (eventList != null)
|
||||||
|
{
|
||||||
|
foreach (Delegate callback in eventList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((Action<T1, T2, T3>)callback)(arg1, arg2, arg3);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Error(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostEvent<T1, T2>(EEvent evt, T1 arg1, T2 arg2)
|
||||||
|
{
|
||||||
|
List<Delegate> eventList = GetEventList(evt);
|
||||||
|
if (eventList != null)
|
||||||
|
{
|
||||||
|
foreach (Delegate callback in eventList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((Action<T1, T2>)callback)(arg1, arg2);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Error(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostEvent<T>(EEvent evt, T arg)
|
||||||
|
{
|
||||||
|
List<Delegate> eventList = GetEventList(evt);
|
||||||
|
if (eventList != null)
|
||||||
|
{
|
||||||
|
foreach (Delegate callback in eventList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((Action<T>)callback)(arg);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Error(e.Message + ", method name : " + callback.Method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostEvent(EEvent evt)
|
||||||
|
{
|
||||||
|
List<Delegate> eventList = GetEventList(evt);
|
||||||
|
if (eventList != null)
|
||||||
|
{
|
||||||
|
foreach (Delegate callback in eventList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((Action)callback)();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Error(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有事件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="evt"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private List<Delegate> GetEventList(EEvent evt)
|
||||||
|
{
|
||||||
|
if (eventDic.ContainsKey(evt))
|
||||||
|
{
|
||||||
|
List<Delegate> tempList = eventDic[evt];
|
||||||
|
if (null != tempList)
|
||||||
|
{
|
||||||
|
return tempList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
using AxibugProtobuf;
|
||||||
|
using AxibugEmuOnline.Server.Common;
|
||||||
|
using AxibugEmuOnline.Server.NetWork;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server.Manager
|
||||||
|
{
|
||||||
|
public class ChatManager
|
||||||
|
{
|
||||||
|
public ChatManager()
|
||||||
|
{
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdChatmsg, RecvPlayerChatMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecvPlayerChatMsg(Socket sk, byte[] reqData)
|
||||||
|
{
|
||||||
|
ClientInfo _c = ServerManager.g_ClientMgr.GetClientForSocket(sk);
|
||||||
|
ServerManager.g_Log.Debug("收到聊天消息请求");
|
||||||
|
Protobuf_ChatMsg msg = ProtoBufHelper.DeSerizlize<Protobuf_ChatMsg>(reqData);
|
||||||
|
byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_ChatMsg_RESP()
|
||||||
|
{
|
||||||
|
ChatMsg = msg.ChatMsg,
|
||||||
|
NickName = _c.Account,
|
||||||
|
Date = Helper.GetNowTimeStamp()
|
||||||
|
});
|
||||||
|
ServerManager.g_ClientMgr.ClientSendALL((int)CommandID.CmdChatmsg, (int)ErrorCode.ErrorOk, respData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,241 @@
|
|||||||
|
using AxibugProtobuf;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Timers;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server.Manager
|
||||||
|
{
|
||||||
|
public class ClientInfo
|
||||||
|
{
|
||||||
|
public long UID { get; set; }
|
||||||
|
public string Account { get; set; }
|
||||||
|
public Socket _socket { get; set; }
|
||||||
|
public bool IsOffline { get; set; } = false;
|
||||||
|
public DateTime LogOutDT { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClientManager
|
||||||
|
{
|
||||||
|
private List<ClientInfo> ClientList = new List<ClientInfo>();
|
||||||
|
private Dictionary<Socket, ClientInfo> _DictSocketClient = new Dictionary<Socket, ClientInfo>();
|
||||||
|
private Dictionary<long?, ClientInfo> _DictUIDClient = new Dictionary<long?, ClientInfo>();
|
||||||
|
private long TestUIDSeed = 0;
|
||||||
|
|
||||||
|
private System.Timers.Timer _ClientCheckTimer;
|
||||||
|
private long _RemoveOfflineCacheMin;
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化并指定检查时间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ticktime">tick检查毫秒数</param>
|
||||||
|
/// <param name="RemoveOfflineCache">清理掉线分钟数</param>
|
||||||
|
public void Init(long ticktime, long RemoveOfflineCacheMin)
|
||||||
|
{
|
||||||
|
//换算成毫秒
|
||||||
|
_RemoveOfflineCacheMin = RemoveOfflineCacheMin;
|
||||||
|
_ClientCheckTimer = new System.Timers.Timer();
|
||||||
|
_ClientCheckTimer.Interval = ticktime;
|
||||||
|
_ClientCheckTimer.AutoReset = true;
|
||||||
|
_ClientCheckTimer.Elapsed += new ElapsedEventHandler(ClientCheckClearOffline_Elapsed);
|
||||||
|
_ClientCheckTimer.Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long GetNextUID()
|
||||||
|
{
|
||||||
|
return ++TestUIDSeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClientCheckClearOffline_Elapsed(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
DateTime CheckDT = DateTime.Now.AddMinutes(-1 * _RemoveOfflineCacheMin);
|
||||||
|
ClientInfo[] OfflineClientlist = ClientList.Where(w => w.IsOffline == true && w.LogOutDT < CheckDT).ToArray();
|
||||||
|
|
||||||
|
Console.WriteLine("开始清理离线过久的玩家的缓存");
|
||||||
|
for (int i = 0; i < OfflineClientlist.Length; i++)
|
||||||
|
{
|
||||||
|
//to do 掉线处理
|
||||||
|
RemoveClient(OfflineClientlist[i]);
|
||||||
|
}
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//通用处理
|
||||||
|
#region clientlist 处理
|
||||||
|
|
||||||
|
public ClientInfo JoinNewClient(Protobuf_Login data, Socket _socket)
|
||||||
|
{
|
||||||
|
//也许这个函数需加lock
|
||||||
|
ClientInfo cinfo = GetClientForSocket(_socket);
|
||||||
|
//如果连接还在
|
||||||
|
if (cinfo != null)
|
||||||
|
{
|
||||||
|
cinfo.IsOffline = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cinfo = new ClientInfo()
|
||||||
|
{
|
||||||
|
UID = GetNextUID(),
|
||||||
|
_socket = _socket,
|
||||||
|
Account = data.Account,
|
||||||
|
IsOffline = false,
|
||||||
|
};
|
||||||
|
AddClient(cinfo);
|
||||||
|
}
|
||||||
|
return cinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 增加用户
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
void AddClient(ClientInfo clientInfo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("追加连接玩家 UID=>" + clientInfo.UID + " | " + clientInfo.Account);
|
||||||
|
lock (ClientList)
|
||||||
|
{
|
||||||
|
_DictUIDClient.Add(clientInfo.UID, clientInfo);
|
||||||
|
_DictSocketClient.Add(clientInfo._socket, clientInfo);
|
||||||
|
ClientList.Add(clientInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ex.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理连接
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
public void RemoveClient(ClientInfo client)
|
||||||
|
{
|
||||||
|
lock (ClientList)
|
||||||
|
{
|
||||||
|
if (_DictUIDClient.ContainsKey(client.UID))
|
||||||
|
_DictUIDClient.Remove(client.UID);
|
||||||
|
|
||||||
|
if (_DictSocketClient.ContainsKey(client._socket))
|
||||||
|
_DictSocketClient.Remove(client._socket);
|
||||||
|
|
||||||
|
ClientList.Remove(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理连接
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
public bool GetClientByUID(long uid,out ClientInfo client)
|
||||||
|
{
|
||||||
|
lock (ClientList)
|
||||||
|
{
|
||||||
|
if (!_DictUIDClient.ContainsKey(uid))
|
||||||
|
{
|
||||||
|
client = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = _DictUIDClient[uid];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ClientInfo GetClientForSocket(Socket sk)
|
||||||
|
{
|
||||||
|
return _DictSocketClient.ContainsKey(sk) ? _DictSocketClient[sk] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取在线玩家
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<ClientInfo> GetOnlineClientList()
|
||||||
|
{
|
||||||
|
return ClientList.Where(w => w.IsOffline == false).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置玩家离线
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sk"></param>
|
||||||
|
public void SetClientOfflineForSocket(Socket sk)
|
||||||
|
{
|
||||||
|
if (!_DictSocketClient.ContainsKey(sk))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ClientInfo cinfo = _DictSocketClient[sk];
|
||||||
|
Console.WriteLine("标记玩家UID" + cinfo.UID + "为离线");
|
||||||
|
cinfo.IsOffline = true;
|
||||||
|
cinfo.LogOutDT = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveClientForSocket(Socket sk)
|
||||||
|
{
|
||||||
|
if (!_DictSocketClient.ContainsKey(sk))
|
||||||
|
return;
|
||||||
|
|
||||||
|
RemoveClient(_DictSocketClient[sk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void ClientSendALL(int CMDID, int ERRCODE, byte[] data, long SkipUID = -1)
|
||||||
|
{
|
||||||
|
ClientSend(ClientList, CMDID, ERRCODE, data, SkipUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 给一组用户发送数据
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_toclientlist"></param>
|
||||||
|
/// <param name="CMDID"></param>
|
||||||
|
/// <param name="ERRCODE"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public void ClientSend(List<ClientInfo> _toclientlist, int CMDID, int ERRCODE, byte[] data,long SkipUID = -1)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _toclientlist.Count(); i++)
|
||||||
|
{
|
||||||
|
if (_toclientlist[i] == null || _toclientlist[i].IsOffline)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(SkipUID > -1 && _toclientlist[i].UID == SkipUID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ServerManager.g_SocketMgr.SendToSocket(_toclientlist[i]._socket, CMDID, ERRCODE, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientSend(Socket _socket, int CMDID, int ERRCODE, byte[] data)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("发送数据 CMDID->"+ CMDID);
|
||||||
|
ServerManager.g_SocketMgr.SendToSocket(_socket, CMDID, ERRCODE, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 给一个连接发送数据
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_c"></param>
|
||||||
|
/// <param name="CMDID"></param>
|
||||||
|
/// <param name="ERRCODE"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public void ClientSend(ClientInfo _c, int CMDID, int ERRCODE, byte[] data)
|
||||||
|
{
|
||||||
|
if (_c == null || _c.IsOffline)
|
||||||
|
return;
|
||||||
|
ServerManager.g_SocketMgr.SendToSocket(_c._socket, CMDID, ERRCODE, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetOnlineClient()
|
||||||
|
{
|
||||||
|
return ClientList.Where(w => !w.IsOffline).Count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
using AxibugEmuOnline.Server.Common;
|
||||||
|
using AxibugEmuOnline.Server.Manager;
|
||||||
|
using AxibugEmuOnline.Server.NetWork;
|
||||||
|
using AxibugProtobuf;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server
|
||||||
|
{
|
||||||
|
|
||||||
|
public class GameManager
|
||||||
|
{
|
||||||
|
public GameManager()
|
||||||
|
{
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdScreen, OnCmdScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCmdScreen(Socket sk, byte[] reqData)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Debug($"OnCmdScreen lenght:{reqData.Length}");
|
||||||
|
ClientInfo _c = ServerManager.g_ClientMgr.GetClientForSocket(sk);
|
||||||
|
Protobuf_Screnn_Frame msg = ProtoBufHelper.DeSerizlize<Protobuf_Screnn_Frame>(reqData);
|
||||||
|
ServerManager.g_ClientMgr.ClientSendALL((int)CommandID.CmdScreen, (int)ErrorCode.ErrorOk, reqData, _c.UID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
namespace AxibugEmuOnline.Server.Manager
|
||||||
|
{
|
||||||
|
public class LogManager
|
||||||
|
{
|
||||||
|
public void Info(string str)
|
||||||
|
{
|
||||||
|
Console.WriteLine(str);
|
||||||
|
}
|
||||||
|
public void Debug(string str)
|
||||||
|
{
|
||||||
|
Console.WriteLine(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning(string str)
|
||||||
|
{
|
||||||
|
Console.WriteLine(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Error(string str)
|
||||||
|
{
|
||||||
|
Console.WriteLine(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(int logtype, string str)
|
||||||
|
{
|
||||||
|
Console.WriteLine(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
using AxibugProtobuf;
|
||||||
|
using AxibugEmuOnline.Server.Common;
|
||||||
|
using AxibugEmuOnline.Server.NetWork;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server.Manager
|
||||||
|
{
|
||||||
|
public class LoginManager
|
||||||
|
{
|
||||||
|
public LoginManager()
|
||||||
|
{
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdLogin, UserLogin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UserLogin(Socket _socket, byte[] reqData)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Debug("收到新的登录请求");
|
||||||
|
Protobuf_Login msg = ProtoBufHelper.DeSerizlize<Protobuf_Login>(reqData);
|
||||||
|
ClientInfo cinfo = ServerManager.g_ClientMgr.JoinNewClient(msg, _socket);
|
||||||
|
|
||||||
|
byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Login_RESP()
|
||||||
|
{
|
||||||
|
Status = LoginResultStatus.Ok,
|
||||||
|
RegDate = "",
|
||||||
|
LastLoginDate = "",
|
||||||
|
Token = "",
|
||||||
|
UID = cinfo.UID
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
using AxibugEmuOnline.Server.Manager;
|
||||||
|
using AxibugEmuOnline.Server.NetWork;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server
|
||||||
|
{
|
||||||
|
|
||||||
|
public static class ServerManager
|
||||||
|
{
|
||||||
|
public static ClientManager g_ClientMgr;
|
||||||
|
public static LogManager g_Log;
|
||||||
|
public static LoginManager g_Login;
|
||||||
|
public static ChatManager g_Chat;
|
||||||
|
public static IOCPNetWork g_SocketMgr;
|
||||||
|
public static GameManager g_Game;
|
||||||
|
|
||||||
|
public static void InitServer(int port)
|
||||||
|
{
|
||||||
|
g_ClientMgr = new ClientManager();
|
||||||
|
g_ClientMgr.Init(45000, 120);
|
||||||
|
g_Log = new LogManager();
|
||||||
|
g_Login = new LoginManager();
|
||||||
|
g_Chat = new ChatManager();
|
||||||
|
//g_SocketMgr = new IOCPNetWork(1024, 1024);
|
||||||
|
g_SocketMgr = new IOCPNetWork(1024, 4096);
|
||||||
|
g_Game = new GameManager();
|
||||||
|
|
||||||
|
g_SocketMgr.Init();
|
||||||
|
g_SocketMgr.Start(new IPEndPoint(IPAddress.Any.Address, port));
|
||||||
|
Console.WriteLine("Succeed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
using HaoYueNet.ServerNetwork;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server.NetWork
|
||||||
|
{
|
||||||
|
public class IOCPNetWork : TcpSaeaServer
|
||||||
|
{
|
||||||
|
public IOCPNetWork(int numConnections, int receiveBufferSize)
|
||||||
|
: base(numConnections, receiveBufferSize)
|
||||||
|
{
|
||||||
|
OnClientNumberChange += ClientNumberChange;
|
||||||
|
OnReceive += ReceiveData;
|
||||||
|
OnDisconnected += OnDisconnect;
|
||||||
|
OnNetLog += OnShowNetLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClientNumberChange(int num, AsyncUserToken token)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Client数发生变化");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 接受包回调
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="CMDID">协议ID</param>
|
||||||
|
/// <param name="ERRCODE">错误编号</param>
|
||||||
|
/// <param name="data">业务数据</param>
|
||||||
|
private void ReceiveData(AsyncUserToken token, int CMDID, byte[] data)
|
||||||
|
{
|
||||||
|
DataCallBack(token.Socket, CMDID, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DataCallBack(Socket sk, int CMDID, byte[] data)
|
||||||
|
{
|
||||||
|
//ServerManager.g_Log.Debug("收到消息 CMDID =>" + CMDID + " 数据长度=>" + data.Length);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//抛出网络数据
|
||||||
|
NetMsg.Instance.PostNetMsgEvent(CMDID, sk, data);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("逻辑处理错误:" + ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 断开连接
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sk"></param>
|
||||||
|
public void OnDisconnect(AsyncUserToken token)
|
||||||
|
{
|
||||||
|
Console.WriteLine("断开连接");
|
||||||
|
ServerManager.g_ClientMgr.SetClientOfflineForSocket(token.Socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnShowNetLog(string msg)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Debug(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Server.NetWork
|
||||||
|
{
|
||||||
|
|
||||||
|
public class NetMsg
|
||||||
|
{
|
||||||
|
private static NetMsg instance = new NetMsg();
|
||||||
|
public static NetMsg Instance { get { return instance; } }
|
||||||
|
|
||||||
|
private Dictionary<int, List<Delegate>> netEventDic = new Dictionary<int, List<Delegate>>(128);
|
||||||
|
|
||||||
|
private NetMsg() { }
|
||||||
|
|
||||||
|
|
||||||
|
#region RegisterMsgEvent
|
||||||
|
|
||||||
|
public void RegNetMsgEvent(int cmd, Action<Socket, byte[]> callback)
|
||||||
|
{
|
||||||
|
InterRegNetMsgEvent(cmd, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InterRegNetMsgEvent(int cmd, Delegate callback)
|
||||||
|
{
|
||||||
|
if (netEventDic.ContainsKey(cmd))
|
||||||
|
{
|
||||||
|
if (netEventDic[cmd].IndexOf(callback) < 0)
|
||||||
|
{
|
||||||
|
netEventDic[cmd].Add(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
netEventDic.Add(cmd, new List<Delegate>() { callback });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UnregisterCMD
|
||||||
|
|
||||||
|
public void UnregisterCMD(int cmd, Action<Socket, byte[]> callback)
|
||||||
|
{
|
||||||
|
Delegate tempDelegate = callback;
|
||||||
|
InterUnregisterCMD(cmd, tempDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InterUnregisterCMD(int cmd, Delegate callback)
|
||||||
|
{
|
||||||
|
if (netEventDic.ContainsKey(cmd))
|
||||||
|
{
|
||||||
|
netEventDic[cmd].Remove(callback);
|
||||||
|
if (netEventDic[cmd].Count == 0) netEventDic.Remove(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region PostEvent
|
||||||
|
public void PostNetMsgEvent(int cmd, Socket arg1, byte[] arg2)
|
||||||
|
{
|
||||||
|
List<Delegate> eventList = GetNetEventDicList(cmd);
|
||||||
|
if (eventList != null)
|
||||||
|
{
|
||||||
|
foreach (Delegate callback in eventList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((Action<Socket, byte[]>)callback)(arg1, arg2);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServerManager.g_Log.Error(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有事件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cmd"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private List<Delegate> GetNetEventDicList(int cmd)
|
||||||
|
{
|
||||||
|
if (netEventDic.ContainsKey(cmd))
|
||||||
|
{
|
||||||
|
List<Delegate> tempList = netEventDic[cmd];
|
||||||
|
if (null != tempList)
|
||||||
|
{
|
||||||
|
return tempList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
AxibugEmuOnline.Server/AxibugEmuOnline.Server/Program.cs
Normal file
17
AxibugEmuOnline.Server/AxibugEmuOnline.Server/Program.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace AxibugEmuOnline.Server
|
||||||
|
{
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
static string Title = "AxibugEmuOnline.Server";
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.Title = Title;
|
||||||
|
ServerManager.InitServer(10492);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Any CPU</Platform>
|
||||||
|
<PublishDir>bin\Release\net8.0\publish\win-x64\</PublishDir>
|
||||||
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
|
<_TargetId>Folder</_TargetId>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
<SelfContained>false</SelfContained>
|
||||||
|
<PublishSingleFile>false</PublishSingleFile>
|
||||||
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<History>True|2024-06-28T08:25:59.3159172Z;True|2024-06-28T15:30:49.8257235+08:00;</History>
|
||||||
|
<LastFailureDetails />
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
File diff suppressed because it is too large
Load Diff
BIN
Lib/Google.Protobuf.dll
Normal file
BIN
Lib/Google.Protobuf.dll
Normal file
Binary file not shown.
BIN
Lib/HaoYueNet.ServerNetwork.dll
Normal file
BIN
Lib/HaoYueNet.ServerNetwork.dll
Normal file
Binary file not shown.
16
ProtobufCore/build_cs.bat
Normal file
16
ProtobufCore/build_cs.bat
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set "PROTOC_EXE=%cd%\protoc.exe"
|
||||||
|
set "WORK_DIR=%cd%\proto"
|
||||||
|
set "CS_OUT_PATH=%cd%\out\CS"
|
||||||
|
|
||||||
|
echo "==>>buildStart"
|
||||||
|
for /f "delims=" %%i in ('dir /b proto "proto/*.proto"') do (
|
||||||
|
echo build file:%%%i
|
||||||
|
%PROTOC_EXE% --proto_path="%WORK_DIR%" --csharp_out="%CS_OUT_PATH%" "%WORK_DIR%\%%i"
|
||||||
|
)
|
||||||
|
echo "==>>build finish"
|
||||||
|
echo "==>>copy cs"
|
||||||
|
|
||||||
|
::copy %cd%\out\CS\ ..\AxibugEmuOnline.Server\AxibugEmuOnline.Server\Protobuf
|
||||||
|
pause
|
1398
ProtobufCore/out/CS/ProtobufAxibugEmuOnline.cs
Normal file
1398
ProtobufCore/out/CS/ProtobufAxibugEmuOnline.cs
Normal file
File diff suppressed because it is too large
Load Diff
81
ProtobufCore/proto/protobuf_AxibugEmuOnline.proto
Normal file
81
ProtobufCore/proto/protobuf_AxibugEmuOnline.proto
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package AxibugProtobuf;
|
||||||
|
option optimize_for = SPEED;
|
||||||
|
|
||||||
|
enum CommandID
|
||||||
|
{
|
||||||
|
CMD_DEFAUL = 0;//缺省不使用
|
||||||
|
|
||||||
|
CMD_LOGIN = 2001; //自动登录上行 | 下行 对应 Protobuf_Login | Protobuf_Login_RESP
|
||||||
|
|
||||||
|
CMD_CHATMSG = 4001; //广播信息上行 | 下行 对应 Protobuf_ChatMsg | Protobuf_ChatMsg_RESP
|
||||||
|
|
||||||
|
CMD_Screen = 5001; //画面同步 | 同步广播 对应 Protobuf_Screnn_Frame
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ErrorCode
|
||||||
|
{
|
||||||
|
ERROR_DEFAUL = 0;//缺省不使用
|
||||||
|
ERROR_OK = 1; //成功
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LoginType
|
||||||
|
{
|
||||||
|
BaseDefault = 0;//缺省不使用
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DeviceType
|
||||||
|
{
|
||||||
|
DeviceType_Default = 0;//缺省不使用
|
||||||
|
PC = 1;
|
||||||
|
Android = 2;
|
||||||
|
IOS = 3;
|
||||||
|
PSV = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LoginResultStatus
|
||||||
|
{
|
||||||
|
LoginResultStatus_BaseDefault = 0;//缺省不使用
|
||||||
|
OK = 1;
|
||||||
|
AccountErr = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//聊天 上行
|
||||||
|
message Protobuf_ChatMsg
|
||||||
|
{
|
||||||
|
string ChatMsg = 1;//消息
|
||||||
|
}
|
||||||
|
|
||||||
|
//聊天 下行
|
||||||
|
message Protobuf_ChatMsg_RESP
|
||||||
|
{
|
||||||
|
string NickName = 1;//昵称
|
||||||
|
string ChatMsg = 2;//消息
|
||||||
|
int64 Date = 3;//时间
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//登录数据上行
|
||||||
|
message Protobuf_Login
|
||||||
|
{
|
||||||
|
LoginType loginType = 1;//登录操作类型 [0]皓月通行证 [3] 皓月BF3 [4] 皓月BF4
|
||||||
|
DeviceType deviceType = 2;//设备类型 [0]PC [1]AndroidPad预留 [3]IPad预留
|
||||||
|
string Account = 3;//用户名
|
||||||
|
string Password = 4;//密码
|
||||||
|
}
|
||||||
|
|
||||||
|
//登录数据下行
|
||||||
|
message Protobuf_Login_RESP
|
||||||
|
{
|
||||||
|
string Token = 1;//登录凭据 (本次登录之后,所有业务请求凭据,需要存储在内存中)
|
||||||
|
string LastLoginDate = 2;//上次登录时间(只用于呈现的字符串,若界面需求需要)
|
||||||
|
string RegDate = 3;//注册时间(只用于呈现的字符串,若界面需求需要)
|
||||||
|
LoginResultStatus Status = 4;//账号状态 (预留) [1]正常[0]被禁封
|
||||||
|
int64 UID = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Protobuf_Screnn_Frame
|
||||||
|
{
|
||||||
|
int32 FrameID = 1;//帧编号
|
||||||
|
bytes RawBitmap = 2;//渲染层画面
|
||||||
|
}
|
BIN
ProtobufCore/protoc.exe
Normal file
BIN
ProtobufCore/protoc.exe
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user