1. Tired of not being able to see links? Want to chat with other members? Need help?

Updating Packet Structures

Discussion in 'Habbo Tutorials' started by Sledmore, Oct 9, 2016.

  1. Sledmore

    Sledmore Chaturbate Livestreamer Staff Member

    It's been a long time since I wrote the previous guide. So I guess it's time I write this guide. Hopefully this is written in good enough quality, although I've done it in quite a rush.

    I will miss certain bits out, but for the most part the previous guide should cover it (AS3 Sorcerer and so on).
    - [ Want to see this link? Register ! ]

    Updating packet structures is very easy, after 3-5 times of doing it you'll no longer require looking at this guide. Now, let's begin.

    In this tutorial I'll be using the following revisions:
    • PRODUCTION-201601012205-226667486 (My original PlusEMU release).
    • PRODUCTION-201609221203-707282381
    I'll go through a couple of packets that I know have since changed.
    PHP:
        class AvailabilityStatusComposer ServerPacket
        
    {
            public 
    AvailabilityStatusComposer()
                : 
    base(ServerPacketHeader.AvailabilityStatusMessageComposer)
            {
                
    base.WriteBoolean(true);
                
    base.WriteBoolean(false);
            }
        }
    PHP:
        class MessengerInitComposer ServerPacket
        
    {
            public 
    MessengerInitComposer()
                : 
    base(ServerPacketHeader.MessengerInitMessageComposer)
            {
                
    base.WriteInteger(PlusStaticGameSettings.MessengerFriendLimit);//Friends max.
                
    base.WriteInteger(300);
                
    base.WriteInteger(800);
                
    base.WriteInteger(1100);
                
    base.WriteInteger(0); // category count
            
    }
        }
    PHP:
        class ModeratorInitComposer ServerPacket
        
    {
            public 
    ModeratorInitComposer(ICollection<stringUserPresetsICollection<stringRoomPresetsDictionary<string, List<ModerationPresetActionMessages>> UserActionPresetsICollection<SupportTicketTickets)
                : 
    base(ServerPacketHeader.ModeratorInitMessageComposer)
            {
                
    base.WriteInteger(Tickets.Count);
                foreach (
    SupportTicket ticket in Tickets.ToList())
                {
                    
    base.WriteInteger(ticket.Id);
                    
    base.WriteInteger(ticket.TabId);
                    
    base.WriteInteger(1); // Type
                    
    base.WriteInteger(114); // Category
                    
    base.WriteInteger(((int)PlusEnvironment.GetUnixTimestamp() - Convert.ToInt32(ticket.Timestamp)) * 1000);
                    
    base.WriteInteger(ticket.Score);
                    
    base.WriteInteger(0);
                    
    base.WriteInteger(ticket.SenderId);
                    
    base.WriteString(ticket.SenderName);
                    
    base.WriteInteger(ticket.ReportedId);
                    
    base.WriteString(ticket.ReportedName);
                    
    base.WriteInteger((ticket.Status == TicketStatus.PICKED) ? ticket.ModeratorId 0);
                    
    base.WriteString(ticket.ModName);
                    
    base.WriteString(ticket.Message);
                    
    base.WriteInteger(0);
                    
    base.WriteInteger(0);
                }

                
    base.WriteInteger(UserPresets.Count);
                foreach (
    string pre in UserPresets)
                {
                    
    base.WriteString(pre);
                }

                
    base.WriteInteger(UserActionPresets.Count);
                foreach (
    KeyValuePair<string, List<ModerationPresetActionMessages>> Cat in UserActionPresets.ToList())
                {
                    
    base.WriteString(Cat.Key);
                    
    base.WriteBoolean(true);
                    
    base.WriteInteger(Cat.Value.Count);
                    foreach (
    ModerationPresetActionMessages Preset in Cat.Value.ToList())
                    {
                        
    base.WriteString(Preset.Caption);
                        
    base.WriteString(Preset.MessageText);
                        
    base.WriteInteger(Preset.BanTime); // Account Ban Hours
                        
    base.WriteInteger(Preset.IPBanTime); // IP Ban Hours
                        
    base.WriteInteger(Preset.MuteTime); // Mute in Hours
                        
    base.WriteInteger(0);//Trading lock duration
                        
    base.WriteString(Preset.Notice "\n\nPlease Note: Avatar ban is an IP ban!");
                        
    base.WriteBoolean(false);//Show HabboWay
                    
    }
                }

                
    base.WriteBoolean(true); // Ticket right
                
    base.WriteBoolean(true); // Chatlogs
                
    base.WriteBoolean(true); // User actions alert etc
                
    base.WriteBoolean(true); // Kick users
                
    base.WriteBoolean(true); // Ban users
                
    base.WriteBoolean(true); // Caution etc
                
    base.WriteBoolean(true); // Love you, Tom

                
    base.WriteInteger(RoomPresets.Count);
                foreach (
    string pre in RoomPresets)
                {
                    
    base.WriteString(pre);
                }
            }
        }

    Okay, so starting from easy to "hard". Again, it's important to select match case on your text editor. So first, we search for the header in the AS3 Sorcerer scripts.

    To make it easier, we search for the header in the following format "[PACKET_ID]", so in out case "[2468]". This will (in most times) bring us straight to the HabboMessages class, with a bunch of other packet IDs.

    Result:
    Code:
    _-09d[2468] = _-Dz;
    Okay, so to break that down the first part (which will always change) identifies one of the hash maps/dictionaries at the top in our case:
    Code:
    private static const _-09d:Map = new _-5vF();
    private static const _-5Ii:Map = new _-5vF();
    In our case, knowing this is useless - but it may help you get somewhat more familiar.

    We just need to know the value, which is "_-Dz". This is the class, exactly where our packet structure is. So the next step is to find that.

    Search for "class _-Dz" in your text editor (again, remember to have match case enabled in your text editor).

    Result:
    Code:
    //------------------------------------------------------------
    //_-51J._-Dz
    
    package _-51J
    {
        import _-6Pm._-3gB;
        import _-4Ie._-4rz;
        import _-6Pm.*;
    
        public class _-Dz extends _-3gB implements _-4LU 
        {
            public function _-Dz(_arg1:Function)
            {
                super(_arg1, _-4rz);
            }
            public function _-1EC():_-4rz
            {
                return ((_-3LD as _-4rz));
            }
        }
    }//package _-51J
    Okay, so I don't really have much to explain here. I only know a select bits regarding the SWF, I haven't ever bothered to learn everything - I can make a pretty accurate guess about this class, but won't be explaining much.

    There is two ways we can find the packet structure here, look at both the first and second methods - notice what sticks out the most?

    This class: "_-4rz", now you can simply do it this way. However I typically prefer to use the namespaces - I've always done it that way for around 2 years or so.

    So you can simply search "class _-4rz" to find the packet structure. But hold that thought for now. An alternative way is to use the namespaces.

    So how do we do this? it's always the second to last namespace. In our case?

    Code:
    _-4Ie._-4rz
    You may have to search a couple of times, but you'll soon hit the packet structure class - which you may forget by the time you search, so the way to identify that you're in the right place?

    Result:
    Code:
    //_-4Ie._-4rz
    Which the full class will read:
    Code:
    //------------------------------------------------------------
    //_-4Ie._-4rz
    
    package _-4Ie
    {
        import _-6Pm._-402;
        import _-6Pm.*;
    
        public class _-4rz implements for 
        {
    
            private var _-4iW:Boolean;
            private var _-6gh:Boolean;
    
            public function get isOpen():Boolean
            {
                return (this._-4iW);
            }
            public function get _-4jg():Boolean
            {
                return (this._-6gh);
            }
            public function flush():Boolean
            {
                this._-4iW = false;
                this._-6gh = false;
                return (true);
            }
            public function parse(_arg1:_-402):Boolean
            {
                this._-4iW = _arg1.readBoolean();
                this._-6gh = _arg1.readBoolean();
                return (true);
            }
    
        }
    }//package _-4Ie
    So now we get down to business. You will always see a method in the class named "parse", in our case:

    Code:
            public function parse(_arg1:_-402):Boolean
            {
                this._-4iW = _arg1.readBoolean();
                this._-6gh = _arg1.readBoolean();
                return (true);
            }
    And bingo - our packet structure. We now know that this packet has two booleans, however this is for our old revision - so we have to do the exact same process again in the new revision. I'm not going to show that process, as it's the exact same - and our thread will be too long, instead I'll just include the class.

    Code:
    //------------------------------------------------------------
    //_-6bS._-2dx
    
    package _-6bS
    {
        import _-4vy._-3SP;
        import _-4vy.*;
    
        public class _-2dx implements _-5Jv 
        {
    
            private var _-0lw:Boolean;
            private var _-OK:Boolean;
            private var _-5iM:Boolean;
    
            public function get isOpen():Boolean
            {
                return (this._-0lw);
            }
            public function get _-0ZD():Boolean
            {
                return (this._-OK);
            }
            public function get _-2Ou():Boolean
            {
                return (this._-5iM);
            }
            public function flush():Boolean
            {
                this._-0lw = false;
                this._-OK = false;
                this._-5iM = false;
                return (true);
            }
            public function parse(_arg1:_-3SP):Boolean
            {
                this._-0lw = _arg1.readBoolean();
                this._-OK = _arg1.readBoolean();
                if (_arg1.bytesAvailable){
                    this._-5iM = _arg1.readBoolean();
                };
                return (true);
            }
    
        }
    }//package _-6bS
    So again, all we need here is the parse method. We can see here that there are three booleans - need I say more? A new boolean needs adding to the bottom of your class. I'll have to go into finding the value etc another time.

    Let's try the messenger.

    Repeat the process. Here are both parse methods in the order of old revision to new revision.

    Old Revision:
    Code:
            public function parse(_arg1:_-402):Boolean
            {
                this._-O8 = _arg1._-4pl();
                this._-6I- = _arg1._-4pl();
                this._-1y0 = _arg1._-4pl();
                this._-0rL = _arg1._-4pl();
                var k:int = _arg1._-4pl();
                var k:int;
                while (k < k) {
                    this._-0SH.push(new _-2h(_arg1));
                    k++;
                };
                return (true);
            }
    New Revision:
    Code:
            public function parse(_arg1:_-3SP):Boolean
            {
                this._-8e = _arg1._-0qG();
                this._-4tz = _arg1._-0qG();
                this._-1QF = _arg1._-0qG();
                var k:int = _arg1._-0qG();
                var k:int;
                while (k < k) {
                    this._-0X3.push(new _-3Bk(_arg1));
                    k++;
                };
                return (true);
            }
    So, we'll break down this one. I don't feel I need to explain how to identify a string, integer and boolean as it's straight forward (just look over the class, you can see within 5 seconds what is an integer or not).

    The old structure is: INT, INT, INT, INT (count) { // }
    The new structure is: INT, INT, INT, INT (count) { // }

    So we simply need to remove one of the integers, again it's tricky to explain on how to find which one we need to remove - so we'll save that for now, just simply compare the classes to find out.

    Another thing - we haven't completed the structure there, as we need to figure out what the structure inside the loop is.

    Code:
    while (k < k) {
                    this._-0X3.push(new _-3Bk(_arg1));
                    k++;
                };
    Simply take the instance in the middle, where the argument is. "_-3Bk". It's pretty obvious that this is a class. So what do we do? Duh.

    Search for "class _-3Bk" and bingo. The constructor contains the missing packet structure:
    Code:
            public function _-3Bk(_arg1:_-3SP)
            {
                this._-6BE = _arg1._-0qG();
                this._name = _arg1.readString();
            }
    Which means our final structure is:
    Code:
    INTEGER,
    INTEGER,
    INTEGER,
    INTEGER (COUNT)
    {
    INTEGER,
    STRING
    }
    
    And that about wraps it up. I was going to include the moderation packet, but I think this thread is already too long. If someone wants to do that and post it in the comments I'll happily answer if it's correct or not.

    Thanks.
     
  2. LukeOx

    LukeOx PeakRP.com

    Great guide, will definitely be putting this to use. Thanks for all your contributions!
     
  3. Josemy

    Josemy New Member

    how i know the new packet structures ?

    great tutorial (Y)
     
  4. Louka

    Louka Member

    You need to actually Read the Tutorial so you can understand it it's very simple.
     
  5. Josemy

    Josemy New Member

    No... How i know the packets that changed, for after update it
     
  6. Seriosk

    Seriosk Programmer;

    Read the thread.. I don't think he can make it any clearer... seems to me your the kind of person who just wants to be told all in one sentence on how to do this..

    P.S, Good thread.. you have just raised the community's independence to update packets by a lot..
     
  7. Josemy

    Josemy New Member

    Your reading comprehension is not very good, I'm asking him, that to update structures, first you have to know what has changed (not explained) and then update them (if explained)
     
  8. Seriosk

    Seriosk Programmer;

    Hes given you an example of a few that have changed, the rest is down to you.. You should KNOW if a packet has been changed as it will be unhanded in your emulator if the ID is wrong..

    Missing information can be found on this thread for as3sorcerer etc
    [ Want to see this link? Register ! ]
     

Share This Page

Loading...