using AcDream.Core.Net.Packets;
namespace AcDream.Core.Net.Messages;
///
/// Outbound GameAction 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.
///
///
/// Wire layout (see
/// references/ACE/Source/ACE.Server/Network/GameAction/GameActionPacket.cs
/// and references/ACE/Source/ACE.Server/Network/GameAction/Actions/GameActionLoginComplete.cs):
///
///
/// - u32 game-message opcode = 0xF7B1 (GameAction)
/// - u32 sequence — ACE's GameActionPacket.HandleGameAction
/// reads this and currently ignores its value (// TODO: verify
/// sequence in the source). 0 is fine.
/// - u32 GameActionType opcode = 0x000000A1 (LoginComplete)
/// - (no payload)
///
///
///
/// Retail clients send it once the portal-space transition animation finishes.
/// acdream's F751 teleport path now does the same through
/// TeleportAnimSequencer.FireLoginComplete. Initial session bootstrap
/// still sends from the PlayerCreate handler; that remaining ordering gap is
/// tracked as TS-28 in the divergence register.
///
///
public static class GameActionLoginComplete
{
public const uint GameActionOpcode = 0xF7B1u;
public const uint LoginCompleteActionType = 0x000000A1u;
///
/// Build the body bytes for an outbound GameAction(LoginComplete).
/// Layout: opcode(4) + sequence(4) + actionType(4) = 12 bytes total.
///
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();
}
}