public static async Task OnPlayerMovePrototype(PacketHandlerContext c)
        {
            var request   = new MSG_MOVE_GENERIC(c.Packet, c.Client.Build);
            var character = c.GetCharacter();

            // Always trust the client (for now..)
            character.Position.X           = request.MapX;
            character.Position.Y           = request.MapY;
            character.Position.Z           = request.MapZ;
            character.Position.Orientation = request.MapO;

            foreach (var client in c.World.Connections)
            {
                if (!client.IsInWorld)
                {
                    continue;
                }
                if (client.CharacterId == c.Client.CharacterId)
                {
                    continue;
                }

                // Put that in a queue and dont await it?
                await client.SendPacket(new MovementUpdate(character, request, c.Opcode, client.Build));
            }
        }
示例#2
0
        public static async Task OnCharacterCreate(PacketHandlerContext c)
        {
            byte status;
            var  character = CharacterFactory.Create(new CMSG_CHAR_CREATE(c.Packet));

            if (!c.World.CharacterService.AddCharacter(character))
            {
                c.Client.Log($"Could not add created character {character.Name} - {character.Id}.", LogLevel.Warning);
                status = c.Client.Build switch
                {
                    ClientBuild.Vanilla => (byte)CharacterHandlerCode_Vanilla.CHAR_CREATE_ERROR,
                    ClientBuild.TBC => (byte)CharacterHandlerCode_TBC.CHAR_CREATE_ERROR,
                    _ => throw new NotImplementedException($"OnCharacterCreate(build: {c.Client.Build})"),
                };
            }
            else
            {
                var account = c.AccountService.GetAccount(c.Client.Identifier);
                account.Characters.Add(character.Id);
                c.AccountService.UpdateAccount(account);

                status = c.Client.Build switch
                {
                    ClientBuild.Vanilla => (byte)CharacterHandlerCode_Vanilla.CHAR_CREATE_SUCCESS,
                    ClientBuild.TBC => (byte)CharacterHandlerCode_TBC.CHAR_CREATE_SUCCESS,
                    _ => throw new NotImplementedException($"OnCharacterCreate(build: {c.Client.Build})"),
                };
            }

            await c.Client.SendPacket(new SMSG_CHAR_CREATE(status));
        }
示例#3
0
        public static Task OnSetSelection(PacketHandlerContext c)
        {
            var request = new CMSG_SET_SELECTION(c.Packet);

            c.Client.Player.TargetId = request.TargetId;
            return(Task.CompletedTask);
        }
示例#4
0
        public static async Task OnCharacterDelete(PacketHandlerContext c)
        {
            var request = new CMSG_CHAR_DELETE(c.Packet);
            var account = c.AccountService.GetAccount(c.Client.Identifier);

            // Removing character of other account
            if (!account.Characters.Contains(request.CharacterId))
            {
                await c.Client.SendPacket(GetFailedPacket(c.Client.Build));

                return;
            }

            if (!c.World.CharacterService.DeleteCharacter(request.CharacterId))
            {
                await c.Client.SendPacket(GetFailedPacket(c.Client.Build));

                return;
            }

            account.Characters.Remove(request.CharacterId);
            c.AccountService.UpdateAccount(account);

            var status = c.Client.Build switch
            {
                ClientBuild.Vanilla => (byte)CharacterHandlerCode_Vanilla.CHAR_DELETE_SUCCESS,
                ClientBuild.TBC => (byte)CharacterHandlerCode_TBC.CHAR_DELETE_SUCCESS,
                _ => throw new NotImplementedException($"OnCharacterDelete(build: {c.Client.Build})"),
            };

            await c.Client.SendPacket(new SMSG_CHAR_DELETE(status));
        }
示例#5
0
        public static async Task OnRealmSplit(PacketHandlerContext c)
        {
            using var reader = new PacketReader(c.Packet);
            var decision = reader.ReadUInt32();

            await c.Client.SendPacket(new SMSG_REALM_SPLIT(decision));
        }
示例#6
0
        public static async Task OnCharacterEnum(PacketHandlerContext c)
        {
            var account    = c.AccountService.GetAccount(c.Client.Identifier);
            var characters = new List <Character>();

            foreach (var id in account.Characters)
            {
                var character = c.World.CharacterService.GetCharacter(id);
                if (character is null)
                {
                    c.Client.Log($"Could not find character with id {id} from player {account.Identifier}.", LogLevel.Warning);
                    continue;
                }

                characters.Add(character);
            }

            ServerPacketBase <Opcode> characterEnum = c.Client.Build switch
            {
                ClientBuild.Vanilla => new SMSG_CHAR_ENUM_VANILLA(characters),
                ClientBuild.TBC => new SMSG_CHAR_ENUM_TBC(characters),
                _ => throw new NotImplementedException($"OnCharacterEnum(build: {c.Client.Build})"),
            };

            await c.Client.SendPacket(characterEnum);
        }
示例#7
0
        public static async Task OnCastSpell(PacketHandlerContext c)
        {
            var request = new CMSG_CAST_SPELL(c.Packet);

            c.Client.Log($"Casting: {request.SpellId}");

            var unit = c.World.Creatures.SingleOrDefault(creature => creature.ID == request.TargetId);

            if (unit is null)
            {
                c.Client.Log($"Could not find unit: {request.TargetId}");
                return;
            }
            else
            {
                c.Client.Log($"{unit.ID} - {unit.Model}");
            }

            // ????
            //await args.Client.SendPacket(SMSG_CAST_RESULT.Success(request.SpellId));

            // Opcode.SMSG_SPELLLOGEXECUTE
            //m_spellLogData.Initialize(SMSG_SPELLLOGEXECUTE);
            //m_spellLogData << m_spell->GetCaster()->GetPackGUID();
            //m_spellLogData << uint32(m_spell->m_spellInfo->Id);
            //m_spellLogDataEffectsCounterPos = m_spellLogData.wpos();
            //m_spellLogData << uint32(0);                            //placeholder
            //m_spellLogDataEffectsCounter = 0;
        }
示例#8
0
        public static async Task OnAttackSwing(PacketHandlerContext c)
        {
            var request = new CMSG_ATTACKSWING(c.Packet);

            // TODO: Also check players
            var unit = c.World.Creatures.SingleOrDefault(creature => creature.ID == request.Guid);

            if (unit is null)
            {
                c.Client.Log($"Could not find unit: {request.Guid}");
                return;
            }

            // TODO: Checks if can attack, range check etc.
            await c.Client.SendPacket(new SMSG_ATTACKSTART(c.Client.CharacterId, unit.ID));

            // TODO: Do this somewhere else (Add AttackController to Player??)
            _ = Task.Run(async() =>
            {
                c.Client.Log("Attacking...", LogLevel.Information);
                for (var i = 0; i < 500; i++)
                {
                    await Task.Delay(500);
                    await c.Client.SendPacket(new SMSG_ATTACKERSTATEUPDATE(c.Client.CharacterId, unit.ID));
                }
            });
        }
示例#9
0
    public static Task OnZoneUpdate(PacketHandlerContext c)
    {
        var request = new CMSG_ZONEUPDATE(c.Packet);

        c.Client.Log($"{c.Client.Player.Name} entered {request.NewZone}");
        c.GetCharacter().Position.Zone = request.NewZone;
        return(Task.CompletedTask);
    }
示例#10
0
    public static async Task OnPlayerLogoutRequested(PacketHandlerContext c)
    {
        await c.Client.SendPacket(SMSG_LOGOUT_COMPLETE.Success());

        c.Client.CharacterId = default;
        c.Client.Player      = null;

        // TODO: Remove from other clients
    }
示例#11
0
        public static async Task OnNameQuery(PacketHandlerContext c)
        {
            var request   = new CMSG_NAME_QUERY(c.Packet);
            var character = c.World.CharacterService.GetCharacter(request.CharacterID);

            if (character is null)
            {
                return;
            }
            await c.Client.SendPacket(new SMSG_NAME_QUERY_RESPONSE(character, c.Client.Build));
        }
示例#12
0
        public static async Task OnMessageChat(PacketHandlerContext c)
        {
            var request = new CMSG_MESSAGECHAT(c.Packet);

            // debugging stuff :D
            if (request.Message.StartsWith(".spawn"))
            {
                var spawnId  = int.Parse(request.Message.Split(" ")[1]);
                var creature = new Creature {
                    Model = spawnId, Position = c.GetCharacter().Position.Copy()
                };
                await c.World.SpawnCreature(creature);
            }
        }
示例#13
0
    public static async Task OnAttackSwing(PacketHandlerContext c)
    {
        var request = new CMSG_ATTACKSWING(c.Packet);

        // TODO: Also check players
        var unit = c.World.Creatures.SingleOrDefault(creature => creature.ID == request.Guid);

        if (unit is null)
        {
            c.Client.Log($"Could not find unit: {request.Guid}");
            return;
        }

        await c.Client.AttackController.StartAttacking(unit);
    }
        public static async Task OnClientAuthenticationSession(PacketHandlerContext c)
        {
            var request = CMSG_AUTH_SESSION.Read(c.Packet);
            var build   = (int)request.Build;

            if (c.Client.Build != build)
            {
                c.Client.Log($"Expected build {c.Client.Build} but is {build}.", LogLevel.Warning);
                c.Client.Build = build;
            }

            var session = c.AccountService.GetSession(request.Identifier);

            if (session is null)
            {
                // return [SMSG_AUTH_RESPONSE, 21]
                throw new ArgumentException($"No user with name {request.Identifier} found in db.");
            }

            ////: if server is full and NOT GM return [SMSG_AUTH_RESPONSE, 21]
            ////: if player is already connected return [SMSG_AUTH_RESPONSE, 13]

            using var sha = new SHA1CryptoServiceProvider();
            var calculatedDigest = sha.ComputeHash(
                Encoding.ASCII.GetBytes(request.Identifier)
                .Concat(new byte[] { 0, 0, 0, 0 })
                .Concat(BitConverter.GetBytes(request.Seed))
                .Concat(SMSG_AUTH_CHALLENGE.AuthSeed)
                .Concat(session.SessionKey)
                .ToArray());

            if (!calculatedDigest.SequenceEqual(request.Digest))
            {
                //return [SMSG_AUTH_RESPONSE, 21]
                throw new InvalidOperationException("Wrong digest SMSG_AUTH_RESPONSE");
            }

            c.Client.HeaderCrypt = HeaderCryptFactory.Create(session.SessionKey, build);
            c.Client.Identifier  = request.Identifier;
            await c.Client.SendPacket(new SMSG_AUTH_RESPONSE(build));
        }
示例#15
0
        public static async Task GroupInvite(PacketHandlerContext c)
        {
            var request   = new CMSG_GROUP_INVITE(c.Packet);
            var recipient = c.GetCharacter(request.Membername);

            if (recipient is null)
            {
                c.Client.Log($"Could not find player {request.Membername}", LogLevel.Warning);
                return; // TODO Send response to sender
            }

            var recipientClient = c.World.Connections.SingleOrDefault(c => c.CharacterId == recipient.Id);

            if (recipientClient is null)
            {
                // This should only rarely happen -> critical
                c.Client.Log($"Could not find WorldClient of player {request.Membername}", LogLevel.Critical);
                return; // TODO Send response to sender
            }

            await recipientClient.SendPacket(new SMSG_GROUP_INVITE(c.GetCharacter().Name));
        }
示例#16
0
    public static async Task OnMessageChat(PacketHandlerContext c)
    {
        var request = new CMSG_MESSAGECHAT(c.Packet);

        // debugging stuff :D
        if (request.Message == ".update")
        {
            if (c.IsVanilla())
            {
                await c.Client.SendPacket(SMSG_UPDATE_OBJECT_VANILLA.UpdateValues(c.World.Creatures));
            }
            return;
        }
        if (request.Message.StartsWith(".spawn"))
        {
            var spawnId  = int.Parse(request.Message.Split(" ")[1]);
            var creature = new Creature {
                Model = spawnId, Position = c.GetCharacter().Position.Copy()
            };
            await c.World.SpawnCreature(creature);
        }
    }
示例#17
0
 public void HandlePacket(PacketHandlerContext ctx)
 {
     /*if(!ctx.HasUser)
      *  return;
      *
      * if(!long.TryParse(ctx.Args.ElementAtOrDefault(1), out long userId) || ctx.User.UserId != userId)
      *  return;
      *
      * string channelName = ctx.Args.ElementAtOrDefault(2)?.ToLowerInvariant();
      * if(!string.IsNullOrWhiteSpace(channelName))
      *  return;
      *
      * IChannel channel = ctx.User.GetChannels().FirstOrDefault(c => c.Name.ToLowerInvariant() == channelName);
      * if(channel == null || !channel.CanType(ctx.User))
      *  return;
      *
      * ctx.Session.LastChannel = channel;
      *
      * ChannelTyping info = channel.RegisterTyping(ctx.User);
      * if(info == null)
      *  return;
      *
      * channel.SendPacket(new TypingPacket(channel, info));*/
 }
 public static bool IsTBC(this PacketHandlerContext c) => c.Client.Build == ClientBuild.TBC;
 public static Character GetCharacter(this PacketHandlerContext c) => c.World.CharacterService.GetCharacter(c.Client.CharacterId);
示例#20
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
    }
示例#21
0
 public static Task OnAttackStop(PacketHandlerContext c)
 {
     c.Client.AttackController.StopAttacking();
     return(Task.CompletedTask);
 }
示例#22
0
 public static async Task OnQueryTime(PacketHandlerContext c) => await c.Client.SendPacket(new SMSG_QUERY_TIME_RESPONSE());
 public static Character GetCharacter(this PacketHandlerContext c, string name) => c.World.CharacterService.GetCharacter(name);
示例#24
0
 public static async Task OnPing(PacketHandlerContext c)
 {
     var request = new CMSG_PING(c.Packet);
     await c.Client.SendPacket(new SMSG_PONG(request.Latency));
 }
 public static async Task SendPacket <T>(this PacketHandlerContext c) where T : ServerPacketBase <Opcode>, new()
 => await c.Client.SendPacket(new T());
示例#26
0
    public static Task UpdateAccountData(PacketHandlerContext c)
    {
        var request = new CMSG_UPDATE_ACCOUNT_DATA(c.Packet);

        return(Task.CompletedTask);
    }
 public static Character GetCharacter(this PacketHandlerContext c, ulong id) => c.World.CharacterService.GetCharacter(id);
示例#28
0
        public static async Task OnSetSheathed(PacketHandlerContext c)
        {
            var request = new CMSG_SETSHEATHED(c.Packet);

            c.Client.Log(request.Sheated.ToString());
        }
 public static bool IsVanilla(this PacketHandlerContext c) => c.Client.Build == ClientBuild.Vanilla;
示例#30
0
 public static async Task OnAttackStop(PacketHandlerContext c)
 {
     // AttackController.Stop???
 }