Smooth
Administrateurs
-
Adhésion
-
Dernière visite
-
Actuellement
Forum de consultation : Suggestions
Tout ce qui a été publié par Smooth
-
MapChangeOrientationRequest
Asks the server to turn the played character to face a new direction, without moving it. Kind requestArea Game.GamemapNamed by beta, gamemapping Turning is a first-class action in DOFUS, separate from moving: a character can turn on the spot without changing cell. Facing decides which way the sprite looks and which animation set plays, and it matters mechanically - backstab bonuses depend on the relative facing of attacker and target. DO NOT APPLY THE TURN OPTIMISTICALLY. The server validates it and broadcasts the result to everyone on the map INCLUDING BACK TO YOU, as MapChangeOrientationEvent. The real client waits for that echo, and your world model should too. IT CARRIES NO ACTOR ID, AND THAT IS DELIBERATE. The server knows who is asking from the connection. You cannot turn anyone but yourself with this message - which is why the outbound half has one member where the inbound half has two. In the client the action hangs off the right-click menu on your own character (the localisation key is ui.orientCharacter) and off the action-bar banner menu. The equivalent menus for other players and for NPCs do not offer it. When you may send it Requires context_ready inferred Raised by: the player picks a facing from the right-click menu on their own character proven Related messages You will then receive MapChangeOrientationEvent inferred — the server validates and broadcasts the turn to everyone on the map, including back to the requester Fields #FieldTypeMeaningYou set it 1directionDirectionThe facing to turn to. A Direction value.required Recovered with score 150, confidence 0.93, margin 150 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 1.
-
IdentificationRequest
Presents an authentication ticket on a freshly opened game-server socket; always the first frame written on that connection. Kind requestArea Game.ConnectionNamed by beta, gamemapping THE FIRST FRAME ON EVERY GAME-SERVER SOCKET. Nothing else is accepted until it is answered, and the client does not wait for the socket to finish opening before writing it: the message is built inside the connect routine and handed to the connection object while the TCP handshake is still in flight. The connection queues it and flushes it the instant the channel goes live. WHEN TO SEND IT There are exactly two moments, and both are the opening of a NEW socket. 1. ENTERING A SERVER. The trigger is NOT the login server's server-selection reply. That reply only hands you three things - a ticket, a host, and a LIST of candidate ports - which the client stores. The client then lets the LOGIN connection close, and only once that socket is gone does it dial the game host and send this message. A capture of a full sign-in therefore shows two connections that do not overlap. 2. TRANSFERRING TO A FIGHT SERVER. A second game connection, opened ALONGSIDE the first, which stays up. The server sends a transfer message carrying its own host, its own ticket and its own port list; the client opens a second socket, sends this message on it, and from then on drives both connections at once. The destination is a dedicated arena server - see ServerType.KOLIZEUM. THE PORT LIST IS A CANDIDATE LIST, NOT A CHOICE. You are given several ports for one host. The client takes its configured port when that port is in the list and the first one otherwise; on a failed connect it drops that port and retries the next, until the list is empty. The identification request is NOT rebuilt per attempt - it is queued once, on the connection object, and written on whichever attempt succeeds. The number of TCP attempts and the number of identification requests are not the same number. THE TICKET IS NOT SOMETHING YOU CAN INVENT. It comes from an exchange on an earlier, separate connection, and the two moments above use two DIFFERENT tickets: entering a server uses the one from the server-selection reply, the fight transfer uses the one carried by the transfer message. They are not interchangeable. ONE SESSION, TWO SOCKETS. Because the fight transfer identifies on a second socket while the first one is still authenticated, "already authenticated" does not mean "must not send this". What is illegal is sending it TWICE ON ONE SOCKET. Scope the rule to the connection, not to the session. BEWARE THE NAME COLLISION. A message called IdentificationRequest exists in BOTH protocols: one in the Connection protocol (login server) and this one in the Game protocol. They are different messages with different payloads, and a single sign-in sends both. DO NOT COPY FIELD NUMBERS FROM AN OLDER SCHEMA. This message has been renumbered - the reference build carries the ticket and the locale as fields 1 and 2, the current build does not. Read the numbers off this page. Acceptance is followed immediately by a burst of state events in the same millisecond - server settings, optional features, account capabilities and rights, trust status - ending with ServerSessionReadyEvent. When you may send it Requires transport_established observed Raised by: a client-side state change - one of the two connect routines opening a game-server socket, either entering a server (after the login connection has closed) or transferring to a fight server (a second socket beside the first). The message is built inside that routine and queued on the connection before the TCP handshake finishes, so it leaves as the first frame the moment the socket goes live proven State it changes Establishes authenticated observed — acceptance opens the session; every later message is gated on it Related messages You will then receive ServerSessionReadyEvent observed — the session value the challenge exchange is built on; 1 of 1 login capture You will then receive ServerSettingsEvent observed — server identity and settings, in the same inbound burst You will then receive OptionalFeaturesEvent observed — which optional features this server enables You will then receive TrustStatusEvent observed — whether the server considers the client trusted You will receive one of AuthenticationTicketAcceptedEvent observed — the ticket was accepted You will receive one of AuthenticationTicketRefusedEvent observed — the ticket was rejected Fields #FieldTypeMeaningYou set it 1ticket_keystringThe authentication ticket for THIS connection, issued by the exchange that sent you here. Two different tickets are in play. Entering a server uses the one carried by the login server's server-selection reply; transferring to a fight server uses the one carried by the transfer message. They are not interchangeable, and neither can be derived from anything you already hold.required 2language_codestringThe client's current locale, e.g. fr or en. The server uses it to localise the text it sends back. Observed: fr Read from the client's one global locale at the moment of connecting, so every connection of a session carries the same value.required Recovered with score 135, confidence 0.92, margin 135 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 2 of 2.
-
GuildWeeklyNextResetRequest
Asks when the guild's current mission week ends. Empty payload. Kind requestArea Game.GuildNamed by gamemapping Guild missions run on a weekly cycle and THE CLIENT DOES NOT COMPUTE THE BOUNDARY LOCALLY - it asks the server and caches the answer. Progress bars, countdowns and the save affordances in the mission windows all depend on it. Carries nothing. Do the same: ask once and cache. Recomputing the week boundary from your own clock will disagree with the server across timezone and daylight-saving boundaries, which is exactly when it matters. When you may send it Requires character_loaded observed Raised by: opening a guild-mission window (tier, or ranks-and-categories). The send is GUARDED on a service state enum, so in practice it fetches once per session proven Related messages You will then receive GuildWeeklyNextResetResponse observed — observed on the wire as a Response, matching a direct reply rather than a push Recovered with score 100, confidence 0.93, margin 100 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 0 of 0.
-
GuildMemberWarnOnConnectionStopRequest
Asks the server to stop notifying this character when a guild member comes online. Empty payload. Kind requestArea Game.GuildNamed by gamemapping The unsubscribe half of a mutually exclusive pair with GuildMemberWarnOnConnectionStartRequest. Both carry nothing; WHICH MESSAGE YOU SEND IS THE ENTIRE PAYLOAD. THE SERVER HOLDS THE SUBSCRIPTION STATE, NOT YOU. The client keeps its own copy of the checkbox as a persisted option, but that copy is a UI convenience and IS NEVER REPLAYED TO THE SERVER - it is not sent at login and not sent on reconnect. So the server's idea of your subscription survives your client restarting, and sending nothing means "leave it as it was". Send one of the pair only when the setting actually changes. When you may send it Requires character_loaded observed Raised by: the player ticks or unticks the guild-member connection warning in the guild members panel proven Related messages Nothing answers it - send it and move on the server holds the subscription; no dumped build has an acknowledgement message for it No fields you may set. Recovered with score 160, confidence 0.90, margin 160 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 0 of 1.
-
GuildMemberWarnOnConnectionStartRequest
Asks the server to start notifying this character when a guild member comes online. Empty payload. Kind requestArea Game.GuildNamed by gamemapping The subscribe half of a mutually exclusive pair with GuildMemberWarnOnConnectionStopRequest. Both carry nothing; WHICH MESSAGE YOU SEND IS THE ENTIRE PAYLOAD. THE SERVER HOLDS THE SUBSCRIPTION STATE, NOT YOU. The client keeps its own copy of the checkbox as a persisted option, but that copy is a UI convenience and IS NEVER REPLAYED TO THE SERVER - it is not sent at login and not sent on reconnect. So the server's idea of your subscription survives your client restarting, and sending nothing means "leave it as it was". Send one of the pair only when the setting actually changes. When you may send it Requires character_loaded observed Raised by: the player ticks or unticks the guild-member connection warning in the guild members panel proven Related messages Nothing answers it - send it and move on the server holds the subscription; no dumped build has an acknowledgement message for it No fields you may set. Recovered with score 145, confidence 0.92, margin 145 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 0 of 1.
-
GuildInformationRequest
Asks for one section of the player's guild data - general, members, boosts, houses, recruitment or logbook. Kind requestArea Game.GuildNamed by beta, gamemapping THE GUILD WINDOW DOES NOT GET EVERYTHING AT ONCE. Each tab asks for the section it needs and the server answers with the matching event. This request carries nothing but the section selector, so it is a pure "give me X". ASK FOR THE SECTION YOU ACTUALLY WANT. The sections are separate round trips; asking for all six because you might need one is traffic the real client does not produce - it asks on tab navigation. information_type IS RENUMBERED RELATIVE TO THE REFERENCE BUILD AND THIS IS THE TRAP. See InformationType: three of the six values moved, so code carried across from an older schema asks for the wrong section without any error. The client also sends this once at world entry, as the last of the four-request burst that follows ContextCreationRequest - see FriendListRequest for the whole burst. When you may send it Requires character_loaded observed Raised by: the player opens the guild window or switches one of its tabs proven Related messages Reply not yet recovered: each section is answered by its own event - general information, member list, boosts, houses, recruitment settings, logbook. None of those has a signature here yet, so match them by arrival. Sequence Step post_character_load.4 observed — of 4 requests; a capture shows it three milliseconds after the first three Fields #FieldTypeMeaningYou set it 1information_typeInformationTypeWhich section of the guild data is wanted. An InformationType value. RENUMBERED since the reference build - read the enum page before hardcoding a number.required Recovered with score 100, confidence 0.94, margin 100 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 1.
-
FriendSetWarnOnLevelGainRequest
Turns on or off the notification shown when a friend, guild member or nearby character gains a level. Kind requestArea Game.SocialNamed by beta, gamemapping One of the social "warn me when..." toggles the client mirrors to the server. THE SERVER HAS TO BE TOLD because it is the side that decides whether to push the notification; the client cannot honour the setting locally. IT IS SENT IMMEDIATELY ON EVERY FLIP, WITH NO DEBOUNCE. The option lives in Options -> General, in the Social block. Flipping it publishes a one-boolean event that a writer turns straight into this message. A script that toggles this in a loop produces a burst of requests that no human interaction could. SEND IT ONLY WHEN THE SETTING ACTUALLY CHANGES. It is a persisted client option replayed verbatim, not a query and not a subscription. When you may send it Requires character_loaded observed Raised by: the player flips the toggle in Options -> General, Social block proven Related messages Nothing answers it - send it and move on it mirrors a stored client option to the server; no dumped build has a matching acknowledgement message Fields #FieldTypeMeaningYou set it 2enableboolTrue to be notified when a friend, guild member or character on the current map levels up; false to suppress it. The persisted client option, replayed verbatim.required Recovered with score 100, confidence 0.95, margin 100 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 2.
-
FriendSetWarnOnConnectionRequest
Turns on or off the notification shown when a mutual contact logs in. Kind requestArea Game.SocialNamed by beta, gamemapping One of the social "warn me when..." toggles the client mirrors to the server. THE SERVER HAS TO BE TOLD because it is the side that decides whether to push the notification; the client cannot honour the setting locally. IT IS SENT IMMEDIATELY ON EVERY FLIP, WITH NO DEBOUNCE. The option lives in Options -> General, in the Social block. Flipping it publishes a one-boolean event that a writer turns straight into this message. A script that toggles this in a loop produces a burst of requests that no human interaction could. SEND IT ONLY WHEN THE SETTING ACTUALLY CHANGES. It is a persisted client option replayed verbatim, not a query and not a subscription. When you may send it Requires character_loaded observed Raised by: the player flips the toggle in Options -> General, Social block proven Related messages Nothing answers it - send it and move on it mirrors a stored client option to the server; no dumped build has a matching acknowledgement message Fields #FieldTypeMeaningYou set it 1enableboolTrue to be notified when a mutual contact comes online; false to suppress it. The persisted client option, replayed verbatim.required Recovered with score 100, confidence 0.95, margin 100 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 1.
-
FriendSetStatusShareRequest
Turns on or off sharing your online status and activity with your contacts. Kind requestArea Game.SocialNamed by beta, gamemapping The wire half of the client's "share my status" setting. With sharing on, your contacts see that you are connected and what you are doing; with it off you appear as not sharing. THE SERVER HAS TO BE TOLD because it is the side that answers other players' contact-list queries - the client cannot honour this locally. It travels the same machinery as the four warn-toggles and is sent immediately on every flip, with no debounce. Send it only when the setting actually changes. When you may send it Requires character_loaded observed Raised by: the player flips the status-sharing control proven Related messages Nothing answers it - send it and move on it mirrors a stored client option to the server; no dumped build has a matching acknowledgement message Fields #FieldTypeMeaningYou set it 1shareboolTrue to share your online status and activity with your contacts; false to withhold it. The stored client option, copied straight through.required Recovered with score 100, confidence 0.95, margin 100 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 2.
-
FriendListRequest
Asks for the character's friend list. Empty payload - the server knows who is asking. Kind requestArea Game.SocialNamed by beta, gamemapping It is one of a FIXED FOUR-REQUEST BURST the client fires once per entry into the world, straight after asking for the game context. The client's own name for the routine survives obfuscation: SendRequestAfterCharacterLoaded. The order is constant: ContextCreationRequest (the context first) 1. FriendListRequest 2. AcquaintanceListRequest 3. SpouseInformationRequest 4. GuildInformationRequest That order is not guessed from traffic: it is the order the routine allocates the four objects in, and a live capture reproduces it exactly - the first three land inside the same millisecond, the guild request three milliseconds later. SEND IT ONCE, AT THAT POINT. NEVER POLL IT. The trigger is "the character finished loading", not a timer. THERE IS A SECOND TRIGGER, AND IT IS A UI ONE. The client also sends this every time the friends panel is shown - the panel's OnEnable refreshes its data, which the contact service turns into this request. A script with no friends panel has no reason to reproduce that one. Carries nothing. There is a name collision worth knowing about: a DIFFERENT FriendListRequest exists in the Connection protocol. This is the Game one. When you may send it Requires character_loaded observed Related messages Reply not yet recovered: the friend list arrives as an event that has no signature here yet. Sequence Step post_character_load.1 observed — of 4 requests, in the order the client's own routine allocates them Recovered with score 270, confidence 0.90, margin 270 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 0 of 0.
-
FileCheckRequest
The measurement of the file the server asked about, returned with the algorithm it asked for. Kind requestArea Game.Client.VerificationNamed by beta, gamemapping The answer to FileCheckEvent. It carries the measurement as a STRING - a decimal byte count or a checksum, depending on which CheckType the challenge selected - and the same check type echoed back. COPY THE CHECK TYPE THROUGH UNCHANGED. The client does exactly that: the value from the event is written into the reply without transformation. The current build declares a SECOND field of the same CheckType type that no writer ever populates. It is a decoy; leave it at its default. The live one is the field named here. When you may send it Requires authenticated observed Related messages Answers FileCheckEvent Fields #FieldTypeMeaningYou set it 1valuestringThe measurement, as a string: a decimal byte length or a checksum. Which of the two it is depends on the CheckType the challenge selected.required 3check_typeCheckTypeThe check type from the challenge, copied through unchanged. A CheckType value. The record declares a second field of this type that is never populated - leave it default.required Recovered with score 200, confidence 0.99, margin 200 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 2 of 3.
-
DialogLeaveRequest
Closes whatever dialog you are in. No payload - the server knows which one. Kind requestArea Game.DialogNamed by beta, gamemapping CARRIES NOTHING, AND DOES NOT NEED TO. There is one dialog open at a time and the server knows which; you are saying "I am done with it", not naming it. WHEN TO SEND IT WHEN THE DIALOG WINDOW GOES AWAY - and that is a wider condition than "the player clicked close". In the real client most of these windows raise the leave intent from Unity's OnDisable hook, which runs however the window disappeared: the bank, the exchange, the NPC shop, the auction house and the craft window all do exactly that. A few add explicit paths on top - the zaap picker also raises it from its close button AND its Esc shortcut, the house window from its own CloseWindow, the NPC dialogue from its close handler and from the reply that ends the conversation rather than continuing it. So the honest rule for a script is not "send it when I press close", it is SEND IT WHEN YOU STOP BEING IN THE DIALOG, whatever ended it on your side. ONE PER CLOSE. Fourteen different windows raise the same intent and several services listen for it, but only the service of the feature you are actually in is subscribed at the time, so exactly one request goes out. Do not send one per window you think might be open. NOTHING GATES IT. The handlers do no checking at all - they construct the empty message and hand it to the connection. If you reach the condition, it goes. WHEN NOT TO SEND IT DO NOT ANSWER DialogLeaveEvent WITH THIS. This is the one that will bite you. When the SERVER closes the dialog - you walked away, the NPC ended it, it timed out - it announces the close, and the natural-looking reaction is to confirm with a leave request. The real client cannot do that, and it is not an accident: on that event the feature's service disables itself FIRST and only then asks the UI to close, so by the time the window's OnDisable fires there is nobody subscribed to raise the intent. The close the server caused produces no request. Echoing it means asking the server to close a dialog that is already gone. DO NOT SEND IT WHEN NO DIALOG IS OPEN. Nothing in the client does, and there is nothing to close. WHAT COMES BACK DialogLeaveEvent, carrying the DialogType that closed - but read that record before you rely on it. It is a broadcast, not a receipt: the same message arrives when the server closes a dialog on its own, so a script that blocks waiting for "my" answer can be woken by someone else's. IT IS UNCORRELATED. Envelope uid -1, nothing to match. If you need to know your dialog is gone, key on the TYPE in the event, not on the timing. THE DECLARED MEMBER IS PADDING. Some builds give this message a field. No client has ever written it, and neither should you. When you may send it Requires context_ready observed Raised by: a client-side state change: the dialog's window going away. For most windows the intent is raised from Unity's OnDisable hook, so it fires however the window disappeared; the zaap picker adds an explicit close button and an Esc shortcut, and the NPC dialogue adds its close path and the reply that ends the conversation. Only the active feature's service is subscribed, so one close produces exactly one request inferred Related messages You will then receive DialogLeaveEvent observed — the server answers by announcing which dialog closed Recovered with score 195, confidence 0.86, margin 195 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 0 of 0.
-
ContextReadyRequest
Tells the server the client has finished loading a map and is ready to play in it. Once per map, every map. Kind requestArea Game.ContextNamed by beta, gamemapping THE SERVER GATES THE WORLD ON THIS. Until it arrives your character is loaded but not live: actors do not move for you, interactive elements do not respond, and the map's contents are not sent. It is the second half of being on a map, and the half you have to do yourself. WHEN TO SEND IT ONCE PER MAP LOAD, EVERY MAP LOAD. This is not a session handshake and it is not the same kind of thing as ContextCreationRequest, which you send once for the whole session. This one fires again on every teleport, every zaap, every map change and every fight transition, for as long as you are connected. THE CUE IS YOUR OWN LOADING, NOT THE SERVER'S MESSAGE. The client does not send this when the map data arrives on the wire; it sends it when its map renderer picks up the loaded map asset and announces it internally. Everything that cares about "a new map is here" hangs off that one announcement - the grid generator, the interactive-cell manager, several gameplay services, and two outbound requests: map asset finished loading -> ContextReadyRequest (this message) -> MapInformationRequest -> the client's own map-dependent services wake up That is why MapInformationRequest and this message go out together, in the same millisecond in a capture. They are two subscribers to one event, not a sequence. For a script the practical translation is: whatever you treat as "I have the map now", send both from that same point. WHAT TO PUT IN IT SEND THE ID YOU WERE JUST GIVEN, NOT ONE YOU REMEMBER. The client copies the map id off the notification that carries the freshly loaded map and writes it unmodified. It never consults a cached "current map", and that matters: during a transition your idea of the current map and the map that just finished loading are different for a while. WHAT COMES BACK The map's contents: actors, interactive elements, stated elements. There is no Response and nothing acknowledges the request itself - the traffic that follows IS the answer. The envelope is uncorrelated, so its uid goes out as -1; do not allocate one and do not wait to match anything against it. IF YOU NEVER SEND IT you stay connected, the connection looks healthy, and nothing arrives. That silence is the symptom. When you may send it Requires context_ready observed Raised by: a client-side state change: the client's own map-loaded notification, published by the map renderer the moment it starts handling a freshly loaded map asset. It fires once per map load - every teleport, zaap, map change and fight transition - and the writer copies the id straight off that notification proven Related messages Reply not yet recovered: the map's contents arrive immediately: actors, interactive elements and stated elements. Those messages are recovered but not documented yet. Fields #FieldTypeMeaningYou set it 1map_idint64The map that just finished loading on the client. (map id) Take it from the load you are reporting, not from a cached "current map" - the client copies it unmodified off its own map-loaded notification, and during a transition the two are not the same value.required Recovered with score 170, confidence 0.86, margin 170 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 1.
-
ContextCreationRequest
Asks the server to create the character's game context. Sent once per game entry, not once per map. Kind requestArea Game.ContextNamed by beta, gamemapping THIS IS THE STEP THAT PUTS YOU IN THE WORLD. Before it, the server knows who you are and which character you picked, but you have no map, no entities and no context. After it, everything gated on a game context becomes legal. It carries no payload - the message IS the ask. WHEN TO SEND IT ONCE PER GAME ENTRY. NOT ONCE PER MAP. This is the single most expensive mistake you can make with this message. Map changes, teleports, zaaps and fight transitions do NOT re-create the context and the real client does not re-send this - what it re-sends on every map is ContextReadyRequest and MapInformationRequest. The client has exactly two places that build this message, and neither of them is on the map-change path. PATH 1 - ENTERING THE GAME. The chain starts at a successful CharacterSelectionEvent and runs entirely inside the client: CharacterSelectionEvent (success) -> the client starts its enter-game routine -> it shows the loading screen and WAITS ONE FULL SECOND -> it loads the character-selection-to-game data set -> it waits for the account options to be loaded -> it switches on the first batch of gameplay services -> ContextCreationRequest <-- here -> it switches on the rest of the gameplay services So the honest rule is: send it after the selection succeeded, and after a delay. A capture shows it about 1.4 seconds behind the character finishing loading, and the one-second wait above is a literal constant in the client, not jitter. Firing it in the same millisecond as the selection result is a timing no real client produces. CharacterLoadingCompleteEvent arrives during that window, which is why a capture makes it look like the cue. On this path it is not: the client does not key on it. It is still a good practical checkpoint, because it always lands before the request does. PATH 2 - ARRIVING ON A FIGHT SERVER. When the client is handed over to an arena server it opens a SECOND game connection beside the first (see IdentificationRequest), and on that connection the rule is different: the moment CharacterLoadingCompleteEvent arrives there, the client sends this request immediately, with no delay and no gate. The check is on which socket the event arrived on - the same event on the ordinary game connection does nothing. So: once when you enter the world, and once more per fight-server hand-over, on the new socket. WHAT COMES BACK About 30ms later the server pushes a context-creation event carrying the context kind (roleplay or fight), followed by the map and character state. Only then is anything gated on a game context legal. Nothing about this exchange is correlated: the request goes out on the plain send path, so its envelope uid is -1 and there is no response to match against it. Watch for the inbound burst, not for a reply. THE CONTEXT IS NOT PERMANENT. The server tears it down and rebuilds it during the session - entering and leaving a fight is the obvious case - and it does so on its own initiative, by pushing destroy and create events. Treat the context as a state the server owns and announces, not as a latch you set once. What you must not do is try to drive those rebuilds yourself by re-sending this request. When you may send it Requires character_loaded observed Raised by: a client-side state change: the enter-game routine reaching its network step. That routine is started by a successful CharacterSelectionEvent, then waits a fixed one second, loads the character-selection-to-game data set, and only sends once the account options are loaded - so it lands roughly 1-1.5s after the selection result, never immediately. The fight-server transfer has its own second path inferred State it changes Establishes context_ready observed — the server answers with the map and character state that world messages depend on Related messages Reply not yet recovered: about 30ms later the server sends a burst carrying map and character state. Those messages are recovered but not documented yet, so no ref is given here. Recovered with score 150, confidence 0.92, margin 150 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 0 of 0.
-
ContactWarnOnPermanentDeathSetRequest
Turns on or off the notification shown when a contact dies permanently on an epic server. Kind requestArea Game.SocialNamed by beta, gamemapping One of the social "warn me when..." toggles the client mirrors to the server. THE SERVER HAS TO BE TOLD because it is the side that decides whether to push the notification; the client cannot honour the setting locally. IT IS SENT IMMEDIATELY ON EVERY FLIP, WITH NO DEBOUNCE. The option lives in Options -> General, in the Social block. Flipping it publishes a one-boolean event that a writer turns straight into this message. A script that toggles this in a loop produces a burst of requests that no human interaction could. SEND IT ONLY WHEN THE SETTING ACTUALLY CHANGES. It is a persisted client option replayed verbatim, not a query and not a subscription. It only means anything on a server with permanent death - see ServerType.EPIC. When you may send it Requires character_loaded observed Raised by: the player flips the toggle in Options -> General, Social block proven Related messages Nothing answers it - send it and move on it mirrors a stored client option to the server; no dumped build has a matching acknowledgement message Fields #FieldTypeMeaningYou set it 1enableboolTrue to be notified when a friend, guild member or character on the current map dies permanently; false to suppress it. The persisted client option, replayed verbatim.required Recovered with score 100, confidence 0.95, margin 100 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 2.
-
ContactWarnOnAchievementCompleteSetRequest
Turns on or off the notification shown when a friend, guild member or nearby character unlocks an achievement. Kind requestArea Game.SocialNamed by beta, gamemapping One of the social "warn me when..." toggles the client mirrors to the server. THE SERVER HAS TO BE TOLD because it is the side that decides whether to push the notification; the client cannot honour the setting locally. IT IS SENT IMMEDIATELY ON EVERY FLIP, WITH NO DEBOUNCE. The option lives in Options -> General, in the Social block. Flipping it publishes a one-boolean event that a writer turns straight into this message. A script that toggles this in a loop produces a burst of requests that no human interaction could. SEND IT ONLY WHEN THE SETTING ACTUALLY CHANGES. It is a persisted client option replayed verbatim, not a query and not a subscription. When you may send it Requires character_loaded observed Raised by: the player flips the toggle in Options -> General, Social block proven Related messages Nothing answers it - send it and move on it mirrors a stored client option to the server; no dumped build has a matching acknowledgement message Fields #FieldTypeMeaningYou set it 1enableboolTrue to receive the achievement notification for friends, guild members and characters on the current map; false to suppress it. The persisted client option, replayed verbatim.required Recovered with score 100, confidence 0.95, margin 100 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 1.
-
ClientIdRequest
Answers the server's verification poll with a fresh cryptographic commitment - step 1 of a three-step proof of identity. Kind requestArea Game.Client.VerificationNamed by beta, gamemapping Answers ServerVerificationEvent. It opens a three-step proof that you hold a private key, and the value it carries is a COMMITMENT - not an identifier, not something you own, and not something you can look up. WHEN TO SEND IT IMMEDIATELY, ONCE PER POLL, AND FROM NOWHERE ELSE. The client builds it in exactly one place - the handler for the poll - and answers unconditionally. It reads NOTHING out of the poll; the event's arrival is the entire instruction. IT COMES EARLY. The poll can arrive on the bare connection, before the ticket exchange has finished, so this is one of the first things you ever send. Do not gate it on being logged in. WHAT TO PUT IN IT k = a fresh 400-bit random integer (50 random bytes, read little-endian) id = decimal string of G^k mod P P and G are not secret, not negotiated and not per-session: the client hard-codes the RFC 2409 768-bit MODP group - "Oakley group 1" - which is a published constant, with G = 2 and Q = (P - 1) / 2. The whole handshake lives in that one group. KEEP k. IT IS THE POINT OF THIS MESSAGE. Only G^k travels; k itself never does, and ClientChallengeProofRequest cannot be computed without it. Generate it here, store it, and use that exact value later. NEVER REUSE k. A Schnorr nonce answered against two different challenges leaks the private key by simple arithmetic - this is the classic way these schemes are broken. The real client draws a new one on every poll and overwrites the old, so a second poll silently invalidates any proof you had not yet sent. Recompute, do not cache. USE A REAL RANDOM SOURCE. The client uses a cryptographic generator. A predictable k is as bad as a reused one. IT IS A CORRELATED REQUEST. The client allocates an envelope uid for it, which most of the protocol does not - all three messages of this handshake do. The value is derived, never stored: it differs on every poll and on every run. IT STAYS ON THE MAIN CONNECTION. While a fight-server transfer has a second socket open (see IdentificationRequest) the client routes outbound traffic by message type, and all three verification requests are pinned to the FIRST connection. Gameplay traffic is what moves to the fight server, not this. THE COMPLETE ALGORITHM IS ON ONE PAGE. Constants, both exponents, both branches, what the server checks and the ways an implementation goes wrong are written out in full under ClientChallengeProofRequest. Read that before implementing any part of this exchange. When you may send it Requires transport_established observed Related messages Answers ServerVerificationEvent Fields #FieldTypeMeaningYou set it 3idstringDecimal string of G^k mod P - a commitment to a fresh secret, not an identity. k is 50 random bytes read as a little-endian unsigned integer. Keep it: ClientChallengeProofRequest needs it and it never travels.required; recomputed on every poll, never reused Recovered with score 185, confidence 0.94, margin 185 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 3.
-
ClientChallengeProofRequest
Closes the proof-of-identity handshake by answering the server's challenge with a Schnorr response. Kind requestArea Game.Client.VerificationNamed by beta, gamemapping Answers ServerChallengeEvent and ends the three-step exchange opened by ClientIdRequest and ClientChallengeInitRequest. WHEN TO SEND IT IMMEDIATELY ON ServerChallengeEvent, once, unconditionally. One construction site and no other path. THE WHOLE SCHEME, END TO END This is the one page that carries the complete algorithm. It is a Schnorr proof of identity, and everything below is read out of the client rather than guessed: CONSTANTS the client hard-codes one group and never negotiates it P the RFC 2409 section 6.1 prime, 768-bit MODP, "Oakley group 1" G 2 Q (P - 1) / 2 SECRETS neither ever travels x int(1024 random bytes, unsigned, LITTLE-endian) mod P drawn ONCE per process, kept for its whole life k int( 50 random bytes, unsigned, LITTLE-endian) drawn afresh for every verification poll THE FOUR STEPS 1 ServerVerificationEvent -> ClientIdRequest id = decimal string of G^k mod P (commitment R) 2 ServerSessionReadyEvent -> ClientChallengeInitRequest challenge_key = decimal string of G^x mod P (public key A) 3 ServerChallengeEvent carries c, a decimal string 4 this message proof = decimal string of (k + c*x) mod Q and if that came out negative, add Q back WHAT THE SERVER CHECKS It recomputes G^proof mod P and compares it with (id * challenge_key^c) mod P. Those agree exactly when you knew both secrets, which is the entire point of the exchange. The arithmetic works because 2 generates the order-Q subgroup of that prime. If you skipped either earlier message there is nothing to compare against, and no amount of guessing here will pass. FOUR WAYS TO GET THIS WRONG, ALL OF THEM SILENT Each of these produces a well-formed message that simply fails, with no error you can see and nothing in the traffic to tell you which one you hit. ENDIANNESS. Both random values are read LITTLE-endian and unsigned. Most big-integer libraries default to big-endian, and the number you get is completely different. DECIMAL, NOT HEX. Every value on the wire is a base-10 string. There is no hex, no base64 and no binary anywhere in this exchange. P VERSUS Q. The two exponentiations reduce modulo P; the proof reduces modulo Q. Swapping them is easy and fatal. THE SIGN. The client reduces modulo Q and then adds Q back if the result came out negative. Languages disagree about the sign of a remainder, so normalise explicitly rather than trusting your own operator. IF THE CHALLENGE IS ABSENT, YOU ANSWER YOURSELF The challenge field has explicit presence, and the client checks whether it is there. If the event arrives with NO value, the client does not skip the reply and does not error - it derives its own challenge and answers anyway: c = SHA-256 of the decimal strings of G, G^x mod P and G^k mod P, concatenated with the client's device fingerprint, and read back as a big-endian integer proof = (k + c*x) mod Q, forced non-negative, exactly as above THAT BRANCH SIGNS A MACHINE IDENTIFIER. The device fingerprint is the uppercase hex SHA-256 of the machine's unique device id concatenated with the MAC addresses of every network interface. So two machines answering the same value-less event produce different proofs, and the same fingerprint is also sent during login on the separate connection-server exchange. If you are reproducing the client's behaviour you have to reproduce this too, and if you are not, be aware of what it identifies. THE NUMBERING GAP IS PADDING. This message also declares a six-value enum that no dumped build ever writes; proto3 leaves a zero-valued enum off the wire entirely. There is nothing for you to set there. IT IS A CORRELATED REQUEST, like the other two steps. WHAT IS READ AND WHAT IS INFERRED The constants, the byte counts, both formulas and the value-less branch are read out of the client's own code, and the same structure is present in every dumped build. Two things are NOT: the verification equation above is what the server must be doing for this arithmetic to mean anything, but nothing in a client dump can see the server; and no capture has been observed of a challenge arriving without a value, so that branch is code that certainly exists rather than behaviour that has certainly been seen. THIS IS AN ANTI-TAMPER HANDSHAKE, NOT A SECURITY BOUNDARY. A 768-bit MODP group has been below recommended strength for many years, and nothing here is encrypted - the exchange proves that whoever is talking held a key across three messages, and that is all it proves. Do not read more assurance into it than that, in either direction. IT STAYS ON THE MAIN CONNECTION. While a fight-server transfer has a second socket open (see IdentificationRequest) the client routes outbound traffic by message type, and all three verification requests are pinned to the FIRST connection. Gameplay traffic is what moves to the fight server, not this. When you may send it Requires authenticated observed Related messages Answers ServerChallengeEvent Fields #FieldTypeMeaningYou set it 1proofstringDecimal string of (k + c*x) mod Q, normalised non-negative. k is the nonce from ClientIdRequest, x the private exponent behind ClientChallengeInitRequest, c the server's challenge, Q = (P-1)/2 for the RFC 2409 768-bit group. When the challenge arrives with no value the client hashes its own, including a device fingerprint - see the description.required Recovered with score 130, confidence 0.94, margin 130 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 1.
-
ClientChallengeInitRequest
Publishes the client's long-lived public key, opening the session half of the proof-of-identity handshake. Kind requestArea Game.Client.VerificationNamed by beta, gamemapping Answers ServerSessionReadyEvent. It carries your PUBLIC KEY - the value the server will check your proof against. WHEN TO SEND IT IMMEDIATELY ON ServerSessionReadyEvent, once, unconditionally. One construction site, no timer, no other path. That event closes the burst that follows a successful IdentificationRequest, so in practice this is the first thing you send once the session exists. WHAT TO PUT IN IT x = your private exponent, drawn ONCE at start-up challenge_key = decimal string of G^x mod P P and G are not secret, not negotiated and not per-session: the client hard-codes the RFC 2409 768-bit MODP group - "Oakley group 1" - which is a published constant, with G = 2 and Q = (P - 1) / 2. The whole handshake lives in that one group. x IS PER-PROCESS, NOT PER-CONNECTION. The real client draws it once, when its verification service starts, and keeps it for the life of the process: 1024 random bytes read as a LITTLE-endian unsigned integer, then reduced modulo P. Every connection that process makes publishes the SAME challenge_key. Redrawing it per connection is not what the client does, and it is a difference a server can see across reconnects. x IS THE SECRET THE WHOLE EXCHANGE PROTECTS. It never travels. Anyone who learns it can answer any challenge in your name, so treat it like a password rather than like a session value. DO NOT CONFUSE IT WITH THE OTHER EXPONENT. ClientIdRequest publishes G^k for a throwaway k that changes on every poll; this one publishes G^x for the long-lived x. Both are decimal strings in the same group and they look identical on the wire. Sending the wrong one makes the proof fail with no useful error. IT IS A CORRELATED REQUEST: the client allocates an envelope uid for it. Do not read too much into that - when ServerChallengeEvent comes back the client matches it by message type and never looks at the uid. The server answers with ServerChallengeEvent, which you close with ClientChallengeProofRequest. IT STAYS ON THE MAIN CONNECTION. While a fight-server transfer has a second socket open (see IdentificationRequest) the client routes outbound traffic by message type, and all three verification requests are pinned to the FIRST connection. Gameplay traffic is what moves to the fight server, not this. THE COMPLETE ALGORITHM IS ON ONE PAGE. Constants, both exponents, both branches, what the server checks and the ways an implementation goes wrong are written out in full under ClientChallengeProofRequest. Read that before implementing any part of this exchange. When you may send it Requires authenticated observed Related messages Answers ServerSessionReadyEvent You will then receive ServerChallengeEvent observed — the server answers the init with its own challenge Fields #FieldTypeMeaningYou set it 1challenge_keystringDecimal string of G^x mod P - the client's public key for the proof exchange. x is drawn once per process, not per connection, so this value is stable across every connection the same client makes.required Recovered with score 160, confidence 0.94, margin 160 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 1.
-
ChatPrivateMessageRequest
Sends a private message to one player, addressed either by character name or by account tag. Kind requestArea Game.ChatNamed by beta, gamemapping Talks to one player rather than a channel. THE RECIPIENT IS A ONEOF - SET EXACTLY ONE BRANCH. name addresses a CHARACTER by its displayed name; tag addresses an ACCOUNT by its tag, which is a name plus a numeric discriminator and reaches the person whichever character they are playing. Setting neither sends a whisper to nobody; the message is not rejected for it. content is the text. It is the singular string that is NOT inside the oneof - worth saying, because the name branch is also a string. metadata carries the same rich attachments as a channel line; see Metadata. UNSOLICITED WHISPERS ARE THE FASTEST WAY TO GET A SCRIPT REPORTED. Whatever you do here is read by a human on the other end. When you may send it Requires character_loaded observed Raised by: the player sends a private message from the chat window observed Related messages Reply not yet recovered: the server delivers the whisper and confirms it to the sender through the private-message event, which has no signature here yet. Fields #FieldTypeMeaningYou set it 1metadataMetadataRich content attached to the whisper. See Metadata. Beta called this field object.optional 2contentstringThe text to whisper. The singular string outside the target oneof.required 3namestringThe recipient, addressed by character name.one of the two target branches 4tagtype not documented yetThe recipient, addressed by account tag - a name plus its numeric discriminator. Reaches the account rather than one character.one of the two target branches Recovered with score 225, confidence 0.85, margin 225 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 4 of 4.
-
ChatChannelMessageRequest
Says something on a chat channel. This is the message a script sends to talk. Kind requestArea Game.ChatNamed by beta, gamemapping Talk on a channel. The server echoes your own line back as ChatChannelMessageEvent, so do not render it locally - wait for the echo, as the client does. channel DECIDES WHO HEARS YOU AND IT IS EASY TO GET WRONG. It has no explicit presence, so leaving it unset does not mean "default channel" in any safe sense: it means the enum's zero value, which is Channel.GLOBAL - the loudest channel in the game. Set it deliberately every time. TO WHISPER ONE PERSON, THIS IS THE WRONG MESSAGE. Use ChatPrivateMessageRequest. metadata carries rich attachments - item and monster-group links - and stays present but empty for an ordinary line. The visible words always go in content; the link data rides alongside so the recipient's client can render and hover it. Chat is the most visible thing a script does. Rate, timing and repetition here are what a human moderator looks at first. When you may send it Requires character_loaded observed Raised by: the player types a line in the chat window and presses enter observed Related messages You will then receive ChatChannelMessageEvent observed — the server echoes the line back to the sender as well as to everyone else on the channel Fields #FieldTypeMeaningYou set it 2channelChannelWhich channel to say it on. A Channel value. NO EXPLICIT PRESENCE: unset means the zero value, Channel.GLOBAL, not 'unspecified'.required 3contentstringThe text being said. The only string the message carries.required 4metadataMetadataRich content attached to the line - item and monster-group links. Present but empty for an ordinary text message. See Metadata.optional Recovered with score 185, confidence 0.80, margin 185 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 3 of 5.
-
CharacterSelectionRequest
Asks to enter the world with one of the account's characters. Kind requestArea Game.Character.ManagementNamed by beta, gamemapping Sent after reading CharacterListEvent. The id MUST come from that list. The real client also sends it automatically for the first listed character when the player has enabled auto-selection, so a capture may show it without any visible interaction. SELECTING WITHIN A FEW MILLISECONDS OF RECEIVING THE LIST IS FASTER THAN ANY HUMAN. In a capture of a real sign-in the gap is about two seconds - the time a person takes to look at the screen and click. Add a plausible delay. On success the server starts the session and pushes a long burst of character state, ending with CharacterLoadingCompleteEvent. When you may send it Requires authenticated observed Forbidden while character_selected observed Raised by: the player picking a character from the list proven Related messages You will then receive CharacterSelectionEvent observed — the server answers with success or an error You will then receive CharacterLoadingCompleteEvent observed — closes the long inbound burst the selection opens; 1 of 1 login capture Fields #FieldTypeMeaningYou set it 1character_idint64Id of the character to play, taken from CharacterListEvent. (character id)required Recovered with score 110, confidence 0.93, margin 110 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 1.
-
CharacterReplayRequest
Enters the game with a character as a replay rather than an ordinary selection. Kind requestArea Game.Character.ManagementNamed by beta, gamemapping THE THIRD WAY INTO THE GAME. CharacterSelectionRequest enters with a character you have played, CharacterFirstSelectionRequest with one you just created, and this one with a character the client resolves to a replay instead. WHEN TO SEND IT FROM THE SAME SCREEN ACTION AS THE OTHER TWO. All three come out of one method in the real client, chosen by two flags the character-selection screen passes with the character id: no flags means the ordinary selection, one means first selection, the other means this. The replay path is raised from a closure inside the screen's own choose-a-character handler, so it is a decision the screen makes about the character you picked, not a separate menu. IF YOU ARE SCRIPTING SELECTION, the safe default is CharacterSelectionRequest. Reach for this one only when you are reproducing a client that resolved the character to the replay path; there is no server-side signal in this exchange telling you that you should have. WHAT TO PUT IN IT THE CHARACTER ID - AND ON SOME BUILDS THE REAL CLIENT SENDS NOTHING AT ALL. That is not a guess: on three of the seven dumped builds the client allocates this message, populates no member, and sends it. On the other four it writes the character id. The member is therefore recovered where the client proves it and left unnamed where it does not. The practical reading: send the character id. It is what the message is for according to the reference build, and what the more recent clients do. WHAT COMES BACK The ordinary game-entry sequence - there is no dedicated reply. Uncorrelated, so the envelope uid is -1 and there is nothing to match against. When you may send it Requires authenticated observed Raised by: a client-side state change: the character-selection screen resolving a chosen character to the replay path rather than an ordinary selection. A closure inside the same screen method that handles an ordinary choice raises an intent carrying only the character id inferred Related messages Reply not yet recovered: the game-entry burst follows, the same as for an ordinary selection. Those messages are recovered but not documented yet. Fields #FieldTypeMeaningYou set it 2character_idint64The character to replay.required Recovered with score 195, confidence 0.92, margin 195 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 1 of 3.
-
CharacterNameSuggestionRequest
Asks the server to propose a character name. Empty payload. Kind requestArea Game.CharacterNamed by beta, gamemapping Carries nothing - it is a pure "give me a name". Any field the current build declares here is unused by the client and is left unresolved; send it empty. One request yields one suggestion. Asking repeatedly to fish for a name you like is a traffic pattern a human clicking a button does not produce at machine speed. When you may send it Requires authenticated observed Raised by: the player asks the creation screen for a name suggestion inferred Related messages You will then receive CharacterNameSuggestionEvent inferred — the server answers with one proposed name Recovered with score 215, confidence 0.83, margin 215 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 0 of 0.
-
CharacterListRequest
Asks for the account's characters on this server. Kind requestArea Game.Character.ManagementNamed by beta, gamemapping Carries no payload. Send it once, straight after authentication is accepted - in a capture it goes out ~35ms after AuthenticationTicketAcceptedEvent. NOTHING PUSHES THE CHARACTER LIST. If you never send this you never learn what characters exist, and you cannot select one, because the id required by CharacterSelectionRequest is only obtainable from the answer. When you may send it Requires authenticated observed Forbidden while character_selected observed Related messages Answers AuthenticationTicketAcceptedEvent You will then receive CharacterListEvent observed — the server answers with the list ~30ms later Recovered with score 120, confidence 0.99, margin 120 over the runner-up. A margin close to the score means nothing else came near; a thin margin means a decoy nearly won. Members recovered: 0 of 0.