74 lines
4.0 KiB
C#
74 lines
4.0 KiB
C#
using Auto = Ananta.Server.RpcTypes.Client4229938.Auto;
|
||
|
||
namespace Ananta.Server.Protocol.Client4229938;
|
||
|
||
/// <summary>
|
||
/// 「已拥有哪几套房」→ 客户端认识的线格式 —— 2026-09-30。
|
||
///
|
||
/// <para><b>两个消费点,必须字节一致</b>:</para>
|
||
/// <list type="number">
|
||
/// <item>登录包 <c>PlayerClientInfoMinor.housesInfo.HouseInfoList</c>
|
||
/// (<c>RuntimePayloadFactory.SeedOwnedHouses4229938</c>)—— 决定「重登后房子还在不在」。</item>
|
||
/// <item>购买瞬间的 <c>SyncAddHouse</c>(64459483) 推送
|
||
/// (<c>GameRouter.House.cs</c> 的 <c>PushSyncAddHouseAsync</c>)——
|
||
/// payload 就是**单个** <c>HouseBaseInfo</c> 的 complex,不是列表。
|
||
/// 客户端 Lua <c>BuyHouseUtils.SyncAddHouse</c> 拿到之后自己
|
||
/// <c>table.insert</c> 进上面那个 <c>HouseInfoList</c>。</item>
|
||
/// </list>
|
||
/// <para>所以两边都走 <see cref="ToWire"/>,避免同一个结构手抄两遍抄岔。</para>
|
||
///
|
||
/// <para><b>线格式</b>(<c>LuaGen/AutoGen/RPCDeserializeAuto.lua</c> 的
|
||
/// <c>Auto.Reader[368]</c> 逐字对照,2026-09-30 核对):</para>
|
||
/// <code>
|
||
/// HouseId u32
|
||
/// ParkingSpaceVehicleIdDict Dict<i32,u32> ← Base.ReadDict = marker 0xFF + Int32 计数
|
||
/// Version u32
|
||
/// SocialInfo complex(1143)
|
||
/// FurnitureIndex u32
|
||
/// </code>
|
||
/// <para>注意 <c>SyncAddHouse</c> 的客户端 reader 是
|
||
/// <c>Base.ReadComplex(reader, Auto.Reader[368])</c> —— 整包只有**一个** complex 包装,
|
||
/// 所以推送时直接把 <c>HouseActiveInfo</c> 交给 <c>NotifyAsync<T></c> 即可
|
||
/// (<c>UxSerializer</c> 对非 Inline 的 <c>[UxContract]</c> 类型会自动写那一个 0xFF),
|
||
/// **不要**再包一层 Inline 壳 —— 那会多出一个 0xFF 把整包错位。</para>
|
||
///
|
||
/// <para>⛔⛔ <b><c>SocialInfo</c> 绝对不能给 <c>null</c>。</b>
|
||
/// 判据:客户端自己的 <c>UX.Game.HouseBaseInfo</c> 类上**没有** <c>[NullableContext]</c>,
|
||
/// 而同一个 namespace 下的 <c>HouseSocialInfo</c> 有 <c>[NullableContext(2)]</c>
|
||
/// (dump.cs TypeDefIndex 33341 / 33342);Lua 侧 <c>Auto.WriteHouseBaseInfo</c> 里这个字段的
|
||
/// nullable 标记也是 <c>false</c>(对照 <c>HouseAddFurnitureResult.PlacedFurnitureInfo</c> 是
|
||
/// <c>true</c>,那个类确实带 <c>[NullableContext(2)]</c>)⇒ 客户端按**非空**读。
|
||
/// 给 null 会让 <c>UxSerializer</c> 只写一个 0x00,后面的 <c>FurnitureIndex</c> 整体错位。
|
||
/// 正确默认是空对象(两个空串)。</para>
|
||
/// </summary>
|
||
internal static class HouseOwnershipWire4229938
|
||
{
|
||
/// <summary>
|
||
/// 一套房 → 一个 <c>HouseBaseInfo</c>。
|
||
/// <c>Version</c> / <c>FurnitureIndex</c> 恒 0 —— 这一轮只做所有权 + 车库指派,不碰装修。
|
||
///
|
||
/// <para><b>2026-09-30 起 <c>ParkingSpaceVehicleIdDict</c> 不再留空</b>:
|
||
/// 客户端 <c>GarageManager.CheckHouseInfo</c> 读的就是登录包这一份
|
||
/// (<c>housesInfo.HouseInfoList[i].ParkingSpaceVehicleIdDict</c>),
|
||
/// 键 = 车位号 <b>0 基</b>,值 = 车辆 configId。重登后车库「哪个车位有车」靠它恢复。</para>
|
||
/// </summary>
|
||
/// <param name="parking">
|
||
/// 这套房的车位指派(车位号 0 基 → 车辆 configId);<c>null</c> / 空 = 车库全空
|
||
/// (与改动前的空字典逐字节一致)。</param>
|
||
internal static Auto.HouseActiveInfo ToWire(uint houseId, IReadOnlyDictionary<int, uint>? parking = null)
|
||
=> new()
|
||
{
|
||
HouseId = houseId,
|
||
ParkingSpaceVehicleIdDict = parking is null || parking.Count == 0
|
||
? new Dictionary<int, uint>()
|
||
: new Dictionary<int, uint>(parking),
|
||
Version = 0u,
|
||
SocialInfo = new Auto.HouseSocialInfo
|
||
{
|
||
PromoImageUrl = string.Empty,
|
||
WelcomeText = string.Empty,
|
||
},
|
||
FurnitureIndex = 0u,
|
||
};
|
||
}
|