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>
53 lines
2.2 KiB
C#
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();
|
|
}
|
|
}
|