issy123 / agario-protocol

Protocol for agar.io version 2.1.5
8 stars 2 forks source link

Protocol 20 - custom skin proto-message research #25

Open Barbosik opened 5 years ago

Barbosik commented 5 years ago

I found very interesting proto-message: agario_protoUser$skins$create$request But unfortunately there are no usage for this message in the web client.

    agario_proto_User_$skins_$create_$request.prototype = $extend(protohx_Message.prototype, {
        content: null,
        meta: null
    }

It has two string fields: content and meta. But it's not so clear what content and format is expected for these fields?

Let's look how agario downloading custom skins. For example, here is a data of custom skin:

At a glance, it looks that the meta field should contains meta xml file the same as downloaded from agario server. But what about content field?

Any idea on how to place my custom skin from PNG file into these two string fields? (content and meta) :blush:

AmazingGamerBoy commented 5 years ago

Hi, barbosik. Could you please add me on Skype? https://join.skype.com/invite/sWWpaYwB2wrd I'm a C++ developer, just cannot figure out how to decode the new protocol packet. Once I get started there, the rest can be done easily. Thank you

Barbosik commented 5 years ago

once you will find the code for message processing in agario.core.js, you also will find out how to decode messages. It will require encryption key, but you can trace code in the debugger and find out how to obtain it. This is not so complicated actually.

But my question is not related to encryption. There is no need to know about encryption, because you can send proto message with proxyMobileData function. It will do all job for you. But you're need to know what data needs to be set for the content and meta fields. There is no information about it in the agario.core.js. That's the problem.

AmazingGamerBoy commented 5 years ago

@Barbosik Could you add me up on Skype / Discord anyway? There's something I got to talk with you about.

Barbosik commented 5 years ago

@AmazingGamerBoy: you can email me

Barbosik commented 5 years ago

Regarding to the custom skin feature. I found that there is need to purchase skin token before send agario_protoUser$skins$create$request message. It can be done with soft_purchase_request, productId name is "1_create_skin_token". It cost 90 DNA.

Unfortunately format of the content field is still unknown. I loss most important request packet due to bad sniffer, it skips large packets. So needs to capture it again.

NuclearC commented 5 years ago

Content might be base64 png file

Barbosik commented 5 years ago

no, after all, I captured it from mobile protocol. Content appears just binary data. Actually this is byte array which contains bytes directly from PNG file (proto message stores string field as byte array, so it's safe to store binary data instead of string) :) Meta field contains XML string, the same as downloaded from config server for custom skins.

But agario web server doesn't accept my PNG file for some unknown reason. I suspect that it may accept PNG in specific format only (the same as used for all agario skins). Or may be this message is disabled for web clients. Needs to check more deep :)

Barbosik commented 5 years ago

Tried to pass PNG file taken from agario skins, the server accept it from web client with no disconnect. So it really depends on PNG format (incorrect format leads to server disconnect). But unfortunately there is no response for skins create request. Just a silence... Probably it is disabled for web clients. :(

NuclearC commented 5 years ago

PNG is data format with data fields, probably they have some custom chunk data in it? Edit: also might be the image size? Edit2: as I understand right now, desktop servers accept different messages than mobile servers right now, e.g. LoginRequest is different for both, so I think there is no support for create_skin_request in desktop servers. However It's still possible to send the request to mobile servers.

Barbosik commented 5 years ago

@NuclearC: loginRequest/loginResponse messages is identical for both - for mobile and for web versions. The difference is that mobile version sending device.platform="android" and device.version="13.0.5", at least I don't see any difference. My proto parser for desktop(web) version don't show any error for a bunch of messages captured from mobile version: Screenshot

As you can see, mobile version also don't set uncompressedSize field for message Envelope. But you can detect end of stream from zlib decompressor, so this is a not big deal. Also, mobile server still set this field in the response.

And desktop server definitely checks skinsCreate request content. It accept only compatible PNG (needs to investigate what limitations are exactly), but for some reason it silently ignore good request (copied from mobile version).

Do you know how to obtain mobile server? I catch some mobile-live dns, but it looks it can be changed. As I understand it is obtained in SSL traffic so it's not so easy to catch it. Needs to play with certificates.

NuclearC commented 5 years ago

@Barbosik Isn't it in the login response? ServerInfo field tcp host and port?

Barbosik commented 5 years ago

hm... I thought that this host also used for gameplay. But it turns out this dns is hardcoded in the application. :) So, this is just a bouncer and in order to join the game, I need to connect to the host provided in serverInfo field? Needs to test it :)

BorysDev commented 5 years ago

Imagine Fortnite dances in agar

Barbosik commented 5 years ago

@NuclearC: do you know what means message udp_handshake in the mobile protocol? The client sometimes sends some binary data (16 bytes) encoded in base64. What is it?

NuclearC commented 5 years ago

@Barbosik it is used to authorize the guest token for mobile servers. You send that packet to the udp server specified in ServerInfo field(host:udp_port)

Barbosik commented 5 years ago

I see that this token received from udp. But my android sniffer is very simple and doesn't allow to capture udp and tcp packets simultaneously, needs to rework it.

I don't understand for what reason there are two connections - tcp and udp to the same server? I check udp session and it looks very similar to tcp one. So, I'm confused why it uses two connections simultaneously? I tried to use just tcp and it worked some time, but now, the server close connection on game_enter_request. But previously it worked and I seen moving cells...

How guest token is obtained?

NuclearC commented 5 years ago

@Barbosik you've got to send login_request with realm GUEST and empty token field, server responds with login response and your new guest token. And it has to send back UDP handshake packet as I remember. You simply forward that packet to the UDP server from login response, then again forward the response from UDP server to the TCP mobile server. Then you can send game_enter and stuff. But last time I've done this was years ago. So I am not sure.

BorysDev commented 5 years ago

Imagine agar dances in fortnite

Barbosik commented 5 years ago

@NuclearC ok, I will investigate tokens later. Just implemented base functionality with loginrequest/reconnect. It works :) But there is a new issue. I cannot find cell color field in the Game$arena$cell$state, so all cells are black... Where is color field?

Also cannot find split and eject messages... Hm.. As I remember they were present in the past, but now I don't see it

Barbosik commented 5 years ago

It is almost done, I played my first game on mobile server with my custom desktop client :) Split and eject messages are missing from web code. But they are empty, so you can just create Request message and set type=game_arena_player_split (51) or type=game_arena_player_shootmass (52) with no need to set message field and it works :) Almost all works, except for the color. There is no color field in the Game$arena$cell$state message... Any idea how to obtain cells color?

NuclearC commented 5 years ago

@Barbosik there was uint32 field for color before, but they have probably removed it. I don't know how it works now. Might be calculated from ID?

Edit: there's a nice protobuf decoder here: https://protogen.marcgravell.com/decode You can use this to decode arena state packets and get the fields (without needing the original compiled message formats)

BorysDev commented 5 years ago

Imagine call of duty dances but in battlefield 1

NuclearC commented 5 years ago

@AmazingGamerBoy I can help you on discord

BorysDev commented 5 years ago

Imagine discord dances but on skype

Tombez commented 5 years ago

The difference with TCP and UDP is that the former makes sure that the other end receives the message, even if it needs to send it multiple times, while the latter just sends and forgets, which sometimes means the other end never sees it.

I'm just guessing, but mobile could use the TCP socket for important messages that must get through, like login, skin creation, purchases. Then maybe the UDP socket is used for game updates which are okay to never see, because by the time the server sent in again, it would be an outdated update anyway.

Barbosik commented 5 years ago

@NuclearC: tried to generate color from cellId or ownerId (for normal cells), works good :)

            var isPlayer = e.type == ProtoGameArenaCellStateCellType.normal_cell;
            var isVirus = e.type == ProtoGameArenaCellStateCellType.virus;
            var isEject = e.radius >= 32 && e.type == ProtoGameArenaCellStateCellType.food;
            var isPellet = e.radius < 32 && e.type == ProtoGameArenaCellStateCellType.food;
            var isAgitated = false;
            var isEjectEnemy = false;
            var name = e.nickname;

            int? color = null;
            if (isVirus) color = 0x33ff33;
            if (isPellet) color = GetColorById(e.cellId);
            if (isPlayer && e.ownerId.HasValue) color = GetColorById(e.ownerId.Value);
            if (isEject && e.ownerId.HasValue) color = GetColorById(e.ownerId.Value);
        private static int GetColorById(uint id)
        {
            var salt = (byte)(id ^ (id >> 8) ^ (id >> 16) ^ (id >> 24));
            var h = (float)(360 * salt) / 255f;
            var s = 0.97f;
            var v = 1f;
            return new ColorHsv(h, s, v).ToRgb().ToArgb32();
        }

There is also difference in mouse message. Mobile version sends normalized direction vector instead of coordinate on the map. It can be transformed from the map coordinate in the following way:

                var dir = _mouseCache - _camera.Center;
                var dl = Math.Min(dir.Length(), 820F);
                if (dl < 5f) dir = Vector2.Zero;
                else dir /= dl;

where _mouseCache is the current mouse coordinate in the game world coordinate system. And dir is the direction vector that should be sent to the server. With this transformation, mouse control feeling is the same as on the web version.

Regarding the proto message structure, I'm using it from web version. Works good. The only thing that I caught is that the server sometimes sends some message with ID=65. It sends it at the end of the game. Sometimes it sends usual game_over message, but sometimes this 65 message instead of game_over. This 65 message structure is not defined in the web version. But I think it's not so hard to reconstruct it because this format is pretty generic.

Barbosik commented 5 years ago

And of course user_skins_create_request message works. I din't tried large PNG, but for 5 KB and smaller it works ok :) Field format is the following:

Unfortunately, the web version of agario server now declines user_skins_create_request message with any content. But it works good on mobile version server :)

Barbosik commented 5 years ago

The physics of mobile version agario is much worse than on the web version. I think it's because of mouse message format. It sends just direction vector, so if you own several cells instead of one, they all will move to the same direction. In the web version all cells follows to the mouse pointer independently, and it feels much more nice and natural. Especially if you have 16 cells and 15 of them is very small they follows mouse very beautiful on the web version. On mobile version in such case it looks not natural and sometimes even abnormal. For the same reason, remerge on mobile version looks ugly. If you place mouse between two cells, they will just no move, because you place mouse at the center and direction vector will be zero :) Also there is something bad with split on the mobile version, it's not so smooth as on the web version, especially for very large cells.

Barbosik commented 5 years ago

Here is structure of unknown message with ID=65 for mobile agario protocol:

    public class Proto65 : ProtoMessage
    {
        public uint v1;         // wireType=0, number=1
        public uint v2;         // wireType=0, number=2
        public string v3;       // wireType=2, number=3

Usually it has the following values: v1=catch different values, for example: 201, 205 v2 = 1 v3= it contains some string with length for about 258 bytes.

The v3 string looks like base64, but it is not, because it contains invalid symbols for base64. I think this message is related with advertisement. For example it informs which ad needs to be shown. Because it appears just at the end of game, when mobile client usually shows ad.

NuclearC commented 5 years ago

@Barbosik have you tried creating custom skin and using it in desktop/web?

Edit: I think mobile client must use some kind of interpolation different than web agar, so it might look a little bit better

Barbosik commented 5 years ago

@NuclearC yes, it works on desktop/web, if you create it on mobile. But there is need to wait some time (for about day) before it will be displayed on desktop/web version, probably there is need for some time to synchronize databases. For this time period your skin on desktop/web will be missing (actually skin name is sent by server, but the picture is not available for some time). In browser console log there is error for this time period: DataManager.hx:1024: / datamanager / Error loading custom skin:

I think mobile client must use some kind of interpolation different than web agar, so it might look a little bit better

I don't think so, because gameplay on mobile server is almost the same as on the desktop/web. The difference is very noticeable when you split, because all your cells moving in parallel direction. This is opposite to desktop/web, where all your cells moving to the point of your mouse cursor.

It happens because server cannot determine your mouse position with mouse message format, which sends direction vector instead of mouse position. It is more simple to implement touch screen control, but if you connect mouse to your tablet, it will be very ugly in comparison to desktop/web version. For example you're need to stop (move mouse exactly at center, or release touch) in order to remerge, because if you move your mouse between your cells, they will not move to mouse cursor :) They both will move at the same direction with the same speed.

You cannot feed your team mate between your cells, because all ejects flying in parallel from each your cell. :) This is also very-very uncomfortable.

Due to these glitch in control, gameplay on mobile version looks like on some ogario server with incorrect physics :) But I found that a lot of players on mobile accustomed to such control and even using physics glitches for quick remerge, which is almost impossible on desktop/web version.

Actually, they may use mouse coordinate the same as in desktop version and make calculations for touch control, but they decided to use direction vector for some reason. So, when you split, it is very ugly to control your cells on mobile version :)

Regarding to the physics it's the same smoth as on the desktop/web version, but there are some bugs in physics engine. The difference very noticeable when very big cell splits. On mobile version the cell jumps too fast. The same as on first ogario servers. Also there are some physics glitch with eject. Ejects doesn't bounce off the map border. They just stop to move :)

Barbosik commented 5 years ago

By the way, mobile version has very inconsistent protocol. For example, in order to join FFA, there is need to send game_enter_request message with player name. In order to rejoin there is need to send this message again. If you send game_arena_player_respawn message, it will not work.

But for Rush mode there is completely different story. In order to join Rush, there is need to send game_lobby_enter message with type=rush_mode (2) and player name. In order to rejoin in Rush mode there is need to send game_arena_player_respawn message. And it seems there is no way to exit from this mode, because it just ignore game_enter_request message in rush mode until game will not be finished.

There is also present type=free_for_all (1) for game_lobby_enter message, but it doesn't works for some reason.

And the most frustrating thing on mobile version - there is no spectate mode. You can see map when you in the game. When your cell eaten, you will stop to receive update messages and cannot see what happens on the map.

NuclearC commented 5 years ago

@Barbosik mobile agar.io also has no IP limit and no protection from bots, there is enough info right here to make mobile agar.io bots and destroy agar.io even more Also it's possible to make mobile agar.io private servers, with maybe better physics than official ones

Barbosik commented 5 years ago

yeah, that's not good, if someone will do that, the protocol will be changed very quickly, it can take 1 day max. This is stupid idea doing it, because the door will be closed very quickly. And mobile platform is not so open like web in the browser. So, reverse will be very hard.

mahirozdin commented 5 years ago

@Barbosik mobile agar.io also has no IP limit and no protection from bots, there is enough info right here to make mobile agar.io bots and destroy agar.io even more Also it's possible to make mobile agar.io private servers, with maybe better physics than official ones

@NuclearC hi , mahirtaha #7740 can you help me to fix node js agar.io bots they are protocol 18 and i need to make them move on protocol 20

BorysDev commented 5 years ago

can you don't

BorysDev commented 5 years ago

@Barbosik @NuclearC Good work guys :+1:

Barbosik commented 5 years ago

Here is a nice hack to use PNG file as custom skin. You can start edit your skin, then exit and replace file in the game files. When you enter editor again, you will see replaced image, even no need to do something with protocol, any user can do it :) This hack is used by a lot of players to get custom skin :)

https://www.youtube.com/watch?v=ZEAxaQtpZjo

Elitis commented 5 years ago

@AmazingGamerBoy: you can email me

Whats your email?

Elitis commented 5 years ago

@Barbosik whats your email?