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 }
/// <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); }