Beispiel #1
0
    public async Task SpawnPlayer(Character character, int build)
    {
        var updateForOtherActivePlayers = new Dictionary <int, SMSG_UPDATE_OBJECT>
        {
            { ClientBuild.Vanilla, SMSG_UPDATE_OBJECT.CreatePlayer(character, ClientBuild.Vanilla) },
            { ClientBuild.TBC, SMSG_UPDATE_OBJECT.CreatePlayer(character, ClientBuild.TBC) },
        };

        var _this = this.Connections.Single(x => x.CharacterId == character.Id);

        foreach (var other in this.Connections)
        {
            if (!other.IsInWorld)
            {
                continue;
            }
            if (other.CharacterId == character.Id)
            {
                continue;
            }

            var otherCharacter = this.CharacterService.GetCharacter(other.CharacterId);

            if (!IsInRange(character, otherCharacter))
            {
                continue;
            }

            await _this.SendPacket(SMSG_UPDATE_OBJECT.CreatePlayer(otherCharacter, build));

            await other.SendPacket(updateForOtherActivePlayers[other.Build]);
        }
    }
Beispiel #2
0
        public static async Task OnPlayerLogin(WorldClient client, byte[] data)
        {
            var request   = new CMSG_PLAYER_LOGIN(data);
            var character = client.User.Characters.Single(x => x.ID == request.CharacterID);

            client.Log($"Player logged in with char {character.Name}");

            await client.SendPacket(new SMSG_LOGIN_VERIFY_WORLD(character));

            await client.SendPacket(new SMSG_ACCOUNT_DATA_TIMES());

            await client.SendPacket(new SMSG_MESSAGECHAT(character.ID, "Hello World"));

            await client.SendPacket(new SMSG_MESSAGECHAT(character.ID, "World Hello"));

            await client.SendPacket(new SMSG_SET_REST_START());

            await client.SendPacket(new SMSG_BINDPOINTUPDATE(character));

            await client.SendPacket(new SMSG_TUTORIAL_FLAGS());

            await client.SendPacket(new SMSG_LOGIN_SETTIMESPEED());

            await client.SendPacket(new SMSG_INITIAL_SPELLS());

            await client.SendPacket(new SMSG_ACTION_BUTTONS());

            await client.SendPacket(new SMSG_INITIALIZE_FACTIONS());

            // TODO: SMSG_TRIGGER_CINEMATIC (Human_ID = 81??)

            await client.SendPacket(new SMSG_CORPSE_RECLAIM_DELAY());

            await client.SendPacket(new SMSG_INIT_WORLD_STATES());

            await client.SendPacket(SMSG_UPDATE_OBJECT.CreateOwnPlayerObject(character, out var player));

            client.Player = player;
        }
Beispiel #3
0
    public static async Task OnPlayerLogin(PacketHandlerContext c)
    {
        var request   = new CMSG_PLAYER_LOGIN(c.Packet);
        var character = c.GetCharacter(request.CharacterID);
        var account   = c.AccountService.GetAccount(c.Client.Identifier);

        // Login with a deleted character or a character from another account.
        // TODO: Split for different log messages.
        if (character is null || !account.Characters.Contains(character.Id))
        {
            c.Client.Log(
                $"{account.Identifier} tried to login with a deleted character or a character from another account.",
                LogLevel.Warning);
            return;
        }

        c.Client.Log($"Player logged in with char {character.Name}");

        if (c.IsTBC())
        {
            await c.SendPacket <MSG_SET_DUNGEON_DIFFICULTY>();
        }

        await c.Client.SendPacket(new SMSG_LOGIN_VERIFY_WORLD(character));

        await c.SendPacket <SMSG_ACCOUNT_DATA_TIMES>();

        if (c.IsTBC())
        {
            await c.SendPacket <SMSG_FEATURE_SYSTEM_STATUS>();
        }

        await c.Client.SendPacket(new SMSG_EXPECTED_SPAM_RECORDS(Enumerable.Empty <string>()));

        if (c.IsVanilla())
        {
            await c.Client.SendPacket(new SMSG_MESSAGECHAT(character.Id, MessageOfTheDay));
        }
        else if (c.IsTBC())
        {
            await c.Client.SendPacket(new SMSG_MOTD(MessageOfTheDay));
        }

        // await args.Client.SendPacket(new SMSG_NAME_QUERY_RESPONSE(character, args.Client.Build));
        // if (GUILD) -> SMSG_GUILD_EVENT

        if (character.Stats.Life == 0)
        {
            await c.SendPacket <SMSG_CORPSE_RECLAIM_DELAY>();
        }

        await c.SendPacket <SMSG_SET_REST_START>();

        await c.Client.SendPacket(new SMSG_BINDPOINTUPDATE(character));

        await c.SendPacket <SMSG_TUTORIAL_FLAGS>();

        if (c.IsTBC())
        {
            await c.SendPacket <SMSG_INSTANCE_DIFFICULTY>();
        }

        await c.Client.SendPacket(new SMSG_INITIAL_SPELLS(character.Spells));

        // SMSG_SEND_UNLEARN_SPELLS
        await c.Client.SendPacket(new SMSG_ACTION_BUTTONS(character.ActionBar));

        await c.Client.SendPacket(new SMSG_INITIALIZE_FACTIONS(ClientBuild.Vanilla)); // BUG??

        await c.SendPacket <SMSG_LOGIN_SETTIMESPEED>();

        // await args.Client.SendPacket(new SMSG_TRIGGER_CINEMATIC(CinematicID.NightElf));

        c.Client.CharacterId = character.Id;
        await c.Client.SendPacket(SMSG_UPDATE_OBJECT.CreateOwnPlayerObject(character, c.Client.Build, out var player));

        c.Client.Player = player;

        // TODO: Implement for TBC
        if (c.IsVanilla())
        {
            // Initially spawn all creatures
            foreach (var unit in c.World.Creatures)
            {
                // TODO: Add range check
                await c.Client.SendPacket(SMSG_UPDATE_OBJECT_VANILLA.CreateUnit(unit));
            }
        }

        await c.World.SpawnPlayer(character, c.Client.Build);

        // if (GROUP) -> SMSG_GROUP_LIST
        // if Vanilla
        //     SMSG_FRIEND_LIST
        //     SMSG_IGNORE_LIST
        // if TBC
        //     SMSG_CONTACT_LIST

        if (c.IsTBC())
        {
            await c.SendPacket <SMSG_TIME_SYNC_REQ>();
        }

        // SMSG_ITEM_ENCHANT_TIME_UPDATE
        // SMSG_ITEM_TIME_UPDATE
        // SMSG_FRIEND_STATUS
    }
    public static SMSG_UPDATE_OBJECT CreatePlayer(Character character, int build)
    {
        var update = new SMSG_UPDATE_OBJECT();

        update.Writer
        .WriteUInt32(1)    // blocks.Count
        .WriteUInt8(0)     // hasTransport

        .WriteUInt8((byte)ObjectUpdateType.UPDATETYPE_CREATE_OBJECT_SELF)
        .WriteBytes(character.Id.ToPackedUInt64())

        .WriteUInt8((byte)TypeId.TypeidPlayer);

        var updateFlags = build switch
        {
            ClientBuild.Vanilla => (byte)(ObjectUpdateFlag_VANILLA.All
                                          | ObjectUpdateFlag_VANILLA.HasPosition
                                          | ObjectUpdateFlag_VANILLA.Living),
            ClientBuild.TBC => (byte)(ObjectUpdateFlag_TBC.Highguid
                                      | ObjectUpdateFlag_TBC.HasPosition
                                      | ObjectUpdateFlag_TBC.Living),
            _ => throw new NotImplementedException($"GetUpdateFlags(build: {build})"),
        };

        update.Writer
        .WriteUInt8(updateFlags)
        .WriteUInt32((uint)MovementFlags.None);

        if (build == ClientBuild.TBC)
        {
            update.Writer.WriteUInt8(0);                           // moveFlags2
        }
        update.Writer
        .WriteUInt32((uint)Environment.TickCount)
        .WriteMap(character.Position)

        .WriteFloat(0)     // ??

        .WriteFloat(2.5f)  // WalkSpeed
        .WriteFloat(7f)    // RunSpeed
        .WriteFloat(2.5f)  // Backwards WalkSpeed
        .WriteFloat(4.72f) // SwimSpeed
        .WriteFloat(2.5f); // Backwards SwimSpeed

        if (build == ClientBuild.TBC)
        {
            update.Writer
            .WriteFloat(14f)     // MOVE_FLIGHT
            .WriteFloat(14f);    // MOVE_FLIGHT_BACK
        }

        update.Writer
        .WriteFloat(3.14f)   // TurnSpeed
        .WriteUInt32(0);     // ??

        // TODO: Can be done somewhere else?
        var player = new PlayerEntity(character, build);

        player.WriteUpdateFields(update.Writer);
        return(update);
    }