acdream/src/AcDream.Core.Net/Messages/GameActionLoginComplete.cs
Erik eab23cbdd1 feat(world): port retail portal-space viewport
Replace the opaque teleport cover with the DAT-authored CreatureMode tunnel, exact retail camera/light/animation timing and easing, and animation-hook audio routing. Compose portal and fade passes below retained UI so gameplay windows and input remain active through F751 travel.

Co-authored-by: OpenAI Codex <codex@openai.com>
2026-07-15 21:59:23 +02:00

53 lines
2.2 KiB
C#

using AcDream.Core.Net.Packets;
namespace AcDream.Core.Net.Messages;
/// <summary>
/// Outbound <c>GameAction</c> message announcing that the client has
/// finished loading into the world. Without this, the server keeps the
/// character in a transitional "exiting portal space" state forever —
/// other players see the character rendered as a stationary purple haze
/// (AC's loading-screen indicator) instead of a real avatar, and the
/// server doesn't push initial property updates / equipment overrides
/// to the client either.
///
/// <para>
/// Wire layout (see
/// <c>references/ACE/Source/ACE.Server/Network/GameAction/GameActionPacket.cs</c>
/// and <c>references/ACE/Source/ACE.Server/Network/GameAction/Actions/GameActionLoginComplete.cs</c>):
/// </para>
/// <list type="bullet">
/// <item>u32 game-message opcode = 0xF7B1 (<c>GameAction</c>)</item>
/// <item>u32 sequence — ACE's <c>GameActionPacket.HandleGameAction</c>
/// reads this and currently ignores its value (<c>// TODO: verify
/// sequence</c> in the source). 0 is fine.</item>
/// <item>u32 GameActionType opcode = 0x000000A1 (<c>LoginComplete</c>)</item>
/// <item>(no payload)</item>
/// </list>
///
/// <para>
/// Retail clients send it once the portal-space transition animation finishes.
/// acdream's F751 teleport path now does the same through
/// <c>TeleportAnimSequencer.FireLoginComplete</c>. Initial session bootstrap
/// still sends from the PlayerCreate handler; that remaining ordering gap is
/// tracked as TS-28 in the divergence register.
/// </para>
/// </summary>
public static class GameActionLoginComplete
{
public const uint GameActionOpcode = 0xF7B1u;
public const uint LoginCompleteActionType = 0x000000A1u;
/// <summary>
/// Build the body bytes for an outbound <c>GameAction(LoginComplete)</c>.
/// Layout: opcode(4) + sequence(4) + actionType(4) = 12 bytes total.
/// </summary>
public static byte[] Build()
{
var w = new PacketWriter(16);
w.WriteUInt32(GameActionOpcode);
w.WriteUInt32(0u); // sequence — server ignores per ACE source
w.WriteUInt32(LoginCompleteActionType);
return w.ToArray();
}
}