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
This commit is contained in:
2026-07-07 12:02:15 +08:00
commit e9616125ce
958 changed files with 158203 additions and 0 deletions

View File

@ -0,0 +1,250 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MrWu.Debug;
using NetWorkMessage;
using Server.Core;
namespace ActorCore
{
public abstract class Actor : IActor, ITimerManager, ICoroutineLockManager, IMailBox
{
public ActorId ActorId { get; private set; }
public bool IsRegister { get; set; }
public bool IsDisposed { get; private set; }
public abstract SchedulerType SchedulerType { get; }
public ThreadSynchronizationContext ThreadSynchronizationContext { get; private set; }
private const int TIMEOUT_TIME = 40 * 1000;
private uint RpcId;
public int Id => ActorId.ActorTypeId;
private readonly MailBox MailBox;
protected readonly CoroutineLockManager CoroutineLockManager;
private readonly TimerManager TimerManager;
public Actor(byte moduleId, byte nodeNum, byte actorTypeId)
{
this.ActorId = new ActorId(moduleId, nodeNum, actorTypeId);
this.ThreadSynchronizationContext = new ThreadSynchronizationContext(actorTypeId);
this.CoroutineLockManager = new CoroutineLockManager();
this.TimerManager = new TimerManager();
this.MailBox = new MailBox(this);
}
void IActor.IUpdate()
{
MailBox.Update();
CoroutineLockManager.Update();
TimerManager.Update();
Update();
}
void IActor.ILateUpdate()
{
LateUpdate();
}
protected virtual void Update()
{
}
protected virtual void LateUpdate()
{
}
public virtual void Dispose()
{
if (IsRegister)
{
//如果这个没有正确被Manager管理这里将会移除错误的Id
ActorMessageQueue.Instance.RemoveQueue(this.Id);
}
}
public void Send(ActorId actorId, IMessage message)
{
MailBox.Send(actorId, (MessageObject)message);
}
public void Reply(ActorId actorId, IResponse response)
{
MailBox.Send(actorId, (MessageObject)response);
}
public async Task<IResponse> Call(ActorId actorId, IRequest request)
{
IResponse response;
if (actorId.Process == this.ActorId.Process)
{
//内部Rpc
response = await CallInner(actorId, request);
}
else
{
//外部Rpc
NetInnerRequest netInnerRequest = NetInnerRequest.Create();
netInnerRequest.FromActorId = this.ActorId;
netInnerRequest.ActorId = actorId;
netInnerRequest.MessageObject = request;
NetInnerResponse innerResponse = (NetInnerResponse)await CallInner(
new ActorId(this.ActorId.Process, ActorTypeId.NetInner),
netInnerRequest);
//把错误码传递给响应体
if (innerResponse.MessageObject == null)
{
innerResponse.MessageObject =
MessageHelper.CreateResponse(request.GetType(), request.RpcId, innerResponse.Error);
}
response = innerResponse.MessageObject;
innerResponse.Dispose();
}
return response;
}
private async Task<IResponse> CallInner(ActorId actorId, IRequest request)
{
uint rpcId = GetRpcId();
request.RpcId = rpcId;
if (actorId == default)
{
throw new Exception($"acotr id is 0:{request}");
}
IResponse response;
Type requestType = request.GetType();
MessageSenderStruct messageSenderStruct = new MessageSenderStruct(actorId, requestType);
Debug.Log($"CallInner:{request.GetType()} {rpcId}");
if (!MailBox.AddActorRpcResponse(rpcId, messageSenderStruct))
{
Debug.Error("RpcId 竟然有重复的现象!!!");
response = MessageHelper.CreateResponse(requestType, rpcId, NetErrorCode.ERR_RpcIdAddFail);
return response;
}
if (!ActorMessageQueue.Instance.Send(this.ActorId, actorId, (MessageObject)request))
{
response = MessageHelper.CreateResponse(requestType, rpcId, NetErrorCode.ERR_NotFoundActor);
return response;
}
async Task Timeout()
{
await WaitAsync(TIMEOUT_TIME);
if (!MailBox.RemoveActorRpcResponse(rpcId, out MessageSenderStruct action))
{
return;
}
//超时
IResponse timeOutResponse = MessageHelper.CreateResponse(requestType, rpcId, NetErrorCode.ERR_Timeout);
action.SetResult(timeOutResponse);
}
_ = Timeout();
long beginTime = TimeInfo.Instance.FrameTime;
response = await messageSenderStruct.Wait();
long endTime = TimeInfo.Instance.FrameTime;
long costTime = endTime - beginTime;
if (costTime > 200)
{
Debug.Warning($"actor rpc time > 200 {costTime} {requestType.FullName}");
}
return response;
}
private uint GetRpcId()
{
return ++RpcId;
}
#region ITimerManager
public Task WaitTillAsync(long tillTIme)
{
return TimerManager.WaitTillAsync(tillTIme);
}
public Task WaitFrameAsync()
{
return TimerManager.WaitFrameAsync();
}
public Task WaitAsync(long time)
{
return TimerManager.WaitAsync(time);
}
public long NewOnceTimer(long tillTime, Action<object> action, object args = null)
{
return TimerManager.NewOnceTimer(tillTime, action, args);
}
public long NewFrameTimer(Action<object> action, object args = null)
{
return TimerManager.NewFrameTimer(action, args);
}
public long NewRepeatedTimer(long time, Action<object> action, object args = null)
{
return TimerManager.NewRepeatedTimer(time, action, args);
}
public bool Remove(ref long id)
{
return TimerManager.Remove(ref id);
}
#endregion ITimerManager
#region ICoroutineLockManager
public async Task<CoroutineLock> Wait(int coroutineLockType, long key, int time = 600000)
{
return await CoroutineLockManager.Wait(coroutineLockType, key, time);
}
#endregion ICoroutineLockManager
#region IMailBox
public abstract MailBoxType MailBoxType { get; }
public virtual int HandleMaxMessageCount => 200;
public virtual void RegisterHandle()
{
}
public void RegisterMessageHandle(Type type, ActorHandle handle)
{
MailBox.RegisterMessageHandle(type, handle);
}
public void RegisterRPCHandle(Type type, ActorRpcHandle rpcHandle)
{
MailBox.RegisterRPCHandle(type, rpcHandle);
}
#endregion IMailBox
}
}

View File

@ -0,0 +1,109 @@
using System;
namespace ActorCore
{
/// <summary>
/// ActorID
/// </summary>
public struct ActorId
{
/// <summary>
/// 模块Id
/// </summary>
public ProcessInfo Process;
/// <summary>
/// ActorType 类型
/// </summary>
public byte ActorTypeId;
public byte ModuleId => Process.ModuleId;
public byte NodeNum => Process.NodeNum;
public ActorId(ProcessInfo process, byte actorTypeId)
{
this.Process = process;
this.ActorTypeId = actorTypeId;
}
public ActorId(byte moduleId, byte nodeNum, byte actorTypeId)
{
this.Process = new ProcessInfo(moduleId, nodeNum);
ActorTypeId = actorTypeId;
}
public int GetChannelId()
{
return ModuleId * 10 + NodeNum;
}
public override string ToString()
{
return $"{ModuleId}:{NodeNum}:{ActorTypeId}";
}
public static bool operator == (ActorId left, ActorId right)
{
return left.Process == right.Process && left.ActorTypeId == right.ActorTypeId;
}
public static bool operator !=(ActorId left, ActorId right)
{
return !(left == right);
}
public override int GetHashCode()
{
return ModuleId * 1000 + NodeNum * 100 + ActorTypeId;
}
}
public struct ProcessInfo
{
/// <summary>
/// 模块Id
/// </summary>
public byte ModuleId;
/// <summary>
/// 节点编号
/// </summary>
public byte NodeNum;
public ProcessInfo(byte moduleId, byte nodeNum)
{
ModuleId = moduleId;
NodeNum = nodeNum;
}
public override string ToString()
{
return $"{ModuleId}:{NodeNum}";
}
public bool Equals(ProcessInfo other)
{
return this.ModuleId == other.ModuleId && this.NodeNum == other.NodeNum;
}
public override bool Equals(object obj)
{
if (obj is ProcessInfo)
{
return Equals((ProcessInfo)obj);
}
return false;
}
public static bool operator == (ProcessInfo left, ProcessInfo right)
{
return left.NodeNum == right.NodeNum && left.ModuleId == right.ModuleId;
}
public static bool operator != (ProcessInfo left, ProcessInfo right)
{
return !(left == right);
}
}
}

View File

@ -0,0 +1,128 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using MrWu.Debug;
using Server.Core;
namespace ActorCore
{
public enum SchedulerType
{
Main = 0,
Thread,
ThreadPool,
Max
}
/// <summary>
/// Actor 管理器
/// </summary>
public class ActorManager : Singleton<ActorManager>
{
/// <summary>
/// 当前进程信息
/// </summary>
public ProcessInfo ProcessInfo
{
get;
private set;
}
/// <summary>
/// 当前的Actor
/// </summary>
[ThreadStatic]
public static IActor Current;
private IScheduler[] _schedulers = new IScheduler[(int)SchedulerType.Max];
private ConcurrentDictionary<int, IActor> _actors = new ConcurrentDictionary<int, IActor>();
private MainThreadScheduler _mainThreadScheduler;
private List<int> actorIds = new List<int>();
protected override void Awake()
{
_mainThreadScheduler = new MainThreadScheduler(this);
_schedulers[(int)SchedulerType.Main] = _mainThreadScheduler;
_schedulers[(int)SchedulerType.Thread] = new ThreadScheduler(this);
_schedulers[(int)SchedulerType.ThreadPool] = new ThreadPoolScheduler(this);
}
public void Init(ProcessInfo processInfo)
{
this.ProcessInfo = processInfo;
}
public void Update()
{
this._mainThreadScheduler.Update();
}
public void LateUpdate()
{
this._mainThreadScheduler.LateUpdate();
}
protected override void Destroy()
{
foreach (var scheduler in _schedulers)
{
scheduler.Dispose();
}
foreach (var kv in _actors)
{
kv.Value.Dispose();
}
_actors.Clear();
}
public void RegisterActor(IActor actor)
{
if (!_actors.TryAdd(actor.Id,actor))
{
Debug.Error($"actor already existed, actorTypeId:{actor.Id}");
return;
}
ActorMessageQueue.Instance.AddQueue(actor.Id);
actor.IsRegister = true;
_schedulers[(int)actor.SchedulerType].Add(actor.Id);
actor.RegisterHandle();
_actorIds[actor.ActorId.ActorTypeId] = actor.ActorId;
actorIds.Add(actor.Id);
}
public IActor Get(int actorTypeId)
{
this._actors.TryGetValue(actorTypeId, out IActor actor);
return actor;
}
public int Count()
{
return this._actors.Count;
}
public IEnumerable<int> GetActorIds()
{
return actorIds;
}
private Dictionary<int,ActorId> _actorIds = new Dictionary<int, ActorId>();
public ActorId GetActorId(int actorTypeId)
{
if (_actorIds.TryGetValue(actorTypeId,out ActorId actorId))
{
return actorId;
}
return default(ActorId);
}
}
}

View File

@ -0,0 +1,77 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using MrWu.Debug;
using NetWorkMessage;
using Server.Core;
namespace ActorCore
{
/// <summary>
/// 当前进程的消息队列也可以给进程内其他Actor发送消息
/// </summary>
public class ActorMessageQueue : Singleton<ActorMessageQueue>
{
/// <summary>
/// 接收到的Actor消息暂存在这里等待Actor进行处理
/// </summary>
private readonly ConcurrentDictionary<int, ConcurrentQueue<MessageInfo>> m_actorMessageQueue =
new ConcurrentDictionary<int, ConcurrentQueue<MessageInfo>>();
/// <summary>
/// 取出待处理消息
/// </summary>
/// <param name="actorTypeId"></param>
/// <param name="count"></param>
/// <param name="list"></param>
public void Fetch(int actorTypeId, int count, List<MessageInfo> list)
{
if (!this.m_actorMessageQueue.TryGetValue(actorTypeId,out var queue))
{
Debug.Error($"没有这个ActorType{actorTypeId}");
return;
}
for (int i = 0; i < count; i++)
{
if (!queue.TryDequeue(out MessageInfo message))
{
break;
}
list.Add(message);
}
//Debug.Log($"拿走后还剩多少:{queue.Count}");
}
public void AddQueue(int actorTypeId)
{
var queue = new ConcurrentQueue<MessageInfo>();
this.m_actorMessageQueue[actorTypeId] = queue;
}
public void RemoveQueue(int actorTypeId)
{
this.m_actorMessageQueue.TryRemove(actorTypeId, out _);
}
/// <summary>
/// 给内部Actor发包
/// </summary>
/// <param name="fromActorId"></param>
/// <param name="actorId"></param>
/// <param name="messageObject"></param>
/// <returns></returns>
public bool Send(ActorId fromActorId,ActorId actorId,MessageObject messageObject)
{
if (!m_actorMessageQueue.TryGetValue(actorId.ActorTypeId,out var queue))
{
Debug.Error($"发送失败没有这个Actor! {actorId}");
return false;
}
//Debug.Info($"添加到内部消息:{fromActorId} {actorId}");
queue.Enqueue(new MessageInfo(){FormActorId = fromActorId,MessageObject = messageObject});
return true;
}
}
}

View File

@ -0,0 +1,31 @@
namespace ActorCore
{
public static class ActorTypeId
{
/// <summary>
/// 主Actor 主线程用
/// </summary>
public const int Main = 0;
/// <summary>
/// 内网Actor用来给内网模块通讯
/// </summary>
public const int NetInner = 1;
/// <summary>
/// 外网Actor, 用来发送给外网模块
/// </summary>
public const int OuterNet = 2;
/// <summary>
/// 用户网络Actor 处理用户的包
/// </summary>
public const int UserNet = 3;
/// <summary>
/// 游戏中心用户统计
/// </summary>
public const int GameCenterUserStatics = 4;
}
}

View File

@ -0,0 +1,65 @@
using System;
using NetWorkMessage;
using Server.Core;
namespace ActorCore
{
/// <summary>
/// IActor
/// </summary>
public interface IActor : IDisposable
{
ActorId ActorId
{
get;
}
/// <summary>
/// 是否被Manager管理
/// </summary>
bool IsRegister
{
get;
set;
}
bool IsDisposed
{
get;
}
SchedulerType SchedulerType
{
get;
}
/// <summary>
/// 由ActorManager管理其他地方不可以设置
/// </summary>
int Id
{
get;
}
/// <summary>
/// 线程同步上下文
/// </summary>
ThreadSynchronizationContext ThreadSynchronizationContext
{
get;
}
void RegisterHandle();
void IUpdate();
void ILateUpdate();
/// <summary>
/// 发送消息
/// </summary>
/// <param name="actorId"></param>
/// <param name="message"></param>
void Send(ActorId actorId, IMessage message);
}
}