Ejemplo n.º 1
0
        public static async void CharacterDelete(ClientPacketFragment fragment, Session session)
        {
            string account       = fragment.Payload.ReadString16L();
            uint   characterSlot = fragment.Payload.ReadUInt32();

            if (account != session.Account)
            {
                session.SendCharacterError(CharacterError.Delete);
                return;
            }

            var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.SlotId == characterSlot);

            if (cachedCharacter == null)
            {
                session.SendCharacterError(CharacterError.Delete);
                return;
            }

            // TODO: check if character is already pending removal

            var characterDelete         = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum);
            var characterDeleteFragment = new ServerPacketFragment(9, FragmentOpcode.CharacterDelete);

            characterDelete.Fragments.Add(characterDeleteFragment);

            NetworkManager.SendPacket(ConnectionType.Login, characterDelete, session);

            DatabaseManager.Character.DeleteOrRestore(WorldManager.GetUnixTime() + 3600ul, cachedCharacter.Guid.Low);

            var result = await DatabaseManager.Character.GetByAccount(session.Id);

            AuthenticationHandler.CharacterListSelectCallback(result, session);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Processes a fragment, combining split fragments as needed, then handling them
        /// </summary>
        /// <param name="fragment">ClientPacketFragment to process</param>
        private void ProcessFragment(ClientPacketFragment fragment)
        {
            log.DebugFormat("[{0}] Processing fragment {1}", session.LoggingIdentifier, fragment.Header.Sequence);
            ClientMessage message = null;

            // Check if this fragment is split
            if (fragment.Header.Count != 1)
            {
                // Packet is split
                log.DebugFormat("[{0}] Fragment {1} is split, this index {2} of {3} fragments", session.LoggingIdentifier, fragment.Header.Sequence, fragment.Header.Index, fragment.Header.Count);

                MessageBuffer buffer = null;
                if (partialFragments.TryGetValue(fragment.Header.Sequence, out buffer))
                {
                    // Existing buffer, add this to it and check if we are finally complete.
                    buffer.AddFragment(fragment);
                    log.DebugFormat("[{0}] Added fragment {1} to existing buffer. Buffer at {2} of {3}", session.LoggingIdentifier, fragment.Header.Sequence, buffer.Count, buffer.TotalFragments);
                    if (buffer.Complete)
                    {
                        // The buffer is complete, so we can go ahead and handle
                        log.DebugFormat("[{0}] Buffer {1} is complete", session.LoggingIdentifier, buffer.Sequence);
                        message = buffer.GetMessage();
                        MessageBuffer removed = null;
                        partialFragments.TryRemove(fragment.Header.Sequence, out removed);
                    }
                }
                else
                {
                    // No existing buffer, so add a new one for this fragment sequence.
                    log.DebugFormat("[{0}] Creating new buffer {1} for this split fragment", session.LoggingIdentifier, fragment.Header.Sequence);
                    var newBuffer = new MessageBuffer(fragment.Header.Sequence, fragment.Header.Count);
                    newBuffer.AddFragment(fragment);

                    log.DebugFormat("[{0}] Added fragment {1} to the new buffer. Buffer at {2} of {3}", session.LoggingIdentifier, fragment.Header.Sequence, newBuffer.Count, newBuffer.TotalFragments);
                    partialFragments.TryAdd(fragment.Header.Sequence, newBuffer);
                }
            }
            else
            {
                // Packet is not split, proceed with handling it.
                log.DebugFormat("[{0}] Fragment {1} is not split", session.LoggingIdentifier, fragment.Header.Sequence);
                message = new ClientMessage(fragment.Data);
            }

            // If message is not null, we have a complete message to handle
            if (message != null)
            {
                // First check if this message is the next sequence, if it is not, add it to our outOfOrderFragments
                if (fragment.Header.Sequence == lastReceivedFragmentSequence + 1)
                {
                    log.DebugFormat("[{0}] Handling fragment {1}", session.LoggingIdentifier, fragment.Header.Sequence);
                    HandleFragment(message);
                }
                else
                {
                    log.DebugFormat("[{0}] Fragment {1} is early, lastReceivedFragmentSequence = {2}", session.LoggingIdentifier, fragment.Header.Sequence, lastReceivedFragmentSequence);
                    outOfOrderFragments.TryAdd(fragment.Header.Sequence, message);
                }
            }
        }
Ejemplo n.º 3
0
        public static void CharacterEnterWorldRequest(ClientPacketFragment fragment, Session session)
        {
            var characterEnterWorldServerReady = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum);

            characterEnterWorldServerReady.Fragments.Add(new ServerPacketFragment(9, FragmentOpcode.CharacterEnterWorldServerReady));

            NetworkManager.SendPacket(ConnectionType.Login, characterEnterWorldServerReady, session);
        }
Ejemplo n.º 4
0
 public void AddFragment(ClientPacketFragment fragment)
 {
     lock (fragments)
     {
         if (!Complete && !fragments.Any(x => x.Header.Index == fragment.Header.Index))
         {
             fragments.Add(fragment);
         }
     }
 }
Ejemplo n.º 5
0
 public static void HandleGameAction(GameActionOpcode opcode, ClientPacketFragment fragment, Session session)
 {
     if (!actionHandlers.ContainsKey(opcode))
     {
         Console.WriteLine($"Received unhandled action opcode: 0x{((uint)opcode).ToString("X4")}");
     }
     else
     {
         Type actionType;
         if (actionHandlers.TryGetValue(opcode, out actionType))
         {
             var gameAction = (GameActionPacket)Activator.CreateInstance(actionType, session, fragment);
             gameAction.Read();
             gameAction.Handle();
         }
     }
 }
Ejemplo n.º 6
0
        public static void CharacterEnterWorld(ClientPacketFragment fragment, Session session)
        {
            ObjectGuid guid    = fragment.Payload.ReadGuid();
            string     account = fragment.Payload.ReadString16L();

            if (account != session.Account)
            {
                session.SendCharacterError(CharacterError.EnterGameCharacterNotOwned);
                return;
            }

            var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.Guid.Full == guid.Full);

            if (cachedCharacter == null)
            {
                session.SendCharacterError(CharacterError.EnterGameCharacterNotOwned);
                return;
            }

            session.CharacterRequested = cachedCharacter;

            // this isn't really that necessary since ACE doesn't split login/world to multiple daemons, handle it anyway
            byte[] connectionKey = new byte[sizeof(ulong)];
            RandomNumberGenerator.Create().GetNonZeroBytes(connectionKey);

            session.WorldConnectionKey = BitConverter.ToUInt64(connectionKey, 0);

            var referralPacket = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum | PacketHeaderFlags.Referral);

            referralPacket.Payload.Write(session.WorldConnectionKey);
            referralPacket.Payload.Write((ushort)2);
            referralPacket.Payload.WriteUInt16BE((ushort)ConfigManager.Config.Server.Network.WorldPort);
            referralPacket.Payload.Write(ConfigManager.Host);
            referralPacket.Payload.Write(0ul);
            referralPacket.Payload.Write((ushort)0x18);
            referralPacket.Payload.Write((ushort)0);
            referralPacket.Payload.Write(0u);

            NetworkManager.SendPacket(ConnectionType.Login, referralPacket, session);

            session.State = SessionState.WorldLoginRequest;
        }
Ejemplo n.º 7
0
        public static async void CharacterCreate(ClientPacketFragment fragment, Session session)
        {
            // known issues:
            // 1. getting the "next" character id is not thread-safe

            string account = fragment.Payload.ReadString16L();

            if (account != session.Account)
            {
                return;
            }

            Character character = Character.CreateFromClientFragment(fragment, session.Id);

            // TODO: profanity filter
            // sendCharacterCreateResponse(session, 4);

            bool isAvailable = DatabaseManager.Character.IsNameAvailable(character.Name);

            if (!isAvailable)
            {
                SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameInUse);
                return;
            }

            uint lowGuid = DatabaseManager.Character.GetMaxId();

            character.Id        = lowGuid;
            character.AccountId = session.Id;

            if (!await DatabaseManager.Character.CreateCharacter(character))
            {
                SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.DatabaseDown);
                return;
            }

            var guid = new ObjectGuid(lowGuid, GuidType.Player);

            session.CachedCharacters.Add(new CachedCharacter(guid, (byte)session.CachedCharacters.Count, character.Name, 0));

            SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Ok, guid, character.Name);
        }
Ejemplo n.º 8
0
        public static void CharacterRestore(ClientPacketFragment fragment, Session session)
        {
            ObjectGuid guid = fragment.Payload.ReadGuid();

            var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.Guid.Full == guid.Full);

            if (cachedCharacter == null)
            {
                return;
            }

            DatabaseManager.Character.DeleteOrRestore(0, guid.Low);

            var characterRestore         = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum);
            var characterRestoreFragment = new ServerPacketFragment(9, FragmentOpcode.CharacterRestoreResponse);

            characterRestoreFragment.Payload.Write(1u /* Verification OK flag */);
            characterRestoreFragment.Payload.WriteGuid(guid);
            characterRestoreFragment.Payload.WriteString16L(cachedCharacter.Name);
            characterRestoreFragment.Payload.Write(0u /* secondsGreyedOut */);
            characterRestore.Fragments.Add(characterRestoreFragment);

            NetworkManager.SendPacket(ConnectionType.Login, characterRestore, session);
        }
Ejemplo n.º 9
0
        public static async void CharacterCreate(ClientPacketFragment fragment, Session session)
        {
            // known issues:
            // 1. getting the "next" character id is not thread-safe

            string account = fragment.Payload.ReadString16L();

            if (account != session.Account)
            {
                return;
            }

            Character character = Character.CreateFromClientFragment(fragment, session.Id);

            // TODO: profanity filter
            // sendCharacterCreateResponse(session, 4);

            bool isAvailable = DatabaseManager.Character.IsNameAvailable(character.Name);

            if (!isAvailable)
            {
                SendCharacterCreateResponse(session, 3);    /* Name already in use. */
                return;
            }

            uint guid = DatabaseManager.Character.GetMaxId() + 1;

            character.Id        = guid;
            character.AccountId = session.Id;

            await DatabaseManager.Character.CreateCharacter(character);

            session.CachedCharacters.Add(new CachedCharacter(guid, (byte)session.CachedCharacters.Count, character.Name, 0));

            SendCharacterCreateResponse(session, 1, guid, character.Name);
        }
Ejemplo n.º 10
0
        public static void CharacterCreate(ClientPacketFragment fragment, Session session)
        {
            string account = fragment.Payload.ReadString16L();

            if (account != session.Account)
            {
                return;
            }

            fragment.Payload.Skip(4);   /* Unknown constant (1) */

            uint   race           = fragment.Payload.ReadUInt32();
            uint   gender         = fragment.Payload.ReadUInt32();
            uint   eyes           = fragment.Payload.ReadUInt32();
            uint   nose           = fragment.Payload.ReadUInt32();
            uint   mouth          = fragment.Payload.ReadUInt32();
            uint   hairColor      = fragment.Payload.ReadUInt32();
            uint   eyeColor       = fragment.Payload.ReadUInt32();
            uint   hairStyle      = fragment.Payload.ReadUInt32();
            uint   headgearStyle  = fragment.Payload.ReadUInt32();
            uint   headgearColor  = fragment.Payload.ReadUInt32();
            uint   shirtStyle     = fragment.Payload.ReadUInt32();
            uint   shirtColor     = fragment.Payload.ReadUInt32();
            uint   pantsStyle     = fragment.Payload.ReadUInt32();
            uint   pantsColor     = fragment.Payload.ReadUInt32();
            uint   footwearStyle  = fragment.Payload.ReadUInt32();
            uint   footwearColor  = fragment.Payload.ReadUInt32();
            double skinHue        = fragment.Payload.ReadDouble();
            double hairHue        = fragment.Payload.ReadDouble();
            double headgearHue    = fragment.Payload.ReadDouble();
            double shirtHue       = fragment.Payload.ReadDouble();
            double pantsHue       = fragment.Payload.ReadDouble();
            double footwearHue    = fragment.Payload.ReadDouble();
            uint   templateOption = fragment.Payload.ReadUInt32();
            uint   strength       = fragment.Payload.ReadUInt32();
            uint   endurance      = fragment.Payload.ReadUInt32();
            uint   coordination   = fragment.Payload.ReadUInt32();
            uint   quickness      = fragment.Payload.ReadUInt32();
            uint   focus          = fragment.Payload.ReadUInt32();
            uint   self           = fragment.Payload.ReadUInt32();
            uint   slot           = fragment.Payload.ReadUInt32();
            uint   classId        = fragment.Payload.ReadUInt32();

            List <NewCharacterSkill> skills = new List <NewCharacterSkill>();

            uint numOfSkills = fragment.Payload.ReadUInt32();

            for (uint i = 0; i < numOfSkills; i++)
            {
                if (new[] { 0u, 1u, 2u, 3u, 4u, 5u, 8u, 9u, 10u, 11u, 12u, 13u, 17u, 25u, 26u, 42u, 53u }.Contains(i))   /* Inactive / retired  skills */
                {
                    fragment.Payload.Skip(4);
                    continue;
                }

                var newSkill = new NewCharacterSkill();
                newSkill.Skill  = (CharacterSkill)i;
                newSkill.Status = (SkillStatus)fragment.Payload.ReadUInt32();
                skills.Add(newSkill);
            }

            string characterName    = fragment.Payload.ReadString16L();
            uint   startArea        = fragment.Payload.ReadUInt32();
            bool   isAdmin          = Convert.ToBoolean(fragment.Payload.ReadUInt32());
            bool   isEnvoy          = Convert.ToBoolean(fragment.Payload.ReadUInt32());
            uint   totalSkillPoints = fragment.Payload.ReadUInt32();

            // TODO : profanity filter
            // sendCharacterCreateError(session, 4);

            var result = DatabaseManager.Character.SelectPreparedStatement(CharacterPreparedStatement.CharacterUniqueNameSelect, characterName);

            Debug.Assert(result != null);

            uint charsWithName = result.Read <uint>(0, "cnt");

            if (charsWithName > 0)
            {
                sendCharacterCreateResponse(session, 3);    /* Name already in use. */
                return;
            }

            result = DatabaseManager.Character.SelectPreparedStatement(CharacterPreparedStatement.CharacterMaxIndex);
            Debug.Assert(result != null);

            uint guid = result.Read <uint>(0, "MAX(`guid`)") + 1;

            DatabaseManager.Character.ExecutePreparedStatement(CharacterPreparedStatement.CharacterInsert, guid, session.Id, characterName, templateOption, startArea, isAdmin, isEnvoy);

            // TODO : Persist appearance, stats and skills.

            session.CachedCharacters.Add(new CachedCharacter(guid, (byte)session.CachedCharacters.Count, characterName));

            sendCharacterCreateResponse(session, 1, guid, characterName);
        }