feat: Upgrade server with HyNB v2.4 modular architecture, minigames, admin GM web panel, companion summons, and car radio
This commit is contained in:
1 parent
74e2963a12
commit
3e5adf1dc5
1571 files changed
+336468
-6348
No files matched your search
@@ -0,0 +1,85 @@
|
||||
namespace Ananta.Server.Protocol.Client4229938;
|
||||
|
||||
/// <summary>
|
||||
/// GM 控制台(ALT+F1)下发过的一条职业记录。
|
||||
///
|
||||
/// 服务端不持有职业表(职业/等级全在客户端配置里),所以一条职业只在某个 <c>GmJob*</c> 命令
|
||||
/// 点名它的 jobClassId 之后才存在;这份记录既是命令自身返回值的来源,也是
|
||||
/// <c>SyncSpiritJobInfo</c> 推送的来源。
|
||||
/// </summary>
|
||||
internal sealed class GmJobRecord4229938
|
||||
{
|
||||
internal uint JobClassId { get; init; }
|
||||
|
||||
internal byte Level { get; set; } = 1;
|
||||
|
||||
/// <summary>最后一条到达的职业命令(只用于日志与面板展示)。</summary>
|
||||
internal GmJobAction4229938 Action { get; set; }
|
||||
|
||||
internal DateTime UpdatedUtc { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 六种 <c>GmJob*</c> 命令。这是服务端自己的记账枚举,<b>不进 wire</b>(wire 上只有 jobClassId /
|
||||
/// level 两个标量),所以底层类型怎么写都不影响协议。
|
||||
/// </summary>
|
||||
internal enum GmJobAction4229938 : byte
|
||||
{
|
||||
Take,
|
||||
Start,
|
||||
Quit,
|
||||
Promote,
|
||||
SetLevel,
|
||||
End,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 一个会话上 GM 职业命令的全部效果。
|
||||
///
|
||||
/// 移植自捐赠端 DremkaPS 的 <c>GmTaskState4229938</c>,<b>但只取其中的职业(job)部分</b>:
|
||||
/// 捐赠端那一份还带着任务 / 事件 / 对话框 / NPC 行为项四组状态,而本服
|
||||
/// <c>GameRouter.Tasks.cs</c> 已经四次证明任务面板在 4229938 下渲染不出来
|
||||
/// (<c>TaskPublishEnabled = false</c>),搬那四组只会得到一堆写进去没人读的状态。
|
||||
/// </summary>
|
||||
internal sealed class GmJobState4229938
|
||||
{
|
||||
/// <summary>
|
||||
/// 自带锁而不是复用 <c>WorldEntryState.SyncRoot</c>:面板端点跑在 HTTP 线程上,会话被切走或
|
||||
/// 拆掉之后仍可能摸到这个对象;而且只有 GmJobs 这一条路径会碰它。
|
||||
/// </summary>
|
||||
internal object SyncRoot { get; } = new();
|
||||
|
||||
/// <summary>jobClassId → 记录。空表示还没收到过任何职业命令。</summary>
|
||||
internal Dictionary<uint, GmJobRecord4229938> Jobs { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 客户端当前所处的职业。
|
||||
///
|
||||
/// ⛑⛑ 默认必须是 <see cref="RuntimePayloadFactory.JoblessUrbanJob4229938"/>(100,Jobless)
|
||||
/// 而不是 0 —— 0 不是合法的 <c>UrbanJobConfig</c> id,一旦带着职业记录发出去,客户端
|
||||
/// <c>SpiritJobManager</c> 会去解引用一个不存在的配置。捐赠端这里默认 0、quit/end 之后也回落 0,
|
||||
/// 那是它的一个坑,<b>本服不照搬</b>。
|
||||
/// </summary>
|
||||
internal uint CurrentJob { get; set; } = RuntimePayloadFactory.JoblessUrbanJob4229938;
|
||||
|
||||
/// <summary>
|
||||
/// 是否有过至少一条 <c>GmJob*</c> 命令。用来区分「GM 没动过职业,照旧用配置驱动的那份」
|
||||
/// 与「GM 动过了,以控制台为准」—— 没有这个标志的话,一次无关命令就会把角色原本的职业顶掉。
|
||||
/// </summary>
|
||||
internal bool HasGmOverride { get; set; }
|
||||
|
||||
/// <summary>取一条记录,没有就按给定等级建一条。</summary>
|
||||
internal GmJobRecord4229938 Ensure(uint jobClassId, byte level)
|
||||
{
|
||||
if (Jobs.TryGetValue(jobClassId, out var existing))
|
||||
return existing;
|
||||
|
||||
var record = new GmJobRecord4229938
|
||||
{
|
||||
JobClassId = jobClassId,
|
||||
Level = Math.Max((byte)1, level),
|
||||
};
|
||||
Jobs[jobClassId] = record;
|
||||
return record;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user