48 lines
2.1 KiB
C#
48 lines
2.1 KiB
C#
namespace AcDream.App.Streaming;
|
|
|
|
/// <summary>
|
|
/// Classifies both whether the player crosses an AC landblock boundary and
|
|
/// whether acdream's asynchronous streaming origin must recenter. These are
|
|
/// distinct while a teleport destination is aimed but not yet placed. Cell
|
|
/// identity comes from the complete retail <c>Position</c>, never from its frame
|
|
/// coordinates: dungeon EnvCells may have valid negative local origins.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Retail carries <c>Position::objcell_id</c> through
|
|
/// <c>SmartBox::TeleportPlayer</c> (0x00453910) into
|
|
/// <c>CPhysicsObj::SetPositionSimple</c> (0x005162B0). acdream's asynchronous
|
|
/// streaming layer needs this extra comparison, but preserves that identity rule.
|
|
/// See <c>docs/research/2026-07-13-same-dungeon-respawn-landblock-identity-pseudocode.md</c>.
|
|
/// </remarks>
|
|
internal readonly record struct TeleportLandblockTransition(
|
|
uint SourceLandblockId,
|
|
uint DestinationLandblockId,
|
|
uint StreamingCenterLandblockId)
|
|
{
|
|
public bool CrossesLandblock => SourceLandblockId != DestinationLandblockId;
|
|
public bool ChangesStreamingCenter =>
|
|
StreamingCenterLandblockId != DestinationLandblockId;
|
|
|
|
/// <summary>
|
|
/// Build the transition from the player's current cell and the received
|
|
/// destination cell. A zero source can occur before initial placement; in
|
|
/// that case the current streaming center is the only valid identity fallback.
|
|
/// </summary>
|
|
public static TeleportLandblockTransition Classify(
|
|
uint sourceCellId,
|
|
uint destinationCellId,
|
|
uint currentStreamingCenterLandblockId)
|
|
{
|
|
uint sourceLandblockId = sourceCellId != 0
|
|
? NormalizeLandblockId(sourceCellId)
|
|
: NormalizeLandblockId(currentStreamingCenterLandblockId);
|
|
|
|
return new TeleportLandblockTransition(
|
|
sourceLandblockId,
|
|
NormalizeLandblockId(destinationCellId),
|
|
NormalizeLandblockId(currentStreamingCenterLandblockId));
|
|
}
|
|
|
|
private static uint NormalizeLandblockId(uint cellOrLandblockId)
|
|
=> (cellOrLandblockId & 0xFFFF0000u) | 0xFFFFu;
|
|
}
|