The apigen tool is a specialized Go code generator that automates the creation of the Dota 2 Game Coordinator (GC) client API. It processes compiled protobuf types and the EDOTAGCMsg enumeration to emit client_generated.go (API methods on the Dota2 struct) and events/generated.go (typed event structs for GC-to-client notifications).
For the broader pipeline that invokes apigen as a step (protobuf compilation, Makefile targets, GitHub Actions), see Build System and Tools For how snapshot files record the known message inventory, see Protocol Buffer Generation
apigen reads the compiled protocol package and emits two primary files:
| Output file | Contents | Role |
|---|---|---|
client_generated.go | Methods on *Dota2 | Client-initiated requests (e.g., JoinLobby, SetLobbyDetails) |
events/generated.go | Exported event structs | GC-initiated notifications (e.g., LobbyUpdateBroadcastChannelInfo) |
Every generated method and event struct is annotated with a Go doc comment naming the request/response message IDs and corresponding proto types apigen/api_generate_func.go75-129
apigen Tool — Inputs and Outputs
Sources: apigen/api_generate.go17-78 apigen/cmd_generate.go35-71 apigen/api_generate_func.go23-72 apigen/api_generate_event.go16-32
Each EDOTAGCMsg value is assigned a MsgSender value that determines whether a method, an event, or nothing is generated for it apigen/msg_sender.go12-19
MsgSender value | Meaning | Generator output |
|---|---|---|
MsgSenderClient | Client sends this message to the GC | A method on *Dota2 in client_generated.go |
MsgSenderGC | GC sends this message to the client | An event struct in events/generated.go |
MsgSenderNone | Server-to-server or internal | Skipped — nothing generated |
The classification follows a tiered logic:
GetMessageSender apigen/msg_sender.go22-79 Messages beginning with k_EMsgClientToGC are assigned MsgSenderClient apigen/msg_sender.go38-43; those beginning with k_EMsgGCToClient are assigned MsgSenderGC apigen/msg_sender.go60-61msgSenderOverrides map in apigen/msg_overrides.go takes precedence over the heuristic for any message listed there apigen/msg_sender.go27-29Message Classification Flow
Sources: apigen/api_generate.go46-78 apigen/msg_overrides.go10-123 apigen/msg_sender.go22-79
Override maps defined in apigen/msg_overrides.go allow manual correction of the generator's automated guesses.
msgSenderOverridesapigen/msg_overrides.go10-123
Overrides the heuristic sender classification. Used to suppress internal messages (e.g., k_EMsgGCLiveScoreboardUpdate set to MsgSenderNone apigen/msg_overrides.go11) or fix mislabeled ones like k_EMsgGCPracticeLobbyList set to MsgSenderClient apigen/msg_overrides.go29
msgMethodNameOverridesapigen/msg_overrides.go126-144
Sets the Go method name for a MsgSenderClient message.
k_EMsgGCAbandonCurrentGame → AbandonLobby apigen/msg_overrides.go130msgResponseOverridesapigen/msg_overrides.go148-159
Maps a request ID to its expected response ID. The heuristic in GetResponseMessageID apigen/msg_response.go14-69 matches Request suffixes to Response counterparts; this map handles irregular pairs like k_EMsgClientToGCMyTeamInfoRequest mapping to k_EMsgGCToClientTeamInfo apigen/msg_overrides.go151
msgProtoTypeOverridesapigen/msg_overrides.go162-230
Maps a message ID to a specific proto.Message Go type. This is vital when the naming convention k_EMsg... → CMsg... fails.
k_EMsgGCToClientTeamInfo maps to &protocol.CMsgDOTATeamInfo{} apigen/msg_overrides.go174msgArgAsParameterOverridesapigen/msg_overrides.go232-235
If true, the generated method accepts a single request struct pointer rather than expanding proto fields into multiple arguments. This is automatically triggered if a message has >8 fields apigen/api_generate.go105-108
msgEventNameOverridesapigen/msg_overrides.go237-242
Overrides the Go struct name for MsgSenderGC events.
For client messages, apigen determines if the call is "fire-and-forget" or requires a context-aware response.
Logic in GetResponseMessageID:
msgResponseOverrides apigen/msg_response.go15-17k_EMsg and Request suffix from the enum name apigen/msg_response.go21-24Response, RequestResponse, or Result enum value apigen/msg_response.go29-63Decision flow in buildGeneratedRequestFunc:
Sources: apigen/api_generate_func.go23-72 apigen/msg_response.go14-69
When respMsgID == 0, the generator emits a method that writes the message to the GC but does not wait for a specific response. The generated logic for these methods typically involves creating the request object and calling d.write apigen/api_generate.go212-231
When respMsgID != 0, the generator emits a method taking context.Context and returning (*RespType, error). It internally uses d.MakeRequest apigen/api_generate.go237-245
Generated Code Pattern Decision
Sources: apigen/api_generate_func.go14-20 apigen/api_generate.go212-245
Every MsgSenderGC message produces a typed event struct in events/generated.go. These structs wrap the underlying protobuf message and implement the event interface apigen/api_generate_event.go16-32
| Method | Implementation |
|---|---|
GetDotaEventMsgID() | Returns the EDOTAGCMsg constant events/generated.go15-17 |
GetEventBody() | Returns a pointer to the embedded proto events/generated.go20-22 |
GetEventName() | Returns the struct name as a string events/generated.go25-27 |
Sources: apigen/api_generate_event.go16-32 apigen/api_generate.go64-78 events/generated.go8-28
apigen attempts to generate human-readable documentation by analyzing method names against a verb dictionary in apigen/msg_verb.go.
Verb dictionary
IsWordVerb(word string) bool apigen/msg_verb.go70-73 checks a word against ~60 common GC actions like Abandon, Claim, Join, Kick, Set, and Submit apigen/msg_verb.go10-63
Comment construction logic apigen/api_generate_func.go75-129:
"[Verb]s a [Noun]." apigen/api_generate_func.go100-105"[Verb]s for/from a [Noun]." apigen/api_generate_func.go107-113"is undocumented." apigen/api_generate_func.go76Sources: apigen/msg_verb.go1-73 apigen/api_generate_func.go75-129
Refresh this wiki