Ejemplo n.º 1
0
        protected void FindHabboMessageClasses(ASClass habboMessageClass)
        {
            if (habboMessageClass == null)
            {
                throw new NullReferenceException(nameof(habboMessageClass));
            }

            if (OutgoingMessages != null && IncomingMessages != null)
            {
                return;
            }

            ABCFile abc = habboMessageClass.ABC;

            if (habboMessageClass.Traits.Count < 2)
            {
                return;
            }

            int incomingMapTypeIndex = habboMessageClass.Traits[0].NameIndex;
            int outgoingMapTypeIndex = habboMessageClass.Traits[1].NameIndex;

            var outgoingClasses = new Dictionary <ushort, ASClass>();
            var incomingClasses = new Dictionary <ushort, ASClass>();

            ASMethod constructor = habboMessageClass.Constructor;

            using (var inCode = new FlashReader(constructor.Body.Bytecode))
            {
                while (inCode.IsDataAvailable)
                {
                    object[] values = inCode.ReadValuesUntil(OPCode.GetLex);
                    if (values == null)
                    {
                        break;
                    }

                    // Check if the instruction is referencing one of the in/out map types.
                    int  getLexTypeIndex = (int)values[0];
                    bool isOutgoing      = (getLexTypeIndex == outgoingMapTypeIndex);
                    if (!isOutgoing && getLexTypeIndex != incomingMapTypeIndex)
                    {
                        continue;
                    }

                    OPCode op = 0;
                    values = inCode.ReadValuesUntilEither(out op, OPCode.PushByte, OPCode.PushShort);

                    if (values == null)
                    {
                        return;
                    }
                    var header = Convert.ToUInt16(values[0]);

                    values = inCode.ReadValuesUntil(OPCode.GetLex);
                    if (values == null)
                    {
                        return;
                    }

                    getLexTypeIndex = (int)values[0];
                    ASMultiname messageType  = abc.Constants.Multinames[getLexTypeIndex];
                    ASClass     messageClass = abc.FindFirstClassByName(messageType.Name);

                    Dictionary <ushort, ASClass> messageClasses =
                        (isOutgoing ? outgoingClasses : incomingClasses);

                    messageClasses[header]           = messageClass;
                    _isMessageOutgoing[messageClass] = isOutgoing;
                }
            }

            #region Organize Outgoing Message Dictionaries
            IOrderedEnumerable <KeyValuePair <ushort, ASClass> > orderedOutgoing =
                outgoingClasses.OrderBy(kvp => kvp.Key);

            _outgoingHeaders = orderedOutgoing
                               .ToDictionary(kvp => kvp.Value, kvp => kvp.Key);

            OutgoingMessages = new ReadOnlyDictionary <ushort, ASClass>(
                orderedOutgoing.ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
            #endregion
            #region Organize Incoming Message Dictionaries
            IOrderedEnumerable <KeyValuePair <ushort, ASClass> > orderedIncoming =
                incomingClasses.OrderBy(kvp => kvp.Key);

            _incomingHeaders = orderedIncoming
                               .ToDictionary(kvp => kvp.Value, kvp => kvp.Key);

            IncomingMessages = new ReadOnlyDictionary <ushort, ASClass>(
                orderedIncoming.ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
            #endregion
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Returns the Incoming message's parser class.
        /// </summary>
        /// <param name="messageClass">The Incoming message class to extract the parser class from.</param>
        /// <returns></returns>
        public ASClass GetIncomingMessageParser(ASClass messageClass)
        {
            if (_messageParsers.ContainsKey(messageClass))
            {
                return(_messageParsers[messageClass]);
            }

            ABCFile    abc = messageClass.ABC;
            ASClass    incomingMsgParserClass = null;
            ASInstance incomingMsgInstance    = messageClass.Instance;

            try
            {
                ASInstance incomingMsgSuperInstance = abc.FindFirstInstanceByName(
                    incomingMsgInstance.SuperType.Name);

                ASMultiname parserReturnType = incomingMsgSuperInstance
                                               .FindFirstGetter("parser", null).ReturnType;

                List <ASMethod> methods =
                    incomingMsgInstance.FindMethodGetterSetterTraits()
                    .Select(mgsTrait => mgsTrait.Method).ToList();

                methods.Add(incomingMsgInstance.Constructor);
                foreach (ASMethod method in methods)
                {
                    var referencedClasses = new List <ASClass>();
                    using (var inCode = new FlashReader(method.Body.Bytecode))
                    {
                        while (inCode.IsDataAvailable)
                        {
                            OPCode   op     = 0;
                            object[] values = inCode.ReadValuesUntilEither(out op, OPCode.FindPropStrict, OPCode.GetLex);
                            if (values == null)
                            {
                                break;
                            }

                            var         typeIndex = (int)values[0];
                            ASMultiname type      = abc.Constants.Multinames[typeIndex];

                            List <ASClass> instances = abc.FindClassesByName(type.Name);
                            referencedClasses.AddRange(instances);
                        }
                    }
                    foreach (ASClass referencedClass in referencedClasses)
                    {
                        ASInstance referencedInstance = referencedClass.Instance;
                        if (referencedInstance.ContainsInterface(parserReturnType.Name))
                        {
                            incomingMsgParserClass = referencedClass;
                            return(incomingMsgParserClass);
                        }
                    }
                }
            }
            finally
            {
                if (incomingMsgParserClass != null)
                {
                    _messageParsers[messageClass] =
                        incomingMsgParserClass;
                }
            }
            return(incomingMsgParserClass);
        }