From de7a99fb67d2c2259fa30ba461df5dd1c8a977e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 24 Jan 2024 00:01:59 +0300 Subject: [PATCH 01/50] =?UTF-8?q?=F0=9F=AA=A7Compile=20protobufs=20into=20?= =?UTF-8?q?`.py`=20mirrors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Done with `protoc -I . --python_betterproto_out=protos dota_gcmessages_client_watch.proto` using 1.2.5 betterproto and manual edits --- steam/ext/dota2/protobufs/__init__.py | 11 + .../protobufs/dota_gcmessages_client_watch.py | 246 +++ .../dota2/protobufs/dota_gcmessages_common.py | 1838 +++++++++++++++++ .../dota2/protobufs/dota_gcmessages_msgid.py | 896 ++++++++ .../ext/dota2/protobufs/dota_shared_enums.py | 838 ++++++++ steam/ext/dota2/protobufs/gcsdk_gcmessages.py | 581 ++++++ steam/ext/dota2/protobufs/gcsystemmsgs.py | 32 + steam/ext/dota2/protobufs/steammessages.py | 102 + .../steammessages_steamlearn/steamworkssdk.py | 530 +++++ .../steamworkssdk.py | 10 + 10 files changed, 5084 insertions(+) create mode 100644 steam/ext/dota2/protobufs/__init__.py create mode 100644 steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py create mode 100644 steam/ext/dota2/protobufs/dota_gcmessages_common.py create mode 100644 steam/ext/dota2/protobufs/dota_gcmessages_msgid.py create mode 100644 steam/ext/dota2/protobufs/dota_shared_enums.py create mode 100644 steam/ext/dota2/protobufs/gcsdk_gcmessages.py create mode 100644 steam/ext/dota2/protobufs/gcsystemmsgs.py create mode 100644 steam/ext/dota2/protobufs/steammessages.py create mode 100644 steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py create mode 100644 steam/ext/dota2/protobufs/steammessages_unified_base/steamworkssdk.py diff --git a/steam/ext/dota2/protobufs/__init__.py b/steam/ext/dota2/protobufs/__init__.py new file mode 100644 index 00000000..a180edb6 --- /dev/null +++ b/steam/ext/dota2/protobufs/__init__.py @@ -0,0 +1,11 @@ +from typing import Final + +import betterproto + +APP_ID: Final = 570 + +from ....protobufs.msg import GCProtobufMessage +from . import dota_gcmessages_client_watch as dota_gcmessages_client_watch +from . import gcsdk_gcmessages as gcsdk_gcmessages + +[setattr(cls, "_betterproto", betterproto.ProtoClassMetadata(cls)) for cls in GCProtobufMessage.__subclasses__()] diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py b/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py new file mode 100644 index 00000000..1116e292 --- /dev/null +++ b/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py @@ -0,0 +1,246 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_gcmessages_client_watch.proto +# plugin: python-betterproto + +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING + +import betterproto + +from ....protobufs.msg import GCProtobufMessage +from .dota_gcmessages_msgid import EDOTAGCMsg + +if TYPE_CHECKING: + from dota_gcmessages_common import CMsgDOTAMatchMinimal + + +class CMsgSpectateFriendGameResponseEWatchLiveResult(betterproto.Enum): + SUCCESS = 0 + ERROR_GENERIC = 1 + ERROR_NO_PLUS = 2 + ERROR_NOT_FRIENDS = 3 + ERROR_LOBBY_NOT_FOUND = 4 + ERROR_SPECTATOR_IN_A_LOBBY = 5 + ERROR_LOBBY_IS_LAN = 6 + ERROR_WRONG_LOBBY_TYPE = 7 + ERROR_WRONG_LOBBY_STATE = 8 + ERROR_PLAYER_NOT_PLAYER = 9 + ERROR_TOO_MANY_SPECTATORS = 10 + ERROR_SPECTATOR_SWITCHED_TEAMS = 11 + ERROR_FRIENDS_ON_BOTH_SIDES = 12 + ERROR_SPECTATOR_IN_THIS_LOBBY = 13 + ERROR_LOBBY_IS_LEAGUE = 14 + + +class CMsgWatchGameResponseWatchGameResult(betterproto.Enum): + PENDING = 0 + READY = 1 + GAMESERVERNOTFOUND = 2 + UNAVAILABLE = 3 + CANCELLED = 4 + INCOMPATIBLEVERSION = 5 + MISSINGLEAGUESUBSCRIPTION = 6 + LOBBYNOTFOUND = 7 + + +@dataclass +class CSourceTVGameSmall(betterproto.Message): + activate_time: int = betterproto.uint32_field(1) + deactivate_time: int = betterproto.uint32_field(2) + server_steam_id: int = betterproto.uint64_field(3) + lobby_id: int = betterproto.uint64_field(4) + league_id: int = betterproto.uint32_field(5) + lobby_type: int = betterproto.uint32_field(6) + game_time: int = betterproto.int32_field(7) + delay: int = betterproto.uint32_field(8) + spectators: int = betterproto.uint32_field(9) + game_mode: int = betterproto.uint32_field(10) + average_mmr: int = betterproto.uint32_field(11) + match_id: int = betterproto.uint64_field(12) + series_id: int = betterproto.uint32_field(13) + team_name_radiant: str = betterproto.string_field(15) + team_name_dire: str = betterproto.string_field(16) + team_logo_radiant: float = betterproto.fixed64_field(24) + team_logo_dire: float = betterproto.fixed64_field(25) + team_id_radiant: int = betterproto.uint32_field(30) + team_id_dire: int = betterproto.uint32_field(31) + sort_score: int = betterproto.uint32_field(17) + last_update_time: float = betterproto.float_field(18) + radiant_lead: int = betterproto.int32_field(19) + radiant_score: int = betterproto.uint32_field(20) + dire_score: int = betterproto.uint32_field(21) + players: list[CSourceTVGameSmallPlayer] = betterproto.message_field(22) + building_state: float = betterproto.fixed32_field(23) + weekend_tourney_tournament_id: int = betterproto.uint32_field(26) + weekend_tourney_division: int = betterproto.uint32_field(27) + weekend_tourney_skill_level: int = betterproto.uint32_field(28) + weekend_tourney_bracket_round: int = betterproto.uint32_field(29) + custom_game_difficulty: int = betterproto.uint32_field(32) + + +@dataclass +class CSourceTVGameSmallPlayer(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + hero_id: int = betterproto.uint32_field(2) + team_slot: int = betterproto.uint32_field(3) + team: int = betterproto.uint32_field(4) + + +class CMsgClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EDOTAGCMsg.k_EMsgClientToGCFindTopSourceTVGames): + search_key: str = betterproto.string_field(1) + league_id: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + start_game: int = betterproto.uint32_field(4) + game_list_index: int = betterproto.uint32_field(5) + lobby_ids: list[int] = betterproto.uint64_field(6) + + +class CMsgGCToClientFindTopSourceTVGamesResponse( + GCProtobufMessage, msg=EDOTAGCMsg.k_EMsgGCToClientFindTopSourceTVGamesResponse +): + search_key: str = betterproto.string_field(1) + league_id: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + start_game: int = betterproto.uint32_field(4) + num_games: int = betterproto.uint32_field(5) + game_list_index: int = betterproto.uint32_field(6) + game_list: list[CSourceTVGameSmall] = betterproto.message_field(7) + specific_games: bool = betterproto.bool_field(8) + bot_game: CSourceTVGameSmall = betterproto.message_field(9) + + +@dataclass +class CMsgGCToClientTopWeekendTourneyGames(betterproto.Message): + live_games: list[CSourceTVGameSmall] = betterproto.message_field(1) + + +@dataclass +class CMsgClientToGCTopLeagueMatchesRequest(betterproto.Message): + pass + + +@dataclass +class CMsgClientToGCTopFriendMatchesRequest(betterproto.Message): + pass + + +@dataclass +class CMsgClientToGCMatchesMinimalRequest(betterproto.Message): + match_ids: list[int] = betterproto.uint64_field(1) + + +@dataclass +class CMsgClientToGCMatchesMinimalResponse(betterproto.Message): + matches: list[CMsgDOTAMatchMinimal] = betterproto.message_field(1) + last_match: bool = betterproto.bool_field(2) + + +@dataclass +class CMsgGCToClientTopLeagueMatchesResponse(betterproto.Message): + matches: list[CMsgDOTAMatchMinimal] = betterproto.message_field(2) + + +@dataclass +class CMsgGCToClientTopFriendMatchesResponse(betterproto.Message): + matches: list[CMsgDOTAMatchMinimal] = betterproto.message_field(1) + + +@dataclass +class CMsgSpectateFriendGame(betterproto.Message): + steam_id: float = betterproto.fixed64_field(1) + live: bool = betterproto.bool_field(2) + + +@dataclass +class CMsgSpectateFriendGameResponse(betterproto.Message): + server_steamid: float = betterproto.fixed64_field(4) + watch_live_result: CMsgSpectateFriendGameResponseEWatchLiveResult = betterproto.enum_field(5) + + +@dataclass +class CDOTAReplayDownloadInfo(betterproto.Message): + match: CMsgDOTAMatchMinimal = betterproto.message_field(1) + title: str = betterproto.string_field(2) + description: str = betterproto.string_field(3) + size: int = betterproto.uint32_field(4) + tags: list[str] = betterproto.string_field(5) + exists_on_disk: bool = betterproto.bool_field(6) + + +@dataclass +class CDOTAReplayDownloadInfoHighlight(betterproto.Message): + timestamp: int = betterproto.uint32_field(1) + description: str = betterproto.string_field(2) + + +@dataclass +class CMsgWatchGame(betterproto.Message): + server_steamid: float = betterproto.fixed64_field(1) + client_version: int = betterproto.uint32_field(2) + watch_server_steamid: float = betterproto.fixed64_field(3) + lobby_id: int = betterproto.uint64_field(4) + regions: list[int] = betterproto.uint32_field(5) + + +@dataclass +class CMsgCancelWatchGame(betterproto.Message): + pass + + +@dataclass +class CMsgWatchGameResponse(betterproto.Message): + watch_game_result: CMsgWatchGameResponseWatchGameResult = betterproto.enum_field(1) + source_tv_public_addr: int = betterproto.uint32_field(2) + source_tv_private_addr: int = betterproto.uint32_field(3) + source_tv_port: int = betterproto.uint32_field(4) + game_server_steamid: float = betterproto.fixed64_field(5) + watch_server_steamid: float = betterproto.fixed64_field(6) + watch_tv_unique_secret_code: float = betterproto.fixed64_field(7) + + +@dataclass +class CMsgPartyLeaderWatchGamePrompt(betterproto.Message): + game_server_steamid: float = betterproto.fixed64_field(5) + + +@dataclass +class CDOTABroadcasterInfo(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + server_steam_id: float = betterproto.fixed64_field(2) + live: bool = betterproto.bool_field(3) + team_name_radiant: str = betterproto.string_field(4) + team_name_dire: str = betterproto.string_field(5) + series_game: int = betterproto.uint32_field(7) + upcoming_broadcast_timestamp: int = betterproto.uint32_field(9) + allow_live_video: bool = betterproto.bool_field(10) + node_type: int = betterproto.uint32_field(11) + node_name: str = betterproto.string_field(12) + + +@dataclass +class CMsgDOTASeries(betterproto.Message): + series_id: int = betterproto.uint32_field(1) + series_type: int = betterproto.uint32_field(2) + team_1: CMsgDOTASeriesTeamInfo = betterproto.message_field(3) + team_2: CMsgDOTASeriesTeamInfo = betterproto.message_field(4) + match_minimal: list[CMsgDOTAMatchMinimal] = betterproto.message_field(5) + live_game: CMsgDOTASeriesLiveGame = betterproto.message_field(6) + + +@dataclass +class CMsgDOTASeriesTeamInfo(betterproto.Message): + team_id: int = betterproto.uint32_field(1) + team_name: str = betterproto.string_field(2) + team_logo_url: str = betterproto.string_field(3) + wager_count: int = betterproto.uint32_field(4) + + +@dataclass +class CMsgDOTASeriesLiveGame(betterproto.Message): + server_steam_id: float = betterproto.fixed64_field(1) + team_radiant: CMsgDOTASeriesTeamInfo = betterproto.message_field(2) + team_dire: CMsgDOTASeriesTeamInfo = betterproto.message_field(3) + team_radiant_score: int = betterproto.uint32_field(4) + team_dire_score: int = betterproto.uint32_field(5) diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_common.py b/steam/ext/dota2/protobufs/dota_gcmessages_common.py new file mode 100644 index 00000000..83667800 --- /dev/null +++ b/steam/ext/dota2/protobufs/dota_gcmessages_common.py @@ -0,0 +1,1838 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_gcmessages_common.proto +# plugin: python-betterproto +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING + +import betterproto + +if TYPE_CHECKING: + from .dota_shared_enums import ( + DOTA_GC_TEAM, + CMsgPendingEventAward, + DOTA_GameMode, + EEvent, + ELeaguePhase, + ELeagueRegion, + EMatchOutcome, + ) + + +class ESpecialPingValue(betterproto.Enum): + k_ESpecialPingValue_NoData = 16382 + k_ESpecialPingValue_Failed = 16383 + + +class EDOTAGCSessionNeed(betterproto.Enum): + k_EDOTAGCSessionNeed_Unknown = 0 + k_EDOTAGCSessionNeed_UserNoSessionNeeded = 100 + k_EDOTAGCSessionNeed_UserInOnlineGame = 101 + k_EDOTAGCSessionNeed_UserInLocalGame = 102 + k_EDOTAGCSessionNeed_UserInUIWasConnected = 103 + k_EDOTAGCSessionNeed_UserInUINeverConnected = 104 + k_EDOTAGCSessionNeed_UserTutorials = 105 + k_EDOTAGCSessionNeed_UserInUIWasConnectedIdle = 106 + k_EDOTAGCSessionNeed_UserInUINeverConnectedIdle = 107 + k_EDOTAGCSessionNeed_GameServerOnline = 200 + k_EDOTAGCSessionNeed_GameServerLocal = 201 + k_EDOTAGCSessionNeed_GameServerIdle = 202 + k_EDOTAGCSessionNeed_GameServerRelay = 203 + k_EDOTAGCSessionNeed_GameServerLocalUpload = 204 + + +class EDOTAMatchPlayerTimeCustomStat(betterproto.Enum): + k_EDOTA_MatchPlayerTimeCustomStat_HPRegenUnderT1Towers = 1 + k_EDOTA_MatchPlayerTimeCustomStat_MagicDamageReducedWithNewFormula_Absolute = 2 + k_EDOTA_MatchPlayerTimeCustomStat_MagicDamageReducedWithNewFormula_PercentOfTotalHP = 3 + + +class DOTA_TournamentEvents(betterproto.Enum): + TE_FIRST_BLOOD = 0 + TE_GAME_END = 1 + TE_MULTI_KILL = 2 + TE_HERO_DENY = 3 + TE_AEGIS_DENY = 4 + TE_AEGIS_STOLEN = 5 + TE_GODLIKE = 6 + TE_COURIER_KILL = 7 + TE_ECHOSLAM = 8 + TE_RAPIER = 9 + TE_EARLY_ROSHAN = 10 + TE_BLACK_HOLE = 11 + + +class EBroadcastTimelineEvent(betterproto.Enum): + EBroadcastTimelineEvent_MatchStarted = 1 + EBroadcastTimelineEvent_GameStateChanged = 2 + EBroadcastTimelineEvent_TowerDeath = 3 + EBroadcastTimelineEvent_BarracksDeath = 4 + EBroadcastTimelineEvent_AncientDeath = 5 + EBroadcastTimelineEvent_RoshanDeath = 6 + EBroadcastTimelineEvent_HeroDeath = 7 + EBroadcastTimelineEvent_TeamFight = 8 + EBroadcastTimelineEvent_FirstBlood = 9 + + +class ECustomGameWhitelistState(betterproto.Enum): + CUSTOM_GAME_WHITELIST_STATE_UNKNOWN = 0 + CUSTOM_GAME_WHITELIST_STATE_APPROVED = 1 + CUSTOM_GAME_WHITELIST_STATE_REJECTED = 2 + + +class EDOTATriviaQuestionCategory(betterproto.Enum): + k_EDOTATriviaQuestionCategory_AbilityIcon = 0 + k_EDOTATriviaQuestionCategory_AbilityCooldown = 1 + k_EDOTATriviaQuestionCategory_HeroAttributes = 2 + k_EDOTATriviaQuestionCategory_HeroMovementSpeed = 3 + k_EDOTATriviaQuestionCategory_TalentTree = 4 + k_EDOTATriviaQuestionCategory_HeroStats = 5 + k_EDOTATriviaQuestionCategory_ItemPrice = 6 + k_EDOTATriviaQuestionCategory_AbilitySound = 7 + k_EDOTATriviaQuestionCategory_InvokerSpells = 8 + k_EDOTATriviaQuestionCategory_AbilityManaCost = 9 + k_EDOTATriviaQuestionCategory_HeroAttackSound = 10 + k_EDOTATriviaQuestionCategory_AbilityName = 11 + k_EDOTATriviaQuestionCategory_ItemComponents = 12 + k_EDOTATriviaQuestionCategory_ItemLore = 13 + k_EDOTATriviaQuestionCategory_ItemPassives = 14 + k_EDOTATriviaQuestionCategory_STATIC_QUESTIONS_END = 15 + k_EDOTATriviaQuestionCategory_DYNAMIC_QUESTIONS_START = 99 + k_EDOTATriviaQuestionCategory_Dynamic_ItemBuild = 100 + + +class EOverwatchConviction(betterproto.Enum): + k_EOverwatchConviction_None = 0 + k_EOverwatchConviction_NotGuilty = 1 + k_EOverwatchConviction_GuiltUnclear = 2 + k_EOverwatchConviction_Guilty = 3 + + +class EHeroRelicRarity(betterproto.Enum): + HERO_RELIC_RARITY_INVALID = -1 + HERO_RELIC_RARITY_COMMON = 0 + HERO_RELIC_RARITY_RARE = 1 + + +class EStickerbookAuditAction(betterproto.Enum): + STICKERBOOK_AUDIT_CREATE_PAGE = 0 + STICKERBOOK_AUDIT_DELETE_PAGE = 1 + STICKERBOOK_AUDIT_STICK_STICKERS = 2 + STICKERBOOK_AUDIT_REPLACE_STICKERS = 3 + STICKERBOOK_AUDIT_HERO_STICKER = 4 + + +class EStickerbookPageType(betterproto.Enum): + STICKER_PAGE_GENERIC = 0 + STICKER_PAGE_TEAM = 1 + STICKER_PAGE_TALENT = 2 + + +class CMsgDOTAProfileCardEStatID(betterproto.Enum): + k_eStat_Wins = 3 + k_eStat_Commends = 4 + k_eStat_GamesPlayed = 5 + k_eStat_FirstMatchDate = 6 + k_eStat_PreviousSeasonRank = 7 + k_eStat_GamesMVP = 8 + + +class CMsgGCRerollPlayerChallengeResponseEResult(betterproto.Enum): + eResult_Success = 0 + eResult_Dropped = 1 + eResult_NotFound = 2 + eResult_CantReroll = 3 + eResult_ServerError = 4 + + +class CMsgDOTARealtimeGameStatsGraphDataeStat(betterproto.Enum): + CreepGoldEarned = 0 + KillGoldEarned = 1 + DeathAndBuybackGoldLost = 2 + XPEarned = 3 + + +class CMsgDOTARealtimeGameStatsGraphDataeLocation(betterproto.Enum): + BotLane = 0 + MidLane = 1 + TopLane = 2 + Jungle = 3 + Ancients = 4 + Other = 5 + + +class CMsgInGamePredictionERawValueTypeT(betterproto.Enum): + Number = 0 + Time = 1 + + +class CMsgInGamePredictionEPredictionType(betterproto.Enum): + Generic = 0 + Hero = 1 + Team = 2 + Player = 3 + Special = 4 + YesNo = 5 + QualifiersTeam = 6 + + +class CMsgInGamePredictionEResolutionTypeT(betterproto.Enum): + InvalidQuery = 0 + FirstToPassQuery = 1 + LastToPassQuery = 2 + LastRemainingQuery = 3 + MaxToPassQuery = 4 + MinToPassQuery = 5 + SumQuery = 6 + MaxTeamSumToPassQuery = 7 + MinTeamSumToPassQuery = 8 + + +class CMsgInGamePredictionERandomSelectionGroupT(betterproto.Enum): + EarlyGame = 0 + MidGame = 1 + LateGame = 2 + Count = 3 + + +class CMsgDOTASeasonPredictionsPredictionEPredictionType(betterproto.Enum): + Generic = 0 + Hero = 1 + Team = 2 + Player = 3 + Special = 4 + YesNo = 5 + QualifiersTeam = 6 + LastChanceTeam = 7 + + +class CMsgDOTASeasonPredictionsPredictionEAnswerType(betterproto.Enum): + SingleInt = 0 + SingleFloat = 1 + MultipleInt = 2 + MultipleFloat = 3 + AnswerTeam = 4 + SingleTime = 5 + MultipleTime = 6 + NoAnswer = 7 + + +class CMsgDOTAMatchReplayState(betterproto.Enum): + REPLAY_AVAILABLE = 0 + REPLAY_NOT_RECORDED = 1 + REPLAY_EXPIRED = 2 + + +class CMsgDOTAMatchPlayerHeroDamageType(betterproto.Enum): + HERO_DAMAGE_PHYSICAL = 0 + HERO_DAMAGE_MAGICAL = 1 + HERO_DAMAGE_PURE = 2 + + +class CMsgServerToGCRequestPlayerRecentAccomplishmentsResponseEResponse(betterproto.Enum): + k_eInternalError = 0 + k_eSuccess = 1 + k_eTooBusy = 2 + k_eDisabled = 3 + + +@dataclass +class CSODOTAGameAccountClient(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + wins: int = betterproto.uint32_field(3) + losses: int = betterproto.uint32_field(4) + xp: int = betterproto.uint32_field(12) + level: int = betterproto.uint32_field(13) + initial_skill: int = betterproto.uint32_field(14) + leaver_count: int = betterproto.uint32_field(15) + secondary_leaver_count: int = betterproto.uint32_field(58) + low_priority_until_date: int = betterproto.uint32_field(18) + prevent_text_chat_until_date: int = betterproto.uint32_field(20) + prevent_voice_until_date: int = betterproto.uint32_field(21) + prevent_public_text_chat_until_date: int = betterproto.uint32_field(86) + prevent_new_player_chat_until_date: int = betterproto.uint32_field(122) + last_abandoned_game_date: int = betterproto.uint32_field(22) + last_secondary_abandoned_game_date: int = betterproto.uint32_field(59) + leaver_penalty_count: int = betterproto.uint32_field(23) + completed_game_streak: int = betterproto.uint32_field(24) + account_disabled_until_date: int = betterproto.uint32_field(38) + account_disabled_count: int = betterproto.uint32_field(39) + match_disabled_until_date: int = betterproto.uint32_field(41) + match_disabled_count: int = betterproto.uint32_field(42) + shutdownlawterminatetimestamp: int = betterproto.uint32_field(47) + low_priority_games_remaining: int = betterproto.uint32_field(48) + recruitment_level: int = betterproto.uint32_field(55) + has_new_notifications: bool = betterproto.bool_field(56) + is_league_admin: bool = betterproto.bool_field(57) + casual_games_played: int = betterproto.uint32_field(60) + solo_competitive_games_played: int = betterproto.uint32_field(61) + party_competitive_games_played: int = betterproto.uint32_field(62) + casual_1v1_games_played: int = betterproto.uint32_field(65) + curr_all_hero_challenge_id: int = betterproto.uint32_field(67) + play_time_points: int = betterproto.uint32_field(68) + account_flags: int = betterproto.uint32_field(69) + play_time_level: int = betterproto.uint32_field(70) + player_behavior_seq_num_last_report: int = betterproto.uint32_field(71) + player_behavior_score_last_report: int = betterproto.uint32_field(72) + player_behavior_report_old_data: bool = betterproto.bool_field(73) + tourney_skill_level: int = betterproto.uint32_field(74) + tourney_recent_participation_date: int = betterproto.uint32_field(85) + anchored_phone_number_id: int = betterproto.uint64_field(88) + ranked_matchmaking_ban_until_date: int = betterproto.uint32_field(89) + recent_game_time_1: int = betterproto.uint32_field(90) + recent_game_time_2: int = betterproto.uint32_field(91) + recent_game_time_3: int = betterproto.uint32_field(92) + favorite_team_packed: int = betterproto.uint64_field(103) + recent_report_time: int = betterproto.uint32_field(104) + custom_game_disabled_until_date: int = betterproto.uint32_field(105) + recent_win_time_1: int = betterproto.uint32_field(106) + recent_win_time_2: int = betterproto.uint32_field(107) + recent_win_time_3: int = betterproto.uint32_field(108) + coach_rating: int = betterproto.uint32_field(109) + queue_points: int = betterproto.uint32_field(114) + role_handicaps: list[CSODOTAGameAccountClientRoleHandicap] = betterproto.message_field(115) + event_mode_recent_time: int = betterproto.uint32_field(120) + mmr_recalibration_time: int = betterproto.uint32_field(121) + + +@dataclass +class CSODOTAGameAccountClientRoleHandicap(betterproto.Message): + role: int = betterproto.uint32_field(1) + handicap: float = betterproto.float_field(2) + + +@dataclass +class CSODOTAGameAccountPlus(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + original_start_date: int = betterproto.uint32_field(2) + plus_flags: int = betterproto.uint32_field(3) + plus_status: int = betterproto.uint32_field(4) + prepaid_time_start: int = betterproto.uint32_field(5) + prepaid_time_balance: int = betterproto.uint32_field(6) + next_payment_date: float = betterproto.fixed32_field(7) + steam_agreement_id: float = betterproto.fixed64_field(8) + + +@dataclass +class CSODOTAChatWheel(betterproto.Message): + message_id: int = betterproto.uint32_field(1) + + +@dataclass +class CMsgLobbyFeaturedGamemodeProgress(betterproto.Message): + accounts: list[CMsgLobbyFeaturedGamemodeProgressAccountProgress] = betterproto.message_field(1) + + +@dataclass +class CMsgLobbyFeaturedGamemodeProgressAccountProgress(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + current_value: int = betterproto.uint32_field(2) + max_value: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgBattleCupVictory(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + win_date: int = betterproto.uint32_field(2) + valid_until: int = betterproto.uint32_field(3) + skill_level: int = betterproto.uint32_field(4) + tournament_id: int = betterproto.uint32_field(5) + division_id: int = betterproto.uint32_field(6) + team_id: int = betterproto.uint32_field(7) + streak: int = betterproto.uint32_field(8) + trophy_id: int = betterproto.uint32_field(9) + + +@dataclass +class CMsgLobbyBattleCupVictoryList(betterproto.Message): + winners: list[CMsgBattleCupVictory] = betterproto.message_field(1) + + +@dataclass +class CMsgDOTABroadcastNotification(betterproto.Message): + message: str = betterproto.string_field(1) + + +@dataclass +class CProtoItemHeroStatue(betterproto.Message): + hero_id: int = betterproto.uint32_field(1) + status_effect_index: int = betterproto.uint32_field(2) + sequence_name: str = betterproto.string_field(3) + cycle: float = betterproto.float_field(4) + wearable: list[int] = betterproto.uint32_field(5) + inscription: str = betterproto.string_field(6) + style: list[int] = betterproto.uint32_field(7) + tournament_drop: bool = betterproto.bool_field(8) + + +@dataclass +class CMatchPlayerAbilityUpgrade(betterproto.Message): + ability: int = betterproto.int32_field(1) + time: int = betterproto.uint32_field(2) + + +@dataclass +class CMatchPlayerTimedCustomStat(betterproto.Message): + stat: EDOTAMatchPlayerTimeCustomStat = betterproto.enum_field(2) + value: float = betterproto.float_field(3) + + +@dataclass +class CMatchPlayerTimedStats(betterproto.Message): + time: int = betterproto.uint32_field(1) + kills: int = betterproto.uint32_field(2) + deaths: int = betterproto.uint32_field(3) + assists: int = betterproto.uint32_field(4) + net_worth: int = betterproto.uint32_field(5) + xp: int = betterproto.uint32_field(6) + last_hits: int = betterproto.uint32_field(7) + denies: int = betterproto.uint32_field(8) + bounty_rune_gold: int = betterproto.uint32_field(9) + range_creep_upgrade_gold: int = betterproto.uint32_field(10) + observer_wards_dewarded: int = betterproto.uint32_field(11) + reliable_gold_earned: int = betterproto.uint32_field(12) + gold_loss_prevented: int = betterproto.uint32_field(13) + hero_kill_gold: int = betterproto.uint32_field(14) + creep_kill_gold: int = betterproto.uint32_field(15) + building_gold: int = betterproto.uint32_field(16) + other_gold: int = betterproto.uint32_field(17) + comeback_gold: int = betterproto.uint32_field(18) + experimental_gold: int = betterproto.uint32_field(19) + experimental2_gold: int = betterproto.uint32_field(20) + creep_deny_gold: int = betterproto.uint32_field(21) + tp_scrolls_purchased_1: int = betterproto.uint32_field(22) + tp_scrolls_purchased_2: int = betterproto.uint32_field(23) + tp_scrolls_purchased_3: int = betterproto.uint32_field(24) + tp_scrolls_purchased_4: int = betterproto.uint32_field(25) + tp_scrolls_purchased_5: int = betterproto.uint32_field(26) + neutral_gold: int = betterproto.uint32_field(27) + courier_gold: int = betterproto.uint32_field(28) + roshan_gold: int = betterproto.uint32_field(29) + income_gold: int = betterproto.uint32_field(30) + item_value: int = betterproto.uint32_field(36) + support_gold_spent: int = betterproto.uint32_field(37) + camps_stacked: int = betterproto.uint32_field(38) + wards_placed: int = betterproto.uint32_field(39) + triple_kills: int = betterproto.uint32_field(40) + rampages: int = betterproto.uint32_field(41) + custom_stats: list[CMatchPlayerTimedCustomStat] = betterproto.message_field(42) + + +@dataclass +class CMatchTeamTimedStats(betterproto.Message): + time: int = betterproto.uint32_field(1) + enemy_towers_killed: int = betterproto.uint32_field(2) + enemy_barracks_killed: int = betterproto.uint32_field(3) + enemy_towers_status: int = betterproto.uint32_field(4) + enemy_barracks_status: int = betterproto.uint32_field(5) + + +@dataclass +class CMatchAdditionalUnitInventory(betterproto.Message): + unit_name: str = betterproto.string_field(1) + items: list[int] = betterproto.int32_field(2) + + +@dataclass +class CMatchPlayerPermanentBuff(betterproto.Message): + permanent_buff: int = betterproto.uint32_field(1) + stack_count: int = betterproto.uint32_field(2) + grant_time: int = betterproto.uint32_field(3) + + +@dataclass +class CMatchHeroSelectEvent(betterproto.Message): + is_pick: bool = betterproto.bool_field(1) + team: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + + +@dataclass +class CMatchClip(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + player_account_id: int = betterproto.uint32_field(2) + game_time_seconds: int = betterproto.uint32_field(3) + duration_seconds: int = betterproto.uint32_field(4) + player_id: int = betterproto.uint32_field(5) + hero_id: int = betterproto.uint32_field(6) + ability_id: int = betterproto.int32_field(7) + camera_mode: int = betterproto.uint32_field(8) + comment: str = betterproto.string_field(9) + + +@dataclass +class CPartySearchClientParty(betterproto.Message): + party_id: float = betterproto.fixed64_field(1) + beacon_type: int = betterproto.int32_field(2) + party_members: list[float] = betterproto.fixed32_field(3) + + +@dataclass +class CMsgDOTAHasItemQuery(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + item_id: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgDOTAHasItemResponse(betterproto.Message): + has_item: bool = betterproto.bool_field(1) + + +@dataclass +class CMsgGCGetPlayerCardItemInfo(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + player_card_item_ids: list[int] = betterproto.uint64_field(2) + all_for_event: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgGCGetPlayerCardItemInfoResponse(betterproto.Message): + player_card_infos: list[CMsgGCGetPlayerCardItemInfoResponsePlayerCardInfo] = betterproto.message_field(1) + + +@dataclass +class CMsgGCGetPlayerCardItemInfoResponsePlayerCardInfo(betterproto.Message): + player_card_item_id: int = betterproto.uint64_field(1) + account_id: int = betterproto.uint32_field(2) + packed_bonuses: int = betterproto.uint64_field(3) + + +@dataclass +class CSODOTAMapLocationState(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + location_id: int = betterproto.int32_field(2) + completed: bool = betterproto.bool_field(3) + + +@dataclass +class CMsgLeagueAdminList(betterproto.Message): + account_ids: list[int] = betterproto.uint32_field(1) + + +@dataclass +class CMsgDOTAProfileCard(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + slots: list[CMsgDOTAProfileCardSlot] = betterproto.message_field(3) + badge_points: int = betterproto.uint32_field(4) + event_points: int = betterproto.uint32_field(5) + event_id: int = betterproto.uint32_field(6) + recent_battle_cup_victory: CMsgBattleCupVictory = betterproto.message_field(7) + rank_tier: int = betterproto.uint32_field(8) + leaderboard_rank: int = betterproto.uint32_field(9) + is_plus_subscriber: bool = betterproto.bool_field(10) + plus_original_start_date: int = betterproto.uint32_field(11) + rank_tier_score: int = betterproto.uint32_field(12) + leaderboard_rank_core: int = betterproto.uint32_field(17) + title: int = betterproto.uint32_field(23) + favorite_team_packed: int = betterproto.uint64_field(24) + lifetime_games: int = betterproto.uint32_field(25) + + +@dataclass +class CMsgDOTAProfileCardSlot(betterproto.Message): + slot_id: int = betterproto.uint32_field(1) + trophy: CMsgDOTAProfileCardSlotTrophy = betterproto.message_field(2) + stat: CMsgDOTAProfileCardSlotStat = betterproto.message_field(3) + item: CMsgDOTAProfileCardSlotItem = betterproto.message_field(4) + hero: CMsgDOTAProfileCardSlotHero = betterproto.message_field(5) + emoticon: CMsgDOTAProfileCardSlotEmoticon = betterproto.message_field(6) + team: CMsgDOTAProfileCardSlotTeam = betterproto.message_field(7) + + +@dataclass +class CMsgDOTAProfileCardSlotTrophy(betterproto.Message): + trophy_id: int = betterproto.uint32_field(1) + trophy_score: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgDOTAProfileCardSlotStat(betterproto.Message): + stat_id: CMsgDOTAProfileCardEStatID = betterproto.enum_field(1) + stat_score: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgDOTAProfileCardSlotItem(betterproto.Message): + serialized_item: bytes = betterproto.bytes_field(1) + item_id: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgDOTAProfileCardSlotHero(betterproto.Message): + hero_id: int = betterproto.uint32_field(1) + hero_wins: int = betterproto.uint32_field(2) + hero_losses: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgDOTAProfileCardSlotEmoticon(betterproto.Message): + emoticon_id: int = betterproto.uint32_field(1) + + +@dataclass +class CMsgDOTAProfileCardSlotTeam(betterproto.Message): + team_id: int = betterproto.uint32_field(1) + + +@dataclass +class CSODOTAPlayerChallenge(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + event_id: int = betterproto.uint32_field(2) + slot_id: int = betterproto.uint32_field(3) + int_param_0: int = betterproto.uint32_field(5) + int_param_1: int = betterproto.uint32_field(6) + created_time: int = betterproto.uint32_field(7) + completed: int = betterproto.uint32_field(8) + sequence_id: int = betterproto.uint32_field(9) + challenge_tier: int = betterproto.uint32_field(10) + flags: int = betterproto.uint32_field(11) + attempts: int = betterproto.uint32_field(12) + complete_limit: int = betterproto.uint32_field(13) + quest_rank: int = betterproto.uint32_field(14) + max_quest_rank: int = betterproto.uint32_field(15) + instance_id: int = betterproto.uint32_field(16) + hero_id: int = betterproto.uint32_field(17) + template_id: int = betterproto.uint32_field(18) + + +@dataclass +class CMsgClientToGCRerollPlayerChallenge(betterproto.Message): + event_id: EEvent = betterproto.enum_field(1) + sequence_id: int = betterproto.uint32_field(3) + hero_id: int = betterproto.uint32_field(4) + + +@dataclass +class CMsgGCRerollPlayerChallengeResponse(betterproto.Message): + result: CMsgGCRerollPlayerChallengeResponseEResult = betterproto.enum_field(1) + + +@dataclass +class CMsgGCTopCustomGamesList(betterproto.Message): + top_custom_games: list[int] = betterproto.uint64_field(1) + game_of_the_day: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgDOTARealtimeGameStats(betterproto.Message): + match: CMsgDOTARealtimeGameStatsMatchDetails = betterproto.message_field(1) + teams: list[CMsgDOTARealtimeGameStatsTeamDetails] = betterproto.message_field(2) + buildings: list[CMsgDOTARealtimeGameStatsBuildingDetails] = betterproto.message_field(3) + graph_data: CMsgDOTARealtimeGameStatsGraphData = betterproto.message_field(4) + delta_frame: bool = betterproto.bool_field(5) + + +@dataclass +class CMsgDOTARealtimeGameStatsTeamDetails(betterproto.Message): + team_number: int = betterproto.uint32_field(1) + team_id: int = betterproto.uint32_field(2) + team_name: str = betterproto.string_field(3) + team_logo: float = betterproto.fixed64_field(4) + team_tag: str = betterproto.string_field(10) + score: int = betterproto.uint32_field(5) + net_worth: int = betterproto.uint32_field(9) + players: list[CMsgDOTARealtimeGameStatsPlayerDetails] = betterproto.message_field(6) + only_team: bool = betterproto.bool_field(7) + cheers: int = betterproto.uint32_field(8) + team_logo_url: str = betterproto.string_field(11) + + +@dataclass +class CMsgDOTARealtimeGameStatsItemDetails(betterproto.Message): + item_ability_id: int = betterproto.int32_field(1) + name: str = betterproto.string_field(2) + time: int = betterproto.int32_field(3) + sold: bool = betterproto.bool_field(4) + stackcount: int = betterproto.uint32_field(5) + + +@dataclass +class CMsgDOTARealtimeGameStatsAbilityDetails(betterproto.Message): + id: int = betterproto.int32_field(1) + name: str = betterproto.string_field(2) + level: int = betterproto.uint32_field(3) + cooldown: float = betterproto.float_field(4) + cooldown_max: float = betterproto.float_field(5) + + +@dataclass +class CMsgDOTARealtimeGameStatsHeroToHeroStats(betterproto.Message): + victimid: int = betterproto.int32_field(1) + kills: int = betterproto.uint32_field(2) + assists: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgDOTARealtimeGameStatsAbilityList(betterproto.Message): + id: list[int] = betterproto.int32_field(1) + + +@dataclass +class CMsgDOTARealtimeGameStatsPlayerDetails(betterproto.Message): + accountid: int = betterproto.uint32_field(1) + playerid: int = betterproto.int32_field(2) + name: str = betterproto.string_field(3) + team: int = betterproto.uint32_field(4) + heroid: int = betterproto.uint32_field(5) + healthpoints: int = betterproto.uint32_field(6) + maxhealthpoints: int = betterproto.uint32_field(7) + healthregenrate: float = betterproto.float_field(8) + manapoints: int = betterproto.uint32_field(9) + maxmanapoints: int = betterproto.uint32_field(10) + manaregenrate: float = betterproto.float_field(11) + base_strength: int = betterproto.uint32_field(12) + base_agility: int = betterproto.uint32_field(13) + base_intelligence: int = betterproto.uint32_field(14) + base_armor: int = betterproto.int32_field(15) + base_movespeed: int = betterproto.uint32_field(16) + base_damage: int = betterproto.uint32_field(17) + strength: int = betterproto.uint32_field(18) + agility: int = betterproto.uint32_field(19) + intelligence: int = betterproto.uint32_field(20) + armor: int = betterproto.int32_field(21) + movespeed: int = betterproto.uint32_field(22) + damage: int = betterproto.uint32_field(23) + hero_damage: int = betterproto.uint32_field(24) + tower_damage: int = betterproto.uint32_field(25) + abilities: list[CMsgDOTARealtimeGameStatsAbilityDetails] = betterproto.message_field(26) + level: int = betterproto.uint32_field(27) + kill_count: int = betterproto.uint32_field(28) + death_count: int = betterproto.uint32_field(29) + assists_count: int = betterproto.uint32_field(30) + denies_count: int = betterproto.uint32_field(31) + lh_count: int = betterproto.uint32_field(32) + hero_healing: int = betterproto.uint32_field(33) + gold_per_min: int = betterproto.uint32_field(34) + xp_per_min: int = betterproto.uint32_field(35) + net_gold: int = betterproto.uint32_field(36) + gold: int = betterproto.uint32_field(37) + x: float = betterproto.float_field(38) + y: float = betterproto.float_field(39) + respawn_time: int = betterproto.int32_field(40) + ultimate_cooldown: int = betterproto.uint32_field(41) + has_buyback: bool = betterproto.bool_field(42) + items: list[CMsgDOTARealtimeGameStatsItemDetails] = betterproto.message_field(43) + stashitems: list[CMsgDOTARealtimeGameStatsItemDetails] = betterproto.message_field(44) + itemshoppinglist: list[CMsgDOTARealtimeGameStatsItemDetails] = betterproto.message_field(45) + levelpoints: list[CMsgDOTARealtimeGameStatsAbilityList] = betterproto.message_field(46) + hero_to_hero_stats: list[CMsgDOTARealtimeGameStatsHeroToHeroStats] = betterproto.message_field(47) + has_ultimate: bool = betterproto.bool_field(48) + has_ultimate_mana: bool = betterproto.bool_field(49) + team_slot: int = betterproto.uint32_field(50) + + +@dataclass +class CMsgDOTARealtimeGameStatsBuildingDetails(betterproto.Message): + team: int = betterproto.uint32_field(2) + heading: float = betterproto.float_field(3) + lane: int = betterproto.uint32_field(4) + tier: int = betterproto.uint32_field(5) + type: int = betterproto.uint32_field(6) + x: float = betterproto.float_field(7) + y: float = betterproto.float_field(8) + destroyed: bool = betterproto.bool_field(9) + + +@dataclass +class CMsgDOTARealtimeGameStatsKillDetails(betterproto.Message): + player_id: int = betterproto.int32_field(1) + death_time: int = betterproto.int32_field(2) + killer_player_id: int = betterproto.int32_field(3) + + +@dataclass +class CMsgDOTARealtimeGameStatsBroadcasterDetails(betterproto.Message): + player_id: int = betterproto.int32_field(1) + + +@dataclass +class CMsgDOTARealtimeGameStatsPickBanDetails(betterproto.Message): + hero: int = betterproto.uint32_field(1) + team: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgDOTARealtimeGameStatsMatchDetails(betterproto.Message): + server_steam_id: float = betterproto.fixed64_field(1) + match_id: int = betterproto.uint64_field(2) + timestamp: int = betterproto.uint32_field(3) + time_of_day: float = betterproto.float_field(4) + is_nightstalker_night: bool = betterproto.bool_field(5) + game_time: int = betterproto.int32_field(6) + game_state: int = betterproto.uint32_field(19) + teamid_radiant: int = betterproto.uint32_field(8) + teamid_dire: int = betterproto.uint32_field(9) + picks: list[CMsgDOTARealtimeGameStatsPickBanDetails] = betterproto.message_field(10) + bans: list[CMsgDOTARealtimeGameStatsPickBanDetails] = betterproto.message_field(11) + kills: list[CMsgDOTARealtimeGameStatsKillDetails] = betterproto.message_field(12) + broadcasters: list[CMsgDOTARealtimeGameStatsBroadcasterDetails] = betterproto.message_field(13) + game_mode: int = betterproto.uint32_field(14) + league_id: int = betterproto.uint32_field(15) + league_node_id: int = betterproto.uint32_field(18) + single_team: bool = betterproto.bool_field(16) + cheers_peak: int = betterproto.uint32_field(17) + lobby_type: int = betterproto.uint32_field(20) + start_timestamp: int = betterproto.uint32_field(21) + + +@dataclass +class CMsgDOTARealtimeGameStatsGraphData(betterproto.Message): + graph_gold: list[int] = betterproto.int32_field(1) + graph_xp: list[int] = betterproto.int32_field(2) + graph_kill: list[int] = betterproto.int32_field(3) + graph_tower: list[int] = betterproto.int32_field(4) + graph_rax: list[int] = betterproto.int32_field(5) + team_loc_stats: list[CMsgDOTARealtimeGameStatsGraphDataTeamLocationStats] = betterproto.message_field(6) + + +@dataclass +class CMsgDOTARealtimeGameStatsGraphDataLocationStats(betterproto.Message): + stats: list[int] = betterproto.int32_field(1) + + +@dataclass +class CMsgDOTARealtimeGameStatsGraphDataTeamLocationStats(betterproto.Message): + loc_stats: list[CMsgDOTARealtimeGameStatsGraphDataLocationStats] = betterproto.message_field(1) + + +@dataclass +class CMsgDOTARealtimeGameStatsTerse(betterproto.Message): + match: CMsgDOTARealtimeGameStatsTerseMatchDetails = betterproto.message_field(1) + teams: list[CMsgDOTARealtimeGameStatsTerseTeamDetails] = betterproto.message_field(2) + buildings: list[CMsgDOTARealtimeGameStatsTerseBuildingDetails] = betterproto.message_field(3) + graph_data: CMsgDOTARealtimeGameStatsTerseGraphData = betterproto.message_field(4) + delta_frame: bool = betterproto.bool_field(5) + + +@dataclass +class CMsgDOTARealtimeGameStatsTerseTeamDetails(betterproto.Message): + team_number: int = betterproto.uint32_field(1) + team_id: int = betterproto.uint32_field(2) + team_name: str = betterproto.string_field(3) + team_tag: str = betterproto.string_field(8) + team_logo: float = betterproto.fixed64_field(4) + score: int = betterproto.uint32_field(5) + net_worth: int = betterproto.uint32_field(7) + team_logo_url: str = betterproto.string_field(9) + players: list[CMsgDOTARealtimeGameStatsTersePlayerDetails] = betterproto.message_field(6) + + +@dataclass +class CMsgDOTARealtimeGameStatsTersePlayerDetails(betterproto.Message): + accountid: int = betterproto.uint32_field(1) + playerid: int = betterproto.int32_field(2) + name: str = betterproto.string_field(3) + team: int = betterproto.uint32_field(4) + heroid: int = betterproto.uint32_field(5) + level: int = betterproto.uint32_field(6) + kill_count: int = betterproto.uint32_field(7) + death_count: int = betterproto.uint32_field(8) + assists_count: int = betterproto.uint32_field(9) + denies_count: int = betterproto.uint32_field(10) + lh_count: int = betterproto.uint32_field(11) + gold: int = betterproto.uint32_field(12) + x: float = betterproto.float_field(13) + y: float = betterproto.float_field(14) + net_worth: int = betterproto.uint32_field(15) + abilities: list[int] = betterproto.int32_field(16) + items: list[int] = betterproto.int32_field(17) + team_slot: int = betterproto.uint32_field(18) + + +@dataclass +class CMsgDOTARealtimeGameStatsTerseBuildingDetails(betterproto.Message): + team: int = betterproto.uint32_field(1) + heading: float = betterproto.float_field(2) + type: int = betterproto.uint32_field(3) + lane: int = betterproto.uint32_field(4) + tier: int = betterproto.uint32_field(5) + x: float = betterproto.float_field(6) + y: float = betterproto.float_field(7) + destroyed: bool = betterproto.bool_field(8) + + +@dataclass +class CMsgDOTARealtimeGameStatsTersePickBanDetails(betterproto.Message): + hero: int = betterproto.uint32_field(1) + team: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgDOTARealtimeGameStatsTerseMatchDetails(betterproto.Message): + server_steam_id: float = betterproto.fixed64_field(1) + match_id: int = betterproto.uint64_field(2) + timestamp: int = betterproto.uint32_field(3) + game_time: int = betterproto.int32_field(4) + steam_broadcaster_account_ids: list[int] = betterproto.uint32_field(6) + game_mode: int = betterproto.uint32_field(7) + league_id: int = betterproto.uint32_field(8) + league_node_id: int = betterproto.uint32_field(9) + game_state: int = betterproto.uint32_field(10) + picks: list[CMsgDOTARealtimeGameStatsTersePickBanDetails] = betterproto.message_field(11) + bans: list[CMsgDOTARealtimeGameStatsTersePickBanDetails] = betterproto.message_field(12) + lobby_type: int = betterproto.uint32_field(13) + start_timestamp: int = betterproto.uint32_field(14) + + +@dataclass +class CMsgDOTARealtimeGameStatsTerseGraphData(betterproto.Message): + graph_gold: list[int] = betterproto.int32_field(1) + + +@dataclass +class CMsgDOTABroadcastTimelineEvent(betterproto.Message): + event: EBroadcastTimelineEvent = betterproto.enum_field(1) + timestamp: float = betterproto.fixed32_field(2) + data: int = betterproto.uint32_field(3) + string_data: str = betterproto.string_field(4) + + +@dataclass +class CMsgGCToClientMatchGroupsVersion(betterproto.Message): + matchgroups_version: int = betterproto.uint32_field(1) + + +@dataclass +class CMsgDOTASDOHeroStatsHistory(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + game_mode: int = betterproto.uint32_field(2) + lobby_type: int = betterproto.uint32_field(3) + start_time: int = betterproto.uint32_field(4) + won: bool = betterproto.bool_field(5) + gpm: int = betterproto.uint32_field(6) + xpm: int = betterproto.uint32_field(7) + kills: int = betterproto.uint32_field(8) + deaths: int = betterproto.uint32_field(9) + assists: int = betterproto.uint32_field(10) + + +@dataclass +class CMsgPredictionChoice(betterproto.Message): + value: int = betterproto.uint32_field(1) + name: str = betterproto.string_field(2) + min_raw_value: int = betterproto.uint32_field(3) + max_raw_value: int = betterproto.uint32_field(4) + + +@dataclass +class CMsgInGamePrediction(betterproto.Message): + id: int = betterproto.uint32_field(1) + name: str = betterproto.string_field(2) + type: CMsgInGamePredictionEPredictionType = betterproto.enum_field(3) + group: CMsgInGamePredictionERandomSelectionGroupT = betterproto.enum_field(4) + question: str = betterproto.string_field(5) + choices: list[CMsgPredictionChoice] = betterproto.message_field(6) + required_heroes: list[str] = betterproto.string_field(7) + query_name: str = betterproto.string_field(8) + query_values: list[CMsgInGamePredictionQueryKeyValues] = betterproto.message_field(9) + answer_resolution_type: CMsgInGamePredictionEResolutionTypeT = betterproto.enum_field(10) + points_to_grant: int = betterproto.uint32_field(11) + reward_action: int = betterproto.uint32_field(12) + debug_force_selection: int = betterproto.uint32_field(13) + raw_value_type: CMsgInGamePredictionERawValueTypeT = betterproto.enum_field(14) + + +@dataclass +class CMsgInGamePredictionQueryKeyValues(betterproto.Message): + name: str = betterproto.string_field(1) + value: str = betterproto.string_field(2) + + +@dataclass +class CMsgDOTASeasonPredictions(betterproto.Message): + predictions: list[CMsgDOTASeasonPredictionsPrediction] = betterproto.message_field(1) + in_game_predictions: list[CMsgInGamePrediction] = betterproto.message_field(2) + in_game_prediction_count_per_game: int = betterproto.uint32_field(3) + in_game_prediction_voting_period_minutes: int = betterproto.uint32_field(4) + + +@dataclass +class CMsgDOTASeasonPredictionsPrediction(betterproto.Message): + type: CMsgDOTASeasonPredictionsPredictionEPredictionType = betterproto.enum_field(1) + question: str = betterproto.string_field(2) + choices: list[CMsgPredictionChoice] = betterproto.message_field(3) + selection_id: int = betterproto.uint32_field(4) + start_date: int = betterproto.uint32_field(5) + lock_date: int = betterproto.uint32_field(6) + reward: int = betterproto.uint32_field(7) + answer_type: CMsgDOTASeasonPredictionsPredictionEAnswerType = betterproto.enum_field(8) + answer_id: int = betterproto.uint32_field(9) + answers: list[CMsgDOTASeasonPredictionsPredictionAnswers] = betterproto.message_field(10) + query_name: str = betterproto.string_field(11) + lock_on_selection_id: int = betterproto.uint32_field(13) + lock_on_selection_value: int = betterproto.uint32_field(14) + lock_on_selection_set: bool = betterproto.bool_field(15) + use_answer_value_ranges: bool = betterproto.bool_field(16) + region: ELeagueRegion = betterproto.enum_field(17) + phases: list[ELeaguePhase] = betterproto.enum_field(18) + reward_event: EEvent = betterproto.enum_field(19) + + +@dataclass +class CMsgDOTASeasonPredictionsPredictionAnswers(betterproto.Message): + answer_id: int = betterproto.uint32_field(1) + + +@dataclass +class CMsgAvailablePredictions(betterproto.Message): + match_predictions: list[CMsgAvailablePredictionsMatchPrediction] = betterproto.message_field(1) + + +@dataclass +class CMsgAvailablePredictionsMatchPrediction(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + predictions: list[CMsgInGamePrediction] = betterproto.message_field(2) + + +@dataclass +class CMsgLeagueWatchedGames(betterproto.Message): + leagues: list[CMsgLeagueWatchedGamesLeague] = betterproto.message_field(1) + + +@dataclass +class CMsgLeagueWatchedGamesSeries(betterproto.Message): + node_id: int = betterproto.uint32_field(1) + game: list[int] = betterproto.uint32_field(2) + + +@dataclass +class CMsgLeagueWatchedGamesLeague(betterproto.Message): + league_id: int = betterproto.uint32_field(1) + series: list[CMsgLeagueWatchedGamesSeries] = betterproto.message_field(2) + + +@dataclass +class CMsgDOTAMatch(betterproto.Message): + duration: int = betterproto.uint32_field(3) + starttime: float = betterproto.fixed32_field(4) + players: list[CMsgDOTAMatchPlayer] = betterproto.message_field(5) + match_id: int = betterproto.uint64_field(6) + tower_status: list[int] = betterproto.uint32_field(8) + barracks_status: list[int] = betterproto.uint32_field(9) + cluster: int = betterproto.uint32_field(10) + first_blood_time: int = betterproto.uint32_field(12) + replay_salt: float = betterproto.fixed32_field(13) + server_ip: float = betterproto.fixed32_field(14) + server_port: int = betterproto.uint32_field(15) + lobby_type: int = betterproto.uint32_field(16) + human_players: int = betterproto.uint32_field(17) + average_skill: int = betterproto.uint32_field(18) + game_balance: float = betterproto.float_field(19) + radiant_team_id: int = betterproto.uint32_field(20) + dire_team_id: int = betterproto.uint32_field(21) + leagueid: int = betterproto.uint32_field(22) + radiant_team_name: str = betterproto.string_field(23) + dire_team_name: str = betterproto.string_field(24) + radiant_team_logo: int = betterproto.uint64_field(25) + dire_team_logo: int = betterproto.uint64_field(26) + radiant_team_logo_url: str = betterproto.string_field(54) + dire_team_logo_url: str = betterproto.string_field(55) + radiant_team_complete: int = betterproto.uint32_field(27) + dire_team_complete: int = betterproto.uint32_field(28) + game_mode: DOTA_GameMode = betterproto.enum_field(31) + picks_bans: list[CMatchHeroSelectEvent] = betterproto.message_field(32) + match_seq_num: int = betterproto.uint64_field(33) + replay_state: CMsgDOTAMatchReplayState = betterproto.enum_field(34) + radiant_guild_id: int = betterproto.uint32_field(35) + dire_guild_id: int = betterproto.uint32_field(36) + radiant_team_tag: str = betterproto.string_field(37) + dire_team_tag: str = betterproto.string_field(38) + series_id: int = betterproto.uint32_field(39) + series_type: int = betterproto.uint32_field(40) + broadcaster_channels: list[CMsgDOTAMatchBroadcasterChannel] = betterproto.message_field(43) + engine: int = betterproto.uint32_field(44) + custom_game_data: CMsgDOTAMatchCustomGameData = betterproto.message_field(45) + match_flags: int = betterproto.uint32_field(46) + private_metadata_key: float = betterproto.fixed32_field(47) + radiant_team_score: int = betterproto.uint32_field(48) + dire_team_score: int = betterproto.uint32_field(49) + match_outcome: EMatchOutcome = betterproto.enum_field(50) + tournament_id: int = betterproto.uint32_field(51) + tournament_round: int = betterproto.uint32_field(52) + pre_game_duration: int = betterproto.uint32_field(53) + coaches: list[CMsgDOTAMatchCoach] = betterproto.message_field(57) + + +@dataclass +class CMsgDOTAMatchPlayer(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + player_slot: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + item_0: int = betterproto.int32_field(4) + item_1: int = betterproto.int32_field(5) + item_2: int = betterproto.int32_field(6) + item_3: int = betterproto.int32_field(7) + item_4: int = betterproto.int32_field(8) + item_5: int = betterproto.int32_field(9) + item_6: int = betterproto.int32_field(59) + item_7: int = betterproto.int32_field(60) + item_8: int = betterproto.int32_field(61) + item_9: int = betterproto.int32_field(76) + expected_team_contribution: float = betterproto.float_field(10) + scaled_metric: float = betterproto.float_field(11) + previous_rank: int = betterproto.uint32_field(12) + rank_change: int = betterproto.sint32_field(13) + mmr_type: int = betterproto.uint32_field(74) + kills: int = betterproto.uint32_field(14) + deaths: int = betterproto.uint32_field(15) + assists: int = betterproto.uint32_field(16) + leaver_status: int = betterproto.uint32_field(17) + gold: int = betterproto.uint32_field(18) + last_hits: int = betterproto.uint32_field(19) + denies: int = betterproto.uint32_field(20) + gold_per_min: int = betterproto.uint32_field(21) + xp_per_min: int = betterproto.uint32_field(22) + gold_spent: int = betterproto.uint32_field(23) + hero_damage: int = betterproto.uint32_field(24) + tower_damage: int = betterproto.uint32_field(25) + hero_healing: int = betterproto.uint32_field(26) + level: int = betterproto.uint32_field(27) + time_last_seen: int = betterproto.uint32_field(28) + player_name: str = betterproto.string_field(29) + support_ability_value: int = betterproto.uint32_field(30) + feeding_detected: bool = betterproto.bool_field(32) + search_rank: int = betterproto.uint32_field(34) + search_rank_uncertainty: int = betterproto.uint32_field(35) + rank_uncertainty_change: int = betterproto.int32_field(36) + hero_play_count: int = betterproto.uint32_field(37) + party_id: float = betterproto.fixed64_field(38) + scaled_hero_damage: int = betterproto.uint32_field(54) + scaled_tower_damage: int = betterproto.uint32_field(55) + scaled_hero_healing: int = betterproto.uint32_field(56) + scaled_kills: float = betterproto.float_field(39) + scaled_deaths: float = betterproto.float_field(40) + scaled_assists: float = betterproto.float_field(41) + claimed_farm_gold: int = betterproto.uint32_field(42) + support_gold: int = betterproto.uint32_field(43) + claimed_denies: int = betterproto.uint32_field(44) + claimed_misses: int = betterproto.uint32_field(45) + misses: int = betterproto.uint32_field(46) + ability_upgrades: list[CMatchPlayerAbilityUpgrade] = betterproto.message_field(47) + additional_units_inventory: list[CMatchAdditionalUnitInventory] = betterproto.message_field(48) + permanent_buffs: list[CMatchPlayerPermanentBuff] = betterproto.message_field(57) + pro_name: str = betterproto.string_field(72) + real_name: str = betterproto.string_field(73) + custom_game_data: CMsgDOTAMatchPlayerCustomGameData = betterproto.message_field(50) + active_plus_subscription: bool = betterproto.bool_field(51) + net_worth: int = betterproto.uint32_field(52) + bot_difficulty: int = betterproto.uint32_field(58) + hero_pick_order: int = betterproto.uint32_field(63) + hero_was_randomed: bool = betterproto.bool_field(64) + hero_was_dota_plus_suggestion: bool = betterproto.bool_field(69) + hero_damage_received: list[CMsgDOTAMatchPlayerHeroDamageReceived] = betterproto.message_field(67) + hero_damage_dealt: list[CMsgDOTAMatchPlayerHeroDamageReceived] = betterproto.message_field(79) + seconds_dead: int = betterproto.uint32_field(70) + gold_lost_to_death: int = betterproto.uint32_field(71) + lane_selection_flags: int = betterproto.uint32_field(75) + bounty_runes: int = betterproto.uint32_field(77) + outposts_captured: int = betterproto.uint32_field(78) + team_number: DOTA_GC_TEAM = betterproto.enum_field(80) + team_slot: int = betterproto.uint32_field(81) + + +@dataclass +class CMsgDOTAMatchPlayerCustomGameData(betterproto.Message): + dota_team: int = betterproto.uint32_field(1) + winner: bool = betterproto.bool_field(2) + + +@dataclass +class CMsgDOTAMatchPlayerHeroDamageReceived(betterproto.Message): + pre_reduction: int = betterproto.uint32_field(1) + post_reduction: int = betterproto.uint32_field(2) + damage_type: CMsgDOTAMatchPlayerHeroDamageType = betterproto.enum_field(3) + + +@dataclass +class CMsgDOTAMatchBroadcasterInfo(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + name: str = betterproto.string_field(2) + + +@dataclass +class CMsgDOTAMatchBroadcasterChannel(betterproto.Message): + country_code: str = betterproto.string_field(1) + description: str = betterproto.string_field(2) + broadcaster_infos: list[CMsgDOTAMatchBroadcasterInfo] = betterproto.message_field(3) + language_code: str = betterproto.string_field(4) + + +@dataclass +class CMsgDOTAMatchCoach(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + coach_name: str = betterproto.string_field(2) + coach_rating: int = betterproto.uint32_field(3) + coach_team: int = betterproto.uint32_field(4) + coach_party_id: int = betterproto.uint64_field(5) + is_private_coach: bool = betterproto.bool_field(6) + + +@dataclass +class CMsgDOTAMatchCustomGameData(betterproto.Message): + custom_game_id: int = betterproto.uint64_field(1) + map_name: str = betterproto.string_field(2) + + +@dataclass +class CMsgPlayerCard(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + stat_modifier: list[CMsgPlayerCardStatModifier] = betterproto.message_field(2) + + +@dataclass +class CMsgPlayerCardStatModifier(betterproto.Message): + stat: int = betterproto.uint32_field(1) + value: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgDOTAFantasyPlayerStats(betterproto.Message): + player_account_id: int = betterproto.uint32_field(1) + match_id: int = betterproto.uint64_field(2) + match_completed: bool = betterproto.bool_field(3) + team_id: int = betterproto.uint32_field(4) + league_id: int = betterproto.uint32_field(5) + delay: int = betterproto.uint32_field(6) + series_id: int = betterproto.uint32_field(7) + series_type: int = betterproto.uint32_field(8) + kills: int = betterproto.uint32_field(10) + deaths: int = betterproto.uint32_field(11) + cs: int = betterproto.uint32_field(12) + gpm: float = betterproto.float_field(13) + tower_kills: int = betterproto.uint32_field(14) + roshan_kills: int = betterproto.uint32_field(15) + teamfight_participation: float = betterproto.float_field(16) + wards_placed: int = betterproto.uint32_field(17) + camps_stacked: int = betterproto.uint32_field(18) + runes_grabbed: int = betterproto.uint32_field(19) + first_blood: int = betterproto.uint32_field(20) + stuns: float = betterproto.float_field(21) + smokes: int = betterproto.uint32_field(22) + neutral_tokens: int = betterproto.uint32_field(23) + watchers: int = betterproto.uint32_field(24) + lotuses: int = betterproto.uint32_field(25) + tormentors: int = betterproto.uint32_field(26) + courier_kills: int = betterproto.uint32_field(27) + title_stats: float = betterproto.fixed64_field(28) + + +@dataclass +class CMsgDOTAFantasyPlayerMatchStats(betterproto.Message): + matches: list[CMsgDOTAFantasyPlayerStats] = betterproto.message_field(1) + + +@dataclass +class CMsgDOTABotDebugInfo(betterproto.Message): + bots: list[CMsgDOTABotDebugInfoBot] = betterproto.message_field(1) + desire_push_lane_top: float = betterproto.float_field(2) + desire_push_lane_mid: float = betterproto.float_field(3) + desire_push_lane_bot: float = betterproto.float_field(4) + desire_defend_lane_top: float = betterproto.float_field(5) + desire_defend_lane_mid: float = betterproto.float_field(6) + desire_defend_lane_bot: float = betterproto.float_field(7) + desire_farm_lane_top: float = betterproto.float_field(8) + desire_farm_lane_mid: float = betterproto.float_field(9) + desire_farm_lane_bot: float = betterproto.float_field(10) + desire_farm_roshan: float = betterproto.float_field(11) + execution_time: float = betterproto.float_field(12) + rune_status: list[int] = betterproto.uint32_field(13) + + +@dataclass +class CMsgDOTABotDebugInfoBot(betterproto.Message): + player_owner_id: int = betterproto.int32_field(1) + hero_id: int = betterproto.uint32_field(2) + difficulty: int = betterproto.uint32_field(3) + power_current: int = betterproto.uint32_field(4) + power_max: int = betterproto.uint32_field(5) + move_target_x: int = betterproto.uint32_field(6) + move_target_y: int = betterproto.uint32_field(7) + move_target_z: int = betterproto.uint32_field(8) + active_mode_id: int = betterproto.uint32_field(9) + execution_time: float = betterproto.float_field(10) + modes: list[CMsgDOTABotDebugInfoBotMode] = betterproto.message_field(11) + action: CMsgDOTABotDebugInfoBotAction = betterproto.message_field(12) + + +@dataclass +class CMsgDOTABotDebugInfoBotMode(betterproto.Message): + mode_id: int = betterproto.uint32_field(1) + desire: float = betterproto.float_field(2) + target_entity: int = betterproto.int32_field(3) + target_x: int = betterproto.uint32_field(4) + target_y: int = betterproto.uint32_field(5) + target_z: int = betterproto.uint32_field(6) + + +@dataclass +class CMsgDOTABotDebugInfoBotAction(betterproto.Message): + action_id: int = betterproto.uint32_field(1) + action_target: str = betterproto.string_field(2) + + +@dataclass +class CMsgSuccessfulHero(betterproto.Message): + hero_id: int = betterproto.uint32_field(1) + win_percent: float = betterproto.float_field(2) + longest_streak: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgRecentMatchInfo(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + game_mode: DOTA_GameMode = betterproto.enum_field(2) + kills: int = betterproto.uint32_field(3) + deaths: int = betterproto.uint32_field(4) + assists: int = betterproto.uint32_field(5) + duration: int = betterproto.uint32_field(6) + player_slot: int = betterproto.uint32_field(7) + match_outcome: EMatchOutcome = betterproto.enum_field(8) + timestamp: int = betterproto.uint32_field(9) + lobby_type: int = betterproto.uint32_field(10) + team_number: int = betterproto.uint32_field(11) + + +@dataclass +class CMsgMatchTips(betterproto.Message): + tips: list[CMsgMatchTipsSingleTip] = betterproto.message_field(2) + + +@dataclass +class CMsgMatchTipsSingleTip(betterproto.Message): + source_account_id: int = betterproto.uint32_field(1) + target_account_id: int = betterproto.uint32_field(2) + tip_amount: int = betterproto.uint32_field(3) + event_id: EEvent = betterproto.enum_field(4) + + +@dataclass +class CMsgDOTAMatchMinimal(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + start_time: float = betterproto.fixed32_field(2) + duration: int = betterproto.uint32_field(3) + game_mode: DOTA_GameMode = betterproto.enum_field(4) + players: list[CMsgDOTAMatchMinimalPlayer] = betterproto.message_field(6) + tourney: CMsgDOTAMatchMinimalTourney = betterproto.message_field(7) + match_outcome: EMatchOutcome = betterproto.enum_field(8) + radiant_score: int = betterproto.uint32_field(9) + dire_score: int = betterproto.uint32_field(10) + lobby_type: int = betterproto.uint32_field(11) + + +@dataclass +class CMsgDOTAMatchMinimalPlayer(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + hero_id: int = betterproto.uint32_field(2) + kills: int = betterproto.uint32_field(3) + deaths: int = betterproto.uint32_field(4) + assists: int = betterproto.uint32_field(5) + items: list[int] = betterproto.int32_field(6) + player_slot: int = betterproto.uint32_field(7) + pro_name: str = betterproto.string_field(8) + level: int = betterproto.uint32_field(9) + team_number: DOTA_GC_TEAM = betterproto.enum_field(10) + + +@dataclass +class CMsgDOTAMatchMinimalTourney(betterproto.Message): + league_id: int = betterproto.uint32_field(1) + series_type: int = betterproto.uint32_field(8) + series_game: int = betterproto.uint32_field(9) + weekend_tourney_tournament_id: int = betterproto.uint32_field(10) + weekend_tourney_season_trophy_id: int = betterproto.uint32_field(11) + weekend_tourney_division: int = betterproto.uint32_field(12) + weekend_tourney_skill_level: int = betterproto.uint32_field(13) + radiant_team_id: int = betterproto.uint32_field(2) + radiant_team_name: str = betterproto.string_field(3) + radiant_team_logo: float = betterproto.fixed64_field(4) + radiant_team_logo_url: str = betterproto.string_field(14) + dire_team_id: int = betterproto.uint32_field(5) + dire_team_name: str = betterproto.string_field(6) + dire_team_logo: float = betterproto.fixed64_field(7) + dire_team_logo_url: str = betterproto.string_field(15) + + +@dataclass +class CMsgConsumableUsage(betterproto.Message): + item_def: int = betterproto.uint32_field(1) + quantity_change: int = betterproto.int32_field(2) + + +@dataclass +class CMsgMatchConsumableUsage(betterproto.Message): + player_consumables_used: list[CMsgMatchConsumableUsagePlayerUsage] = betterproto.message_field(1) + + +@dataclass +class CMsgMatchConsumableUsagePlayerUsage(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + consumables_used: list[CMsgConsumableUsage] = betterproto.message_field(2) + + +@dataclass +class CMsgMatchEventActionGrants(betterproto.Message): + player_grants: list[CMsgMatchEventActionGrantsPlayerGrants] = betterproto.message_field(1) + + +@dataclass +class CMsgMatchEventActionGrantsPlayerGrants(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + actions_granted: list[CMsgPendingEventAward] = betterproto.message_field(3) + + +@dataclass +class CMsgCustomGameWhitelist(betterproto.Message): + version: int = betterproto.uint32_field(1) + custom_games_whitelist: list[int] = betterproto.uint64_field(2) + disable_whitelist: bool = betterproto.bool_field(3) + + +@dataclass +class CMsgCustomGameWhitelistForEdit(betterproto.Message): + whitelist_entries: list[CMsgCustomGameWhitelistForEditWhitelistEntry] = betterproto.message_field(1) + + +@dataclass +class CMsgCustomGameWhitelistForEditWhitelistEntry(betterproto.Message): + custom_game_id: int = betterproto.uint64_field(1) + whitelist_state: ECustomGameWhitelistState = betterproto.enum_field(2) + + +@dataclass +class CMsgPlayerRecentMatchInfo(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + timestamp: int = betterproto.uint32_field(2) + duration: int = betterproto.uint32_field(3) + win: bool = betterproto.bool_field(4) + hero_id: int = betterproto.uint32_field(5) + kills: int = betterproto.uint32_field(6) + deaths: int = betterproto.uint32_field(7) + assists: int = betterproto.uint32_field(8) + + +@dataclass +class CMsgPlayerMatchRecord(betterproto.Message): + wins: int = betterproto.uint32_field(1) + losses: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgPlayerRecentMatchOutcomes(betterproto.Message): + outcomes: int = betterproto.uint32_field(1) + match_count: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgPlayerRecentCommends(betterproto.Message): + commends: int = betterproto.uint32_field(1) + match_count: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgPlayerRecentAccomplishments(betterproto.Message): + recent_outcomes: CMsgPlayerRecentMatchOutcomes = betterproto.message_field(1) + total_record: CMsgPlayerMatchRecord = betterproto.message_field(2) + prediction_streak: int = betterproto.uint32_field(3) + plus_prediction_streak: int = betterproto.uint32_field(4) + recent_commends: CMsgPlayerRecentCommends = betterproto.message_field(5) + first_match_timestamp: int = betterproto.uint32_field(6) + last_match: CMsgPlayerRecentMatchInfo = betterproto.message_field(7) + recent_mvps: CMsgPlayerRecentMatchOutcomes = betterproto.message_field(8) + + +@dataclass +class CMsgPlayerHeroRecentAccomplishments(betterproto.Message): + recent_outcomes: CMsgPlayerRecentMatchOutcomes = betterproto.message_field(1) + total_record: CMsgPlayerMatchRecord = betterproto.message_field(2) + last_match: CMsgPlayerRecentMatchInfo = betterproto.message_field(3) + + +@dataclass +class CMsgRecentAccomplishments(betterproto.Message): + player_accomplishments: CMsgPlayerRecentAccomplishments = betterproto.message_field(1) + hero_accomplishments: CMsgPlayerHeroRecentAccomplishments = betterproto.message_field(2) + + +@dataclass +class CMsgServerToGCRequestPlayerRecentAccomplishments(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + hero_id: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgServerToGCRequestPlayerRecentAccomplishmentsResponse(betterproto.Message): + result: CMsgServerToGCRequestPlayerRecentAccomplishmentsResponseEResponse = betterproto.enum_field(1) + player_accomplishments: CMsgRecentAccomplishments = betterproto.message_field(2) + + +@dataclass +class CMsgArcanaVoteMatchVotes(betterproto.Message): + match_id: int = betterproto.uint32_field(1) + hero_id: int = betterproto.uint32_field(2) + vote_count: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgGCtoGCAssociatedExploiterAccountInfo(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + num_matches_to_search: int = betterproto.uint32_field(2) + min_shared_match_count: int = betterproto.uint32_field(3) + num_additional_players: int = betterproto.uint32_field(4) + + +@dataclass +class CMsgGCtoGCAssociatedExploiterAccountInfoResponse(betterproto.Message): + accounts: list[CMsgGCtoGCAssociatedExploiterAccountInfoResponseAccount] = betterproto.message_field(1) + + +@dataclass +class CMsgGCtoGCAssociatedExploiterAccountInfoResponseAccount(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + num_common_matches: int = betterproto.uint32_field(2) + earliest_common_match: int = betterproto.uint32_field(3) + latest_common_match: int = betterproto.uint32_field(4) + generation: int = betterproto.uint32_field(5) + persona: str = betterproto.string_field(6) + already_banned: bool = betterproto.bool_field(7) + + +@dataclass +class CMsgPullTabsData(betterproto.Message): + slots: list[CMsgPullTabsDataSlot] = betterproto.message_field(1) + jackpots: list[CMsgPullTabsDataJackpot] = betterproto.message_field(2) + last_board: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgPullTabsDataSlot(betterproto.Message): + event_id: int = betterproto.uint32_field(1) + board_id: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + action_id: int = betterproto.uint32_field(4) + redeemed: bool = betterproto.bool_field(5) + + +@dataclass +class CMsgPullTabsDataJackpot(betterproto.Message): + board_id: int = betterproto.uint32_field(1) + action_id: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgUnderDraftData(betterproto.Message): + bench_slots: list[CMsgUnderDraftDataBenchSlot] = betterproto.message_field(1) + shop_slots: list[CMsgUnderDraftDataShopSlot] = betterproto.message_field(2) + gold: int = betterproto.uint32_field(3) + total_gold: int = betterproto.uint32_field(4) + not_restorable: bool = betterproto.bool_field(5) + + +@dataclass +class CMsgUnderDraftDataBenchSlot(betterproto.Message): + slot_id: int = betterproto.uint32_field(1) + hero_id: int = betterproto.uint32_field(2) + stars: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgUnderDraftDataShopSlot(betterproto.Message): + slot_id: int = betterproto.uint32_field(1) + hero_id: int = betterproto.uint32_field(2) + is_special_reward: bool = betterproto.bool_field(3) + + +@dataclass +class CMsgPlayerTitleData(betterproto.Message): + title: list[int] = betterproto.uint32_field(1) + event_id: list[int] = betterproto.uint32_field(2) + active: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgDOTATriviaQuestion(betterproto.Message): + question_id: int = betterproto.uint32_field(1) + category: EDOTATriviaQuestionCategory = betterproto.enum_field(2) + timestamp: int = betterproto.uint32_field(3) + question_value: str = betterproto.string_field(4) + answer_values: list[str] = betterproto.string_field(5) + correct_answer_index: int = betterproto.uint32_field(6) + + +@dataclass +class CMsgDOTATriviaQuestionAnswersSummary(betterproto.Message): + summary_available: bool = betterproto.bool_field(1) + picked_count: list[int] = betterproto.uint32_field(2) + + +@dataclass +class CMsgGameDataSpecialValueBonus(betterproto.Message): + name: str = betterproto.string_field(1) + value: float = betterproto.float_field(2) + operation: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgGameDataSpecialValues(betterproto.Message): + name: str = betterproto.string_field(1) + values_float: list[float] = betterproto.float_field(2) + is_percentage: bool = betterproto.bool_field(4) + heading_loc: str = betterproto.string_field(5) + bonuses: list[CMsgGameDataSpecialValueBonus] = betterproto.message_field(6) + values_shard: list[float] = betterproto.float_field(7) + values_scepter: list[float] = betterproto.float_field(8) + + +@dataclass +class CMsgGameDataAbilityOrItem(betterproto.Message): + id: int = betterproto.int32_field(1) + name: str = betterproto.string_field(2) + name_loc: str = betterproto.string_field(5) + desc_loc: str = betterproto.string_field(6) + lore_loc: str = betterproto.string_field(7) + notes_loc: list[str] = betterproto.string_field(8) + shard_loc: str = betterproto.string_field(9) + scepter_loc: str = betterproto.string_field(10) + type: int = betterproto.uint32_field(20) + behavior: int = betterproto.uint64_field(21) + target_team: int = betterproto.uint32_field(22) + target_type: int = betterproto.uint32_field(23) + flags: int = betterproto.uint32_field(24) + damage: int = betterproto.uint32_field(25) + immunity: int = betterproto.uint32_field(26) + dispellable: int = betterproto.uint32_field(27) + max_level: int = betterproto.uint32_field(28) + cast_ranges: list[int] = betterproto.uint32_field(30) + cast_points: list[float] = betterproto.float_field(31) + channel_times: list[float] = betterproto.float_field(32) + cooldowns: list[float] = betterproto.float_field(33) + durations: list[float] = betterproto.float_field(34) + damages: list[int] = betterproto.uint32_field(35) + mana_costs: list[int] = betterproto.uint32_field(36) + gold_costs: list[int] = betterproto.uint32_field(37) + health_costs: list[int] = betterproto.uint32_field(38) + special_values: list[CMsgGameDataSpecialValues] = betterproto.message_field(40) + is_item: bool = betterproto.bool_field(50) + ability_has_scepter: bool = betterproto.bool_field(60) + ability_has_shard: bool = betterproto.bool_field(61) + ability_is_granted_by_scepter: bool = betterproto.bool_field(62) + ability_is_granted_by_shard: bool = betterproto.bool_field(63) + item_cost: int = betterproto.uint32_field(70) + item_initial_charges: int = betterproto.uint32_field(71) + item_neutral_tier: int = betterproto.uint32_field(72) + item_stock_max: int = betterproto.uint32_field(73) + item_stock_time: float = betterproto.float_field(74) + item_quality: int = betterproto.uint32_field(85) + + +@dataclass +class CMsgGameDataHero(betterproto.Message): + id: int = betterproto.uint32_field(1) + name: str = betterproto.string_field(2) + order_id: int = betterproto.uint32_field(3) + name_loc: str = betterproto.string_field(5) + bio_loc: str = betterproto.string_field(6) + hype_loc: str = betterproto.string_field(7) + npe_desc_loc: str = betterproto.string_field(8) + str_base: int = betterproto.uint32_field(10) + str_gain: float = betterproto.float_field(11) + agi_base: int = betterproto.uint32_field(12) + agi_gain: float = betterproto.float_field(13) + int_base: int = betterproto.uint32_field(14) + int_gain: float = betterproto.float_field(15) + primary_attr: int = betterproto.uint32_field(20) + complexity: int = betterproto.uint32_field(21) + attack_capability: int = betterproto.uint32_field(22) + role_levels: list[int] = betterproto.uint32_field(23) + damage_min: int = betterproto.int32_field(24) + damage_max: int = betterproto.int32_field(25) + attack_rate: float = betterproto.float_field(26) + attack_range: int = betterproto.uint32_field(27) + projectile_speed: int = betterproto.uint32_field(28) + armor: float = betterproto.float_field(29) + magic_resistance: int = betterproto.uint32_field(30) + movement_speed: int = betterproto.uint32_field(31) + turn_rate: float = betterproto.float_field(32) + sight_range_day: int = betterproto.uint32_field(33) + sight_range_night: int = betterproto.uint32_field(34) + max_health: int = betterproto.uint32_field(35) + health_regen: float = betterproto.float_field(36) + max_mana: int = betterproto.uint32_field(37) + mana_regen: float = betterproto.float_field(38) + abilities: list[CMsgGameDataAbilityOrItem] = betterproto.message_field(40) + talents: list[CMsgGameDataAbilityOrItem] = betterproto.message_field(41) + + +@dataclass +class CMsgGameDataAbilities(betterproto.Message): + abilities: list[CMsgGameDataAbilityOrItem] = betterproto.message_field(1) + + +@dataclass +class CMsgGameDataItems(betterproto.Message): + items: list[CMsgGameDataAbilityOrItem] = betterproto.message_field(1) + + +@dataclass +class CMsgGameDataHeroes(betterproto.Message): + heroes: list[CMsgGameDataHero] = betterproto.message_field(1) + + +@dataclass +class CMsgGameDataHeroList(betterproto.Message): + heroes: list[CMsgGameDataHeroListHeroInfo] = betterproto.message_field(1) + + +@dataclass +class CMsgGameDataHeroListHeroInfo(betterproto.Message): + id: int = betterproto.uint32_field(1) + name: str = betterproto.string_field(2) + name_loc: str = betterproto.string_field(3) + name_english_loc: str = betterproto.string_field(4) + primary_attr: int = betterproto.uint32_field(5) + complexity: int = betterproto.uint32_field(6) + + +@dataclass +class CMsgGameDataItemAbilityList(betterproto.Message): + itemabilities: list[CMsgGameDataItemAbilityListItemAbilityInfo] = betterproto.message_field(1) + + +@dataclass +class CMsgGameDataItemAbilityListItemAbilityInfo(betterproto.Message): + id: int = betterproto.int32_field(1) + name: str = betterproto.string_field(2) + name_loc: str = betterproto.string_field(3) + name_english_loc: str = betterproto.string_field(4) + neutral_item_tier: int = betterproto.int32_field(5) + + +@dataclass +class CMsgLobbyAbilityDraftData(betterproto.Message): + shuffle_draft_order: bool = betterproto.bool_field(1) + + +@dataclass +class CSOEconItemDropRateBonus(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + expiration_date: float = betterproto.fixed32_field(2) + bonus: float = betterproto.float_field(3) + bonus_count: int = betterproto.uint32_field(4) + item_id: int = betterproto.uint64_field(5) + def_index: int = betterproto.uint32_field(6) + seconds_left: int = betterproto.uint32_field(7) + booster_type: int = betterproto.uint32_field(8) + + +@dataclass +class CSOEconItemTournamentPassport(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + league_id: int = betterproto.uint32_field(2) + item_id: int = betterproto.uint64_field(3) + original_purchaser_id: int = betterproto.uint32_field(4) + passports_bought: int = betterproto.uint32_field(5) + version: int = betterproto.uint32_field(6) + def_index: int = betterproto.uint32_field(7) + reward_flags: int = betterproto.uint32_field(8) + + +@dataclass +class CMsgStickerbookSticker(betterproto.Message): + item_def_id: int = betterproto.uint32_field(1) + sticker_num: int = betterproto.uint32_field(2) + quality: int = betterproto.uint32_field(3) + position_x: float = betterproto.float_field(4) + position_y: float = betterproto.float_field(5) + position_z: float = betterproto.float_field(8) + rotation: float = betterproto.float_field(6) + scale: float = betterproto.float_field(7) + source_item_id: int = betterproto.uint64_field(9) + depth_bias: int = betterproto.uint32_field(10) + + +@dataclass +class CMsgStickerbookPage(betterproto.Message): + page_num: int = betterproto.uint32_field(1) + event_id: EEvent = betterproto.enum_field(2) + team_id: int = betterproto.uint32_field(3) + stickers: list[CMsgStickerbookSticker] = betterproto.message_field(4) + page_type: EStickerbookPageType = betterproto.enum_field(5) + + +@dataclass +class CMsgStickerbookTeamPageOrderSequence(betterproto.Message): + page_numbers: list[int] = betterproto.uint32_field(1) + + +@dataclass +class CMsgStickerbook(betterproto.Message): + pages: list[CMsgStickerbookPage] = betterproto.message_field(1) + team_page_order_sequence: CMsgStickerbookTeamPageOrderSequence = betterproto.message_field(2) + favorite_page_num: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgStickerHero(betterproto.Message): + hero_id: int = betterproto.uint32_field(1) + item_def_id: int = betterproto.uint32_field(2) + quality: int = betterproto.uint32_field(3) + source_item_id: int = betterproto.uint64_field(4) + + +@dataclass +class CMsgStickerHeroes(betterproto.Message): + heroes: list[CMsgStickerHero] = betterproto.message_field(1) + + +@dataclass +class CMsgHeroRoleStats(betterproto.Message): + lane_selection_flags: int = betterproto.uint32_field(1) + match_count: int = betterproto.uint32_field(2) + win_count: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgHeroRoleHeroStats(betterproto.Message): + hero_id: int = betterproto.uint32_field(1) + role_stats: list[CMsgHeroRoleStats] = betterproto.message_field(2) + + +@dataclass +class CMsgHeroRoleRankStats(betterproto.Message): + rank_tier: int = betterproto.uint32_field(1) + hero_stats: list[CMsgHeroRoleHeroStats] = betterproto.message_field(2) + + +@dataclass +class CMsgHeroRoleAllRanksStats(betterproto.Message): + start_timestamp: int = betterproto.uint32_field(1) + end_timestamp: int = betterproto.uint32_field(2) + rank_stats: list[CMsgHeroRoleRankStats] = betterproto.message_field(3) + + +@dataclass +class CMsgMapStatsSnapshot(betterproto.Message): + timestamp: int = betterproto.uint32_field(1) + lotuses_gained: int = betterproto.uint64_field(2) + wisdom_runes_gained: int = betterproto.uint64_field(3) + roshan_kills_day: int = betterproto.uint64_field(4) + roshan_kills_night: int = betterproto.uint64_field(5) + portals_used: int = betterproto.uint64_field(6) + watchers_taken: int = betterproto.uint64_field(7) + tormentor_kills: int = betterproto.uint64_field(8) + outposts_captured: int = betterproto.uint64_field(9) + shield_runes_gained: int = betterproto.uint64_field(10) + + +@dataclass +class CMsgGlobalMapStats(betterproto.Message): + current: CMsgMapStatsSnapshot = betterproto.message_field(1) + window_start: CMsgMapStatsSnapshot = betterproto.message_field(2) + window_end: CMsgMapStatsSnapshot = betterproto.message_field(3) + + +@dataclass +class CMsgTrackedStat(betterproto.Message): + tracked_stat_id: int = betterproto.uint32_field(1) + tracked_stat_value: int = betterproto.int32_field(2) diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py b/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py new file mode 100644 index 00000000..fa1c6a94 --- /dev/null +++ b/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py @@ -0,0 +1,896 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_gcmessages_msgid.proto +# plugin: python-betterproto + +import betterproto + + +class EDOTAGCMsg(betterproto.Enum): + k_EMsgGCDOTABase = 7000 + k_EMsgGCGameMatchSignOut = 7004 + k_EMsgGCGameMatchSignOutResponse = 7005 + k_EMsgGCJoinChatChannel = 7009 + k_EMsgGCJoinChatChannelResponse = 7010 + k_EMsgGCOtherJoinedChannel = 7013 + k_EMsgGCOtherLeftChannel = 7014 + k_EMsgServerToGCRequestStatus = 7026 + k_EMsgGCStartFindingMatch = 7033 + k_EMsgGCConnectedPlayers = 7034 + k_EMsgGCAbandonCurrentGame = 7035 + k_EMsgGCStopFindingMatch = 7036 + k_EMsgGCPracticeLobbyCreate = 7038 + k_EMsgGCPracticeLobbyLeave = 7040 + k_EMsgGCPracticeLobbyLaunch = 7041 + k_EMsgGCPracticeLobbyList = 7042 + k_EMsgGCPracticeLobbyListResponse = 7043 + k_EMsgGCPracticeLobbyJoin = 7044 + k_EMsgGCPracticeLobbySetDetails = 7046 + k_EMsgGCPracticeLobbySetTeamSlot = 7047 + k_EMsgGCInitialQuestionnaireResponse = 7049 + k_EMsgGCPracticeLobbyResponse = 7055 + k_EMsgGCBroadcastNotification = 7056 + k_EMsgGCLiveScoreboardUpdate = 7057 + k_EMsgGCRequestChatChannelList = 7060 + k_EMsgGCRequestChatChannelListResponse = 7061 + k_EMsgGCReadyUp = 7070 + k_EMsgGCKickedFromMatchmakingQueue = 7071 + k_EMsgGCLeaverDetected = 7072 + k_EMsgGCSpectateFriendGame = 7073 + k_EMsgGCSpectateFriendGameResponse = 7074 + k_EMsgGCReportsRemainingRequest = 7076 + k_EMsgGCReportsRemainingResponse = 7077 + k_EMsgGCSubmitPlayerReport = 7078 + k_EMsgGCSubmitPlayerReportResponse = 7079 + k_EMsgGCPracticeLobbyKick = 7081 + k_EMsgGCSubmitPlayerReportV2 = 7082 + k_EMsgGCSubmitPlayerReportResponseV2 = 7083 + k_EMsgGCRequestSaveGames = 7084 + k_EMsgGCRequestSaveGamesServer = 7085 + k_EMsgGCRequestSaveGamesResponse = 7086 + k_EMsgGCLeaverDetectedResponse = 7087 + k_EMsgGCPlayerFailedToConnect = 7088 + k_EMsgGCGCToRelayConnect = 7089 + k_EMsgGCGCToRelayConnectresponse = 7090 + k_EMsgGCWatchGame = 7091 + k_EMsgGCWatchGameResponse = 7092 + k_EMsgGCBanStatusRequest = 7093 + k_EMsgGCBanStatusResponse = 7094 + k_EMsgGCMatchDetailsRequest = 7095 + k_EMsgGCMatchDetailsResponse = 7096 + k_EMsgGCCancelWatchGame = 7097 + k_EMsgGCPopup = 7102 + k_EMsgGCFriendPracticeLobbyListRequest = 7111 + k_EMsgGCFriendPracticeLobbyListResponse = 7112 + k_EMsgGCPracticeLobbyJoinResponse = 7113 + k_EMsgGCCreateTeam = 7115 + k_EMsgGCCreateTeamResponse = 7116 + k_EMsgGCTeamInvite_InviterToGC = 7122 + k_EMsgGCTeamInvite_GCImmediateResponseToInviter = 7123 + k_EMsgGCTeamInvite_GCRequestToInvitee = 7124 + k_EMsgGCTeamInvite_InviteeResponseToGC = 7125 + k_EMsgGCTeamInvite_GCResponseToInviter = 7126 + k_EMsgGCTeamInvite_GCResponseToInvitee = 7127 + k_EMsgGCKickTeamMember = 7128 + k_EMsgGCKickTeamMemberResponse = 7129 + k_EMsgGCLeaveTeam = 7130 + k_EMsgGCLeaveTeamResponse = 7131 + k_EMsgGCApplyTeamToPracticeLobby = 7142 + k_EMsgGCTransferTeamAdmin = 7144 + k_EMsgGCPracticeLobbyJoinBroadcastChannel = 7149 + k_EMsgGC_TournamentItemEvent = 7150 + k_EMsgGC_TournamentItemEventResponse = 7151 + k_EMsgTeamFanfare = 7156 + k_EMsgResponseTeamFanfare = 7157 + k_EMsgGC_GameServerUploadSaveGame = 7158 + k_EMsgGC_GameServerSaveGameResult = 7159 + k_EMsgGC_GameServerGetLoadGame = 7160 + k_EMsgGC_GameServerGetLoadGameResult = 7161 + k_EMsgGCEditTeamDetails = 7166 + k_EMsgGCEditTeamDetailsResponse = 7167 + k_EMsgGCReadyUpStatus = 7170 + k_EMsgGCToGCMatchCompleted = 7186 + k_EMsgGCBalancedShuffleLobby = 7188 + k_EMsgGCMatchmakingStatsRequest = 7197 + k_EMsgGCMatchmakingStatsResponse = 7198 + k_EMsgGCBotGameCreate = 7199 + k_EMsgGCSetMatchHistoryAccess = 7200 + k_EMsgGCSetMatchHistoryAccessResponse = 7201 + k_EMsgUpgradeLeagueItem = 7203 + k_EMsgUpgradeLeagueItemResponse = 7204 + k_EMsgGCWatchDownloadedReplay = 7206 + k_EMsgClientsRejoinChatChannels = 7217 + k_EMsgGCToGCGetUserChatInfo = 7218 + k_EMsgGCToGCGetUserChatInfoResponse = 7219 + k_EMsgGCToGCLeaveAllChatChannels = 7220 + k_EMsgGCToGCUpdateAccountChatBan = 7221 + k_EMsgGCToGCCanInviteUserToTeam = 7234 + k_EMsgGCToGCCanInviteUserToTeamResponse = 7235 + k_EMsgGCToGCGetUserRank = 7236 + k_EMsgGCToGCGetUserRankResponse = 7237 + k_EMsgGCToGCAdjustUserRank = 7238 + k_EMsgGCToGCAdjustUserRankResponse = 7239 + k_EMsgGCToGCUpdateTeamStats = 7240 + k_EMsgGCToGCValidateTeam = 7241 + k_EMsgGCToGCValidateTeamResponse = 7242 + k_EMsgGCToGCGetLeagueAdmin = 7255 + k_EMsgGCToGCGetLeagueAdminResponse = 7256 + k_EMsgGCLeaveChatChannel = 7272 + k_EMsgGCChatMessage = 7273 + k_EMsgGCGetHeroStandings = 7274 + k_EMsgGCGetHeroStandingsResponse = 7275 + k_EMsgGCItemEditorReservationsRequest = 7283 + k_EMsgGCItemEditorReservationsResponse = 7284 + k_EMsgGCItemEditorReserveItemDef = 7285 + k_EMsgGCItemEditorReserveItemDefResponse = 7286 + k_EMsgGCItemEditorReleaseReservation = 7287 + k_EMsgGCItemEditorReleaseReservationResponse = 7288 + k_EMsgGCRewardTutorialPrizes = 7289 + k_EMsgGCFantasyLivePlayerStats = 7308 + k_EMsgGCFantasyFinalPlayerStats = 7309 + k_EMsgGCFlipLobbyTeams = 7320 + k_EMsgGCToGCEvaluateReportedPlayer = 7322 + k_EMsgGCToGCEvaluateReportedPlayerResponse = 7323 + k_EMsgGCToGCProcessPlayerReportForTarget = 7324 + k_EMsgGCToGCProcessReportSuccess = 7325 + k_EMsgGCNotifyAccountFlagsChange = 7326 + k_EMsgGCSetProfilePrivacy = 7327 + k_EMsgGCSetProfilePrivacyResponse = 7328 + k_EMsgGCClientSuspended = 7342 + k_EMsgGCPartyMemberSetCoach = 7343 + k_EMsgGCPracticeLobbySetCoach = 7346 + k_EMsgGCChatModeratorBan = 7359 + k_EMsgGCLobbyUpdateBroadcastChannelInfo = 7367 + k_EMsgGCToGCGrantTournamentItem = 7372 + k_EMsgGCToGCUpgradeTwitchViewerItems = 7375 + k_EMsgGCToGCGetLiveMatchAffiliates = 7376 + k_EMsgGCToGCGetLiveMatchAffiliatesResponse = 7377 + k_EMsgGCToGCUpdatePlayerPennantCounts = 7378 + k_EMsgGCToGCGetPlayerPennantCounts = 7379 + k_EMsgGCToGCGetPlayerPennantCountsResponse = 7380 + k_EMsgGCGameMatchSignOutPermissionRequest = 7381 + k_EMsgGCGameMatchSignOutPermissionResponse = 7382 + k_EMsgDOTAAwardEventPoints = 7384 + k_EMsgDOTAGetEventPoints = 7387 + k_EMsgDOTAGetEventPointsResponse = 7388 + k_EMsgGCPartyLeaderWatchGamePrompt = 7397 + k_EMsgGCCompendiumSetSelection = 7405 + k_EMsgGCCompendiumDataRequest = 7406 + k_EMsgGCCompendiumDataResponse = 7407 + k_EMsgDOTAGetPlayerMatchHistory = 7408 + k_EMsgDOTAGetPlayerMatchHistoryResponse = 7409 + k_EMsgGCToGCMatchmakingAddParty = 7410 + k_EMsgGCToGCMatchmakingRemoveParty = 7411 + k_EMsgGCToGCMatchmakingRemoveAllParties = 7412 + k_EMsgGCToGCMatchmakingMatchFound = 7413 + k_EMsgGCToGCUpdateMatchManagementStats = 7414 + k_EMsgGCToGCUpdateMatchmakingStats = 7415 + k_EMsgGCToServerPingRequest = 7416 + k_EMsgGCToServerPingResponse = 7417 + k_EMsgGCToServerEvaluateToxicChat = 7418 + k_EMsgServerToGCEvaluateToxicChat = 7419 + k_EMsgServerToGCEvaluateToxicChatResponse = 7420 + k_EMsgGCToGCProcessMatchLeaver = 7426 + k_EMsgGCNotificationsRequest = 7427 + k_EMsgGCNotificationsResponse = 7428 + k_EMsgGCToGCModifyNotification = 7429 + k_EMsgGCLeagueAdminList = 7434 + k_EMsgGCNotificationsMarkReadRequest = 7435 + k_EMsgServerToGCRequestBatchPlayerResources = 7450 + k_EMsgServerToGCRequestBatchPlayerResourcesResponse = 7451 + k_EMsgGCCompendiumSetSelectionResponse = 7453 + k_EMsgGCPlayerInfoSubmit = 7456 + k_EMsgGCPlayerInfoSubmitResponse = 7457 + k_EMsgGCToGCGetAccountLevel = 7458 + k_EMsgGCToGCGetAccountLevelResponse = 7459 + k_EMsgDOTAGetWeekendTourneySchedule = 7464 + k_EMsgDOTAWeekendTourneySchedule = 7465 + k_EMsgGCJoinableCustomGameModesRequest = 7466 + k_EMsgGCJoinableCustomGameModesResponse = 7467 + k_EMsgGCJoinableCustomLobbiesRequest = 7468 + k_EMsgGCJoinableCustomLobbiesResponse = 7469 + k_EMsgGCQuickJoinCustomLobby = 7470 + k_EMsgGCQuickJoinCustomLobbyResponse = 7471 + k_EMsgGCToGCGrantEventPointAction = 7472 + k_EMsgGCToGCSetCompendiumSelection = 7478 + k_EMsgGCHasItemQuery = 7484 + k_EMsgGCHasItemResponse = 7485 + k_EMsgGCToGCGrantEventPointActionMsg = 7488 + k_EMsgGCToGCGetCompendiumSelections = 7492 + k_EMsgGCToGCGetCompendiumSelectionsResponse = 7493 + k_EMsgServerToGCMatchConnectionStats = 7494 + k_EMsgGCToClientTournamentItemDrop = 7495 + k_EMsgSQLDelayedGrantLeagueDrop = 7496 + k_EMsgServerGCUpdateSpectatorCount = 7497 + k_EMsgGCToGCEmoticonUnlock = 7501 + k_EMsgSignOutDraftInfo = 7502 + k_EMsgClientToGCEmoticonDataRequest = 7503 + k_EMsgGCToClientEmoticonData = 7504 + k_EMsgGCPracticeLobbyToggleBroadcastChannelCameramanStatus = 7505 + k_EMsgDOTARedeemItem = 7518 + k_EMsgDOTARedeemItemResponse = 7519 + k_EMsgClientToGCGetAllHeroProgress = 7521 + k_EMsgClientToGCGetAllHeroProgressResponse = 7522 + k_EMsgGCToGCGetServerForClient = 7523 + k_EMsgGCToGCGetServerForClientResponse = 7524 + k_EMsgSQLProcessTournamentGameOutcome = 7525 + k_EMsgSQLGrantTrophyToAccount = 7526 + k_EMsgClientToGCGetTrophyList = 7527 + k_EMsgClientToGCGetTrophyListResponse = 7528 + k_EMsgGCToClientTrophyAwarded = 7529 + k_EMsgGCGameBotMatchSignOut = 7530 + k_EMsgGCGameBotMatchSignOutPermissionRequest = 7531 + k_EMsgSignOutBotInfo = 7532 + k_EMsgGCToGCUpdateProfileCards = 7533 + k_EMsgClientToGCGetProfileCard = 7534 + k_EMsgClientToGCGetProfileCardResponse = 7535 + k_EMsgClientToGCGetBattleReport = 7536 + k_EMsgClientToGCGetBattleReportResponse = 7537 + k_EMsgClientToGCSetProfileCardSlots = 7538 + k_EMsgGCToClientProfileCardUpdated = 7539 + k_EMsgServerToGCVictoryPredictions = 7540 + k_EMsgClientToGCGetBattleReportAggregateStats = 7541 + k_EMsgClientToGCGetBattleReportAggregateStatsResponse = 7542 + k_EMsgClientToGCGetBattleReportInfo = 7543 + k_EMsgClientToGCGetBattleReportInfoResponse = 7544 + k_EMsgSignOutCommunicationSummary = 7545 + k_EMsgServerToGCRequestStatus_Response = 7546 + k_EMsgClientToGCCreateHeroStatue = 7547 + k_EMsgGCToClientHeroStatueCreateResult = 7548 + k_EMsgGCGCToLANServerRelayConnect = 7549 + k_EMsgClientToGCAcknowledgeBattleReport = 7550 + k_EMsgClientToGCAcknowledgeBattleReportResponse = 7551 + k_EMsgClientToGCGetBattleReportMatchHistory = 7552 + k_EMsgClientToGCGetBattleReportMatchHistoryResponse = 7553 + k_EMsgServerToGCReportKillSummaries = 7554 + k_EMsgGCToGCUpdatePlayerPredictions = 7561 + k_EMsgGCToServerPredictionResult = 7562 + k_EMsgGCToGCReplayMonitorValidateReplay = 7569 + k_EMsgLobbyEventPoints = 7572 + k_EMsgGCToGCGetCustomGameTickets = 7573 + k_EMsgGCToGCGetCustomGameTicketsResponse = 7574 + k_EMsgGCToGCCustomGamePlayed = 7576 + k_EMsgGCToGCGrantEventPointsToUser = 7577 + k_EMsgGameserverCrashReport = 7579 + k_EMsgGameserverCrashReportResponse = 7580 + k_EMsgGCToClientSteamDatagramTicket = 7581 + k_EMsgGCToGCSendAccountsEventPoints = 7583 + k_EMsgClientToGCRerollPlayerChallenge = 7584 + k_EMsgServerToGCRerollPlayerChallenge = 7585 + k_EMsgGCRerollPlayerChallengeResponse = 7586 + k_EMsgSignOutUpdatePlayerChallenge = 7587 + k_EMsgClientToGCSetPartyLeader = 7588 + k_EMsgClientToGCCancelPartyInvites = 7589 + k_EMsgSQLGrantLeagueMatchToTicketHolders = 7592 + k_EMsgGCToGCEmoticonUnlockNoRollback = 7594 + k_EMsgClientToGCApplyGemCombiner = 7603 + k_EMsgClientToGCGetAllHeroOrder = 7606 + k_EMsgClientToGCGetAllHeroOrderResponse = 7607 + k_EMsgSQLGCToGCGrantBadgePoints = 7608 + k_EMsgGCToGCCheckOwnsEntireEmoticonRange = 7611 + k_EMsgGCToGCCheckOwnsEntireEmoticonRangeResponse = 7612 + k_EMsgGCToClientRequestLaneSelection = 7623 + k_EMsgGCToClientRequestLaneSelectionResponse = 7624 + k_EMsgServerToGCCavernCrawlIsHeroActive = 7625 + k_EMsgServerToGCCavernCrawlIsHeroActiveResponse = 7626 + k_EMsgClientToGCPlayerCardSpecificPurchaseRequest = 7627 + k_EMsgClientToGCPlayerCardSpecificPurchaseResponse = 7628 + k_EMsgGCtoServerTensorflowInstance = 7629 + k_EMsgSQLSetIsLeagueAdmin = 7630 + k_EMsgGCToGCGetLiveLeagueMatches = 7631 + k_EMsgGCToGCGetLiveLeagueMatchesResponse = 7632 + k_EMsgDOTALeagueInfoListAdminsRequest = 7633 + k_EMsgDOTALeagueInfoListAdminsReponse = 7634 + k_EMsgGCToGCLeagueMatchStarted = 7645 + k_EMsgGCToGCLeagueMatchCompleted = 7646 + k_EMsgGCToGCLeagueMatchStartedResponse = 7647 + k_EMsgDOTALeagueAvailableLobbyNodesRequest = 7650 + k_EMsgDOTALeagueAvailableLobbyNodes = 7651 + k_EMsgGCToGCLeagueRequest = 7652 + k_EMsgGCToGCLeagueResponse = 7653 + k_EMsgGCToGCLeagueNodeGroupRequest = 7654 + k_EMsgGCToGCLeagueNodeGroupResponse = 7655 + k_EMsgGCToGCLeagueNodeRequest = 7656 + k_EMsgGCToGCLeagueNodeResponse = 7657 + k_EMsgGCToGCRealtimeStatsTerseRequest = 7658 + k_EMsgGCToGCRealtimeStatsTerseResponse = 7659 + k_EMsgGCToGCGetTopMatchesRequest = 7660 + k_EMsgGCToGCGetTopMatchesResponse = 7661 + k_EMsgClientToGCGetFilteredPlayers = 7662 + k_EMsgGCToClientGetFilteredPlayersResponse = 7663 + k_EMsgClientToGCRemoveFilteredPlayer = 7664 + k_EMsgGCToClientRemoveFilteredPlayerResponse = 7665 + k_EMsgGCToClientPlayerBeaconState = 7666 + k_EMsgGCToClientPartyBeaconUpdate = 7667 + k_EMsgGCToClientPartySearchInvite = 7668 + k_EMsgClientToGCUpdatePartyBeacon = 7669 + k_EMsgClientToGCRequestActiveBeaconParties = 7670 + k_EMsgGCToClientRequestActiveBeaconPartiesResponse = 7671 + k_EMsgClientToGCManageFavorites = 7672 + k_EMsgGCToClientManageFavoritesResponse = 7673 + k_EMsgClientToGCJoinPartyFromBeacon = 7674 + k_EMsgGCToClientJoinPartyFromBeaconResponse = 7675 + k_EMsgClientToGCGetFavoritePlayers = 7676 + k_EMsgGCToClientGetFavoritePlayersResponse = 7677 + k_EMsgClientToGCVerifyFavoritePlayers = 7678 + k_EMsgGCToClientVerifyFavoritePlayersResponse = 7679 + k_EMsgGCToClientPartySearchInvites = 7680 + k_EMsgGCToClientRequestMMInfo = 7681 + k_EMsgClientToGCMMInfo = 7682 + k_EMsgSignOutTextMuteInfo = 7683 + k_EMsgClientToGCPurchaseLabyrinthBlessings = 7684 + k_EMsgClientToGCPurchaseLabyrinthBlessingsResponse = 7685 + k_EMsgClientToGCPurchaseFilteredPlayerSlot = 7686 + k_EMsgGCToClientPurchaseFilteredPlayerSlotResponse = 7687 + k_EMsgClientToGCUpdateFilteredPlayerNote = 7688 + k_EMsgGCToClientUpdateFilteredPlayerNoteResponse = 7689 + k_EMsgClientToGCClaimSwag = 7690 + k_EMsgGCToClientClaimSwagResponse = 7691 + k_EMsgServerToGCLockCharmTrading = 8004 + k_EMsgClientToGCPlayerStatsRequest = 8006 + k_EMsgGCToClientPlayerStatsResponse = 8007 + k_EMsgGCClearPracticeLobbyTeam = 8008 + k_EMsgClientToGCFindTopSourceTVGames = 8009 + k_EMsgGCToClientFindTopSourceTVGamesResponse = 8010 + k_EMsgGCLobbyList = 8011 + k_EMsgGCLobbyListResponse = 8012 + k_EMsgGCPlayerStatsMatchSignOut = 8013 + k_EMsgClientToGCSocialFeedPostCommentRequest = 8016 + k_EMsgGCToClientSocialFeedPostCommentResponse = 8017 + k_EMsgClientToGCCustomGamesFriendsPlayedRequest = 8018 + k_EMsgGCToClientCustomGamesFriendsPlayedResponse = 8019 + k_EMsgClientToGCFriendsPlayedCustomGameRequest = 8020 + k_EMsgGCToClientFriendsPlayedCustomGameResponse = 8021 + k_EMsgGCTopCustomGamesList = 8024 + k_EMsgClientToGCSetPartyOpen = 8029 + k_EMsgClientToGCMergePartyInvite = 8030 + k_EMsgGCToClientMergeGroupInviteReply = 8031 + k_EMsgClientToGCMergePartyResponse = 8032 + k_EMsgGCToClientMergePartyResponseReply = 8033 + k_EMsgClientToGCGetProfileCardStats = 8034 + k_EMsgClientToGCGetProfileCardStatsResponse = 8035 + k_EMsgClientToGCTopLeagueMatchesRequest = 8036 + k_EMsgClientToGCTopFriendMatchesRequest = 8037 + k_EMsgGCToClientProfileCardStatsUpdated = 8040 + k_EMsgServerToGCRealtimeStats = 8041 + k_EMsgGCToServerRealtimeStatsStartStop = 8042 + k_EMsgGCToGCGetServersForClients = 8045 + k_EMsgGCToGCGetServersForClientsResponse = 8046 + k_EMsgGCPracticeLobbyKickFromTeam = 8047 + k_EMsgDOTAChatGetMemberCount = 8048 + k_EMsgDOTAChatGetMemberCountResponse = 8049 + k_EMsgClientToGCSocialFeedPostMessageRequest = 8050 + k_EMsgGCToClientSocialFeedPostMessageResponse = 8051 + k_EMsgCustomGameListenServerStartedLoading = 8052 + k_EMsgCustomGameClientFinishedLoading = 8053 + k_EMsgGCPracticeLobbyCloseBroadcastChannel = 8054 + k_EMsgGCStartFindingMatchResponse = 8055 + k_EMsgSQLGCToGCGrantAccountFlag = 8057 + k_EMsgGCToClientTopLeagueMatchesResponse = 8061 + k_EMsgGCToClientTopFriendMatchesResponse = 8062 + k_EMsgClientToGCMatchesMinimalRequest = 8063 + k_EMsgClientToGCMatchesMinimalResponse = 8064 + k_EMsgGCToClientChatRegionsEnabled = 8067 + k_EMsgClientToGCPingData = 8068 + k_EMsgGCToGCEnsureAccountInParty = 8071 + k_EMsgGCToGCEnsureAccountInPartyResponse = 8072 + k_EMsgClientToGCGetProfileTickets = 8073 + k_EMsgClientToGCGetProfileTicketsResponse = 8074 + k_EMsgGCToClientMatchGroupsVersion = 8075 + k_EMsgClientToGCH264Unsupported = 8076 + k_EMsgClientToGCGetQuestProgress = 8078 + k_EMsgClientToGCGetQuestProgressResponse = 8079 + k_EMsgSignOutXPCoins = 8080 + k_EMsgGCToClientMatchSignedOut = 8081 + k_EMsgGCGetHeroStatsHistory = 8082 + k_EMsgGCGetHeroStatsHistoryResponse = 8083 + k_EMsgClientToGCPrivateChatInvite = 8084 + k_EMsgClientToGCPrivateChatKick = 8088 + k_EMsgClientToGCPrivateChatPromote = 8089 + k_EMsgClientToGCPrivateChatDemote = 8090 + k_EMsgGCToClientPrivateChatResponse = 8091 + k_EMsgClientToGCLatestConductScorecardRequest = 8095 + k_EMsgClientToGCLatestConductScorecard = 8096 + k_EMsgClientToGCWageringRequest = 8099 + k_EMsgGCToClientWageringResponse = 8100 + k_EMsgClientToGCEventGoalsRequest = 8103 + k_EMsgClientToGCEventGoalsResponse = 8104 + k_EMsgGCToGCLeaguePredictionsUpdate = 8108 + k_EMsgGCToGCAddUserToPostGameChat = 8110 + k_EMsgClientToGCHasPlayerVotedForMVP = 8111 + k_EMsgClientToGCHasPlayerVotedForMVPResponse = 8112 + k_EMsgClientToGCVoteForMVP = 8113 + k_EMsgClientToGCVoteForMVPResponse = 8114 + k_EMsgGCToGCGetEventOwnership = 8115 + k_EMsgGCToGCGetEventOwnershipResponse = 8116 + k_EMsgGCToClientAutomatedTournamentStateChange = 8117 + k_EMsgClientToGCWeekendTourneyOpts = 8118 + k_EMsgClientToGCWeekendTourneyOptsResponse = 8119 + k_EMsgClientToGCWeekendTourneyLeave = 8120 + k_EMsgClientToGCWeekendTourneyLeaveResponse = 8121 + k_EMsgClientToGCTeammateStatsRequest = 8124 + k_EMsgClientToGCTeammateStatsResponse = 8125 + k_EMsgClientToGCGetGiftPermissions = 8126 + k_EMsgClientToGCGetGiftPermissionsResponse = 8127 + k_EMsgClientToGCVoteForArcana = 8128 + k_EMsgClientToGCVoteForArcanaResponse = 8129 + k_EMsgClientToGCRequestArcanaVotesRemaining = 8130 + k_EMsgClientToGCRequestArcanaVotesRemainingResponse = 8131 + k_EMsgGCTransferTeamAdminResponse = 8132 + k_EMsgGCToClientTeamInfo = 8135 + k_EMsgGCToClientTeamsInfo = 8136 + k_EMsgClientToGCMyTeamInfoRequest = 8137 + k_EMsgClientToGCPublishUserStat = 8140 + k_EMsgGCToGCSignoutSpendWager = 8141 + k_EMsgGCSubmitLobbyMVPVote = 8144 + k_EMsgGCSubmitLobbyMVPVoteResponse = 8145 + k_EMsgSignOutCommunityGoalProgress = 8150 + k_EMsgGCToClientLobbyMVPAwarded = 8152 + k_EMsgGCToClientQuestProgressUpdated = 8153 + k_EMsgGCToClientWageringUpdate = 8154 + k_EMsgGCToClientArcanaVotesUpdate = 8155 + k_EMsgClientToGCSetSpectatorLobbyDetails = 8157 + k_EMsgClientToGCSetSpectatorLobbyDetailsResponse = 8158 + k_EMsgClientToGCCreateSpectatorLobby = 8159 + k_EMsgClientToGCCreateSpectatorLobbyResponse = 8160 + k_EMsgClientToGCSpectatorLobbyList = 8161 + k_EMsgClientToGCSpectatorLobbyListResponse = 8162 + k_EMsgSpectatorLobbyGameDetails = 8163 + k_EMsgServerToGCCompendiumInGamePredictionResults = 8166 + k_EMsgServerToGCCloseCompendiumInGamePredictionVoting = 8167 + k_EMsgClientToGCOpenPlayerCardPack = 8168 + k_EMsgClientToGCOpenPlayerCardPackResponse = 8169 + k_EMsgClientToGCSelectCompendiumInGamePrediction = 8170 + k_EMsgClientToGCSelectCompendiumInGamePredictionResponse = 8171 + k_EMsgClientToGCWeekendTourneyGetPlayerStats = 8172 + k_EMsgClientToGCWeekendTourneyGetPlayerStatsResponse = 8173 + k_EMsgClientToGCRecyclePlayerCard = 8174 + k_EMsgClientToGCRecyclePlayerCardResponse = 8175 + k_EMsgClientToGCCreatePlayerCardPack = 8176 + k_EMsgClientToGCCreatePlayerCardPackResponse = 8177 + k_EMsgClientToGCGetPlayerCardRosterRequest = 8178 + k_EMsgClientToGCGetPlayerCardRosterResponse = 8179 + k_EMsgClientToGCSetPlayerCardRosterRequest = 8180 + k_EMsgClientToGCSetPlayerCardRosterResponse = 8181 + k_EMsgServerToGCCloseCompendiumInGamePredictionVotingResponse = 8183 + k_EMsgLobbyBattleCupVictory = 8186 + k_EMsgGCGetPlayerCardItemInfo = 8187 + k_EMsgGCGetPlayerCardItemInfoResponse = 8188 + k_EMsgClientToGCRequestSteamDatagramTicket = 8189 + k_EMsgClientToGCRequestSteamDatagramTicketResponse = 8190 + k_EMsgGCToClientBattlePassRollupRequest = 8191 + k_EMsgGCToClientBattlePassRollupResponse = 8192 + k_EMsgClientToGCTransferSeasonalMMRRequest = 8193 + k_EMsgClientToGCTransferSeasonalMMRResponse = 8194 + k_EMsgGCToGCPublicChatCommunicationBan = 8195 + k_EMsgGCToGCUpdateAccountInfo = 8196 + k_EMsgGCChatReportPublicSpam = 8197 + k_EMsgClientToGCSetPartyBuilderOptions = 8198 + k_EMsgClientToGCSetPartyBuilderOptionsResponse = 8199 + k_EMsgGCToClientPlaytestStatus = 8200 + k_EMsgClientToGCJoinPlaytest = 8201 + k_EMsgClientToGCJoinPlaytestResponse = 8202 + k_EMsgLobbyPlaytestDetails = 8203 + k_EMsgDOTASetFavoriteTeam = 8204 + k_EMsgGCToClientBattlePassRollupListRequest = 8205 + k_EMsgGCToClientBattlePassRollupListResponse = 8206 + k_EMsgDOTAClaimEventAction = 8209 + k_EMsgDOTAClaimEventActionResponse = 8210 + k_EMsgDOTAGetPeriodicResource = 8211 + k_EMsgDOTAGetPeriodicResourceResponse = 8212 + k_EMsgDOTAPeriodicResourceUpdated = 8213 + k_EMsgServerToGCSpendWager = 8214 + k_EMsgGCToGCSignoutSpendWagerToken = 8215 + k_EMsgSubmitTriviaQuestionAnswer = 8216 + k_EMsgSubmitTriviaQuestionAnswerResponse = 8217 + k_EMsgClientToGCGiveTip = 8218 + k_EMsgClientToGCGiveTipResponse = 8219 + k_EMsgStartTriviaSession = 8220 + k_EMsgStartTriviaSessionResponse = 8221 + k_EMsgAnchorPhoneNumberRequest = 8222 + k_EMsgAnchorPhoneNumberResponse = 8223 + k_EMsgUnanchorPhoneNumberRequest = 8224 + k_EMsgUnanchorPhoneNumberResponse = 8225 + k_EMsgGCToGCSignoutSpendRankWager = 8229 + k_EMsgGCToGCGetFavoriteTeam = 8230 + k_EMsgGCToGCGetFavoriteTeamResponse = 8231 + k_EMsgSignOutEventGameData = 8232 + k_EMsgClientToGCQuickStatsRequest = 8238 + k_EMsgClientToGCQuickStatsResponse = 8239 + k_EMsgGCToGCSubtractEventPointsFromUser = 8240 + k_EMsgSelectionPriorityChoiceRequest = 8241 + k_EMsgSelectionPriorityChoiceResponse = 8242 + k_EMsgGCToGCCompendiumInGamePredictionResults = 8243 + k_EMsgGameAutographReward = 8244 + k_EMsgGameAutographRewardResponse = 8245 + k_EMsgDestroyLobbyRequest = 8246 + k_EMsgDestroyLobbyResponse = 8247 + k_EMsgPurchaseItemWithEventPoints = 8248 + k_EMsgPurchaseItemWithEventPointsResponse = 8249 + k_EMsgServerToGCMatchPlayerItemPurchaseHistory = 8250 + k_EMsgGCToGCGrantPlusHeroMatchResults = 8251 + k_EMsgServerToGCMatchStateHistory = 8255 + k_EMsgPurchaseHeroRandomRelic = 8258 + k_EMsgPurchaseHeroRandomRelicResponse = 8259 + k_EMsgClientToGCClaimEventActionUsingItem = 8260 + k_EMsgClientToGCClaimEventActionUsingItemResponse = 8261 + k_EMsgPartyReadyCheckRequest = 8262 + k_EMsgPartyReadyCheckResponse = 8263 + k_EMsgPartyReadyCheckAcknowledge = 8264 + k_EMsgGetRecentPlayTimeFriendsRequest = 8265 + k_EMsgGetRecentPlayTimeFriendsResponse = 8266 + k_EMsgGCToClientCommendNotification = 8267 + k_EMsgProfileRequest = 8268 + k_EMsgProfileResponse = 8269 + k_EMsgProfileUpdate = 8270 + k_EMsgProfileUpdateResponse = 8271 + k_EMsgHeroGlobalDataRequest = 8274 + k_EMsgHeroGlobalDataResponse = 8275 + k_EMsgClientToGCRequestPlusWeeklyChallengeResult = 8276 + k_EMsgClientToGCRequestPlusWeeklyChallengeResultResponse = 8277 + k_EMsgGCToGCGrantPlusPrepaidTime = 8278 + k_EMsgPrivateMetadataKeyRequest = 8279 + k_EMsgPrivateMetadataKeyResponse = 8280 + k_EMsgGCToGCReconcilePlusStatus = 8281 + k_EMsgGCToGCCheckPlusStatus = 8282 + k_EMsgGCToGCCheckPlusStatusResponse = 8283 + k_EMsgGCToGCReconcilePlusAutoGrantItems = 8284 + k_EMsgGCToGCReconcilePlusStatusUnreliable = 8285 + k_EMsgGCToClientCavernCrawlMapPathCompleted = 8288 + k_EMsgClientToGCCavernCrawlClaimRoom = 8289 + k_EMsgClientToGCCavernCrawlClaimRoomResponse = 8290 + k_EMsgClientToGCCavernCrawlUseItemOnRoom = 8291 + k_EMsgClientToGCCavernCrawlUseItemOnRoomResponse = 8292 + k_EMsgClientToGCCavernCrawlUseItemOnPath = 8293 + k_EMsgClientToGCCavernCrawlUseItemOnPathResponse = 8294 + k_EMsgClientToGCCavernCrawlRequestMapState = 8295 + k_EMsgClientToGCCavernCrawlRequestMapStateResponse = 8296 + k_EMsgSignOutTips = 8297 + k_EMsgClientToGCRequestEventPointLogV2 = 8298 + k_EMsgClientToGCRequestEventPointLogResponseV2 = 8299 + k_EMsgClientToGCRequestEventTipsSummary = 8300 + k_EMsgClientToGCRequestEventTipsSummaryResponse = 8301 + k_EMsgClientToGCRequestSocialFeed = 8303 + k_EMsgClientToGCRequestSocialFeedResponse = 8304 + k_EMsgClientToGCRequestSocialFeedComments = 8305 + k_EMsgClientToGCRequestSocialFeedCommentsResponse = 8306 + k_EMsgClientToGCCavernCrawlGetClaimedRoomCount = 8308 + k_EMsgClientToGCCavernCrawlGetClaimedRoomCountResponse = 8309 + k_EMsgGCToGCReconcilePlusAutoGrantItemsUnreliable = 8310 + k_EMsgServerToGCAddBroadcastTimelineEvent = 8311 + k_EMsgGCToServerUpdateSteamBroadcasting = 8312 + k_EMsgClientToGCRecordContestVote = 8313 + k_EMsgGCToClientRecordContestVoteResponse = 8314 + k_EMsgGCToGCGrantAutograph = 8315 + k_EMsgGCToGCGrantAutographResponse = 8316 + k_EMsgSignOutConsumableUsage = 8317 + k_EMsgLobbyEventGameDetails = 8318 + k_EMsgDevGrantEventPoints = 8319 + k_EMsgDevGrantEventPointsResponse = 8320 + k_EMsgDevGrantEventAction = 8321 + k_EMsgDevGrantEventActionResponse = 8322 + k_EMsgDevResetEventState = 8323 + k_EMsgDevResetEventStateResponse = 8324 + k_EMsgGCToGCReconcileEventOwnership = 8325 + k_EMsgConsumeEventSupportGrantItem = 8326 + k_EMsgConsumeEventSupportGrantItemResponse = 8327 + k_EMsgGCToClientClaimEventActionUsingItemCompleted = 8328 + k_EMsgGCToClientCavernCrawlMapUpdated = 8329 + k_EMsgServerToGCRequestPlayerRecentAccomplishments = 8330 + k_EMsgServerToGCRequestPlayerRecentAccomplishmentsResponse = 8331 + k_EMsgClientToGCRequestPlayerRecentAccomplishments = 8332 + k_EMsgClientToGCRequestPlayerRecentAccomplishmentsResponse = 8333 + k_EMsgClientToGCRequestPlayerHeroRecentAccomplishments = 8334 + k_EMsgClientToGCRequestPlayerHeroRecentAccomplishmentsResponse = 8335 + k_EMsgSignOutEventActionGrants = 8336 + k_EMsgClientToGCRequestPlayerCoachMatches = 8337 + k_EMsgClientToGCRequestPlayerCoachMatchesResponse = 8338 + k_EMsgClientToGCSubmitCoachTeammateRating = 8341 + k_EMsgClientToGCSubmitCoachTeammateRatingResponse = 8342 + k_EMsgGCToClientCoachTeammateRatingsChanged = 8343 + k_EMsgClientToGCRequestPlayerCoachMatch = 8345 + k_EMsgClientToGCRequestPlayerCoachMatchResponse = 8346 + k_EMsgClientToGCRequestContestVotes = 8347 + k_EMsgClientToGCRequestContestVotesResponse = 8348 + k_EMsgClientToGCMVPVoteTimeout = 8349 + k_EMsgClientToGCMVPVoteTimeoutResponse = 8350 + k_EMsgMatchMatchmakingStats = 8360 + k_EMsgClientToGCSubmitPlayerMatchSurvey = 8361 + k_EMsgClientToGCSubmitPlayerMatchSurveyResponse = 8362 + k_EMsgSQLGCToGCGrantAllHeroProgressAccount = 8363 + k_EMsgSQLGCToGCGrantAllHeroProgressVictory = 8364 + k_EMsgDevDeleteEventActions = 8365 + k_EMsgDevDeleteEventActionsResponse = 8366 + k_EMsgGCToGCGetAllHeroCurrent = 8635 + k_EMsgGCToGCGetAllHeroCurrentResponse = 8636 + k_EMsgGCSubmitPlayerAvoidRequest = 8637 + k_EMsgGCSubmitPlayerAvoidRequestResponse = 8638 + k_EMsgGCToClientNotificationsUpdated = 8639 + k_EMsgGCtoGCAssociatedExploiterAccountInfo = 8640 + k_EMsgGCtoGCAssociatedExploiterAccountInfoResponse = 8641 + k_EMsgGCtoGCRequestRecalibrationCheck = 8642 + k_EMsgGCToClientVACReminder = 8643 + k_EMsgClientToGCUnderDraftBuy = 8644 + k_EMsgClientToGCUnderDraftBuyResponse = 8645 + k_EMsgClientToGCUnderDraftReroll = 8646 + k_EMsgClientToGCUnderDraftRerollResponse = 8647 + k_EMsgNeutralItemStats = 8648 + k_EMsgClientToGCCreateGuild = 8649 + k_EMsgClientToGCCreateGuildResponse = 8650 + k_EMsgClientToGCSetGuildInfo = 8651 + k_EMsgClientToGCSetGuildInfoResponse = 8652 + k_EMsgClientToGCAddGuildRole = 8653 + k_EMsgClientToGCAddGuildRoleResponse = 8654 + k_EMsgClientToGCModifyGuildRole = 8655 + k_EMsgClientToGCModifyGuildRoleResponse = 8656 + k_EMsgClientToGCRemoveGuildRole = 8657 + k_EMsgClientToGCRemoveGuildRoleResponse = 8658 + k_EMsgClientToGCJoinGuild = 8659 + k_EMsgClientToGCJoinGuildResponse = 8660 + k_EMsgClientToGCLeaveGuild = 8661 + k_EMsgClientToGCLeaveGuildResponse = 8662 + k_EMsgClientToGCInviteToGuild = 8663 + k_EMsgClientToGCInviteToGuildResponse = 8664 + k_EMsgClientToGCDeclineInviteToGuild = 8665 + k_EMsgClientToGCDeclineInviteToGuildResponse = 8666 + k_EMsgClientToGCCancelInviteToGuild = 8667 + k_EMsgClientToGCCancelInviteToGuildResponse = 8668 + k_EMsgClientToGCKickGuildMember = 8669 + k_EMsgClientToGCKickGuildMemberResponse = 8670 + k_EMsgClientToGCSetGuildMemberRole = 8671 + k_EMsgClientToGCSetGuildMemberRoleResponse = 8672 + k_EMsgClientToGCRequestGuildData = 8673 + k_EMsgClientToGCRequestGuildDataResponse = 8674 + k_EMsgGCToClientGuildDataUpdated = 8675 + k_EMsgClientToGCRequestGuildMembership = 8676 + k_EMsgClientToGCRequestGuildMembershipResponse = 8677 + k_EMsgGCToClientGuildMembershipUpdated = 8678 + k_EMsgClientToGCAcceptInviteToGuild = 8681 + k_EMsgClientToGCAcceptInviteToGuildResponse = 8682 + k_EMsgClientToGCSetGuildRoleOrder = 8683 + k_EMsgClientToGCSetGuildRoleOrderResponse = 8684 + k_EMsgClientToGCRequestGuildFeed = 8685 + k_EMsgClientToGCRequestGuildFeedResponse = 8686 + k_EMsgClientToGCRequestAccountGuildEventData = 8687 + k_EMsgClientToGCRequestAccountGuildEventDataResponse = 8688 + k_EMsgGCToClientAccountGuildEventDataUpdated = 8689 + k_EMsgClientToGCRequestActiveGuildContracts = 8690 + k_EMsgClientToGCRequestActiveGuildContractsResponse = 8691 + k_EMsgGCToClientActiveGuildContractsUpdated = 8692 + k_EMsgGCToClientGuildFeedUpdated = 8693 + k_EMsgClientToGCSelectGuildContract = 8694 + k_EMsgClientToGCSelectGuildContractResponse = 8695 + k_EMsgGCToGCCompleteGuildContracts = 8696 + k_EMsgClientToGCAddPlayerToGuildChat = 8698 + k_EMsgClientToGCAddPlayerToGuildChatResponse = 8699 + k_EMsgClientToGCUnderDraftSell = 8700 + k_EMsgClientToGCUnderDraftSellResponse = 8701 + k_EMsgClientToGCUnderDraftRequest = 8702 + k_EMsgClientToGCUnderDraftResponse = 8703 + k_EMsgClientToGCUnderDraftRedeemReward = 8704 + k_EMsgClientToGCUnderDraftRedeemRewardResponse = 8705 + k_EMsgGCToServerLobbyHeroBanRates = 8708 + k_EMsgSignOutGuildContractProgress = 8711 + k_EMsgSignOutMVPStats = 8712 + k_EMsgClientToGCRequestActiveGuildChallenge = 8713 + k_EMsgClientToGCRequestActiveGuildChallengeResponse = 8714 + k_EMsgGCToClientActiveGuildChallengeUpdated = 8715 + k_EMsgClientToGCRequestReporterUpdates = 8716 + k_EMsgClientToGCRequestReporterUpdatesResponse = 8717 + k_EMsgClientToGCAcknowledgeReporterUpdates = 8718 + k_EMsgSignOutGuildChallengeProgress = 8720 + k_EMsgClientToGCRequestGuildEventMembers = 8721 + k_EMsgClientToGCRequestGuildEventMembersResponse = 8722 + k_EMsgClientToGCReportGuildContent = 8725 + k_EMsgClientToGCReportGuildContentResponse = 8726 + k_EMsgClientToGCRequestAccountGuildPersonaInfo = 8727 + k_EMsgClientToGCRequestAccountGuildPersonaInfoResponse = 8728 + k_EMsgClientToGCRequestAccountGuildPersonaInfoBatch = 8729 + k_EMsgClientToGCRequestAccountGuildPersonaInfoBatchResponse = 8730 + k_EMsgGCToClientUnderDraftGoldUpdated = 8731 + k_EMsgGCToServerRecordTrainingData = 8732 + k_EMsgSignOutBounties = 8733 + k_EMsgLobbyFeaturedGamemodeProgress = 8734 + k_EMsgLobbyGauntletProgress = 8735 + k_EMsgClientToGCSubmitDraftTriviaMatchAnswer = 8736 + k_EMsgClientToGCSubmitDraftTriviaMatchAnswerResponse = 8737 + k_EMsgGCToGCSignoutSpendBounty = 8738 + k_EMsgClientToGCApplyGauntletTicket = 8739 + k_EMsgClientToGCUnderDraftRollBackBench = 8740 + k_EMsgClientToGCUnderDraftRollBackBenchResponse = 8741 + k_EMsgGCToGCGetEventActionScore = 8742 + k_EMsgGCToGCGetEventActionScoreResponse = 8743 + k_EMsgServerToGCGetGuildContracts = 8744 + k_EMsgServerToGCGetGuildContractsResponse = 8745 + k_EMsgLobbyEventGameData = 8746 + k_EMsgGCToClientGuildMembersDataUpdated = 8747 + k_EMsgSignOutReportActivityMarkers = 8748 + k_EMsgSignOutDiretideCandy = 8749 + k_EMsgGCToClientPostGameItemAwardNotification = 8750 + k_EMsgClientToGCGetOWMatchDetails = 8751 + k_EMsgClientToGCGetOWMatchDetailsResponse = 8752 + k_EMsgClientToGCSubmitOWConviction = 8753 + k_EMsgClientToGCSubmitOWConvictionResponse = 8754 + k_EMsgGCToGCGetAccountSteamChina = 8755 + k_EMsgGCToGCGetAccountSteamChinaResponse = 8756 + k_EMsgClientToGCClaimLeaderboardRewards = 8757 + k_EMsgClientToGCClaimLeaderboardRewardsResponse = 8758 + k_EMsgClientToGCRecalibrateMMR = 8759 + k_EMsgClientToGCRecalibrateMMRResponse = 8760 + k_EMsgGCToGCGrantEventPointActionList = 8761 + k_EMsgClientToGCChinaSSAURLRequest = 8764 + k_EMsgClientToGCChinaSSAURLResponse = 8765 + k_EMsgClientToGCChinaSSAAcceptedRequest = 8766 + k_EMsgClientToGCChinaSSAAcceptedResponse = 8767 + k_EMsgSignOutOverwatchSuspicion = 8768 + k_EMsgServerToGCGetSuspicionConfig = 8769 + k_EMsgServerToGCGetSuspicionConfigResponse = 8770 + k_EMsgGCToGCGrantPlusHeroChallengeMatchResults = 8771 + k_EMsgGCToClientOverwatchCasesAvailable = 8772 + k_EMsgServerToGCAccountCheck = 8773 + k_EMsgClientToGCStartWatchingOverwatch = 8774 + k_EMsgClientToGCStopWatchingOverwatch = 8775 + k_EMsgSignOutPerfData = 8776 + k_EMsgClientToGCGetDPCFavorites = 8777 + k_EMsgClientToGCGetDPCFavoritesResponse = 8778 + k_EMsgClientToGCSetDPCFavoriteState = 8779 + k_EMsgClientToGCSetDPCFavoriteStateResponse = 8780 + k_EMsgClientToGCOverwatchReplayError = 8781 + k_EMsgServerToGCPlayerChallengeHistory = 8782 + k_EMsgSignOutBanData = 8783 + k_EMsgWebapiDPCSeasonResults = 8784 + k_EMsgClientToGCCoachFriend = 8785 + k_EMsgClientToGCCoachFriendResponse = 8786 + k_EMsgClientToGCRequestPrivateCoachingSession = 8787 + k_EMsgClientToGCRequestPrivateCoachingSessionResponse = 8788 + k_EMsgClientToGCAcceptPrivateCoachingSession = 8789 + k_EMsgClientToGCAcceptPrivateCoachingSessionResponse = 8790 + k_EMsgClientToGCLeavePrivateCoachingSession = 8791 + k_EMsgClientToGCLeavePrivateCoachingSessionResponse = 8792 + k_EMsgClientToGCGetCurrentPrivateCoachingSession = 8793 + k_EMsgClientToGCGetCurrentPrivateCoachingSessionResponse = 8794 + k_EMsgGCToClientPrivateCoachingSessionUpdated = 8795 + k_EMsgClientToGCSubmitPrivateCoachingSessionRating = 8796 + k_EMsgClientToGCSubmitPrivateCoachingSessionRatingResponse = 8797 + k_EMsgClientToGCGetAvailablePrivateCoachingSessions = 8798 + k_EMsgClientToGCGetAvailablePrivateCoachingSessionsResponse = 8799 + k_EMsgClientToGCGetAvailablePrivateCoachingSessionsSummary = 8800 + k_EMsgClientToGCGetAvailablePrivateCoachingSessionsSummaryResponse = 8801 + k_EMsgClientToGCJoinPrivateCoachingSessionLobby = 8802 + k_EMsgClientToGCJoinPrivateCoachingSessionLobbyResponse = 8803 + k_EMsgClientToGCRespondToCoachFriendRequest = 8804 + k_EMsgClientToGCRespondToCoachFriendRequestResponse = 8805 + k_EMsgClientToGCSetEventActiveSeasonID = 8806 + k_EMsgClientToGCSetEventActiveSeasonIDResponse = 8807 + k_EMsgServerToGCMatchPlayerNeutralItemEquipHistory = 8808 + k_EMsgServerToGCCompendiumChosenInGamePredictions = 8809 + k_EMsgClientToGCCreateTeamPlayerCardPack = 8810 + k_EMsgClientToGCCreateTeamPlayerCardPackResponse = 8811 + k_EMsgGCToServerSubmitCheerData = 8812 + k_EMsgGCToServerCheerConfig = 8813 + k_EMsgServerToGCGetCheerConfig = 8814 + k_EMsgServerToGCGetCheerConfigResponse = 8815 + k_EMsgGCToGCGrantAutographByID = 8816 + k_EMsgGCToServerCheerScalesOverride = 8817 + k_EMsgGCToServerGetCheerState = 8818 + k_EMsgServerToGCReportCheerState = 8819 + k_EMsgGCToServerScenarioSave = 8820 + k_EMsgGCToServerAbilityDraftLobbyData = 8821 + k_EMsgSignOutReportCommunications = 8822 + k_EMsgClientToGCBatchGetPlayerCardRosterRequest = 8823 + k_EMsgClientToGCBatchGetPlayerCardRosterResponse = 8824 + k_EMsgClientToGCGetStickerbookRequest = 8825 + k_EMsgClientToGCGetStickerbookResponse = 8826 + k_EMsgClientToGCCreateStickerbookPageRequest = 8827 + k_EMsgClientToGCCreateStickerbookPageResponse = 8828 + k_EMsgClientToGCDeleteStickerbookPageRequest = 8829 + k_EMsgClientToGCDeleteStickerbookPageResponse = 8830 + k_EMsgClientToGCPlaceStickersRequest = 8831 + k_EMsgClientToGCPlaceStickersResponse = 8832 + k_EMsgClientToGCPlaceCollectionStickersRequest = 8833 + k_EMsgClientToGCPlaceCollectionStickersResponse = 8834 + k_EMsgClientToGCOrderStickerbookTeamPageRequest = 8835 + k_EMsgClientToGCOrderStickerbookTeamPageResponse = 8836 + k_EMsgServerToGCGetStickerHeroes = 8837 + k_EMsgServerToGCGetStickerHeroesResponse = 8838 + k_EMsgClientToGCCandyShopGetUserData = 8840 + k_EMsgClientToGCCandyShopGetUserDataResponse = 8841 + k_EMsgGCToClientCandyShopUserDataUpdated = 8842 + k_EMsgClientToGCCandyShopPurchaseReward = 8843 + k_EMsgClientToGCCandyShopPurchaseRewardResponse = 8844 + k_EMsgClientToGCCandyShopDoExchange = 8845 + k_EMsgClientToGCCandyShopDoExchangeResponse = 8846 + k_EMsgClientToGCCandyShopDoVariableExchange = 8847 + k_EMsgClientToGCCandyShopDoVariableExchangeResponse = 8848 + k_EMsgClientToGCCandyShopRerollRewards = 8849 + k_EMsgClientToGCCandyShopRerollRewardsResponse = 8850 + k_EMsgClientToGCSetHeroSticker = 8851 + k_EMsgClientToGCSetHeroStickerResponse = 8852 + k_EMsgClientToGCGetHeroStickers = 8853 + k_EMsgClientToGCGetHeroStickersResponse = 8854 + k_EMsgClientToGCSetFavoritePage = 8855 + k_EMsgClientToGCSetFavoritePageResponse = 8856 + k_EMsgClientToGCCandyShopDevGrantCandy = 8857 + k_EMsgClientToGCCandyShopDevGrantCandyResponse = 8858 + k_EMsgClientToGCCandyShopDevClearInventory = 8859 + k_EMsgClientToGCCandyShopDevClearInventoryResponse = 8860 + k_EMsgClientToGCCandyShopOpenBags = 8861 + k_EMsgClientToGCCandyShopOpenBagsResponse = 8862 + k_EMsgClientToGCCandyShopDevGrantCandyBags = 8863 + k_EMsgClientToGCCandyShopDevGrantCandyBagsResponse = 8864 + k_EMsgClientToGCCandyShopDevShuffleExchange = 8865 + k_EMsgClientToGCCandyShopDevShuffleExchangeResponse = 8866 + k_EMsgClientToGCCandyShopDevGrantRerollCharges = 8867 + k_EMsgClientToGCCandyShopDevGrantRerollChargesResponse = 8868 + k_EMsgLobbyAdditionalAccountData = 8869 + k_EMsgServerToGCLobbyInitialized = 8870 + k_EMsgClientToGCCollectorsCacheAvailableDataRequest = 8871 + k_EMsgGCToClientCollectorsCacheAvailableDataResponse = 8872 + k_EMsgClientToGCUploadMatchClip = 8873 + k_EMsgGCToClientUploadMatchClipResponse = 8874 + k_EMsgGCToServerSetSteamLearnKeysChanged = 8876 + k_EMsgSignOutMuertaMinigame = 8877 + k_EMsgGCToServerLobbyHeroRoleStats = 8878 + k_EMsgClientToGCRankRequest = 8879 + k_EMsgGCToClientRankResponse = 8880 + k_EMsgGCToClientRankUpdate = 8881 + k_EMsgSignOutMapStats = 8882 + k_EMsgClientToGCMapStatsRequest = 8883 + k_EMsgGCToClientMapStatsResponse = 8884 + k_EMsgGCToServerSetSteamLearnInferencing = 8885 + k_EMsgClientToGCShowcaseGetUserData = 8886 + k_EMsgClientToGCShowcaseGetUserDataResponse = 8887 + k_EMsgClientToGCShowcaseSetUserData = 8888 + k_EMsgClientToGCShowcaseSetUserDataResponse = 8889 + k_EMsgClientToGCFantasyCraftingGetData = 8890 + k_EMsgClientToGCFantasyCraftingGetDataResponse = 8891 + k_EMsgClientToGCFantasyCraftingPerformOperation = 8892 + k_EMsgClientToGCFantasyCraftingPerformOperationResponse = 8893 + k_EMsgGCToClientFantasyCraftingGetDataUpdated = 8894 + k_EMsgClientToGCFantasyCraftingDevModifyTablet = 8895 + k_EMsgClientToGCFantasyCraftingDevModifyTabletResponse = 8896 + k_EMsgClientToGCRoadToTIGetQuests = 8897 + k_EMsgClientToGCRoadToTIGetQuestsResponse = 8898 + k_EMsgClientToGCRoadToTIGetActiveQuest = 8899 + k_EMsgClientToGCRoadToTIGetActiveQuestResponse = 8900 + k_EMsgClientToGCBingoGetUserData = 8901 + k_EMsgClientToGCBingoGetUserDataResponse = 8902 + k_EMsgClientToGCBingoClaimRow = 8903 + k_EMsgClientToGCBingoClaimRowResponse = 8904 + k_EMsgClientToGCBingoDevRerollCard = 8905 + k_EMsgClientToGCBingoDevRerollCardResponse = 8906 + k_EMsgClientToGCBingoGetStatsData = 8907 + k_EMsgClientToGCBingoGetStatsDataResponse = 8908 + k_EMsgGCToClientBingoUserDataUpdated = 8909 + k_EMsgGCToClientRoadToTIQuestDataUpdated = 8910 + k_EMsgClientToGCRoadToTIUseItem = 8911 + k_EMsgClientToGCRoadToTIUseItemResponse = 8912 + k_EMsgClientToGCShowcaseSubmitReport = 8913 + k_EMsgClientToGCShowcaseSubmitReportResponse = 8914 + k_EMsgClientToGCShowcaseAdminGetReportsRollupList = 8915 + k_EMsgClientToGCShowcaseAdminGetReportsRollupListResponse = 8916 + k_EMsgClientToGCShowcaseAdminGetReportsRollup = 8917 + k_EMsgClientToGCShowcaseAdminGetReportsRollupResponse = 8918 + k_EMsgClientToGCShowcaseAdminGetUserDetails = 8919 + k_EMsgClientToGCShowcaseAdminGetUserDetailsResponse = 8920 + k_EMsgClientToGCShowcaseAdminConvict = 8921 + k_EMsgClientToGCShowcaseAdminConvictResponse = 8922 + k_EMsgClientToGCShowcaseAdminExonerate = 8923 + k_EMsgClientToGCShowcaseAdminExonerateResponse = 8924 + k_EMsgClientToGCShowcaseAdminReset = 8925 + k_EMsgClientToGCShowcaseAdminResetResponse = 8926 + k_EMsgClientToGCShowcaseAdminLockAccount = 8927 + k_EMsgClientToGCShowcaseAdminLockAccountResponse = 8928 + k_EMsgClientToGCFantasyCraftingSelectPlayer = 8929 + k_EMsgClientToGCFantasyCraftingSelectPlayerResponse = 8930 + k_EMsgClientToGCFantasyCraftingGenerateTablets = 8931 + k_EMsgClientToGCFantasyCraftingGenerateTabletsResponse = 8932 + k_EMsgClientToGcFantasyCraftingUpgradeTablets = 8933 + k_EMsgClientToGcFantasyCraftingUpgradeTabletsResponse = 8934 + k_EMsgClientToGCFantasyCraftingRerollOptions = 8936 + k_EMsgClientToGCFantasyCraftingRerollOptionsResponse = 8937 + k_EMsgClientToGCRoadToTIDevForceQuest = 8935 + k_EMsgLobbyRoadToTIMatchQuestData = 8939 + k_EMsgClientToGCShowcaseModerationGetQueue = 8940 + k_EMsgClientToGCShowcaseModerationGetQueueResponse = 8941 + k_EMsgClientToGCShowcaseModerationApplyModeration = 8942 + k_EMsgClientToGCShowcaseModerationApplyModerationResponse = 8943 diff --git a/steam/ext/dota2/protobufs/dota_shared_enums.py b/steam/ext/dota2/protobufs/dota_shared_enums.py new file mode 100644 index 00000000..9553f196 --- /dev/null +++ b/steam/ext/dota2/protobufs/dota_shared_enums.py @@ -0,0 +1,838 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_shared_enums.proto +# plugin: python-betterproto +from __future__ import annotations + +from dataclasses import dataclass + +import betterproto + + +class DOTA_GameMode(betterproto.Enum): + DOTA_GAMEMODE_NONE = 0 + DOTA_GAMEMODE_AP = 1 + DOTA_GAMEMODE_CM = 2 + DOTA_GAMEMODE_RD = 3 + DOTA_GAMEMODE_SD = 4 + DOTA_GAMEMODE_AR = 5 + DOTA_GAMEMODE_INTRO = 6 + DOTA_GAMEMODE_HW = 7 + DOTA_GAMEMODE_REVERSE_CM = 8 + DOTA_GAMEMODE_XMAS = 9 + DOTA_GAMEMODE_TUTORIAL = 10 + DOTA_GAMEMODE_MO = 11 + DOTA_GAMEMODE_LP = 12 + DOTA_GAMEMODE_POOL1 = 13 + DOTA_GAMEMODE_FH = 14 + DOTA_GAMEMODE_CUSTOM = 15 + DOTA_GAMEMODE_CD = 16 + DOTA_GAMEMODE_BD = 17 + DOTA_GAMEMODE_ABILITY_DRAFT = 18 + DOTA_GAMEMODE_EVENT = 19 + DOTA_GAMEMODE_ARDM = 20 + DOTA_GAMEMODE_1V1MID = 21 + DOTA_GAMEMODE_ALL_DRAFT = 22 + DOTA_GAMEMODE_TURBO = 23 + DOTA_GAMEMODE_MUTATION = 24 + DOTA_GAMEMODE_COACHES_CHALLENGE = 25 + + +class DOTA_GameState(betterproto.Enum): + DOTA_GAMERULES_STATE_INIT = 0 + DOTA_GAMERULES_STATE_WAIT_FOR_PLAYERS_TO_LOAD = 1 + DOTA_GAMERULES_STATE_HERO_SELECTION = 2 + DOTA_GAMERULES_STATE_STRATEGY_TIME = 3 + DOTA_GAMERULES_STATE_PRE_GAME = 4 + DOTA_GAMERULES_STATE_GAME_IN_PROGRESS = 5 + DOTA_GAMERULES_STATE_POST_GAME = 6 + DOTA_GAMERULES_STATE_DISCONNECT = 7 + DOTA_GAMERULES_STATE_TEAM_SHOWCASE = 8 + DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP = 9 + DOTA_GAMERULES_STATE_WAIT_FOR_MAP_TO_LOAD = 10 + DOTA_GAMERULES_STATE_SCENARIO_SETUP = 11 + DOTA_GAMERULES_STATE_PLAYER_DRAFT = 12 + DOTA_GAMERULES_STATE_LAST = 13 + + +class DOTA_GC_TEAM(betterproto.Enum): + DOTA_GC_TEAM_GOOD_GUYS = 0 + DOTA_GC_TEAM_BAD_GUYS = 1 + DOTA_GC_TEAM_BROADCASTER = 2 + DOTA_GC_TEAM_SPECTATOR = 3 + DOTA_GC_TEAM_PLAYER_POOL = 4 + DOTA_GC_TEAM_NOTEAM = 5 + DOTA_GC_TEAM_CUSTOM_1 = 6 + DOTA_GC_TEAM_CUSTOM_2 = 7 + DOTA_GC_TEAM_CUSTOM_3 = 8 + DOTA_GC_TEAM_CUSTOM_4 = 9 + DOTA_GC_TEAM_CUSTOM_5 = 10 + DOTA_GC_TEAM_CUSTOM_6 = 11 + DOTA_GC_TEAM_CUSTOM_7 = 12 + DOTA_GC_TEAM_CUSTOM_8 = 13 + DOTA_GC_TEAM_NEUTRALS = 14 + + +class EEvent(betterproto.Enum): + EVENT_ID_NONE = 0 + EVENT_ID_DIRETIDE = 1 + EVENT_ID_SPRING_FESTIVAL = 2 + EVENT_ID_FROSTIVUS_2013 = 3 + EVENT_ID_COMPENDIUM_2014 = 4 + EVENT_ID_NEXON_PC_BANG = 5 + EVENT_ID_PWRD_DAC_2015 = 6 + EVENT_ID_NEW_BLOOM_2015 = 7 + EVENT_ID_INTERNATIONAL_2015 = 8 + EVENT_ID_FALL_MAJOR_2015 = 9 + EVENT_ID_ORACLE_PA = 10 + EVENT_ID_NEW_BLOOM_2015_PREBEAST = 11 + EVENT_ID_FROSTIVUS = 12 + EVENT_ID_WINTER_MAJOR_2016 = 13 + EVENT_ID_INTERNATIONAL_2016 = 14 + EVENT_ID_FALL_MAJOR_2016 = 15 + EVENT_ID_WINTER_MAJOR_2017 = 16 + EVENT_ID_NEW_BLOOM_2017 = 17 + EVENT_ID_INTERNATIONAL_2017 = 18 + EVENT_ID_PLUS_SUBSCRIPTION = 19 + EVENT_ID_SINGLES_DAY_2017 = 20 + EVENT_ID_FROSTIVUS_2017 = 21 + EVENT_ID_INTERNATIONAL_2018 = 22 + EVENT_ID_FROSTIVUS_2018 = 23 + EVENT_ID_NEW_BLOOM_2019 = 24 + EVENT_ID_INTERNATIONAL_2019 = 25 + EVENT_ID_NEW_PLAYER_EXPERIENCE = 26 + EVENT_ID_FROSTIVUS_2019 = 27 + EVENT_ID_NEW_BLOOM_2020 = 28 + EVENT_ID_INTERNATIONAL_2020 = 29 + EVENT_ID_TEAM_FANDOM = 30 + EVENT_ID_DIRETIDE_2020 = 31 + EVENT_ID_SPRING_2021 = 32 + EVENT_ID_FALL_2021 = 33 + EVENT_ID_TEAM_FANDOM_FALL_2021 = 34 + EVENT_ID_TEAM_2021_2022_TOUR2 = 35 + EVENT_ID_INTERNATIONAL_2022 = 36 + EVENT_ID_TEAM_2021_2022_TOUR3 = 37 + EVENT_ID_TEAM_INTERNATIONAL_2022 = 38 + EVENT_ID_PERMANENT_GRANTS = 39 + EVENT_ID_MUERTA_RELEASE_SPRING2023 = 40 + EVENT_ID_TEAM_2023_TOUR1 = 41 + EVENT_ID_TEAM_2023_TOUR2 = 42 + EVENT_ID_TEAM_2023_TOUR3 = 43 + EVENT_ID_INTERNATIONAL_2023 = 45 + EVENT_ID_10TH_ANNIVERSARY = 46 + EVENT_ID_FROSTIVUS_2023 = 48 + + +class ERankType(betterproto.Enum): + k_ERankType_Invalid = 0 + k_ERankType_Casual = 1 + k_ERankType_Ranked = 2 + k_ERankType_CasualLegacy = 3 + k_ERankType_RankedLegacy = 4 + k_ERankType_CasualGlicko = 5 + k_ERankType_RankedGlicko = 6 + k_ERankType_RankMax = 7 + k_ERankType_BehaviorPrivate = 100 + k_ERankType_BehaviorPublic = 101 + k_ERankType_Max = 102 + + +class DOTALeaverStatusT(betterproto.Enum): + DOTA_LEAVER_NONE = 0 + DOTA_LEAVER_DISCONNECTED = 1 + DOTA_LEAVER_DISCONNECTED_TOO_LONG = 2 + DOTA_LEAVER_ABANDONED = 3 + DOTA_LEAVER_AFK = 4 + DOTA_LEAVER_NEVER_CONNECTED = 5 + DOTA_LEAVER_NEVER_CONNECTED_TOO_LONG = 6 + DOTA_LEAVER_FAILED_TO_READY_UP = 7 + DOTA_LEAVER_DECLINED = 8 + + +class DOTAConnectionStateT(betterproto.Enum): + DOTA_CONNECTION_STATE_UNKNOWN = 0 + DOTA_CONNECTION_STATE_NOT_YET_CONNECTED = 1 + DOTA_CONNECTION_STATE_CONNECTED = 2 + DOTA_CONNECTION_STATE_DISCONNECTED = 3 + DOTA_CONNECTION_STATE_ABANDONED = 4 + DOTA_CONNECTION_STATE_LOADING = 5 + DOTA_CONNECTION_STATE_FAILED = 6 + + +class Fantasy_Roles(betterproto.Enum): + FANTASY_ROLE_UNDEFINED = 0 + FANTASY_ROLE_CORE = 1 + FANTASY_ROLE_SUPPORT = 2 + FANTASY_ROLE_OFFLANE = 3 + FANTASY_ROLE_MID = 4 + + +class Fantasy_Scoring(betterproto.Enum): + FANTASY_SCORING_KILLS = 0 + FANTASY_SCORING_DEATHS = 1 + FANTASY_SCORING_CS = 2 + FANTASY_SCORING_GPM = 3 + FANTASY_SCORING_TOWER_KILLS = 4 + FANTASY_SCORING_ROSHAN_KILLS = 5 + FANTASY_SCORING_TEAMFIGHT_PARTICIPATION = 6 + FANTASY_SCORING_WARDS_PLANTED = 7 + FANTASY_SCORING_CAMPS_STACKED = 8 + FANTASY_SCORING_RUNES_GRABBED = 9 + FANTASY_SCORING_FIRST_BLOOD = 10 + FANTASY_SCORING_STUNS = 11 + FANTASY_SCORING_SMOKES_USED = 12 + FANTASY_SCORING_NEUTRAL_TOKENS_FOUND = 13 + FANTASY_SCORING_WATCHERS_TAKEN = 14 + FANTASY_SCORING_LOTUSES_GAINED = 15 + FANTASY_SCORING_TORMENTOR_KILLS = 16 + FANTASY_SCORING_COURIER_KILLS = 17 + FANTASY_SCORING_TYPES = 18 + FANTASY_SCORING_INVALID = 19 + + +class Fantasy_Team_Slots(betterproto.Enum): + FANTASY_SLOT_NONE = 0 + FANTASY_SLOT_CORE = 1 + FANTASY_SLOT_SUPPORT = 2 + FANTASY_SLOT_ANY = 3 + FANTASY_SLOT_BENCH = 4 + + +class Fantasy_Selection_Mode(betterproto.Enum): + FANTASY_SELECTION_INVALID = 0 + FANTASY_SELECTION_LOCKED = 1 + FANTASY_SELECTION_SHUFFLE = 2 + FANTASY_SELECTION_FREE_PICK = 3 + FANTASY_SELECTION_ENDED = 4 + FANTASY_SELECTION_PRE_SEASON = 5 + FANTASY_SELECTION_PRE_DRAFT = 6 + FANTASY_SELECTION_DRAFTING = 7 + FANTASY_SELECTION_REGULAR_SEASON = 8 + FANTASY_SELECTION_CARD_BASED = 9 + + +class Fantasy_Gem_Type(betterproto.Enum): + FANTASY_GEM_TYPE_RUBY = 0 + FANTASY_GEM_TYPE_SAPPHIRE = 1 + FANTASY_GEM_TYPE_EMERALD = 2 + + +class DOTAChatChannelTypeT(betterproto.Enum): + DOTAChannelType_Regional = 0 + DOTAChannelType_Custom = 1 + DOTAChannelType_Party = 2 + DOTAChannelType_Lobby = 3 + DOTAChannelType_Team = 4 + DOTAChannelType_Guild = 5 + DOTAChannelType_Fantasy = 6 + DOTAChannelType_Whisper = 7 + DOTAChannelType_Console = 8 + DOTAChannelType_Tab = 9 + DOTAChannelType_Invalid = 10 + DOTAChannelType_GameAll = 11 + DOTAChannelType_GameAllies = 12 + DOTAChannelType_GameSpectator = 13 + DOTAChannelType_GameCoaching = 14 + DOTAChannelType_Cafe = 15 + DOTAChannelType_CustomGame = 16 + DOTAChannelType_Private = 17 + DOTAChannelType_PostGame = 18 + DOTAChannelType_BattleCup = 19 + DOTAChannelType_HLTVSpectator = 20 + DOTAChannelType_GameEvents = 21 + DOTAChannelType_Trivia = 22 + DOTAChannelType_NewPlayer = 23 + DOTAChannelType_PrivateCoaching = 24 + + +class EChatSpecialPrivileges(betterproto.Enum): + k_EChatSpecialPrivileges_None = 0 + k_EChatSpecialPrivileges_Moderator = 1 + k_EChatSpecialPrivileges_SuperModerator = 2 + + +class DOTACommTypeT(betterproto.Enum): + DOTA_COMM_TYPE_NONE = 0 + DOTA_COMM_TYPE_PING = 1 + DOTA_COMM_TYPE_CHATWHEEL = 2 + DOTA_COMM_TYPE_TIP = 3 + DOTA_COMM_TYPE_TEXT = 4 + DOTA_COMM_TYPE_SHOWCASE = 5 + DOTA_COMM_TYPE_VOICE = 6 + DOTA_COMM_TYPE_ALLY_ABILITY = 7 + DOTA_COMM_TYPE_PAUSE = 8 + DOTA_COMM_TYPE_COACHING = 9 + DOTA_COMM_TYPE_NOCOOLDOWN = 10 + DOTA_COMM_TYPE_RANKEDMATCHMAKE = 11 + DOTA_COMM_TYPE_DROPS = 12 + DOTA_COMM_TYPE_NEWPLAYER_EXPERT = 13 + DOTA_COMM_TYPE_COACHED = 14 + DOTA_COMM_TYPE_MAPDRAWING = 15 + + +class DOTACommLevelT(betterproto.Enum): + DOTA_COMM_LEVEL_NONE = 0 + DOTA_COMM_LEVEL_COOLDOWN = 1 + DOTA_COMM_LEVEL_PINGS = 2 + DOTA_COMM_LEVEL_MAPDRAWING = 3 + DOTA_COMM_LEVEL_CHAT = 4 + DOTA_COMM_LEVEL_TIPPING = 5 + DOTA_COMM_LEVEL_VOICE = 6 + DOTA_COMM_LEVEL_ALLIED_ABILITY = 7 + + +class DOTABehaviorLevelT(betterproto.Enum): + DOTA_BEHAVIOR_LEVEL_NONE = 0 + DOTA_BEHAVIOR_LEVEL_RANKED_ALLOWED = 1 + DOTA_BEHAVIOR_LEVEL_PAUSING = 2 + DOTA_BEHAVIOR_LEVEL_DROPS = 3 + DOTA_BEHAVIOR_LEVEL_COACHING = 4 + + +class EProfileCardSlotType(betterproto.Enum): + k_EProfileCardSlotType_Empty = 0 + k_EProfileCardSlotType_Stat = 1 + k_EProfileCardSlotType_Trophy = 2 + k_EProfileCardSlotType_Item = 3 + k_EProfileCardSlotType_Hero = 4 + k_EProfileCardSlotType_Emoticon = 5 + k_EProfileCardSlotType_Team = 6 + + +class EMatchGroupServerStatus(betterproto.Enum): + k_EMatchGroupServerStatus_OK = 0 + k_EMatchGroupServerStatus_LimitedAvailability = 1 + k_EMatchGroupServerStatus_Offline = 2 + + +class DOTA_CM_PICK(betterproto.Enum): + DOTA_CM_RANDOM = 0 + DOTA_CM_GOOD_GUYS = 1 + DOTA_CM_BAD_GUYS = 2 + + +class DOTALowPriorityBanType(betterproto.Enum): + DOTA_LOW_PRIORITY_BAN_ABANDON = 0 + DOTA_LOW_PRIORITY_BAN_REPORTS = 1 + DOTA_LOW_PRIORITY_BAN_SECONDARY_ABANDON = 2 + DOTA_LOW_PRIORITY_BAN_PRE_GAME_ROLE = 3 + + +class DOTALobbyReadyState(betterproto.Enum): + DOTALobbyReadyState_UNDECLARED = 0 + DOTALobbyReadyState_ACCEPTED = 1 + DOTALobbyReadyState_DECLINED = 2 + + +class DOTAJoinLobbyResult(betterproto.Enum): + DOTA_JOIN_RESULT_SUCCESS = 0 + DOTA_JOIN_RESULT_ALREADY_IN_GAME = 1 + DOTA_JOIN_RESULT_INVALID_LOBBY = 2 + DOTA_JOIN_RESULT_INCORRECT_PASSWORD = 3 + DOTA_JOIN_RESULT_ACCESS_DENIED = 4 + DOTA_JOIN_RESULT_GENERIC_ERROR = 5 + DOTA_JOIN_RESULT_INCORRECT_VERSION = 6 + DOTA_JOIN_RESULT_IN_TEAM_PARTY = 7 + DOTA_JOIN_RESULT_NO_LOBBY_FOUND = 8 + DOTA_JOIN_RESULT_LOBBY_FULL = 9 + DOTA_JOIN_RESULT_CUSTOM_GAME_INCORRECT_VERSION = 10 + DOTA_JOIN_RESULT_TIMEOUT = 11 + DOTA_JOIN_RESULT_CUSTOM_GAME_COOLDOWN = 12 + DOTA_JOIN_RESULT_BUSY = 13 + DOTA_JOIN_RESULT_NO_PLAYTIME = 14 + + +class DOTASelectionPriorityRules(betterproto.Enum): + k_DOTASelectionPriorityRules_Manual = 0 + k_DOTASelectionPriorityRules_Automatic = 1 + + +class DOTASelectionPriorityChoice(betterproto.Enum): + k_DOTASelectionPriorityChoice_Invalid = 0 + k_DOTASelectionPriorityChoice_FirstPick = 1 + k_DOTASelectionPriorityChoice_SecondPick = 2 + k_DOTASelectionPriorityChoice_Radiant = 3 + k_DOTASelectionPriorityChoice_Dire = 4 + + +class DOTAMatchVote(betterproto.Enum): + DOTAMatchVote_INVALID = 0 + DOTAMatchVote_POSITIVE = 1 + DOTAMatchVote_NEGATIVE = 2 + + +class DOTALobbyVisibility(betterproto.Enum): + DOTALobbyVisibility_Public = 0 + DOTALobbyVisibility_Friends = 1 + DOTALobbyVisibility_Unlisted = 2 + + +class EDOTAPlayerMMRType(betterproto.Enum): + k_EDOTAPlayerMMRType_Invalid = 0 + k_EDOTAPlayerMMRType_GeneralHidden = 1 + k_EDOTAPlayerMMRType_GeneralCompetitive = 3 + + +class EDOTAMMRBoostType(betterproto.Enum): + k_EDOTAMMRBoostType_None = 0 + k_EDOTAMMRBoostType_Leader = 1 + k_EDOTAMMRBoostType_Follower = 2 + + +class MatchType(betterproto.Enum): + MATCH_TYPE_CASUAL = 0 + MATCH_TYPE_COOP_BOTS = 1 + MATCH_TYPE_COMPETITIVE = 4 + MATCH_TYPE_WEEKEND_TOURNEY = 5 + MATCH_TYPE_EVENT = 7 + MATCH_TYPE_COACHES_CHALLENGE = 12 + MATCH_TYPE_NEW_PLAYER_POOL = 14 + + +class DOTABotDifficulty(betterproto.Enum): + BOT_DIFFICULTY_PASSIVE = 0 + BOT_DIFFICULTY_EASY = 1 + BOT_DIFFICULTY_MEDIUM = 2 + BOT_DIFFICULTY_HARD = 3 + BOT_DIFFICULTY_UNFAIR = 4 + BOT_DIFFICULTY_INVALID = 5 + BOT_DIFFICULTY_EXTRA1 = 6 + BOT_DIFFICULTY_EXTRA2 = 7 + BOT_DIFFICULTY_EXTRA3 = 8 + BOT_DIFFICULTY_NPX = 9 + + +class DOTA_BOT_MODE(betterproto.Enum): + DOTA_BOT_MODE_NONE = 0 + DOTA_BOT_MODE_LANING = 1 + DOTA_BOT_MODE_ATTACK = 2 + DOTA_BOT_MODE_ROAM = 3 + DOTA_BOT_MODE_RETREAT = 4 + DOTA_BOT_MODE_SECRET_SHOP = 5 + DOTA_BOT_MODE_SIDE_SHOP = 6 + DOTA_BOT_MODE_RUNE = 7 + DOTA_BOT_MODE_PUSH_TOWER_TOP = 8 + DOTA_BOT_MODE_PUSH_TOWER_MID = 9 + DOTA_BOT_MODE_PUSH_TOWER_BOT = 10 + DOTA_BOT_MODE_DEFEND_TOWER_TOP = 11 + DOTA_BOT_MODE_DEFEND_TOWER_MID = 12 + DOTA_BOT_MODE_DEFEND_TOWER_BOT = 13 + DOTA_BOT_MODE_ASSEMBLE = 14 + DOTA_BOT_MODE_ASSEMBLE_WITH_HUMANS = 15 + DOTA_BOT_MODE_TEAM_ROAM = 16 + DOTA_BOT_MODE_FARM = 17 + DOTA_BOT_MODE_DEFEND_ALLY = 18 + DOTA_BOT_MODE_EVASIVE_MANEUVERS = 19 + DOTA_BOT_MODE_ROSHAN = 20 + DOTA_BOT_MODE_ITEM = 21 + DOTA_BOT_MODE_WARD = 22 + DOTA_BOT_MODE_COMPANION = 23 + DOTA_BOT_MODE_TUTORIAL_BOSS = 24 + DOTA_BOT_MODE_MINION = 25 + DOTA_BOT_MODE_OUTPOST = 26 + + +class MatchLanguages(betterproto.Enum): + MATCH_LANGUAGE_INVALID = 0 + MATCH_LANGUAGE_ENGLISH = 1 + MATCH_LANGUAGE_RUSSIAN = 2 + MATCH_LANGUAGE_CHINESE = 3 + MATCH_LANGUAGE_KOREAN = 4 + MATCH_LANGUAGE_SPANISH = 5 + MATCH_LANGUAGE_PORTUGUESE = 6 + MATCH_LANGUAGE_ENGLISH2 = 7 + + +class ETourneyQueueDeadlineState(betterproto.Enum): + k_ETourneyQueueDeadlineState_Normal = 0 + k_ETourneyQueueDeadlineState_Missed = 1 + k_ETourneyQueueDeadlineState_ExpiredOK = 2 + k_ETourneyQueueDeadlineState_SeekingBye = 3 + k_ETourneyQueueDeadlineState_EligibleForRefund = 4 + k_ETourneyQueueDeadlineState_NA = -1 + k_ETourneyQueueDeadlineState_ExpiringSoon = 101 + + +class EMatchOutcome(betterproto.Enum): + k_EMatchOutcome_Unknown = 0 + k_EMatchOutcome_RadVictory = 2 + k_EMatchOutcome_DireVictory = 3 + k_EMatchOutcome_NeutralVictory = 4 + k_EMatchOutcome_NoTeamWinner = 5 + k_EMatchOutcome_Custom1Victory = 6 + k_EMatchOutcome_Custom2Victory = 7 + k_EMatchOutcome_Custom3Victory = 8 + k_EMatchOutcome_Custom4Victory = 9 + k_EMatchOutcome_Custom5Victory = 10 + k_EMatchOutcome_Custom6Victory = 11 + k_EMatchOutcome_Custom7Victory = 12 + k_EMatchOutcome_Custom8Victory = 13 + k_EMatchOutcome_NotScored_PoorNetworkConditions = 64 + k_EMatchOutcome_NotScored_Leaver = 65 + k_EMatchOutcome_NotScored_ServerCrash = 66 + k_EMatchOutcome_NotScored_NeverStarted = 67 + k_EMatchOutcome_NotScored_Canceled = 68 + k_EMatchOutcome_NotScored_Suspicious = 69 + + +class ELaneType(betterproto.Enum): + LANE_TYPE_UNKNOWN = 0 + LANE_TYPE_SAFE = 1 + LANE_TYPE_OFF = 2 + LANE_TYPE_MID = 3 + LANE_TYPE_JUNGLE = 4 + LANE_TYPE_ROAM = 5 + + +class EBadgeType(betterproto.Enum): + k_EBadgeType_Invalid = 0 + k_EBadgeType_TI7_Midweek = 1 + k_EBadgeType_TI7_Finals = 2 + k_EBadgeType_TI7_AllEvent = 3 + k_EBadgeType_TI8_Midweek = 4 + k_EBadgeType_TI8_Finals = 5 + k_EBadgeType_TI8_AllEvent = 6 + k_EBadgeType_TI10 = 7 + k_EBadgeType_TI11_PlayoffsDay1 = 8 + k_EBadgeType_TI11_PlayoffsDay2 = 9 + k_EBadgeType_TI11_PlayoffsDay3 = 10 + k_EBadgeType_TI11_PlayoffsDay4 = 11 + k_EBadgeType_TI11_FinalsWeekend = 12 + k_EBadgeType_TI12_PlayoffsDay1 = 13 + k_EBadgeType_TI12_PlayoffsDay2 = 14 + k_EBadgeType_TI12_PlayoffsDay3 = 15 + k_EBadgeType_TI12_FinalsWeekend = 16 + k_EBadgeType_TI12_Special = 17 + + +class ELeagueStatus(betterproto.Enum): + LEAGUE_STATUS_UNSET = 0 + LEAGUE_STATUS_UNSUBMITTED = 1 + LEAGUE_STATUS_SUBMITTED = 2 + LEAGUE_STATUS_ACCEPTED = 3 + LEAGUE_STATUS_REJECTED = 4 + LEAGUE_STATUS_CONCLUDED = 5 + LEAGUE_STATUS_DELETED = 6 + + +class ELeagueRegion(betterproto.Enum): + LEAGUE_REGION_UNSET = 0 + LEAGUE_REGION_NA = 1 + LEAGUE_REGION_SA = 2 + LEAGUE_REGION_WEU = 3 + LEAGUE_REGION_EEU = 4 + LEAGUE_REGION_CHINA = 5 + LEAGUE_REGION_SEA = 6 + + +class ELeagueTier(betterproto.Enum): + LEAGUE_TIER_UNSET = 0 + LEAGUE_TIER_AMATEUR = 1 + LEAGUE_TIER_PROFESSIONAL = 2 + LEAGUE_TIER_MINOR = 3 + LEAGUE_TIER_MAJOR = 4 + LEAGUE_TIER_INTERNATIONAL = 5 + LEAGUE_TIER_DPC_QUALIFIER = 6 + LEAGUE_TIER_DPC_LEAGUE_QUALIFIER = 7 + LEAGUE_TIER_DPC_LEAGUE = 8 + LEAGUE_TIER_DPC_LEAGUE_FINALS = 9 + + +class ELeagueTierCategory(betterproto.Enum): + LEAGUE_TIER_CATEGORY_AMATEUR = 1 + LEAGUE_TIER_CATEGORY_PROFESSIONAL = 2 + LEAGUE_TIER_CATEGORY_DPC = 3 + + +class ELeagueDivision(betterproto.Enum): + LEAGUE_DIVISION_UNSET = 0 + LEAGUE_DIVISION_I = 1 + LEAGUE_DIVISION_II = 2 + + +class ELeagueBroadcastProvider(betterproto.Enum): + LEAGUE_BROADCAST_UNKNOWN = 0 + LEAGUE_BROADCAST_STEAM = 1 + LEAGUE_BROADCAST_TWITCH = 2 + LEAGUE_BROADCAST_YOUTUBE = 3 + LEAGUE_BROADCAST_OTHER = 100 + + +class ELeaguePhase(betterproto.Enum): + LEAGUE_PHASE_UNSET = 0 + LEAGUE_PHASE_REGIONAL_QUALIFIER = 1 + LEAGUE_PHASE_GROUP_STAGE = 2 + LEAGUE_PHASE_MAIN_EVENT = 3 + + +class ELeagueAuditAction(betterproto.Enum): + LEAGUE_AUDIT_ACTION_INVALID = 0 + LEAGUE_AUDIT_ACTION_LEAGUE_CREATE = 1 + LEAGUE_AUDIT_ACTION_LEAGUE_EDIT = 2 + LEAGUE_AUDIT_ACTION_LEAGUE_DELETE = 3 + LEAGUE_AUDIT_ACTION_LEAGUE_ADMIN_ADD = 4 + LEAGUE_AUDIT_ACTION_LEAGUE_ADMIN_REVOKE = 5 + LEAGUE_AUDIT_ACTION_LEAGUE_ADMIN_PROMOTE = 6 + LEAGUE_AUDIT_ACTION_LEAGUE_STREAM_ADD = 7 + LEAGUE_AUDIT_ACTION_LEAGUE_STREAM_REMOVE = 8 + LEAGUE_AUDIT_ACTION_LEAGUE_IMAGE_UPDATED = 9 + LEAGUE_AUDIT_ACTION_LEAGUE_MESSAGE_ADDED = 10 + LEAGUE_AUDIT_ACTION_LEAGUE_SUBMITTED = 11 + LEAGUE_AUDIT_ACTION_LEAGUE_SET_PRIZE_POOL = 12 + LEAGUE_AUDIT_ACTION_LEAGUE_ADD_PRIZE_POOL_ITEM = 13 + LEAGUE_AUDIT_ACTION_LEAGUE_REMOVE_PRIZE_POOL_ITEM = 14 + LEAGUE_AUDIT_ACTION_LEAGUE_MATCH_START = 15 + LEAGUE_AUDIT_ACTION_LEAGUE_MATCH_END = 16 + LEAGUE_AUDIT_ACTION_LEAGUE_ADD_INVITED_TEAM = 17 + LEAGUE_AUDIT_ACTION_LEAGUE_REMOVE_INVITED_TEAM = 18 + LEAGUE_AUDIT_ACTION_LEAGUE_STATUS_CHANGED = 19 + LEAGUE_AUDIT_ACTION_LEAGUE_STREAM_EDIT = 20 + LEAGUE_AUDIT_ACTION_LEAGUE_TEAM_SWAP = 21 + LEAGUE_AUDIT_ACTION_NODEGROUP_CREATE = 100 + LEAGUE_AUDIT_ACTION_NODEGROUP_DESTROY = 101 + LEAGUE_AUDIT_ACTION_NODEGROUP_ADD_TEAM = 102 + LEAGUE_AUDIT_ACTION_NODEGROUP_REMOVE_TEAM = 103 + LEAGUE_AUDIT_ACTION_NODEGROUP_SET_ADVANCING = 104 + LEAGUE_AUDIT_ACTION_NODEGROUP_EDIT = 105 + LEAGUE_AUDIT_ACTION_NODEGROUP_POPULATE = 106 + LEAGUE_AUDIT_ACTION_NODEGROUP_COMPLETED = 107 + LEAGUE_AUDIT_ACTION_NODEGROUP_SET_SECONDARY_ADVANCING = 108 + LEAGUE_AUDIT_ACTION_NODEGROUP_SET_TERTIARY_ADVANCING = 109 + LEAGUE_AUDIT_ACTION_NODE_CREATE = 200 + LEAGUE_AUDIT_ACTION_NODE_DESTROY = 201 + LEAGUE_AUDIT_ACTION_NODE_AUTOCREATE = 202 + LEAGUE_AUDIT_ACTION_NODE_SET_TEAM = 203 + LEAGUE_AUDIT_ACTION_NODE_SET_SERIES_ID = 204 + LEAGUE_AUDIT_ACTION_NODE_SET_ADVANCING = 205 + LEAGUE_AUDIT_ACTION_NODE_SET_TIME = 206 + LEAGUE_AUDIT_ACTION_NODE_MATCH_COMPLETED = 207 + LEAGUE_AUDIT_ACTION_NODE_COMPLETED = 208 + LEAGUE_AUDIT_ACTION_NODE_EDIT = 209 + + +class DOTA_COMBATLOG_TYPES(betterproto.Enum): + DOTA_COMBATLOG_INVALID = -1 + DOTA_COMBATLOG_DAMAGE = 0 + DOTA_COMBATLOG_HEAL = 1 + DOTA_COMBATLOG_MODIFIER_ADD = 2 + DOTA_COMBATLOG_MODIFIER_REMOVE = 3 + DOTA_COMBATLOG_DEATH = 4 + DOTA_COMBATLOG_ABILITY = 5 + DOTA_COMBATLOG_ITEM = 6 + DOTA_COMBATLOG_LOCATION = 7 + DOTA_COMBATLOG_GOLD = 8 + DOTA_COMBATLOG_GAME_STATE = 9 + DOTA_COMBATLOG_XP = 10 + DOTA_COMBATLOG_PURCHASE = 11 + DOTA_COMBATLOG_BUYBACK = 12 + DOTA_COMBATLOG_ABILITY_TRIGGER = 13 + DOTA_COMBATLOG_PLAYERSTATS = 14 + DOTA_COMBATLOG_MULTIKILL = 15 + DOTA_COMBATLOG_KILLSTREAK = 16 + DOTA_COMBATLOG_TEAM_BUILDING_KILL = 17 + DOTA_COMBATLOG_FIRST_BLOOD = 18 + DOTA_COMBATLOG_MODIFIER_STACK_EVENT = 19 + DOTA_COMBATLOG_NEUTRAL_CAMP_STACK = 20 + DOTA_COMBATLOG_PICKUP_RUNE = 21 + DOTA_COMBATLOG_REVEALED_INVISIBLE = 22 + DOTA_COMBATLOG_HERO_SAVED = 23 + DOTA_COMBATLOG_MANA_RESTORED = 24 + DOTA_COMBATLOG_HERO_LEVELUP = 25 + DOTA_COMBATLOG_BOTTLE_HEAL_ALLY = 26 + DOTA_COMBATLOG_ENDGAME_STATS = 27 + DOTA_COMBATLOG_INTERRUPT_CHANNEL = 28 + DOTA_COMBATLOG_ALLIED_GOLD = 29 + DOTA_COMBATLOG_AEGIS_TAKEN = 30 + DOTA_COMBATLOG_MANA_DAMAGE = 31 + DOTA_COMBATLOG_PHYSICAL_DAMAGE_PREVENTED = 32 + DOTA_COMBATLOG_UNIT_SUMMONED = 33 + DOTA_COMBATLOG_ATTACK_EVADE = 34 + DOTA_COMBATLOG_TREE_CUT = 35 + DOTA_COMBATLOG_SUCCESSFUL_SCAN = 36 + DOTA_COMBATLOG_END_KILLSTREAK = 37 + DOTA_COMBATLOG_BLOODSTONE_CHARGE = 38 + DOTA_COMBATLOG_CRITICAL_DAMAGE = 39 + DOTA_COMBATLOG_SPELL_ABSORB = 40 + DOTA_COMBATLOG_UNIT_TELEPORTED = 41 + DOTA_COMBATLOG_KILL_EATER_EVENT = 42 + DOTA_COMBATLOG_NEUTRAL_ITEM_EARNED = 43 + + +class EDPCFavoriteType(betterproto.Enum): + FAVORITE_TYPE_ALL = 0 + FAVORITE_TYPE_PLAYER = 1 + FAVORITE_TYPE_TEAM = 2 + FAVORITE_TYPE_LEAGUE = 3 + + +class EDPCPushNotification(betterproto.Enum): + DPC_PUSH_NOTIFICATION_MATCH_STARTING = 1 + DPC_PUSH_NOTIFICATION_PLAYER_LEFT_TEAM = 10 + DPC_PUSH_NOTIFICATION_PLAYER_JOINED_TEAM = 11 + DPC_PUSH_NOTIFICATION_PLAYER_JOINED_TEAM_AS_COACH = 12 + DPC_PUSH_NOTIFICATION_PLAYER_LEFT_TEAM_AS_COACH = 13 + DPC_PUSH_NOTIFICATION_LEAGUE_RESULT = 20 + DPC_PUSH_NOTIFICATION_PREDICTION_MATCHES_AVAILABLE = 30 + DPC_PUSH_NOTIFICATION_PREDICTION_RESULT = 31 + DPC_PUSH_NOTIFICATION_FANTASY_PLAYER_CLEARED = 40 + DPC_PUSH_NOTIFICATION_FANTASY_DAILY_SUMMARY = 41 + DPC_PUSH_NOTIFICATION_FANTASY_FINAL_RESULTS = 42 + + +class EEventActionScoreMode(betterproto.Enum): + k_eEventActionScoreMode_Add = 0 + k_eEventActionScoreMode_Min = 1 + + +class EPlayerChallengeHistoryType(betterproto.Enum): + k_EPlayerChallengeHistoryType_Invalid = 0 + k_EPlayerChallengeHistoryType_KillEater = 1 + k_EPlayerChallengeHistoryType_DotaPlusRelic = 2 + k_EPlayerChallengeHistoryType_DotaPlusHeroPlayerChallenge = 3 + k_EPlayerChallengeHistoryType_InGameEventChallenge = 4 + k_EPlayerChallengeHistoryType_GuildContract = 5 + + +class EOverwatchReportReason(betterproto.Enum): + k_EOverwatchReportReason_Unknown = 0 + k_EOverwatchReportReason_Cheating = 1 + k_EOverwatchReportReason_Feeding = 2 + k_EOverwatchReportReason_Griefing = 3 + k_EOverwatchReportReason_Suspicious = 4 + k_EOverwatchReportReason_AbilityAbuse = 5 + + +@dataclass +class CDOTAClientHardwareSpecs(betterproto.Message): + logical_processors: int = betterproto.uint32_field(1) + cpu_cycles_per_second: float = betterproto.fixed64_field(2) + total_physical_memory: float = betterproto.fixed64_field(3) + is_64_bit_os: bool = betterproto.bool_field(4) + upload_measurement: int = betterproto.uint64_field(5) + prefer_not_host: bool = betterproto.bool_field(6) + crc: list[int] = betterproto.uint32_field(7) + + +@dataclass +class CDOTASaveGame(betterproto.Message): + match_id: int = betterproto.uint64_field(5) + save_time: int = betterproto.uint32_field(2) + players: list[CDOTASaveGamePlayer] = betterproto.message_field(3) + save_instances: list[CDOTASaveGameSaveInstance] = betterproto.message_field(4) + + +@dataclass +class CDOTASaveGamePlayer(betterproto.Message): + team: DOTA_GC_TEAM = betterproto.enum_field(1) + name: str = betterproto.string_field(2) + hero: str = betterproto.string_field(3) + + +@dataclass +class CDOTASaveGameSaveInstance(betterproto.Message): + game_time: int = betterproto.uint32_field(2) + team1_score: int = betterproto.uint32_field(3) + team2_score: int = betterproto.uint32_field(4) + player_positions: list[ + CDOTASaveGameSaveInstancePlayerPositions + ] = betterproto.message_field(5) + save_id: int = betterproto.uint32_field(6) + save_time: int = betterproto.uint32_field(7) + + +@dataclass +class CDOTASaveGameSaveInstancePlayerPositions(betterproto.Message): + x: float = betterproto.float_field(1) + y: float = betterproto.float_field(2) + + +@dataclass +class CMsgDOTACombatLogEntry(betterproto.Message): + type: DOTA_COMBATLOG_TYPES = betterproto.enum_field(1) + target_name: int = betterproto.uint32_field(2) + target_source_name: int = betterproto.uint32_field(3) + attacker_name: int = betterproto.uint32_field(4) + damage_source_name: int = betterproto.uint32_field(5) + inflictor_name: int = betterproto.uint32_field(6) + is_attacker_illusion: bool = betterproto.bool_field(7) + is_attacker_hero: bool = betterproto.bool_field(8) + is_target_illusion: bool = betterproto.bool_field(9) + is_target_hero: bool = betterproto.bool_field(10) + is_visible_radiant: bool = betterproto.bool_field(11) + is_visible_dire: bool = betterproto.bool_field(12) + value: int = betterproto.uint32_field(13) + health: int = betterproto.int32_field(14) + timestamp: float = betterproto.float_field(15) + stun_duration: float = betterproto.float_field(16) + slow_duration: float = betterproto.float_field(17) + is_ability_toggle_on: bool = betterproto.bool_field(18) + is_ability_toggle_off: bool = betterproto.bool_field(19) + ability_level: int = betterproto.uint32_field(20) + location_x: float = betterproto.float_field(21) + location_y: float = betterproto.float_field(22) + gold_reason: int = betterproto.uint32_field(23) + timestamp_raw: float = betterproto.float_field(24) + modifier_duration: float = betterproto.float_field(25) + xp_reason: int = betterproto.uint32_field(26) + last_hits: int = betterproto.uint32_field(27) + attacker_team: int = betterproto.uint32_field(28) + target_team: int = betterproto.uint32_field(29) + obs_wards_placed: int = betterproto.uint32_field(30) + assist_player0: int = betterproto.uint32_field(31) + assist_player1: int = betterproto.uint32_field(32) + assist_player2: int = betterproto.uint32_field(33) + assist_player3: int = betterproto.uint32_field(34) + stack_count: int = betterproto.uint32_field(35) + hidden_modifier: bool = betterproto.bool_field(36) + is_target_building: bool = betterproto.bool_field(37) + neutral_camp_type: int = betterproto.uint32_field(38) + rune_type: int = betterproto.uint32_field(39) + assist_players: list[int] = betterproto.int32_field(40) + is_heal_save: bool = betterproto.bool_field(41) + is_ultimate_ability: bool = betterproto.bool_field(42) + attacker_hero_level: int = betterproto.uint32_field(43) + target_hero_level: int = betterproto.uint32_field(44) + xpm: int = betterproto.uint32_field(45) + gpm: int = betterproto.uint32_field(46) + event_location: int = betterproto.uint32_field(47) + target_is_self: bool = betterproto.bool_field(48) + damage_type: int = betterproto.uint32_field(49) + invisibility_modifier: bool = betterproto.bool_field(50) + damage_category: int = betterproto.uint32_field(51) + networth: int = betterproto.uint32_field(52) + building_type: int = betterproto.uint32_field(53) + modifier_elapsed_duration: float = betterproto.float_field(54) + silence_modifier: bool = betterproto.bool_field(55) + heal_from_lifesteal: bool = betterproto.bool_field(56) + modifier_purged: bool = betterproto.bool_field(57) + spell_evaded: bool = betterproto.bool_field(58) + motion_controller_modifier: bool = betterproto.bool_field(59) + long_range_kill: bool = betterproto.bool_field(60) + modifier_purge_ability: int = betterproto.uint32_field(61) + modifier_purge_npc: int = betterproto.uint32_field(62) + root_modifier: bool = betterproto.bool_field(63) + total_unit_death_count: int = betterproto.uint32_field(64) + aura_modifier: bool = betterproto.bool_field(65) + armor_debuff_modifier: bool = betterproto.bool_field(66) + no_physical_damage_modifier: bool = betterproto.bool_field(67) + modifier_ability: int = betterproto.uint32_field(68) + modifier_hidden: bool = betterproto.bool_field(69) + inflictor_is_stolen_ability: bool = betterproto.bool_field(70) + kill_eater_event: int = betterproto.uint32_field(71) + unit_status_label: int = betterproto.uint32_field(72) + spell_generated_attack: bool = betterproto.bool_field(73) + at_night_time: bool = betterproto.bool_field(74) + attacker_has_scepter: bool = betterproto.bool_field(75) + neutral_camp_team: int = betterproto.uint32_field(76) + regenerated_health: float = betterproto.float_field(77) + will_reincarnate: bool = betterproto.bool_field(78) + uses_charges: bool = betterproto.bool_field(79) + + +@dataclass +class CMsgPendingEventAward(betterproto.Message): + event_id: EEvent = betterproto.enum_field(1) + action_id: int = betterproto.uint32_field(2) + num_to_grant: int = betterproto.uint32_field(3) + score_mode: EEventActionScoreMode = betterproto.enum_field(4) + audit_action: int = betterproto.uint32_field(5) + audit_data: int = betterproto.uint64_field(6) diff --git a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py new file mode 100644 index 00000000..cdef1292 --- /dev/null +++ b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py @@ -0,0 +1,581 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: gcsdk_gcmessages.proto +# plugin: python-betterproto +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING + +import betterproto + +from ....protobufs.msg import GCProtobufMessage +from .gcsystemmsgs import EGCBaseClientMsg + +if TYPE_CHECKING: + from .steammessages import CGCSystemMsg_GetAccountDetails_Response + from .steammessages_steamlearn.steamworkssdk import CMsgSteamLearnHMACKeys + + +class ESourceEngine(betterproto.Enum): + k_ESE_Source1 = 0 + k_ESE_Source2 = 1 + + +class PartnerAccountType(betterproto.Enum): + PARTNER_NONE = 0 + PARTNER_PERFECT_WORLD = 1 + PARTNER_INVALID = 3 + + +class GCConnectionStatus(betterproto.Enum): + GCConnectionStatus_HAVE_SESSION = 0 + GCConnectionStatus_GC_GOING_DOWN = 1 + GCConnectionStatus_NO_SESSION = 2 + GCConnectionStatus_NO_SESSION_IN_LOGON_QUEUE = 3 + GCConnectionStatus_NO_STEAM = 4 + GCConnectionStatus_SUSPENDED = 5 + GCConnectionStatus_STEAM_GOING_DOWN = 6 + + +@dataclass +class CExtraMsgBlock(betterproto.Message): + msg_type: int = betterproto.uint32_field(1) + contents: bytes = betterproto.bytes_field(2) + msg_key: int = betterproto.uint64_field(3) + is_compressed: bool = betterproto.bool_field(4) + + +@dataclass +class CMsgSteamLearnServerInfo(betterproto.Message): + enable_data_submission: bool = betterproto.bool_field(1) + enable_inferencing: bool = betterproto.bool_field(2) + hmac_keys: CMsgSteamLearnHMACKeys = betterproto.message_field(3) + + +@dataclass +class CMsgGCAssertJobData(betterproto.Message): + message_type: str = betterproto.string_field(1) + message_data: bytes = betterproto.bytes_field(2) + + +@dataclass +class CMsgGCConCommand(betterproto.Message): + command: str = betterproto.string_field(1) + + +@dataclass +class CMsgSDOAssert(betterproto.Message): + sdo_type: int = betterproto.int32_field(1) + requests: list["CMsgSDOAssertRequest"] = betterproto.message_field(2) + + +@dataclass +class CMsgSDOAssertRequest(betterproto.Message): + key: list[int] = betterproto.uint64_field(1) + requesting_job: str = betterproto.string_field(2) + + +@dataclass +class CMsgSOIDOwner(betterproto.Message): + type: int = betterproto.uint32_field(1) + id: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgSOSingleObject(betterproto.Message): + type_id: int = betterproto.int32_field(2) + object_data: bytes = betterproto.bytes_field(3) + version: float = betterproto.fixed64_field(4) + owner_soid: "CMsgSOIDOwner" = betterproto.message_field(5) + service_id: int = betterproto.uint32_field(6) + + +@dataclass +class CMsgSOMultipleObjects(betterproto.Message): + objects_modified: list["CMsgSOMultipleObjectsSingleObject"] = betterproto.message_field(2) + version: float = betterproto.fixed64_field(3) + objects_added: list["CMsgSOMultipleObjectsSingleObject"] = betterproto.message_field(4) + objects_removed: list["CMsgSOMultipleObjectsSingleObject"] = betterproto.message_field(5) + owner_soid: "CMsgSOIDOwner" = betterproto.message_field(6) + service_id: int = betterproto.uint32_field(7) + + +@dataclass +class CMsgSOMultipleObjectsSingleObject(betterproto.Message): + type_id: int = betterproto.int32_field(1) + object_data: bytes = betterproto.bytes_field(2) + + +@dataclass +class CMsgSOCacheSubscribed(betterproto.Message): + objects: list["CMsgSOCacheSubscribedSubscribedType"] = betterproto.message_field(2) + version: float = betterproto.fixed64_field(3) + owner_soid: "CMsgSOIDOwner" = betterproto.message_field(4) + service_id: int = betterproto.uint32_field(5) + service_list: list[int] = betterproto.uint32_field(6) + sync_version: float = betterproto.fixed64_field(7) + + +@dataclass +class CMsgSOCacheSubscribedSubscribedType(betterproto.Message): + type_id: int = betterproto.int32_field(1) + object_data: list[bytes] = betterproto.bytes_field(2) + + +@dataclass +class CMsgSOCacheSubscribedUpToDate(betterproto.Message): + version: float = betterproto.fixed64_field(1) + owner_soid: "CMsgSOIDOwner" = betterproto.message_field(2) + service_id: int = betterproto.uint32_field(3) + service_list: list[int] = betterproto.uint32_field(4) + sync_version: float = betterproto.fixed64_field(5) + + +@dataclass +class CMsgSOCacheUnsubscribed(betterproto.Message): + owner_soid: "CMsgSOIDOwner" = betterproto.message_field(2) + + +@dataclass +class CMsgSOCacheSubscriptionCheck(betterproto.Message): + version: float = betterproto.fixed64_field(2) + owner_soid: "CMsgSOIDOwner" = betterproto.message_field(3) + service_id: int = betterproto.uint32_field(4) + service_list: list[int] = betterproto.uint32_field(5) + sync_version: float = betterproto.fixed64_field(6) + + +@dataclass +class CMsgSOCacheSubscriptionRefresh(betterproto.Message): + owner_soid: "CMsgSOIDOwner" = betterproto.message_field(2) + + +@dataclass +class CMsgSOCacheVersion(betterproto.Message): + version: float = betterproto.fixed64_field(1) + + +@dataclass +class CMsgGCMultiplexMessage(betterproto.Message): + msgtype: int = betterproto.uint32_field(1) + payload: bytes = betterproto.bytes_field(2) + steamids: list[float] = betterproto.fixed64_field(3) + + +@dataclass +class CMsgGCToGCSubGCStarting(betterproto.Message): + dir_index: int = betterproto.int32_field(1) + + +@dataclass +class CGCToGCMsgMasterAck(betterproto.Message): + dir_index: int = betterproto.int32_field(1) + machine_name: str = betterproto.string_field(3) + process_name: str = betterproto.string_field(4) + directory: list["CGCToGCMsgMasterAckProcess"] = betterproto.message_field(6) + + +@dataclass +class CGCToGCMsgMasterAckProcess(betterproto.Message): + dir_index: int = betterproto.int32_field(1) + type_instances: list[int] = betterproto.uint32_field(2) + + +@dataclass +class CGCToGCMsgMasterAck_Response(betterproto.Message): + eresult: int = betterproto.int32_field(1) + + +@dataclass +class CMsgGCToGCUniverseStartup(betterproto.Message): + is_initial_startup: bool = betterproto.bool_field(1) + + +@dataclass +class CMsgGCToGCUniverseStartupResponse(betterproto.Message): + eresult: int = betterproto.int32_field(1) + + +@dataclass +class CGCToGCMsgMasterStartupComplete(betterproto.Message): + gc_info: list["CGCToGCMsgMasterStartupCompleteGCInfo"] = betterproto.message_field(1) + + +@dataclass +class CGCToGCMsgMasterStartupCompleteGCInfo(betterproto.Message): + dir_index: int = betterproto.int32_field(1) + machine_name: str = betterproto.string_field(2) + + +@dataclass +class CGCToGCMsgRouted(betterproto.Message): + msg_type: int = betterproto.uint32_field(1) + sender_id: float = betterproto.fixed64_field(2) + net_message: bytes = betterproto.bytes_field(3) + + +@dataclass +class CGCToGCMsgRoutedReply(betterproto.Message): + msg_type: int = betterproto.uint32_field(1) + net_message: bytes = betterproto.bytes_field(2) + + +@dataclass +class CMsgGCUpdateSubGCSessionInfo(betterproto.Message): + updates: list["CMsgGCUpdateSubGCSessionInfoCMsgUpdate"] = betterproto.message_field(1) + + +@dataclass +class CMsgGCUpdateSubGCSessionInfoCMsgUpdate(betterproto.Message): + steamid: float = betterproto.fixed64_field(1) + ip: float = betterproto.fixed32_field(2) + trusted: bool = betterproto.bool_field(3) + + +@dataclass +class CMsgGCRequestSubGCSessionInfo(betterproto.Message): + steamid: float = betterproto.fixed64_field(1) + + +@dataclass +class CMsgGCRequestSubGCSessionInfoResponse(betterproto.Message): + ip: float = betterproto.fixed32_field(1) + trusted: bool = betterproto.bool_field(2) + port: int = betterproto.uint32_field(3) + success: bool = betterproto.bool_field(4) + + +@dataclass +class CMsgSOCacheHaveVersion(betterproto.Message): + soid: "CMsgSOIDOwner" = betterproto.message_field(1) + version: float = betterproto.fixed64_field(2) + service_id: int = betterproto.uint32_field(3) + cached_file_version: int = betterproto.uint32_field(4) + + +class CMsgClientHello(GCProtobufMessage, msg=EGCBaseClientMsg.k_EMsgGCClientHello): + version: int = betterproto.uint32_field(1) + socache_have_versions: list["CMsgSOCacheHaveVersion"] = betterproto.message_field(2) + client_session_need: int = betterproto.uint32_field(3) + client_launcher: "PartnerAccountType" = betterproto.enum_field(4) + secret_key: str = betterproto.string_field(5) + client_language: int = betterproto.uint32_field(6) + engine: "ESourceEngine" = betterproto.enum_field(7) + steamdatagram_login: bytes = betterproto.bytes_field(8) + platform_id: int = betterproto.uint32_field(9) + game_msg: bytes = betterproto.bytes_field(10) + os_type: int = betterproto.int32_field(11) + render_system: int = betterproto.uint32_field(12) + render_system_req: int = betterproto.uint32_field(13) + screen_width: int = betterproto.uint32_field(14) + screen_height: int = betterproto.uint32_field(15) + screen_refresh: int = betterproto.uint32_field(16) + render_width: int = betterproto.uint32_field(17) + render_height: int = betterproto.uint32_field(18) + swap_width: int = betterproto.uint32_field(19) + swap_height: int = betterproto.uint32_field(20) + is_steam_china: bool = betterproto.bool_field(22) + is_steam_china_client: bool = betterproto.bool_field(24) + platform_name: str = betterproto.string_field(23) + + +@dataclass +class CMsgClientWelcome(betterproto.Message): + version: int = betterproto.uint32_field(1) + game_data: bytes = betterproto.bytes_field(2) + outofdate_subscribed_caches: list["CMsgSOCacheSubscribed"] = betterproto.message_field(3) + uptodate_subscribed_caches: list["CMsgSOCacheSubscriptionCheck"] = betterproto.message_field(4) + location: "CMsgClientWelcomeLocation" = betterproto.message_field(5) + save_game_key: bytes = betterproto.bytes_field(6) + gc_socache_file_version: int = betterproto.uint32_field(9) + txn_country_code: str = betterproto.string_field(10) + game_data2: bytes = betterproto.bytes_field(11) + rtime32_gc_welcome_timestamp: int = betterproto.uint32_field(12) + currency: int = betterproto.uint32_field(13) + balance: int = betterproto.uint32_field(14) + balance_url: str = betterproto.string_field(15) + has_accepted_china_ssa: bool = betterproto.bool_field(16) + is_banned_steam_china: bool = betterproto.bool_field(17) + additional_welcome_msgs: "CExtraMsgBlock" = betterproto.message_field(18) + steam_learn_server_info: "CMsgSteamLearnServerInfo" = betterproto.message_field(20) + + +@dataclass +class CMsgClientWelcomeLocation(betterproto.Message): + latitude: float = betterproto.float_field(1) + longitude: float = betterproto.float_field(2) + country: str = betterproto.string_field(3) + + +@dataclass +class CMsgConnectionStatus(betterproto.Message): + status: "GCConnectionStatus" = betterproto.enum_field(1) + client_session_need: int = betterproto.uint32_field(2) + queue_position: int = betterproto.int32_field(3) + queue_size: int = betterproto.int32_field(4) + wait_seconds: int = betterproto.int32_field(5) + estimated_wait_seconds_remaining: int = betterproto.int32_field(6) + + +@dataclass +class CMsgGCToGCSOCacheSubscribe(betterproto.Message): + subscriber: float = betterproto.fixed64_field(1) + subscribe_to_id: float = betterproto.fixed64_field(2) + sync_version: float = betterproto.fixed64_field(3) + have_versions: list["CMsgGCToGCSOCacheSubscribeCMsgHaveVersions"] = betterproto.message_field(4) + subscribe_to_type: int = betterproto.uint32_field(5) + + +@dataclass +class CMsgGCToGCSOCacheSubscribeCMsgHaveVersions(betterproto.Message): + service_id: int = betterproto.uint32_field(1) + version: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgGCToGCSOCacheUnsubscribe(betterproto.Message): + subscriber: float = betterproto.fixed64_field(1) + unsubscribe_from_id: float = betterproto.fixed64_field(2) + unsubscribe_from_type: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgGCClientPing(betterproto.Message): + pass + + +@dataclass +class CMsgGCToGCForwardAccountDetails(betterproto.Message): + steamid: float = betterproto.fixed64_field(1) + account_details: CGCSystemMsg_GetAccountDetails_Response = betterproto.message_field(2) + age_seconds: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgGCToGCLoadSessionSOCache(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + forward_account_details: "CMsgGCToGCForwardAccountDetails" = betterproto.message_field(2) + + +@dataclass +class CMsgGCToGCLoadSessionSOCacheResponse(betterproto.Message): + pass + + +@dataclass +class CMsgGCToGCUpdateSessionStats(betterproto.Message): + user_sessions: int = betterproto.uint32_field(1) + server_sessions: int = betterproto.uint32_field(2) + in_logon_surge: bool = betterproto.bool_field(3) + + +@dataclass +class CMsgGCToClientRequestDropped(betterproto.Message): + pass + + +@dataclass +class CWorkshop_PopulateItemDescriptions_Request(betterproto.Message): + appid: int = betterproto.uint32_field(1) + languages: list[ + "CWorkshop_PopulateItemDescriptions_RequestItemDescriptionsLanguageBlock" + ] = betterproto.message_field(2) + + +@dataclass +class CWorkshop_PopulateItemDescriptions_RequestSingleItemDescription(betterproto.Message): + gameitemid: int = betterproto.uint32_field(1) + item_description: str = betterproto.string_field(2) + + +@dataclass +class CWorkshop_PopulateItemDescriptions_RequestItemDescriptionsLanguageBlock(betterproto.Message): + language: str = betterproto.string_field(1) + descriptions: list["CWorkshop_PopulateItemDescriptions_RequestSingleItemDescription"] = betterproto.message_field(2) + + +@dataclass +class CWorkshop_GetContributors_Request(betterproto.Message): + appid: int = betterproto.uint32_field(1) + gameitemid: int = betterproto.uint32_field(2) + + +@dataclass +class CWorkshop_GetContributors_Response(betterproto.Message): + contributors: list[float] = betterproto.fixed64_field(1) + + +@dataclass +class CWorkshop_SetItemPaymentRules_Request(betterproto.Message): + appid: int = betterproto.uint32_field(1) + gameitemid: int = betterproto.uint32_field(2) + associated_workshop_files: list[ + "CWorkshop_SetItemPaymentRules_RequestWorkshopItemPaymentRule" + ] = betterproto.message_field(3) + partner_accounts: list["CWorkshop_SetItemPaymentRules_RequestPartnerItemPaymentRule"] = betterproto.message_field(4) + validate_only: bool = betterproto.bool_field(5) + make_workshop_files_subscribable: bool = betterproto.bool_field(6) + associated_workshop_file_for_direct_payments: "CWorkshop_SetItemPaymentRules_RequestWorkshopDirectPaymentRule" = ( + betterproto.message_field(7) + ) + + +@dataclass +class CWorkshop_SetItemPaymentRules_RequestWorkshopItemPaymentRule(betterproto.Message): + workshop_file_id: int = betterproto.uint64_field(1) + revenue_percentage: float = betterproto.float_field(2) + rule_description: str = betterproto.string_field(3) + rule_type: int = betterproto.uint32_field(4) + + +@dataclass +class CWorkshop_SetItemPaymentRules_RequestWorkshopDirectPaymentRule(betterproto.Message): + workshop_file_id: int = betterproto.uint64_field(1) + rule_description: str = betterproto.string_field(2) + + +@dataclass +class CWorkshop_SetItemPaymentRules_RequestPartnerItemPaymentRule(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + revenue_percentage: float = betterproto.float_field(2) + rule_description: str = betterproto.string_field(3) + + +@dataclass +class CWorkshop_SetItemPaymentRules_Response(betterproto.Message): + validation_errors: list[str] = betterproto.string_field(1) + + +@dataclass +class CCommunity_ClanAnnouncementInfo(betterproto.Message): + gid: int = betterproto.uint64_field(1) + clanid: int = betterproto.uint64_field(2) + posterid: int = betterproto.uint64_field(3) + headline: str = betterproto.string_field(4) + posttime: int = betterproto.uint32_field(5) + updatetime: int = betterproto.uint32_field(6) + body: str = betterproto.string_field(7) + commentcount: int = betterproto.int32_field(8) + tags: list[str] = betterproto.string_field(9) + language: int = betterproto.int32_field(10) + hidden: bool = betterproto.bool_field(11) + forum_topic_id: float = betterproto.fixed64_field(12) + + +@dataclass +class CCommunity_GetClanAnnouncements_Request(betterproto.Message): + steamid: int = betterproto.uint64_field(1) + offset: int = betterproto.uint32_field(2) + count: int = betterproto.uint32_field(3) + maxchars: int = betterproto.uint32_field(4) + strip_html: bool = betterproto.bool_field(5) + required_tags: list[str] = betterproto.string_field(6) + require_no_tags: bool = betterproto.bool_field(7) + language_preference: list[int] = betterproto.uint32_field(8) + hidden_only: bool = betterproto.bool_field(9) + only_gid: bool = betterproto.bool_field(10) + rtime_oldest_date: int = betterproto.uint32_field(11) + include_hidden: bool = betterproto.bool_field(12) + include_partner_events: bool = betterproto.bool_field(13) + + +@dataclass +class CCommunity_GetClanAnnouncements_Response(betterproto.Message): + maxchars: int = betterproto.uint32_field(1) + strip_html: bool = betterproto.bool_field(2) + announcements: list["CCommunity_ClanAnnouncementInfo"] = betterproto.message_field(3) + + +@dataclass +class CBroadcast_PostGameDataFrame_Request(betterproto.Message): + appid: int = betterproto.uint32_field(1) + steamid: float = betterproto.fixed64_field(2) + broadcast_id: float = betterproto.fixed64_field(3) + frame_data: bytes = betterproto.bytes_field(4) + + +@dataclass +class CMsgSerializedSOCache(betterproto.Message): + file_version: int = betterproto.uint32_field(1) + caches: list["CMsgSerializedSOCacheCache"] = betterproto.message_field(2) + gc_socache_file_version: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgSerializedSOCacheTypeCache(betterproto.Message): + type: int = betterproto.uint32_field(1) + objects: list[bytes] = betterproto.bytes_field(2) + service_id: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgSerializedSOCacheCache(betterproto.Message): + type: int = betterproto.uint32_field(1) + id: int = betterproto.uint64_field(2) + versions: list["CMsgSerializedSOCacheCacheVersion"] = betterproto.message_field(3) + type_caches: list["CMsgSerializedSOCacheTypeCache"] = betterproto.message_field(4) + + +@dataclass +class CMsgSerializedSOCacheCacheVersion(betterproto.Message): + service: int = betterproto.uint32_field(1) + version: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgGCToClientPollConvarRequest(betterproto.Message): + convar_name: str = betterproto.string_field(1) + poll_id: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgGCToClientPollConvarResponse(betterproto.Message): + poll_id: int = betterproto.uint32_field(1) + convar_value: str = betterproto.string_field(2) + + +@dataclass +class CGCMsgCompressedMsgToClient(betterproto.Message): + msg_id: int = betterproto.uint32_field(1) + compressed_msg: bytes = betterproto.bytes_field(2) + + +@dataclass +class CMsgGCToGCMasterBroadcastMessage(betterproto.Message): + users_per_second: int = betterproto.uint32_field(1) + send_to_users: bool = betterproto.bool_field(2) + send_to_servers: bool = betterproto.bool_field(3) + msg_id: int = betterproto.uint32_field(4) + msg_data: bytes = betterproto.bytes_field(5) + + +@dataclass +class CMsgGCToGCMasterSubscribeToCache(betterproto.Message): + soid_type: int = betterproto.uint32_field(1) + soid_id: float = betterproto.fixed64_field(2) + account_ids: list[int] = betterproto.uint32_field(3) + steam_ids: list[float] = betterproto.fixed64_field(4) + + +@dataclass +class CMsgGCToGCMasterSubscribeToCacheResponse(betterproto.Message): + pass + + +@dataclass +class CMsgGCToGCMasterSubscribeToCacheAsync(betterproto.Message): + subscribe_msg: "CMsgGCToGCMasterSubscribeToCache" = betterproto.message_field(1) + + +@dataclass +class CMsgGCToGCMasterUnsubscribeFromCache(betterproto.Message): + soid_type: int = betterproto.uint32_field(1) + soid_id: float = betterproto.fixed64_field(2) + account_ids: list[int] = betterproto.uint32_field(3) + steam_ids: list[float] = betterproto.fixed64_field(4) + + +@dataclass +class CMsgGCToGCMasterDestroyCache(betterproto.Message): + soid_type: int = betterproto.uint32_field(1) + soid_id: float = betterproto.fixed64_field(2) diff --git a/steam/ext/dota2/protobufs/gcsystemmsgs.py b/steam/ext/dota2/protobufs/gcsystemmsgs.py new file mode 100644 index 00000000..ef2e7921 --- /dev/null +++ b/steam/ext/dota2/protobufs/gcsystemmsgs.py @@ -0,0 +1,32 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: gcsystemmsgs.proto +# plugin: python-betterproto + +import betterproto + + +class ESOMsg(betterproto.Enum): + k_ESOMsg_Create = 21 + k_ESOMsg_Update = 22 + k_ESOMsg_Destroy = 23 + k_ESOMsg_CacheSubscribed = 24 + k_ESOMsg_CacheUnsubscribed = 25 + k_ESOMsg_UpdateMultiple = 26 + k_ESOMsg_CacheSubscriptionRefresh = 28 + k_ESOMsg_CacheSubscribedUpToDate = 29 + + +class EGCBaseClientMsg(betterproto.Enum): + k_EMsgGCPingRequest = 3001 + k_EMsgGCPingResponse = 3002 + k_EMsgGCToClientPollConvarRequest = 3003 + k_EMsgGCToClientPollConvarResponse = 3004 + k_EMsgGCCompressedMsgToClient = 3005 + k_EMsgGCCompressedMsgToClient_Legacy = 523 + k_EMsgGCToClientRequestDropped = 3006 + k_EMsgGCClientWelcome = 4004 + k_EMsgGCServerWelcome = 4005 + k_EMsgGCClientHello = 4006 + k_EMsgGCServerHello = 4007 + k_EMsgGCClientConnectionStatus = 4009 + k_EMsgGCServerConnectionStatus = 4010 diff --git a/steam/ext/dota2/protobufs/steammessages.py b/steam/ext/dota2/protobufs/steammessages.py new file mode 100644 index 00000000..e04b2575 --- /dev/null +++ b/steam/ext/dota2/protobufs/steammessages.py @@ -0,0 +1,102 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: steammessages.proto +# plugin: python-betterproto +from __future__ import annotations + +from dataclasses import dataclass + +import betterproto + + +class EGCPlatform(betterproto.Enum): + k_eGCPlatform_None = 0 + k_eGCPlatform_PC = 1 + k_eGCPlatform_Mac = 2 + k_eGCPlatform_Linux = 3 + k_eGCPlatform_Android = 4 + k_eGCPlatform_iOS = 5 + + +class GCProtoBufMsgSrc(betterproto.Enum): + GCProtoBufMsgSrc_Unspecified = 0 + GCProtoBufMsgSrc_FromSystem = 1 + GCProtoBufMsgSrc_FromSteamID = 2 + GCProtoBufMsgSrc_FromGC = 3 + GCProtoBufMsgSrc_ReplySystem = 4 + GCProtoBufMsgSrc_SpoofedSteamID = 5 + + +@dataclass +class CMsgProtoBufHeader(betterproto.Message): + client_steam_id: float = betterproto.fixed64_field(1) + client_session_id: int = betterproto.int32_field(2) + source_app_id: int = betterproto.uint32_field(3) + job_id_source: float = betterproto.fixed64_field(10) + job_id_target: float = betterproto.fixed64_field(11) + target_job_name: str = betterproto.string_field(12) + eresult: int = betterproto.int32_field(13) + error_message: str = betterproto.string_field(14) + gc_msg_src: GCProtoBufMsgSrc = betterproto.enum_field(200) + gc_dir_index_source: int = betterproto.int32_field(201) + + +@dataclass +class CGCSystemMsg_GetAccountDetails(betterproto.Message): + steamid: float = betterproto.fixed64_field(1) + appid: int = betterproto.uint32_field(2) + + +@dataclass +class CGCSystemMsg_GetAccountDetails_Response(betterproto.Message): + eresult_deprecated: int = betterproto.uint32_field(1) + account_name: str = betterproto.string_field(2) + persona_name: str = betterproto.string_field(3) + is_profile_created: bool = betterproto.bool_field(26) + is_profile_public: bool = betterproto.bool_field(4) + is_inventory_public: bool = betterproto.bool_field(5) + is_vac_banned: bool = betterproto.bool_field(7) + is_cyber_cafe: bool = betterproto.bool_field(8) + is_school_account: bool = betterproto.bool_field(9) + is_limited: bool = betterproto.bool_field(10) + is_subscribed: bool = betterproto.bool_field(11) + package: int = betterproto.uint32_field(12) + is_free_trial_account: bool = betterproto.bool_field(13) + free_trial_expiration: int = betterproto.uint32_field(14) + is_low_violence: bool = betterproto.bool_field(15) + is_account_locked_down: bool = betterproto.bool_field(16) + is_community_banned: bool = betterproto.bool_field(17) + is_trade_banned: bool = betterproto.bool_field(18) + trade_ban_expiration: int = betterproto.uint32_field(19) + accountid: int = betterproto.uint32_field(20) + suspension_end_time: int = betterproto.uint32_field(21) + currency: str = betterproto.string_field(22) + steam_level: int = betterproto.uint32_field(23) + friend_count: int = betterproto.uint32_field(24) + account_creation_time: int = betterproto.uint32_field(25) + is_steamguard_enabled: bool = betterproto.bool_field(27) + is_phone_verified: bool = betterproto.bool_field(28) + is_two_factor_auth_enabled: bool = betterproto.bool_field(29) + two_factor_enabled_time: int = betterproto.uint32_field(30) + phone_verification_time: int = betterproto.uint32_field(31) + phone_id: int = betterproto.uint64_field(33) + is_phone_identifying: bool = betterproto.bool_field(34) + rt_identity_linked: int = betterproto.uint32_field(35) + rt_birth_date: int = betterproto.uint32_field(36) + txn_country_code: str = betterproto.string_field(37) + has_accepted_china_ssa: bool = betterproto.bool_field(38) + is_banned_steam_china: bool = betterproto.bool_field(39) + + +@dataclass +class CIPLocationInfo(betterproto.Message): + ip: int = betterproto.uint32_field(1) + latitude: float = betterproto.float_field(2) + longitude: float = betterproto.float_field(3) + country: str = betterproto.string_field(4) + state: str = betterproto.string_field(5) + city: str = betterproto.string_field(6) + + +@dataclass +class CGCMsgGetIPLocationResponse(betterproto.Message): + infos: list[CIPLocationInfo] = betterproto.message_field(1) diff --git a/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py b/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py new file mode 100644 index 00000000..9ee41bc0 --- /dev/null +++ b/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py @@ -0,0 +1,530 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: steammessages_steamlearn.steamworkssdk.proto +# plugin: python-betterproto +from __future__ import annotations + +from dataclasses import dataclass + +import betterproto + + +class ESteamLearnDataType(betterproto.Enum): + STEAMLEARN_DATATYPE_INVALID = 0 + STEAMLEARN_DATATYPE_INT32 = 1 + STEAMLEARN_DATATYPE_FLOAT32 = 2 + STEAMLEARN_DATATYPE_BOOL = 3 + STEAMLEARN_DATATYPE_STRING = 4 + STEAMLEARN_DATATYPE_OBJECT = 5 + + +class ESteammLearnRegisterDataSourceResult(betterproto.Enum): + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR = 0 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_SUCCESS_CREATED = 1 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_SUCCESS_FOUND = 2 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_GENERIC = 3 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_INVALID_NAME = 4 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_INVALID_VERSION = 5 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_DATA_CHANGED = 6 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_DATA_INVALID = 7 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_FORBIDDEN = 8 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_INVALID_TIMESTAMP = 9 + STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_DISABLED = 10 + + +class ESteamLearnCacheDataResult(betterproto.Enum): + STEAMLEARN_CACHE_DATA_ERROR = 0 + STEAMLEARN_CACHE_DATA_SUCCESS = 1 + STEAMLEARN_CACHE_DATA_ERROR_UNKNOWN_DATA_SOURCE = 2 + STEAMLEARN_CACHE_DATA_ERROR_UNCACHED_DATA_SOURCE = 3 + STEAMLEARN_CACHE_DATA_ERROR_INVALID_KEYS = 4 + STEAMLEARN_CACHE_DATA_ERROR_FORBIDDEN = 5 + STEAMLEARN_CACHE_DATA_ERROR_INVALID_TIMESTAMP = 6 + STEAMLEARN_CACHE_DATA_DISABLED = 7 + + +class ESteamLearnSnapshotProjectResult(betterproto.Enum): + STEAMLEARN_SNAPSHOT_PROJECT_ERROR = 0 + STEAMLEARN_SNAPSHOT_PROJECT_SUCCESS_STORED = 1 + STEAMLEARN_SNAPSHOT_PROJECT_SUCCESS_QUEUED = 2 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INVALID_PROJECT_ID = 3 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_UNKNOWN_DATA_SOURCE = 4 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INVALID_DATA_SOURCE_KEY = 5 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_MISSING_CACHE_DURATION = 6 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_NO_PUBLISHED_CONFIG = 7 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_FORBIDDEN = 8 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INVALID_TIMESTAMP = 9 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INTERNAL_DATA_SOURCE_ERROR = 10 + STEAMLEARN_SNAPSHOT_PROJECT_DISABLED = 11 + STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INVALID_PUBLISHED_VERSION = 12 + + +class ESteamLearnGetHMACKeysResult(betterproto.Enum): + STEAMLEARN_GET_HMAC_KEYS_SUCCESS = 0 + + +class ESteamLearnInferenceResult(betterproto.Enum): + STEAMLEARN_INFERENCE_ERROR = 0 + STEAMLEARN_INFERENCE_SUCCESS = 1 + STEAMLEARN_INFERENCE_ERROR_INVALID_PROJECT_ID = 2 + STEAMLEARN_INFERENCE_ERROR_MISSING_CACHED_SCHEMA_DATA = 3 + STEAMLEARN_INFERENCE_ERROR_NO_PUBLISHED_CONFIG = 4 + STEAMLEARN_INFERENCE_ERROR_FORBIDDEN = 5 + STEAMLEARN_INFERENCE_ERROR_INVALID_TIMESTAMP = 6 + STEAMLEARN_INFERENCE_ERROR_INVALID_PUBLISHED_VERSION = 7 + STEAMLEARN_INFERENCE_ERROR_NO_FETCH_ID_FOUND = 8 + STEAMLEARN_INFERENCE_ERROR_TOO_BUSY = 9 + + +class ESteamLearnInferenceMetadataResult(betterproto.Enum): + STEAMLEARN_INFERENCE_METADATA_ERROR = 0 + STEAMLEARN_INFERENCE_METADATA_SUCCESS = 1 + STEAMLEARN_INFERENCE_METADATA_ERROR_INVALID_PROJECT_ID = 2 + STEAMLEARN_INFERENCE_METADATA_ERROR_NO_PUBLISHED_CONFIG = 3 + STEAMLEARN_INFERENCE_METADATA_ERROR_FORBIDDEN = 4 + STEAMLEARN_INFERENCE_METADATA_ERROR_INVALID_TIMESTAMP = 5 + STEAMLEARN_INFERENCE_METADATA_ERROR_INVALID_PUBLISHED_VERSION = 6 + STEAMLEARN_INFERENCE_METADATA_ERROR_NO_FETCH_ID_FOUND = 7 + + +@dataclass +class CMsgSteamLearnDataSourceDescObject(betterproto.Message): + elements: list["CMsgSteamLearnDataSourceDescElement"] = betterproto.message_field(1) + + +@dataclass +class CMsgSteamLearnDataSourceDescElement(betterproto.Message): + name: str = betterproto.string_field(1) + data_type: ESteamLearnDataType = betterproto.enum_field(2) + object: CMsgSteamLearnDataSourceDescObject = betterproto.message_field(3) + count: int = betterproto.uint32_field(4) + + +@dataclass +class CMsgSteamLearnDataSource(betterproto.Message): + id: int = betterproto.uint32_field(1) + name: str = betterproto.string_field(2) + version: int = betterproto.uint32_field(3) + source_description: str = betterproto.string_field(4) + structure: CMsgSteamLearnDataSourceDescObject = betterproto.message_field(5) + structure_crc: int = betterproto.uint32_field(6) + cache_duration_seconds: int = betterproto.uint32_field(7) + + +@dataclass +class CMsgSteamLearnDataObject(betterproto.Message): + elements: list[CMsgSteamLearnDataElement] = betterproto.message_field(1) + + +@dataclass +class CMsgSteamLearnDataElement(betterproto.Message): + name: str = betterproto.string_field(1) + data_int32s: list[int] = betterproto.int32_field(20) + data_floats: list[float] = betterproto.float_field(21) + data_bools: list[bool] = betterproto.bool_field(22) + data_strings: list[str] = betterproto.string_field(23) + data_objects: list[CMsgSteamLearnDataObject] = betterproto.message_field(24) + + +@dataclass +class CMsgSteamLearnData(betterproto.Message): + data_source_id: int = betterproto.uint32_field(1) + keys: list[int] = betterproto.uint64_field(2) + data_object: CMsgSteamLearnDataObject = betterproto.message_field(3) + + +@dataclass +class CMsgSteamLearnDataList(betterproto.Message): + data: list[CMsgSteamLearnData] = betterproto.message_field(1) + + +@dataclass +class CMsgSteamLearn_AccessData(betterproto.Message): + publisher_id: int = betterproto.uint32_field(1) + timestamp: int = betterproto.uint32_field(2) + random_value: int = betterproto.uint64_field(3) + + +@dataclass +class CMsgSteamLearn_RegisterDataSource_Request(betterproto.Message): + access_token: str = betterproto.string_field(1) + access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) + data_source: CMsgSteamLearnDataSource = betterproto.message_field(3) + + +@dataclass +class CMsgSteamLearn_RegisterDataSource_Response(betterproto.Message): + result: ESteammLearnRegisterDataSourceResult = betterproto.enum_field(1) + data_source: CMsgSteamLearnDataSource = betterproto.message_field(2) + + +@dataclass +class CMsgSteamLearn_CacheData_Request(betterproto.Message): + access_token: str = betterproto.string_field(1) + access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) + data: CMsgSteamLearnData = betterproto.message_field(3) + + +@dataclass +class CMsgSteamLearn_CacheData_Response(betterproto.Message): + cache_data_result: ESteamLearnCacheDataResult = betterproto.enum_field(1) + + +@dataclass +class CMsgSteamLearn_SnapshotProject_Request(betterproto.Message): + access_token: str = betterproto.string_field(1) + access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) + project_id: int = betterproto.uint32_field(3) + published_version: int = betterproto.uint32_field(7) + keys: list[int] = betterproto.uint64_field(4) + data: list[CMsgSteamLearnData] = betterproto.message_field(5) + pending_data_limit_seconds: int = betterproto.uint32_field(6) + + +@dataclass +class CMsgSteamLearn_SnapshotProject_Response(betterproto.Message): + snapshot_result: ESteamLearnSnapshotProjectResult = betterproto.enum_field(1) + + +@dataclass +class CMsgSteamLearn_BatchOperation_Request(betterproto.Message): + cache_data_requests: list[CMsgSteamLearn_CacheData_Request] = betterproto.message_field(1) + snapshot_requests: list[CMsgSteamLearn_SnapshotProject_Request] = betterproto.message_field(2) + + +@dataclass +class CMsgSteamLearn_BatchOperation_Response(betterproto.Message): + cache_data_responses: list[CMsgSteamLearn_CacheData_Response] = betterproto.message_field(1) + snapshot_responses: list[CMsgSteamLearn_SnapshotProject_Response] = betterproto.message_field(2) + + +@dataclass +class CMsgSteamLearnHMACKeys(betterproto.Message): + register_data_source_key: str = betterproto.string_field(1) + cache_data_keys: list[CMsgSteamLearnHMACKeysCacheDataKeys] = betterproto.message_field(2) + snapshot_project_keys: list[CMsgSteamLearnHMACKeysSnapshotProjectKeys] = betterproto.message_field(3) + + +@dataclass +class CMsgSteamLearnHMACKeysCacheDataKeys(betterproto.Message): + data_source_id: int = betterproto.uint32_field(1) + version: int = betterproto.uint32_field(3) + key: str = betterproto.string_field(2) + + +@dataclass +class CMsgSteamLearnHMACKeysSnapshotProjectKeys(betterproto.Message): + project_id: int = betterproto.uint32_field(1) + published_version: int = betterproto.uint32_field(3) + key: str = betterproto.string_field(2) + + +@dataclass +class CMsgSteamLearn_GetHMACKeys_Request(betterproto.Message): + appid: int = betterproto.uint32_field(1) + + +@dataclass +class CMsgSteamLearn_GetHMACKeys_Response(betterproto.Message): + result: ESteamLearnGetHMACKeysResult = betterproto.enum_field(1) + keys: CMsgSteamLearnHMACKeys = betterproto.message_field(2) + + +@dataclass +class CMsgSteamLearn_Inference_Request(betterproto.Message): + access_token: str = betterproto.string_field(1) + access_data: "CMsgSteamLearn_AccessData" = betterproto.message_field(2) + project_id: int = betterproto.uint32_field(3) + published_version: int = betterproto.uint32_field(4) + override_train_id: int = betterproto.uint32_field(5) + data: "CMsgSteamLearnDataList" = betterproto.message_field(6) + additional_data: list[float] = betterproto.float_field(7) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_Request(betterproto.Message): + access_token: str = betterproto.string_field(1) + access_data: "CMsgSteamLearn_AccessData" = betterproto.message_field(2) + project_id: int = betterproto.uint32_field(3) + published_version: int = betterproto.uint32_field(4) + override_train_id: int = betterproto.uint32_field(5) + + +@dataclass +class CMsgSteamLearn_InferenceMetadataBackend_Request(betterproto.Message): + project_id: int = betterproto.uint32_field(1) + fetch_id: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_Response(betterproto.Message): + inference_metadata_result: "ESteamLearnInferenceMetadataResult" = betterproto.enum_field(1) + row_range: "CMsgSteamLearn_InferenceMetadata_ResponseRowRange" = betterproto.message_field(2) + ranges: list["CMsgSteamLearn_InferenceMetadata_ResponseRange"] = betterproto.message_field(3) + std_devs: list["CMsgSteamLearn_InferenceMetadata_ResponseStdDev"] = betterproto.message_field(4) + compact_tables: list["CMsgSteamLearn_InferenceMetadata_ResponseCompactTable"] = betterproto.message_field(5) + kmeans: list["CMsgSteamLearn_InferenceMetadata_ResponseKMeans"] = betterproto.message_field(6) + snapshot_histogram: "CMsgSteamLearn_InferenceMetadata_ResponseSnapshotHistogram" = betterproto.message_field(7) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseRowRange(betterproto.Message): + min_row: int = betterproto.uint64_field(1) + max_row: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseRange(betterproto.Message): + data_element_path: str = betterproto.string_field(1) + min_value: float = betterproto.float_field(2) + max_value: float = betterproto.float_field(3) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseStdDev(betterproto.Message): + data_element_path: str = betterproto.string_field(1) + mean: float = betterproto.float_field(2) + std_dev: float = betterproto.float_field(3) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseCompactTable(betterproto.Message): + name: str = betterproto.string_field(1) + map_values: list["CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry"] = betterproto.message_field( + 2 + ) + map_mappings: list[ + "CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapMappingsEntry" + ] = betterproto.message_field(3) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry(betterproto.Message): + value: int = betterproto.uint32_field(1) + mapping: int = betterproto.uint32_field(2) + count: int = betterproto.uint64_field(3) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry(betterproto.Message): + key: int = betterproto.uint32_field(1) + value: "CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry" = betterproto.message_field(2) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapMappingsEntry(betterproto.Message): + key: int = betterproto.uint32_field(1) + value: "CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry" = betterproto.message_field(2) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseKMeans(betterproto.Message): + name: str = betterproto.string_field(1) + clusters: list["CMsgSteamLearn_InferenceMetadata_ResponseKMeansCluster"] = betterproto.message_field(2) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseKMeansCluster(betterproto.Message): + x: float = betterproto.float_field(1) + y: float = betterproto.float_field(2) + radius: float = betterproto.float_field(3) + radius_75pct: float = betterproto.float_field(4) + radius_50pct: float = betterproto.float_field(5) + radius_25pct: float = betterproto.float_field(6) + + +@dataclass +class CMsgSteamLearn_InferenceMetadata_ResponseSnapshotHistogram(betterproto.Message): + min_value: float = betterproto.float_field(1) + max_value: float = betterproto.float_field(2) + num_buckets: int = betterproto.uint32_field(3) + bucket_counts: list[int] = betterproto.uint32_field(4) + + +@dataclass +class CMsgSteamLearn_InferenceBackend_Response(betterproto.Message): + outputs: list["CMsgSteamLearn_InferenceBackend_ResponseOutput"] = betterproto.message_field(1) + + +@dataclass +class CMsgSteamLearn_InferenceBackend_ResponseBinaryCrossEntropyOutput(betterproto.Message): + value: float = betterproto.float_field(1) + + +@dataclass +class CMsgSteamLearn_InferenceBackend_ResponseMutliBinaryCrossEntropyOutput(betterproto.Message): + weight: list[float] = betterproto.float_field(1) + value: list[float] = betterproto.float_field(2) + + +@dataclass +class CMsgSteamLearn_InferenceBackend_ResponseCategoricalCrossEntropyOutput(betterproto.Message): + weight: list[float] = betterproto.float_field(1) + value: list[float] = betterproto.float_field(2) + + +@dataclass +class CMsgSteamLearn_InferenceBackend_ResponseOutput(betterproto.Message): + binary_crossentropy: CMsgSteamLearn_InferenceBackend_ResponseBinaryCrossEntropyOutput = betterproto.message_field( + 1, group="ResponseType" + ) + categorical_crossentropy: CMsgSteamLearn_InferenceBackend_ResponseCategoricalCrossEntropyOutput = ( + betterproto.message_field(2, group="ResponseType") + ) + multi_binary_crossentropy: CMsgSteamLearn_InferenceBackend_ResponseMutliBinaryCrossEntropyOutput = ( + betterproto.message_field(3, group="ResponseType") + ) + + +@dataclass +class CMsgSteamLearn_Inference_Response(betterproto.Message): + inference_result: ESteamLearnInferenceResult = betterproto.enum_field(1) + backend_response: CMsgSteamLearn_InferenceBackend_Response = betterproto.message_field(2) + + +class SteamLearnStub(betterproto.ServiceStub): + async def register_data_source( + self, + *, + access_token: str = "", + access_data: CMsgSteamLearn_AccessData | None = None, + data_source: CMsgSteamLearnDataSource | None = None, + ) -> CMsgSteamLearn_RegisterDataSource_Response: + request = CMsgSteamLearn_RegisterDataSource_Request() + request.access_token = access_token + if access_data is not None: + request.access_data = access_data + if data_source is not None: + request.data_source = data_source + + return await self._unary_unary( + "/.SteamLearn/RegisterDataSource", + request, + CMsgSteamLearn_RegisterDataSource_Response, + ) + + async def cache_data( + self, + *, + access_token: str = "", + access_data: CMsgSteamLearn_AccessData | None = None, + data: CMsgSteamLearnData | None = None, + ) -> CMsgSteamLearn_CacheData_Response: + request = CMsgSteamLearn_CacheData_Request() + request.access_token = access_token + if access_data is not None: + request.access_data = access_data + if data is not None: + request.data = data + + return await self._unary_unary( + "/.SteamLearn/CacheData", + request, + CMsgSteamLearn_CacheData_Response, + ) + + async def snapshot_project( + self, + *, + access_token: str = "", + access_data: CMsgSteamLearn_AccessData | None = None, + project_id: int = 0, + published_version: int = 0, + keys: list[int] = [], + data: list[CMsgSteamLearnData] = [], + pending_data_limit_seconds: int = 0, + ) -> CMsgSteamLearn_SnapshotProject_Response: + request = CMsgSteamLearn_SnapshotProject_Request() + request.access_token = access_token + if access_data is not None: + request.access_data = access_data + request.project_id = project_id + request.published_version = published_version + request.keys = keys + if data is not None: + request.data = data + request.pending_data_limit_seconds = pending_data_limit_seconds + + return await self._unary_unary( + "/.SteamLearn/SnapshotProject", + request, + CMsgSteamLearn_SnapshotProject_Response, + ) + + async def batch_operation( + self, + *, + cache_data_requests: list[CMsgSteamLearn_CacheData_Request] = [], + snapshot_requests: list[CMsgSteamLearn_SnapshotProject_Request] = [], + ) -> CMsgSteamLearn_BatchOperation_Response: + request = CMsgSteamLearn_BatchOperation_Request() + if cache_data_requests is not None: + request.cache_data_requests = cache_data_requests + if snapshot_requests is not None: + request.snapshot_requests = snapshot_requests + + return await self._unary_unary( + "/.SteamLearn/BatchOperation", + request, + CMsgSteamLearn_BatchOperation_Response, + ) + + async def get_h_m_a_c_keys(self, *, appid: int = 0) -> CMsgSteamLearn_GetHMACKeys_Response: + request = CMsgSteamLearn_GetHMACKeys_Request() + request.appid = appid + + return await self._unary_unary( + "/.SteamLearn/GetHMACKeys", + request, + CMsgSteamLearn_GetHMACKeys_Response, + ) + + async def inference( + self, + *, + access_token: str = "", + access_data: CMsgSteamLearn_AccessData | None = None, + project_id: int = 0, + published_version: int = 0, + override_train_id: int = 0, + data: CMsgSteamLearnDataList | None = None, + additional_data: list[float] = [], + ) -> CMsgSteamLearn_Inference_Response: + request = CMsgSteamLearn_Inference_Request() + request.access_token = access_token + if access_data is not None: + request.access_data = access_data + request.project_id = project_id + request.published_version = published_version + request.override_train_id = override_train_id + if data is not None: + request.data = data + request.additional_data = additional_data + + return await self._unary_unary( + "/.SteamLearn/Inference", + request, + CMsgSteamLearn_Inference_Response, + ) + + async def inference_metadata( + self, + *, + access_token: str = "", + access_data: CMsgSteamLearn_AccessData | None = None, + project_id: int = 0, + published_version: int = 0, + override_train_id: int = 0, + ) -> CMsgSteamLearn_InferenceMetadata_Response: + request = CMsgSteamLearn_InferenceMetadata_Request() + request.access_token = access_token + if access_data is not None: + request.access_data = access_data + request.project_id = project_id + request.published_version = published_version + request.override_train_id = override_train_id + + return await self._unary_unary( + "/.SteamLearn/InferenceMetadata", + request, + CMsgSteamLearn_InferenceMetadata_Response, + ) diff --git a/steam/ext/dota2/protobufs/steammessages_unified_base/steamworkssdk.py b/steam/ext/dota2/protobufs/steammessages_unified_base/steamworkssdk.py new file mode 100644 index 00000000..7af6612d --- /dev/null +++ b/steam/ext/dota2/protobufs/steammessages_unified_base/steamworkssdk.py @@ -0,0 +1,10 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: steammessages_unified_base.steamworkssdk.proto +# plugin: python-betterproto + +import betterproto + + +class EProtoExecutionSite(betterproto.Enum): + k_EProtoExecutionSiteUnknown = 0 + k_EProtoExecutionSiteSteamClient = 3 From e21b9efb85fe427ae92bd20565f5130c8b25ee58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 24 Jan 2024 00:05:41 +0300 Subject: [PATCH 02/50] =?UTF-8?q?=F0=9F=90=B8Initial=20implementation=20fo?= =?UTF-8?q?r=20Dota2=20GC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit only introduces one method `fetch_top_source_tv_games` --- steam/ext/dota2/__init__.py | 10 +++ steam/ext/dota2/client.py | 127 ++++++++++++++++++++++++++++++++++++ steam/ext/dota2/state.py | 20 ++++++ 3 files changed, 157 insertions(+) create mode 100644 steam/ext/dota2/__init__.py create mode 100644 steam/ext/dota2/client.py create mode 100644 steam/ext/dota2/state.py diff --git a/steam/ext/dota2/__init__.py b/steam/ext/dota2/__init__.py new file mode 100644 index 00000000..ce837571 --- /dev/null +++ b/steam/ext/dota2/__init__.py @@ -0,0 +1,10 @@ +""" +steam.ext.dota2 +~~~~~~~~~~~~~~ + +A library for interacting with the Dota 2 Game Coordinator. + +Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE +""" + +from .client import * diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py new file mode 100644 index 00000000..6383f8a9 --- /dev/null +++ b/steam/ext/dota2/client.py @@ -0,0 +1,127 @@ +"""Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE""" + +from __future__ import annotations + +import asyncio +from typing import Final, Literal + +from ..._const import timeout +from ..._gc import Client as Client_ +from ...app import DOTA2 +from ...ext import commands +from ...utils import MISSING +from .protobufs.dota_gcmessages_client_watch import ( + CMsgClientToGCFindTopSourceTVGames, + CMsgGCToClientFindTopSourceTVGamesResponse, +) +from .state import GCState # noqa: TCH001 + +__all__ = ( + "Client", + "Bot", +) + + +class Client(Client_): + """Represents a client connection that connects to Steam. This class is used to interact with the Steam API, CMs + and the Dota 2 Game Coordinator. + + :class:`Client` is a subclass of :class:`steam.Client`, so whatever you can do with :class:`steam.Client` you can + do with :class:`Client`. + """ + + _APP: Final = DOTA2 + _state: GCState # type: ignore # PEP 705 + + async def fetch_top_source_tv_games( + self, + *, + search_key: str = MISSING, + league_id: int = MISSING, + hero_id: int = MISSING, + start_game: Literal[0, 10, 20, 30, 40, 50, 60, 70, 80, 90] = 0, + game_list_index: int = MISSING, + lobby_ids: list[int] = MISSING, + ) -> list[CMsgGCToClientFindTopSourceTVGamesResponse]: + """Fetch Top Source TV Games. + + This functionality is somewhat identical to Watch Tab in normal Dota 2 application. + It fetches short data for the following currently on-going Dota 2 matches: + + * tournament games + * highest mmr games + * specific lobbies, like friends' games by their lobby_ids + + Note + ------- + Note that the following documentation for arguments to query against is rather observant + than from official sources. So, please, if you know more or description is incorrect, contact us. + + Parameters + ---------- + search_key : :class: `str`, optional + Unknown purpose. + league_id : :class: `int`, optional + `league_id` for the professional tournament. + hero_id : :class: `int`, optional + `hero_id` to filter results by, just like in-client Watch Tab feature. + start_game : :class: `Literal[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]`, optional + This argument controls how many responses the game coordinator should return. + For example, `start_game=0` returns a list with 1 Response, + `start_game=90` returns a list of 10 Responses. + Game coordinator fills each response in consequent manner with games that satisfy keyword arguments + or with currently live highest average MMR games in case no other argument was given. + game_list_index : :class: `int`, optional + Only get responses matching `game_list_index`. Responses from Game Coordinator change + from time to time. The `game_list_index` indicates that those responses belong to the same chunk. + lobby_ids : :class: `list[int]`, optional + Lobby ids to query against. + + Returns + ------- + list[dota_gcmessages_client_watch.CMsgGCToClientFindTopSourceTVGamesResponse] + The list of responses from Dota 2 Coordinator. + Those are grouped into grouped into chunks of 10 games. + + Raises + ------ + asyncio.TimeoutError + Request time-outed. The reason for this might be inappropriate combination of keyword arguments, + inappropriate argument values or simply Dota 2 Game Coordinator being down. + """ + kwargs = locals() + kwargs.pop("self") + kwargs = {key: value for key, value in kwargs.items() if value is not MISSING} + + def start_game_check(start_game: int): + def predicate(msg: CMsgGCToClientFindTopSourceTVGamesResponse) -> bool: + return msg.start_game == start_game + + return predicate + + futures = [ + self._state.ws.gc_wait_for( + CMsgGCToClientFindTopSourceTVGamesResponse, + check=start_game_check(game_counter), + ) + for game_counter in list(range(0, start_game + 1, 10)) + ] + + await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(**kwargs)) + + try: + async with timeout(10.0): + return await asyncio.gather(*futures) + except asyncio.TimeoutError: + raise asyncio.TimeoutError( + "Request time-outed. The reason might be inappropriate combination of keyword arguments, " + + "inappropriate argument values or simply Dota 2 Game Coordinator being down." + ) + + +class Bot(commands.Bot, Client): + """Represents a Steam bot. + + :class:`Bot` is a subclass of :class:`~steam.ext.commands.Bot`, so whatever you can do with + :class:`~steam.ext.commands.Bot` you can do with :class:`Bot`. + """ diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py new file mode 100644 index 00000000..644f728d --- /dev/null +++ b/steam/ext/dota2/state.py @@ -0,0 +1,20 @@ +"""Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +from ..._gc import GCState as GCState_ +from ...app import DOTA2 +from .protobufs.gcsdk_gcmessages import CMsgClientHello + +if TYPE_CHECKING: + from .client import Client + + +class GCState(GCState_[Any]): # todo: implement basket-analogy for dota2 + client: Client # type: ignore # PEP 705 + _APP = DOTA2 # type: ignore + + def _get_gc_message(self) -> CMsgClientHello: + return CMsgClientHello() From 513ea0c47490ed2dd406d9875eb90de1f48e8365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 24 Jan 2024 00:32:22 +0300 Subject: [PATCH 03/50] =?UTF-8?q?=F0=9F=93=83Initial=20docs=20for=20ext.do?= =?UTF-8?q?ta2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ext/dota2/api.rst | 28 ++++++++++++++++++++++++++++ docs/ext/dota2/index.md | 11 +++++++++++ docs/index.md | 2 ++ 3 files changed, 41 insertions(+) create mode 100644 docs/ext/dota2/api.rst create mode 100644 docs/ext/dota2/index.md diff --git a/docs/ext/dota2/api.rst b/docs/ext/dota2/api.rst new file mode 100644 index 00000000..18f0ce2d --- /dev/null +++ b/docs/ext/dota2/api.rst @@ -0,0 +1,28 @@ +.. currentmodule:: steam.ext.dota2 + +API Reference +=============== + +The following section outlines the API of steam.py's Dota 2 extension module. + + +Client +------ + +.. attributetable:: Client + +.. autoclass:: Client + :members: + :inherited-members: + +Bot +---- + +``ext.dota2`` also provides a :class:`Bot` class, which is a subclass of :class:`Client` and :class:`steam.ext.commands.Bot`. + +.. attributetable:: steam.ext.dota2.Bot + +.. autoclass:: steam.ext.dota2.Bot + :members: + :inherited-members: + diff --git a/docs/ext/dota2/index.md b/docs/ext/dota2/index.md new file mode 100644 index 00000000..f209b324 --- /dev/null +++ b/docs/ext/dota2/index.md @@ -0,0 +1,11 @@ +(steam-ext-dota2)= + +# `steam.ext.dota2` - A Team Fortress 2 Game Coordinator client + +This extension offers the ability to interact with the Dota 2 Game Coordinator (Dota 2 GC) + +```{toctree} +:maxdepth: 2 + +api +``` diff --git a/docs/index.md b/docs/index.md index b72456e6..1824db82 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,6 +29,7 @@ steam API Reference steam.ext.commands API Reference steam.ext.csgo API Reference steam.ext.tf2 API Reference +steam.ext.dota2 API Reference ``` ## Extensions @@ -41,4 +42,5 @@ steam.py has extension modules to help with common tasks. ext/commands/index.rst ext/csgo/index.rst ext/tf2/index.rst +ext/dota2/index.rst ``` From 60e4c398b8d78c4a4757e1163f8ddd2d9fa0e329 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 21:58:20 +0000 Subject: [PATCH 04/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/protobufs/__init__.py | 3 +- .../ext/dota2/protobufs/dota_shared_enums.py | 4 +- steam/ext/dota2/protobufs/gcsdk_gcmessages.py | 74 +++++++++---------- .../steammessages_steamlearn/steamworkssdk.py | 34 ++++----- 4 files changed, 56 insertions(+), 59 deletions(-) diff --git a/steam/ext/dota2/protobufs/__init__.py b/steam/ext/dota2/protobufs/__init__.py index a180edb6..bea50577 100644 --- a/steam/ext/dota2/protobufs/__init__.py +++ b/steam/ext/dota2/protobufs/__init__.py @@ -5,7 +5,6 @@ APP_ID: Final = 570 from ....protobufs.msg import GCProtobufMessage -from . import dota_gcmessages_client_watch as dota_gcmessages_client_watch -from . import gcsdk_gcmessages as gcsdk_gcmessages +from . import dota_gcmessages_client_watch as dota_gcmessages_client_watch, gcsdk_gcmessages as gcsdk_gcmessages [setattr(cls, "_betterproto", betterproto.ProtoClassMetadata(cls)) for cls in GCProtobufMessage.__subclasses__()] diff --git a/steam/ext/dota2/protobufs/dota_shared_enums.py b/steam/ext/dota2/protobufs/dota_shared_enums.py index 9553f196..f8885218 100644 --- a/steam/ext/dota2/protobufs/dota_shared_enums.py +++ b/steam/ext/dota2/protobufs/dota_shared_enums.py @@ -732,9 +732,7 @@ class CDOTASaveGameSaveInstance(betterproto.Message): game_time: int = betterproto.uint32_field(2) team1_score: int = betterproto.uint32_field(3) team2_score: int = betterproto.uint32_field(4) - player_positions: list[ - CDOTASaveGameSaveInstancePlayerPositions - ] = betterproto.message_field(5) + player_positions: list[CDOTASaveGameSaveInstancePlayerPositions] = betterproto.message_field(5) save_id: int = betterproto.uint32_field(6) save_time: int = betterproto.uint32_field(7) diff --git a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py index cdef1292..ec8153ce 100644 --- a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py +++ b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py @@ -66,7 +66,7 @@ class CMsgGCConCommand(betterproto.Message): @dataclass class CMsgSDOAssert(betterproto.Message): sdo_type: int = betterproto.int32_field(1) - requests: list["CMsgSDOAssertRequest"] = betterproto.message_field(2) + requests: list[CMsgSDOAssertRequest] = betterproto.message_field(2) @dataclass @@ -86,17 +86,17 @@ class CMsgSOSingleObject(betterproto.Message): type_id: int = betterproto.int32_field(2) object_data: bytes = betterproto.bytes_field(3) version: float = betterproto.fixed64_field(4) - owner_soid: "CMsgSOIDOwner" = betterproto.message_field(5) + owner_soid: CMsgSOIDOwner = betterproto.message_field(5) service_id: int = betterproto.uint32_field(6) @dataclass class CMsgSOMultipleObjects(betterproto.Message): - objects_modified: list["CMsgSOMultipleObjectsSingleObject"] = betterproto.message_field(2) + objects_modified: list[CMsgSOMultipleObjectsSingleObject] = betterproto.message_field(2) version: float = betterproto.fixed64_field(3) - objects_added: list["CMsgSOMultipleObjectsSingleObject"] = betterproto.message_field(4) - objects_removed: list["CMsgSOMultipleObjectsSingleObject"] = betterproto.message_field(5) - owner_soid: "CMsgSOIDOwner" = betterproto.message_field(6) + objects_added: list[CMsgSOMultipleObjectsSingleObject] = betterproto.message_field(4) + objects_removed: list[CMsgSOMultipleObjectsSingleObject] = betterproto.message_field(5) + owner_soid: CMsgSOIDOwner = betterproto.message_field(6) service_id: int = betterproto.uint32_field(7) @@ -108,9 +108,9 @@ class CMsgSOMultipleObjectsSingleObject(betterproto.Message): @dataclass class CMsgSOCacheSubscribed(betterproto.Message): - objects: list["CMsgSOCacheSubscribedSubscribedType"] = betterproto.message_field(2) + objects: list[CMsgSOCacheSubscribedSubscribedType] = betterproto.message_field(2) version: float = betterproto.fixed64_field(3) - owner_soid: "CMsgSOIDOwner" = betterproto.message_field(4) + owner_soid: CMsgSOIDOwner = betterproto.message_field(4) service_id: int = betterproto.uint32_field(5) service_list: list[int] = betterproto.uint32_field(6) sync_version: float = betterproto.fixed64_field(7) @@ -125,7 +125,7 @@ class CMsgSOCacheSubscribedSubscribedType(betterproto.Message): @dataclass class CMsgSOCacheSubscribedUpToDate(betterproto.Message): version: float = betterproto.fixed64_field(1) - owner_soid: "CMsgSOIDOwner" = betterproto.message_field(2) + owner_soid: CMsgSOIDOwner = betterproto.message_field(2) service_id: int = betterproto.uint32_field(3) service_list: list[int] = betterproto.uint32_field(4) sync_version: float = betterproto.fixed64_field(5) @@ -133,13 +133,13 @@ class CMsgSOCacheSubscribedUpToDate(betterproto.Message): @dataclass class CMsgSOCacheUnsubscribed(betterproto.Message): - owner_soid: "CMsgSOIDOwner" = betterproto.message_field(2) + owner_soid: CMsgSOIDOwner = betterproto.message_field(2) @dataclass class CMsgSOCacheSubscriptionCheck(betterproto.Message): version: float = betterproto.fixed64_field(2) - owner_soid: "CMsgSOIDOwner" = betterproto.message_field(3) + owner_soid: CMsgSOIDOwner = betterproto.message_field(3) service_id: int = betterproto.uint32_field(4) service_list: list[int] = betterproto.uint32_field(5) sync_version: float = betterproto.fixed64_field(6) @@ -147,7 +147,7 @@ class CMsgSOCacheSubscriptionCheck(betterproto.Message): @dataclass class CMsgSOCacheSubscriptionRefresh(betterproto.Message): - owner_soid: "CMsgSOIDOwner" = betterproto.message_field(2) + owner_soid: CMsgSOIDOwner = betterproto.message_field(2) @dataclass @@ -172,7 +172,7 @@ class CGCToGCMsgMasterAck(betterproto.Message): dir_index: int = betterproto.int32_field(1) machine_name: str = betterproto.string_field(3) process_name: str = betterproto.string_field(4) - directory: list["CGCToGCMsgMasterAckProcess"] = betterproto.message_field(6) + directory: list[CGCToGCMsgMasterAckProcess] = betterproto.message_field(6) @dataclass @@ -198,7 +198,7 @@ class CMsgGCToGCUniverseStartupResponse(betterproto.Message): @dataclass class CGCToGCMsgMasterStartupComplete(betterproto.Message): - gc_info: list["CGCToGCMsgMasterStartupCompleteGCInfo"] = betterproto.message_field(1) + gc_info: list[CGCToGCMsgMasterStartupCompleteGCInfo] = betterproto.message_field(1) @dataclass @@ -222,7 +222,7 @@ class CGCToGCMsgRoutedReply(betterproto.Message): @dataclass class CMsgGCUpdateSubGCSessionInfo(betterproto.Message): - updates: list["CMsgGCUpdateSubGCSessionInfoCMsgUpdate"] = betterproto.message_field(1) + updates: list[CMsgGCUpdateSubGCSessionInfoCMsgUpdate] = betterproto.message_field(1) @dataclass @@ -247,7 +247,7 @@ class CMsgGCRequestSubGCSessionInfoResponse(betterproto.Message): @dataclass class CMsgSOCacheHaveVersion(betterproto.Message): - soid: "CMsgSOIDOwner" = betterproto.message_field(1) + soid: CMsgSOIDOwner = betterproto.message_field(1) version: float = betterproto.fixed64_field(2) service_id: int = betterproto.uint32_field(3) cached_file_version: int = betterproto.uint32_field(4) @@ -255,12 +255,12 @@ class CMsgSOCacheHaveVersion(betterproto.Message): class CMsgClientHello(GCProtobufMessage, msg=EGCBaseClientMsg.k_EMsgGCClientHello): version: int = betterproto.uint32_field(1) - socache_have_versions: list["CMsgSOCacheHaveVersion"] = betterproto.message_field(2) + socache_have_versions: list[CMsgSOCacheHaveVersion] = betterproto.message_field(2) client_session_need: int = betterproto.uint32_field(3) - client_launcher: "PartnerAccountType" = betterproto.enum_field(4) + client_launcher: PartnerAccountType = betterproto.enum_field(4) secret_key: str = betterproto.string_field(5) client_language: int = betterproto.uint32_field(6) - engine: "ESourceEngine" = betterproto.enum_field(7) + engine: ESourceEngine = betterproto.enum_field(7) steamdatagram_login: bytes = betterproto.bytes_field(8) platform_id: int = betterproto.uint32_field(9) game_msg: bytes = betterproto.bytes_field(10) @@ -283,9 +283,9 @@ class CMsgClientHello(GCProtobufMessage, msg=EGCBaseClientMsg.k_EMsgGCClientHell class CMsgClientWelcome(betterproto.Message): version: int = betterproto.uint32_field(1) game_data: bytes = betterproto.bytes_field(2) - outofdate_subscribed_caches: list["CMsgSOCacheSubscribed"] = betterproto.message_field(3) - uptodate_subscribed_caches: list["CMsgSOCacheSubscriptionCheck"] = betterproto.message_field(4) - location: "CMsgClientWelcomeLocation" = betterproto.message_field(5) + outofdate_subscribed_caches: list[CMsgSOCacheSubscribed] = betterproto.message_field(3) + uptodate_subscribed_caches: list[CMsgSOCacheSubscriptionCheck] = betterproto.message_field(4) + location: CMsgClientWelcomeLocation = betterproto.message_field(5) save_game_key: bytes = betterproto.bytes_field(6) gc_socache_file_version: int = betterproto.uint32_field(9) txn_country_code: str = betterproto.string_field(10) @@ -296,8 +296,8 @@ class CMsgClientWelcome(betterproto.Message): balance_url: str = betterproto.string_field(15) has_accepted_china_ssa: bool = betterproto.bool_field(16) is_banned_steam_china: bool = betterproto.bool_field(17) - additional_welcome_msgs: "CExtraMsgBlock" = betterproto.message_field(18) - steam_learn_server_info: "CMsgSteamLearnServerInfo" = betterproto.message_field(20) + additional_welcome_msgs: CExtraMsgBlock = betterproto.message_field(18) + steam_learn_server_info: CMsgSteamLearnServerInfo = betterproto.message_field(20) @dataclass @@ -309,7 +309,7 @@ class CMsgClientWelcomeLocation(betterproto.Message): @dataclass class CMsgConnectionStatus(betterproto.Message): - status: "GCConnectionStatus" = betterproto.enum_field(1) + status: GCConnectionStatus = betterproto.enum_field(1) client_session_need: int = betterproto.uint32_field(2) queue_position: int = betterproto.int32_field(3) queue_size: int = betterproto.int32_field(4) @@ -322,7 +322,7 @@ class CMsgGCToGCSOCacheSubscribe(betterproto.Message): subscriber: float = betterproto.fixed64_field(1) subscribe_to_id: float = betterproto.fixed64_field(2) sync_version: float = betterproto.fixed64_field(3) - have_versions: list["CMsgGCToGCSOCacheSubscribeCMsgHaveVersions"] = betterproto.message_field(4) + have_versions: list[CMsgGCToGCSOCacheSubscribeCMsgHaveVersions] = betterproto.message_field(4) subscribe_to_type: int = betterproto.uint32_field(5) @@ -354,7 +354,7 @@ class CMsgGCToGCForwardAccountDetails(betterproto.Message): @dataclass class CMsgGCToGCLoadSessionSOCache(betterproto.Message): account_id: int = betterproto.uint32_field(1) - forward_account_details: "CMsgGCToGCForwardAccountDetails" = betterproto.message_field(2) + forward_account_details: CMsgGCToGCForwardAccountDetails = betterproto.message_field(2) @dataclass @@ -378,7 +378,7 @@ class CMsgGCToClientRequestDropped(betterproto.Message): class CWorkshop_PopulateItemDescriptions_Request(betterproto.Message): appid: int = betterproto.uint32_field(1) languages: list[ - "CWorkshop_PopulateItemDescriptions_RequestItemDescriptionsLanguageBlock" + CWorkshop_PopulateItemDescriptions_RequestItemDescriptionsLanguageBlock ] = betterproto.message_field(2) @@ -391,7 +391,7 @@ class CWorkshop_PopulateItemDescriptions_RequestSingleItemDescription(betterprot @dataclass class CWorkshop_PopulateItemDescriptions_RequestItemDescriptionsLanguageBlock(betterproto.Message): language: str = betterproto.string_field(1) - descriptions: list["CWorkshop_PopulateItemDescriptions_RequestSingleItemDescription"] = betterproto.message_field(2) + descriptions: list[CWorkshop_PopulateItemDescriptions_RequestSingleItemDescription] = betterproto.message_field(2) @dataclass @@ -410,12 +410,12 @@ class CWorkshop_SetItemPaymentRules_Request(betterproto.Message): appid: int = betterproto.uint32_field(1) gameitemid: int = betterproto.uint32_field(2) associated_workshop_files: list[ - "CWorkshop_SetItemPaymentRules_RequestWorkshopItemPaymentRule" + CWorkshop_SetItemPaymentRules_RequestWorkshopItemPaymentRule ] = betterproto.message_field(3) - partner_accounts: list["CWorkshop_SetItemPaymentRules_RequestPartnerItemPaymentRule"] = betterproto.message_field(4) + partner_accounts: list[CWorkshop_SetItemPaymentRules_RequestPartnerItemPaymentRule] = betterproto.message_field(4) validate_only: bool = betterproto.bool_field(5) make_workshop_files_subscribable: bool = betterproto.bool_field(6) - associated_workshop_file_for_direct_payments: "CWorkshop_SetItemPaymentRules_RequestWorkshopDirectPaymentRule" = ( + associated_workshop_file_for_direct_payments: CWorkshop_SetItemPaymentRules_RequestWorkshopDirectPaymentRule = ( betterproto.message_field(7) ) @@ -483,7 +483,7 @@ class CCommunity_GetClanAnnouncements_Request(betterproto.Message): class CCommunity_GetClanAnnouncements_Response(betterproto.Message): maxchars: int = betterproto.uint32_field(1) strip_html: bool = betterproto.bool_field(2) - announcements: list["CCommunity_ClanAnnouncementInfo"] = betterproto.message_field(3) + announcements: list[CCommunity_ClanAnnouncementInfo] = betterproto.message_field(3) @dataclass @@ -497,7 +497,7 @@ class CBroadcast_PostGameDataFrame_Request(betterproto.Message): @dataclass class CMsgSerializedSOCache(betterproto.Message): file_version: int = betterproto.uint32_field(1) - caches: list["CMsgSerializedSOCacheCache"] = betterproto.message_field(2) + caches: list[CMsgSerializedSOCacheCache] = betterproto.message_field(2) gc_socache_file_version: int = betterproto.uint32_field(3) @@ -512,8 +512,8 @@ class CMsgSerializedSOCacheTypeCache(betterproto.Message): class CMsgSerializedSOCacheCache(betterproto.Message): type: int = betterproto.uint32_field(1) id: int = betterproto.uint64_field(2) - versions: list["CMsgSerializedSOCacheCacheVersion"] = betterproto.message_field(3) - type_caches: list["CMsgSerializedSOCacheTypeCache"] = betterproto.message_field(4) + versions: list[CMsgSerializedSOCacheCacheVersion] = betterproto.message_field(3) + type_caches: list[CMsgSerializedSOCacheTypeCache] = betterproto.message_field(4) @dataclass @@ -564,7 +564,7 @@ class CMsgGCToGCMasterSubscribeToCacheResponse(betterproto.Message): @dataclass class CMsgGCToGCMasterSubscribeToCacheAsync(betterproto.Message): - subscribe_msg: "CMsgGCToGCMasterSubscribeToCache" = betterproto.message_field(1) + subscribe_msg: CMsgGCToGCMasterSubscribeToCache = betterproto.message_field(1) @dataclass diff --git a/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py b/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py index 9ee41bc0..69438594 100644 --- a/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py +++ b/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py @@ -88,7 +88,7 @@ class ESteamLearnInferenceMetadataResult(betterproto.Enum): @dataclass class CMsgSteamLearnDataSourceDescObject(betterproto.Message): - elements: list["CMsgSteamLearnDataSourceDescElement"] = betterproto.message_field(1) + elements: list[CMsgSteamLearnDataSourceDescElement] = betterproto.message_field(1) @dataclass @@ -232,18 +232,18 @@ class CMsgSteamLearn_GetHMACKeys_Response(betterproto.Message): @dataclass class CMsgSteamLearn_Inference_Request(betterproto.Message): access_token: str = betterproto.string_field(1) - access_data: "CMsgSteamLearn_AccessData" = betterproto.message_field(2) + access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) project_id: int = betterproto.uint32_field(3) published_version: int = betterproto.uint32_field(4) override_train_id: int = betterproto.uint32_field(5) - data: "CMsgSteamLearnDataList" = betterproto.message_field(6) + data: CMsgSteamLearnDataList = betterproto.message_field(6) additional_data: list[float] = betterproto.float_field(7) @dataclass class CMsgSteamLearn_InferenceMetadata_Request(betterproto.Message): access_token: str = betterproto.string_field(1) - access_data: "CMsgSteamLearn_AccessData" = betterproto.message_field(2) + access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) project_id: int = betterproto.uint32_field(3) published_version: int = betterproto.uint32_field(4) override_train_id: int = betterproto.uint32_field(5) @@ -257,13 +257,13 @@ class CMsgSteamLearn_InferenceMetadataBackend_Request(betterproto.Message): @dataclass class CMsgSteamLearn_InferenceMetadata_Response(betterproto.Message): - inference_metadata_result: "ESteamLearnInferenceMetadataResult" = betterproto.enum_field(1) - row_range: "CMsgSteamLearn_InferenceMetadata_ResponseRowRange" = betterproto.message_field(2) - ranges: list["CMsgSteamLearn_InferenceMetadata_ResponseRange"] = betterproto.message_field(3) - std_devs: list["CMsgSteamLearn_InferenceMetadata_ResponseStdDev"] = betterproto.message_field(4) - compact_tables: list["CMsgSteamLearn_InferenceMetadata_ResponseCompactTable"] = betterproto.message_field(5) - kmeans: list["CMsgSteamLearn_InferenceMetadata_ResponseKMeans"] = betterproto.message_field(6) - snapshot_histogram: "CMsgSteamLearn_InferenceMetadata_ResponseSnapshotHistogram" = betterproto.message_field(7) + inference_metadata_result: ESteamLearnInferenceMetadataResult = betterproto.enum_field(1) + row_range: CMsgSteamLearn_InferenceMetadata_ResponseRowRange = betterproto.message_field(2) + ranges: list[CMsgSteamLearn_InferenceMetadata_ResponseRange] = betterproto.message_field(3) + std_devs: list[CMsgSteamLearn_InferenceMetadata_ResponseStdDev] = betterproto.message_field(4) + compact_tables: list[CMsgSteamLearn_InferenceMetadata_ResponseCompactTable] = betterproto.message_field(5) + kmeans: list[CMsgSteamLearn_InferenceMetadata_ResponseKMeans] = betterproto.message_field(6) + snapshot_histogram: CMsgSteamLearn_InferenceMetadata_ResponseSnapshotHistogram = betterproto.message_field(7) @dataclass @@ -289,11 +289,11 @@ class CMsgSteamLearn_InferenceMetadata_ResponseStdDev(betterproto.Message): @dataclass class CMsgSteamLearn_InferenceMetadata_ResponseCompactTable(betterproto.Message): name: str = betterproto.string_field(1) - map_values: list["CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry"] = betterproto.message_field( + map_values: list[CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry] = betterproto.message_field( 2 ) map_mappings: list[ - "CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapMappingsEntry" + CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapMappingsEntry ] = betterproto.message_field(3) @@ -307,19 +307,19 @@ class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry(betterproto.Mes @dataclass class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry(betterproto.Message): key: int = betterproto.uint32_field(1) - value: "CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry" = betterproto.message_field(2) + value: CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry = betterproto.message_field(2) @dataclass class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapMappingsEntry(betterproto.Message): key: int = betterproto.uint32_field(1) - value: "CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry" = betterproto.message_field(2) + value: CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry = betterproto.message_field(2) @dataclass class CMsgSteamLearn_InferenceMetadata_ResponseKMeans(betterproto.Message): name: str = betterproto.string_field(1) - clusters: list["CMsgSteamLearn_InferenceMetadata_ResponseKMeansCluster"] = betterproto.message_field(2) + clusters: list[CMsgSteamLearn_InferenceMetadata_ResponseKMeansCluster] = betterproto.message_field(2) @dataclass @@ -342,7 +342,7 @@ class CMsgSteamLearn_InferenceMetadata_ResponseSnapshotHistogram(betterproto.Mes @dataclass class CMsgSteamLearn_InferenceBackend_Response(betterproto.Message): - outputs: list["CMsgSteamLearn_InferenceBackend_ResponseOutput"] = betterproto.message_field(1) + outputs: list[CMsgSteamLearn_InferenceBackend_ResponseOutput] = betterproto.message_field(1) @dataclass From 89bdc979f344b1e6ea4dab67bb5328a0e0a45a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 24 Jan 2024 01:10:29 +0300 Subject: [PATCH 05/50] =?UTF-8?q?=E2=9C=92=EF=B8=8FStealth=20edit=20to=20`?= =?UTF-8?q?fetch=5Ftop=5Fsource=5Ftv=5Fgames`=20docstring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 6383f8a9..cc5d3722 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -45,17 +45,17 @@ async def fetch_top_source_tv_games( ) -> list[CMsgGCToClientFindTopSourceTVGamesResponse]: """Fetch Top Source TV Games. - This functionality is somewhat identical to Watch Tab in normal Dota 2 application. - It fetches short data for the following currently on-going Dota 2 matches: + This functionality is similar to game list in the Watch Tab of Dota 2 game application. + It fetches summary data for the currently on-going Dota 2 matches from the following categories: * tournament games - * highest mmr games + * highest average mmr games * specific lobbies, like friends' games by their lobby_ids Note ------- - Note that the following documentation for arguments to query against is rather observant - than from official sources. So, please, if you know more or description is incorrect, contact us. + Note that the following documentation for keyword arguments to query against is rather observant + than from official. So, please, if you know more or description is incorrect, contact us. Parameters ---------- @@ -65,7 +65,7 @@ async def fetch_top_source_tv_games( `league_id` for the professional tournament. hero_id : :class: `int`, optional `hero_id` to filter results by, just like in-client Watch Tab feature. - start_game : :class: `Literal[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]`, optional + start_game : :class: `Literal[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]`, optional, by default 0 This argument controls how many responses the game coordinator should return. For example, `start_game=0` returns a list with 1 Response, `start_game=90` returns a list of 10 Responses. @@ -110,7 +110,7 @@ def predicate(msg: CMsgGCToClientFindTopSourceTVGamesResponse) -> bool: await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(**kwargs)) try: - async with timeout(10.0): + async with timeout(30.0): return await asyncio.gather(*futures) except asyncio.TimeoutError: raise asyncio.TimeoutError( From dd0a3b84334bff31c83631ac452fbdff345cded7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 22:10:47 +0000 Subject: [PATCH 06/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../dota2/protobufs/steammessages_steamlearn/steamworkssdk.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py b/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py index 69438594..e2be2657 100644 --- a/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py +++ b/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py @@ -289,9 +289,7 @@ class CMsgSteamLearn_InferenceMetadata_ResponseStdDev(betterproto.Message): @dataclass class CMsgSteamLearn_InferenceMetadata_ResponseCompactTable(betterproto.Message): name: str = betterproto.string_field(1) - map_values: list[CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry] = betterproto.message_field( - 2 - ) + map_values: list[CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry] = betterproto.message_field(2) map_mappings: list[ CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapMappingsEntry ] = betterproto.message_field(3) From 6355e21092aae926cf23ba386e5fad767336785d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= <33165440+Aluerie@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:04:45 +0000 Subject: [PATCH 07/50] Apply suggestions from code review by Gobot Co-authored-by: James Hilton-Balfe --- docs/ext/dota2/index.md | 2 +- steam/ext/dota2/client.py | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/docs/ext/dota2/index.md b/docs/ext/dota2/index.md index f209b324..6fbd5903 100644 --- a/docs/ext/dota2/index.md +++ b/docs/ext/dota2/index.md @@ -1,6 +1,6 @@ (steam-ext-dota2)= -# `steam.ext.dota2` - A Team Fortress 2 Game Coordinator client +# `steam.ext.dota2` - A Dota 2 Game Coordinator client This extension offers the ability to interact with the Dota 2 Game Coordinator (Dota 2 GC) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index cc5d3722..cc60a5ef 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -33,7 +33,7 @@ class Client(Client_): _APP: Final = DOTA2 _state: GCState # type: ignore # PEP 705 - async def fetch_top_source_tv_games( + async def top_source_tv_games( self, *, search_key: str = MISSING, @@ -102,21 +102,15 @@ def predicate(msg: CMsgGCToClientFindTopSourceTVGamesResponse) -> bool: futures = [ self._state.ws.gc_wait_for( CMsgGCToClientFindTopSourceTVGamesResponse, - check=start_game_check(game_counter), + check=partial(lambda start_game, msg: msg.start_game == start_game, start_game), ) - for game_counter in list(range(0, start_game + 1, 10)) - ] + for start_game in range(0, start_game + 1, 10) + ] await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(**kwargs)) - try: - async with timeout(30.0): - return await asyncio.gather(*futures) - except asyncio.TimeoutError: - raise asyncio.TimeoutError( - "Request time-outed. The reason might be inappropriate combination of keyword arguments, " - + "inappropriate argument values or simply Dota 2 Game Coordinator being down." - ) + async with timeout(30.0): + return await asyncio.gather(*futures) class Bot(commands.Bot, Client): From 89b5b016fdea6be0d81c05da8aa18b8914c915ca Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:04:58 +0000 Subject: [PATCH 08/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index cc60a5ef..460e7b80 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -105,7 +105,7 @@ def predicate(msg: CMsgGCToClientFindTopSourceTVGamesResponse) -> bool: check=partial(lambda start_game, msg: msg.start_game == start_game, start_game), ) for start_game in range(0, start_game + 1, 10) - ] + ] await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(**kwargs)) From ca12e0e7988d87f0fba85820cc4ae9dc6d986ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= <33165440+Aluerie@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:08:00 +0000 Subject: [PATCH 09/50] Apply suggestions from code review Co-authored-by: James Hilton-Balfe --- steam/ext/dota2/client.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 460e7b80..36f400c7 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -59,29 +59,25 @@ async def top_source_tv_games( Parameters ---------- - search_key : :class: `str`, optional - Unknown purpose. - league_id : :class: `int`, optional - `league_id` for the professional tournament. - hero_id : :class: `int`, optional - `hero_id` to filter results by, just like in-client Watch Tab feature. - start_game : :class: `Literal[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]`, optional, by default 0 + league_id + The league ID for the professional tournament. + hero_id + `hero_id` to filter results by which can be found in the client Watch Tab feature. + start_game This argument controls how many responses the game coordinator should return. For example, `start_game=0` returns a list with 1 Response, `start_game=90` returns a list of 10 Responses. - Game coordinator fills each response in consequent manner with games that satisfy keyword arguments + The GC fills each response in consequent manner with games that satisfy keyword arguments or with currently live highest average MMR games in case no other argument was given. - game_list_index : :class: `int`, optional - Only get responses matching `game_list_index`. Responses from Game Coordinator change + game_list_index + Only get responses matching `game_list_index`. Responses from GC change from time to time. The `game_list_index` indicates that those responses belong to the same chunk. - lobby_ids : :class: `list[int]`, optional - Lobby ids to query against. + lobby_ids + The lobby IDs of the games to fetch. Returns ------- - list[dota_gcmessages_client_watch.CMsgGCToClientFindTopSourceTVGamesResponse] - The list of responses from Dota 2 Coordinator. - Those are grouped into grouped into chunks of 10 games. + The responses from the GC. They are grouped into grouped into chunks of 10. games. Raises ------ From 728fa0ea489925096c3f19c791a52954284c7347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 24 Jan 2024 03:31:58 +0300 Subject: [PATCH 10/50] =?UTF-8?q?=E2=9B=94Remove=20Steam=20NonSense?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/protobufs/gcsdk_gcmessages.py | 9 +- .../steammessages_steamlearn/steamworkssdk.py | 528 ------------------ .../steamworkssdk.py | 10 - 3 files changed, 1 insertion(+), 546 deletions(-) delete mode 100644 steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py delete mode 100644 steam/ext/dota2/protobufs/steammessages_unified_base/steamworkssdk.py diff --git a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py index ec8153ce..69c3fea0 100644 --- a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py +++ b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py @@ -45,13 +45,6 @@ class CExtraMsgBlock(betterproto.Message): is_compressed: bool = betterproto.bool_field(4) -@dataclass -class CMsgSteamLearnServerInfo(betterproto.Message): - enable_data_submission: bool = betterproto.bool_field(1) - enable_inferencing: bool = betterproto.bool_field(2) - hmac_keys: CMsgSteamLearnHMACKeys = betterproto.message_field(3) - - @dataclass class CMsgGCAssertJobData(betterproto.Message): message_type: str = betterproto.string_field(1) @@ -297,7 +290,7 @@ class CMsgClientWelcome(betterproto.Message): has_accepted_china_ssa: bool = betterproto.bool_field(16) is_banned_steam_china: bool = betterproto.bool_field(17) additional_welcome_msgs: CExtraMsgBlock = betterproto.message_field(18) - steam_learn_server_info: CMsgSteamLearnServerInfo = betterproto.message_field(20) + # steam_learn_server_info: CMsgSteamLearnServerInfo = betterproto.message_field(20) @dataclass diff --git a/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py b/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py deleted file mode 100644 index e2be2657..00000000 --- a/steam/ext/dota2/protobufs/steammessages_steamlearn/steamworkssdk.py +++ /dev/null @@ -1,528 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: steammessages_steamlearn.steamworkssdk.proto -# plugin: python-betterproto -from __future__ import annotations - -from dataclasses import dataclass - -import betterproto - - -class ESteamLearnDataType(betterproto.Enum): - STEAMLEARN_DATATYPE_INVALID = 0 - STEAMLEARN_DATATYPE_INT32 = 1 - STEAMLEARN_DATATYPE_FLOAT32 = 2 - STEAMLEARN_DATATYPE_BOOL = 3 - STEAMLEARN_DATATYPE_STRING = 4 - STEAMLEARN_DATATYPE_OBJECT = 5 - - -class ESteammLearnRegisterDataSourceResult(betterproto.Enum): - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR = 0 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_SUCCESS_CREATED = 1 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_SUCCESS_FOUND = 2 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_GENERIC = 3 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_INVALID_NAME = 4 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_INVALID_VERSION = 5 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_DATA_CHANGED = 6 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_DATA_INVALID = 7 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_FORBIDDEN = 8 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_ERROR_INVALID_TIMESTAMP = 9 - STEAMLEARN_REGISTER_DATA_SOURCE_RESULT_DISABLED = 10 - - -class ESteamLearnCacheDataResult(betterproto.Enum): - STEAMLEARN_CACHE_DATA_ERROR = 0 - STEAMLEARN_CACHE_DATA_SUCCESS = 1 - STEAMLEARN_CACHE_DATA_ERROR_UNKNOWN_DATA_SOURCE = 2 - STEAMLEARN_CACHE_DATA_ERROR_UNCACHED_DATA_SOURCE = 3 - STEAMLEARN_CACHE_DATA_ERROR_INVALID_KEYS = 4 - STEAMLEARN_CACHE_DATA_ERROR_FORBIDDEN = 5 - STEAMLEARN_CACHE_DATA_ERROR_INVALID_TIMESTAMP = 6 - STEAMLEARN_CACHE_DATA_DISABLED = 7 - - -class ESteamLearnSnapshotProjectResult(betterproto.Enum): - STEAMLEARN_SNAPSHOT_PROJECT_ERROR = 0 - STEAMLEARN_SNAPSHOT_PROJECT_SUCCESS_STORED = 1 - STEAMLEARN_SNAPSHOT_PROJECT_SUCCESS_QUEUED = 2 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INVALID_PROJECT_ID = 3 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_UNKNOWN_DATA_SOURCE = 4 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INVALID_DATA_SOURCE_KEY = 5 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_MISSING_CACHE_DURATION = 6 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_NO_PUBLISHED_CONFIG = 7 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_FORBIDDEN = 8 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INVALID_TIMESTAMP = 9 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INTERNAL_DATA_SOURCE_ERROR = 10 - STEAMLEARN_SNAPSHOT_PROJECT_DISABLED = 11 - STEAMLEARN_SNAPSHOT_PROJECT_ERROR_INVALID_PUBLISHED_VERSION = 12 - - -class ESteamLearnGetHMACKeysResult(betterproto.Enum): - STEAMLEARN_GET_HMAC_KEYS_SUCCESS = 0 - - -class ESteamLearnInferenceResult(betterproto.Enum): - STEAMLEARN_INFERENCE_ERROR = 0 - STEAMLEARN_INFERENCE_SUCCESS = 1 - STEAMLEARN_INFERENCE_ERROR_INVALID_PROJECT_ID = 2 - STEAMLEARN_INFERENCE_ERROR_MISSING_CACHED_SCHEMA_DATA = 3 - STEAMLEARN_INFERENCE_ERROR_NO_PUBLISHED_CONFIG = 4 - STEAMLEARN_INFERENCE_ERROR_FORBIDDEN = 5 - STEAMLEARN_INFERENCE_ERROR_INVALID_TIMESTAMP = 6 - STEAMLEARN_INFERENCE_ERROR_INVALID_PUBLISHED_VERSION = 7 - STEAMLEARN_INFERENCE_ERROR_NO_FETCH_ID_FOUND = 8 - STEAMLEARN_INFERENCE_ERROR_TOO_BUSY = 9 - - -class ESteamLearnInferenceMetadataResult(betterproto.Enum): - STEAMLEARN_INFERENCE_METADATA_ERROR = 0 - STEAMLEARN_INFERENCE_METADATA_SUCCESS = 1 - STEAMLEARN_INFERENCE_METADATA_ERROR_INVALID_PROJECT_ID = 2 - STEAMLEARN_INFERENCE_METADATA_ERROR_NO_PUBLISHED_CONFIG = 3 - STEAMLEARN_INFERENCE_METADATA_ERROR_FORBIDDEN = 4 - STEAMLEARN_INFERENCE_METADATA_ERROR_INVALID_TIMESTAMP = 5 - STEAMLEARN_INFERENCE_METADATA_ERROR_INVALID_PUBLISHED_VERSION = 6 - STEAMLEARN_INFERENCE_METADATA_ERROR_NO_FETCH_ID_FOUND = 7 - - -@dataclass -class CMsgSteamLearnDataSourceDescObject(betterproto.Message): - elements: list[CMsgSteamLearnDataSourceDescElement] = betterproto.message_field(1) - - -@dataclass -class CMsgSteamLearnDataSourceDescElement(betterproto.Message): - name: str = betterproto.string_field(1) - data_type: ESteamLearnDataType = betterproto.enum_field(2) - object: CMsgSteamLearnDataSourceDescObject = betterproto.message_field(3) - count: int = betterproto.uint32_field(4) - - -@dataclass -class CMsgSteamLearnDataSource(betterproto.Message): - id: int = betterproto.uint32_field(1) - name: str = betterproto.string_field(2) - version: int = betterproto.uint32_field(3) - source_description: str = betterproto.string_field(4) - structure: CMsgSteamLearnDataSourceDescObject = betterproto.message_field(5) - structure_crc: int = betterproto.uint32_field(6) - cache_duration_seconds: int = betterproto.uint32_field(7) - - -@dataclass -class CMsgSteamLearnDataObject(betterproto.Message): - elements: list[CMsgSteamLearnDataElement] = betterproto.message_field(1) - - -@dataclass -class CMsgSteamLearnDataElement(betterproto.Message): - name: str = betterproto.string_field(1) - data_int32s: list[int] = betterproto.int32_field(20) - data_floats: list[float] = betterproto.float_field(21) - data_bools: list[bool] = betterproto.bool_field(22) - data_strings: list[str] = betterproto.string_field(23) - data_objects: list[CMsgSteamLearnDataObject] = betterproto.message_field(24) - - -@dataclass -class CMsgSteamLearnData(betterproto.Message): - data_source_id: int = betterproto.uint32_field(1) - keys: list[int] = betterproto.uint64_field(2) - data_object: CMsgSteamLearnDataObject = betterproto.message_field(3) - - -@dataclass -class CMsgSteamLearnDataList(betterproto.Message): - data: list[CMsgSteamLearnData] = betterproto.message_field(1) - - -@dataclass -class CMsgSteamLearn_AccessData(betterproto.Message): - publisher_id: int = betterproto.uint32_field(1) - timestamp: int = betterproto.uint32_field(2) - random_value: int = betterproto.uint64_field(3) - - -@dataclass -class CMsgSteamLearn_RegisterDataSource_Request(betterproto.Message): - access_token: str = betterproto.string_field(1) - access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) - data_source: CMsgSteamLearnDataSource = betterproto.message_field(3) - - -@dataclass -class CMsgSteamLearn_RegisterDataSource_Response(betterproto.Message): - result: ESteammLearnRegisterDataSourceResult = betterproto.enum_field(1) - data_source: CMsgSteamLearnDataSource = betterproto.message_field(2) - - -@dataclass -class CMsgSteamLearn_CacheData_Request(betterproto.Message): - access_token: str = betterproto.string_field(1) - access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) - data: CMsgSteamLearnData = betterproto.message_field(3) - - -@dataclass -class CMsgSteamLearn_CacheData_Response(betterproto.Message): - cache_data_result: ESteamLearnCacheDataResult = betterproto.enum_field(1) - - -@dataclass -class CMsgSteamLearn_SnapshotProject_Request(betterproto.Message): - access_token: str = betterproto.string_field(1) - access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) - project_id: int = betterproto.uint32_field(3) - published_version: int = betterproto.uint32_field(7) - keys: list[int] = betterproto.uint64_field(4) - data: list[CMsgSteamLearnData] = betterproto.message_field(5) - pending_data_limit_seconds: int = betterproto.uint32_field(6) - - -@dataclass -class CMsgSteamLearn_SnapshotProject_Response(betterproto.Message): - snapshot_result: ESteamLearnSnapshotProjectResult = betterproto.enum_field(1) - - -@dataclass -class CMsgSteamLearn_BatchOperation_Request(betterproto.Message): - cache_data_requests: list[CMsgSteamLearn_CacheData_Request] = betterproto.message_field(1) - snapshot_requests: list[CMsgSteamLearn_SnapshotProject_Request] = betterproto.message_field(2) - - -@dataclass -class CMsgSteamLearn_BatchOperation_Response(betterproto.Message): - cache_data_responses: list[CMsgSteamLearn_CacheData_Response] = betterproto.message_field(1) - snapshot_responses: list[CMsgSteamLearn_SnapshotProject_Response] = betterproto.message_field(2) - - -@dataclass -class CMsgSteamLearnHMACKeys(betterproto.Message): - register_data_source_key: str = betterproto.string_field(1) - cache_data_keys: list[CMsgSteamLearnHMACKeysCacheDataKeys] = betterproto.message_field(2) - snapshot_project_keys: list[CMsgSteamLearnHMACKeysSnapshotProjectKeys] = betterproto.message_field(3) - - -@dataclass -class CMsgSteamLearnHMACKeysCacheDataKeys(betterproto.Message): - data_source_id: int = betterproto.uint32_field(1) - version: int = betterproto.uint32_field(3) - key: str = betterproto.string_field(2) - - -@dataclass -class CMsgSteamLearnHMACKeysSnapshotProjectKeys(betterproto.Message): - project_id: int = betterproto.uint32_field(1) - published_version: int = betterproto.uint32_field(3) - key: str = betterproto.string_field(2) - - -@dataclass -class CMsgSteamLearn_GetHMACKeys_Request(betterproto.Message): - appid: int = betterproto.uint32_field(1) - - -@dataclass -class CMsgSteamLearn_GetHMACKeys_Response(betterproto.Message): - result: ESteamLearnGetHMACKeysResult = betterproto.enum_field(1) - keys: CMsgSteamLearnHMACKeys = betterproto.message_field(2) - - -@dataclass -class CMsgSteamLearn_Inference_Request(betterproto.Message): - access_token: str = betterproto.string_field(1) - access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) - project_id: int = betterproto.uint32_field(3) - published_version: int = betterproto.uint32_field(4) - override_train_id: int = betterproto.uint32_field(5) - data: CMsgSteamLearnDataList = betterproto.message_field(6) - additional_data: list[float] = betterproto.float_field(7) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_Request(betterproto.Message): - access_token: str = betterproto.string_field(1) - access_data: CMsgSteamLearn_AccessData = betterproto.message_field(2) - project_id: int = betterproto.uint32_field(3) - published_version: int = betterproto.uint32_field(4) - override_train_id: int = betterproto.uint32_field(5) - - -@dataclass -class CMsgSteamLearn_InferenceMetadataBackend_Request(betterproto.Message): - project_id: int = betterproto.uint32_field(1) - fetch_id: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_Response(betterproto.Message): - inference_metadata_result: ESteamLearnInferenceMetadataResult = betterproto.enum_field(1) - row_range: CMsgSteamLearn_InferenceMetadata_ResponseRowRange = betterproto.message_field(2) - ranges: list[CMsgSteamLearn_InferenceMetadata_ResponseRange] = betterproto.message_field(3) - std_devs: list[CMsgSteamLearn_InferenceMetadata_ResponseStdDev] = betterproto.message_field(4) - compact_tables: list[CMsgSteamLearn_InferenceMetadata_ResponseCompactTable] = betterproto.message_field(5) - kmeans: list[CMsgSteamLearn_InferenceMetadata_ResponseKMeans] = betterproto.message_field(6) - snapshot_histogram: CMsgSteamLearn_InferenceMetadata_ResponseSnapshotHistogram = betterproto.message_field(7) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseRowRange(betterproto.Message): - min_row: int = betterproto.uint64_field(1) - max_row: int = betterproto.uint64_field(2) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseRange(betterproto.Message): - data_element_path: str = betterproto.string_field(1) - min_value: float = betterproto.float_field(2) - max_value: float = betterproto.float_field(3) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseStdDev(betterproto.Message): - data_element_path: str = betterproto.string_field(1) - mean: float = betterproto.float_field(2) - std_dev: float = betterproto.float_field(3) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseCompactTable(betterproto.Message): - name: str = betterproto.string_field(1) - map_values: list[CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry] = betterproto.message_field(2) - map_mappings: list[ - CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapMappingsEntry - ] = betterproto.message_field(3) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry(betterproto.Message): - value: int = betterproto.uint32_field(1) - mapping: int = betterproto.uint32_field(2) - count: int = betterproto.uint64_field(3) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapValuesEntry(betterproto.Message): - key: int = betterproto.uint32_field(1) - value: CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry = betterproto.message_field(2) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseCompactTableMapMappingsEntry(betterproto.Message): - key: int = betterproto.uint32_field(1) - value: CMsgSteamLearn_InferenceMetadata_ResponseCompactTableEntry = betterproto.message_field(2) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseKMeans(betterproto.Message): - name: str = betterproto.string_field(1) - clusters: list[CMsgSteamLearn_InferenceMetadata_ResponseKMeansCluster] = betterproto.message_field(2) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseKMeansCluster(betterproto.Message): - x: float = betterproto.float_field(1) - y: float = betterproto.float_field(2) - radius: float = betterproto.float_field(3) - radius_75pct: float = betterproto.float_field(4) - radius_50pct: float = betterproto.float_field(5) - radius_25pct: float = betterproto.float_field(6) - - -@dataclass -class CMsgSteamLearn_InferenceMetadata_ResponseSnapshotHistogram(betterproto.Message): - min_value: float = betterproto.float_field(1) - max_value: float = betterproto.float_field(2) - num_buckets: int = betterproto.uint32_field(3) - bucket_counts: list[int] = betterproto.uint32_field(4) - - -@dataclass -class CMsgSteamLearn_InferenceBackend_Response(betterproto.Message): - outputs: list[CMsgSteamLearn_InferenceBackend_ResponseOutput] = betterproto.message_field(1) - - -@dataclass -class CMsgSteamLearn_InferenceBackend_ResponseBinaryCrossEntropyOutput(betterproto.Message): - value: float = betterproto.float_field(1) - - -@dataclass -class CMsgSteamLearn_InferenceBackend_ResponseMutliBinaryCrossEntropyOutput(betterproto.Message): - weight: list[float] = betterproto.float_field(1) - value: list[float] = betterproto.float_field(2) - - -@dataclass -class CMsgSteamLearn_InferenceBackend_ResponseCategoricalCrossEntropyOutput(betterproto.Message): - weight: list[float] = betterproto.float_field(1) - value: list[float] = betterproto.float_field(2) - - -@dataclass -class CMsgSteamLearn_InferenceBackend_ResponseOutput(betterproto.Message): - binary_crossentropy: CMsgSteamLearn_InferenceBackend_ResponseBinaryCrossEntropyOutput = betterproto.message_field( - 1, group="ResponseType" - ) - categorical_crossentropy: CMsgSteamLearn_InferenceBackend_ResponseCategoricalCrossEntropyOutput = ( - betterproto.message_field(2, group="ResponseType") - ) - multi_binary_crossentropy: CMsgSteamLearn_InferenceBackend_ResponseMutliBinaryCrossEntropyOutput = ( - betterproto.message_field(3, group="ResponseType") - ) - - -@dataclass -class CMsgSteamLearn_Inference_Response(betterproto.Message): - inference_result: ESteamLearnInferenceResult = betterproto.enum_field(1) - backend_response: CMsgSteamLearn_InferenceBackend_Response = betterproto.message_field(2) - - -class SteamLearnStub(betterproto.ServiceStub): - async def register_data_source( - self, - *, - access_token: str = "", - access_data: CMsgSteamLearn_AccessData | None = None, - data_source: CMsgSteamLearnDataSource | None = None, - ) -> CMsgSteamLearn_RegisterDataSource_Response: - request = CMsgSteamLearn_RegisterDataSource_Request() - request.access_token = access_token - if access_data is not None: - request.access_data = access_data - if data_source is not None: - request.data_source = data_source - - return await self._unary_unary( - "/.SteamLearn/RegisterDataSource", - request, - CMsgSteamLearn_RegisterDataSource_Response, - ) - - async def cache_data( - self, - *, - access_token: str = "", - access_data: CMsgSteamLearn_AccessData | None = None, - data: CMsgSteamLearnData | None = None, - ) -> CMsgSteamLearn_CacheData_Response: - request = CMsgSteamLearn_CacheData_Request() - request.access_token = access_token - if access_data is not None: - request.access_data = access_data - if data is not None: - request.data = data - - return await self._unary_unary( - "/.SteamLearn/CacheData", - request, - CMsgSteamLearn_CacheData_Response, - ) - - async def snapshot_project( - self, - *, - access_token: str = "", - access_data: CMsgSteamLearn_AccessData | None = None, - project_id: int = 0, - published_version: int = 0, - keys: list[int] = [], - data: list[CMsgSteamLearnData] = [], - pending_data_limit_seconds: int = 0, - ) -> CMsgSteamLearn_SnapshotProject_Response: - request = CMsgSteamLearn_SnapshotProject_Request() - request.access_token = access_token - if access_data is not None: - request.access_data = access_data - request.project_id = project_id - request.published_version = published_version - request.keys = keys - if data is not None: - request.data = data - request.pending_data_limit_seconds = pending_data_limit_seconds - - return await self._unary_unary( - "/.SteamLearn/SnapshotProject", - request, - CMsgSteamLearn_SnapshotProject_Response, - ) - - async def batch_operation( - self, - *, - cache_data_requests: list[CMsgSteamLearn_CacheData_Request] = [], - snapshot_requests: list[CMsgSteamLearn_SnapshotProject_Request] = [], - ) -> CMsgSteamLearn_BatchOperation_Response: - request = CMsgSteamLearn_BatchOperation_Request() - if cache_data_requests is not None: - request.cache_data_requests = cache_data_requests - if snapshot_requests is not None: - request.snapshot_requests = snapshot_requests - - return await self._unary_unary( - "/.SteamLearn/BatchOperation", - request, - CMsgSteamLearn_BatchOperation_Response, - ) - - async def get_h_m_a_c_keys(self, *, appid: int = 0) -> CMsgSteamLearn_GetHMACKeys_Response: - request = CMsgSteamLearn_GetHMACKeys_Request() - request.appid = appid - - return await self._unary_unary( - "/.SteamLearn/GetHMACKeys", - request, - CMsgSteamLearn_GetHMACKeys_Response, - ) - - async def inference( - self, - *, - access_token: str = "", - access_data: CMsgSteamLearn_AccessData | None = None, - project_id: int = 0, - published_version: int = 0, - override_train_id: int = 0, - data: CMsgSteamLearnDataList | None = None, - additional_data: list[float] = [], - ) -> CMsgSteamLearn_Inference_Response: - request = CMsgSteamLearn_Inference_Request() - request.access_token = access_token - if access_data is not None: - request.access_data = access_data - request.project_id = project_id - request.published_version = published_version - request.override_train_id = override_train_id - if data is not None: - request.data = data - request.additional_data = additional_data - - return await self._unary_unary( - "/.SteamLearn/Inference", - request, - CMsgSteamLearn_Inference_Response, - ) - - async def inference_metadata( - self, - *, - access_token: str = "", - access_data: CMsgSteamLearn_AccessData | None = None, - project_id: int = 0, - published_version: int = 0, - override_train_id: int = 0, - ) -> CMsgSteamLearn_InferenceMetadata_Response: - request = CMsgSteamLearn_InferenceMetadata_Request() - request.access_token = access_token - if access_data is not None: - request.access_data = access_data - request.project_id = project_id - request.published_version = published_version - request.override_train_id = override_train_id - - return await self._unary_unary( - "/.SteamLearn/InferenceMetadata", - request, - CMsgSteamLearn_InferenceMetadata_Response, - ) diff --git a/steam/ext/dota2/protobufs/steammessages_unified_base/steamworkssdk.py b/steam/ext/dota2/protobufs/steammessages_unified_base/steamworkssdk.py deleted file mode 100644 index 7af6612d..00000000 --- a/steam/ext/dota2/protobufs/steammessages_unified_base/steamworkssdk.py +++ /dev/null @@ -1,10 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: steammessages_unified_base.steamworkssdk.proto -# plugin: python-betterproto - -import betterproto - - -class EProtoExecutionSite(betterproto.Enum): - k_EProtoExecutionSiteUnknown = 0 - k_EProtoExecutionSiteSteamClient = 3 From f96967f27aa63d567da002a70e99b8bd9e6ee99a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 24 Jan 2024 03:33:26 +0300 Subject: [PATCH 11/50] =?UTF-8?q?=F0=9F=94=A8Fix=20bad=20enum=20namings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../protobufs/dota_gcmessages_client_watch.py | 4 +- .../dota2/protobufs/dota_gcmessages_common.py | 214 +- .../dota2/protobufs/dota_gcmessages_msgid.py | 1776 ++++++++--------- .../ext/dota2/protobufs/dota_shared_enums.py | 1142 +++++------ steam/ext/dota2/protobufs/gcsdk_gcmessages.py | 27 +- steam/ext/dota2/protobufs/gcsystemmsgs.py | 42 +- steam/ext/dota2/protobufs/steammessages.py | 24 +- 7 files changed, 1614 insertions(+), 1615 deletions(-) diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py b/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py index 1116e292..428d99cc 100644 --- a/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py +++ b/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py @@ -88,7 +88,7 @@ class CSourceTVGameSmallPlayer(betterproto.Message): team: int = betterproto.uint32_field(4) -class CMsgClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EDOTAGCMsg.k_EMsgClientToGCFindTopSourceTVGames): +class CMsgClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EDOTAGCMsg.ClientToGCFindTopSourceTVGames): search_key: str = betterproto.string_field(1) league_id: int = betterproto.uint32_field(2) hero_id: int = betterproto.uint32_field(3) @@ -98,7 +98,7 @@ class CMsgClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EDOTAGCMsg.k_EMs class CMsgGCToClientFindTopSourceTVGamesResponse( - GCProtobufMessage, msg=EDOTAGCMsg.k_EMsgGCToClientFindTopSourceTVGamesResponse + GCProtobufMessage, msg=EDOTAGCMsg.GCToClientFindTopSourceTVGamesResponse ): search_key: str = betterproto.string_field(1) league_id: int = betterproto.uint32_field(2) diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_common.py b/steam/ext/dota2/protobufs/dota_gcmessages_common.py index 83667800..fe85f5cf 100644 --- a/steam/ext/dota2/protobufs/dota_gcmessages_common.py +++ b/steam/ext/dota2/protobufs/dota_gcmessages_common.py @@ -10,9 +10,9 @@ if TYPE_CHECKING: from .dota_shared_enums import ( - DOTA_GC_TEAM, CMsgPendingEventAward, - DOTA_GameMode, + DOTAGameMode, + DOTAGCTeam, EEvent, ELeaguePhase, ELeagueRegion, @@ -21,129 +21,129 @@ class ESpecialPingValue(betterproto.Enum): - k_ESpecialPingValue_NoData = 16382 - k_ESpecialPingValue_Failed = 16383 + NoData = 16382 + Failed = 16383 class EDOTAGCSessionNeed(betterproto.Enum): - k_EDOTAGCSessionNeed_Unknown = 0 - k_EDOTAGCSessionNeed_UserNoSessionNeeded = 100 - k_EDOTAGCSessionNeed_UserInOnlineGame = 101 - k_EDOTAGCSessionNeed_UserInLocalGame = 102 - k_EDOTAGCSessionNeed_UserInUIWasConnected = 103 - k_EDOTAGCSessionNeed_UserInUINeverConnected = 104 - k_EDOTAGCSessionNeed_UserTutorials = 105 - k_EDOTAGCSessionNeed_UserInUIWasConnectedIdle = 106 - k_EDOTAGCSessionNeed_UserInUINeverConnectedIdle = 107 - k_EDOTAGCSessionNeed_GameServerOnline = 200 - k_EDOTAGCSessionNeed_GameServerLocal = 201 - k_EDOTAGCSessionNeed_GameServerIdle = 202 - k_EDOTAGCSessionNeed_GameServerRelay = 203 - k_EDOTAGCSessionNeed_GameServerLocalUpload = 204 + Unknown = 0 + UserNoSessionNeeded = 100 + UserInOnlineGame = 101 + UserInLocalGame = 102 + UserInUIWasConnected = 103 + UserInUINeverConnected = 104 + UserTutorials = 105 + UserInUIWasConnectedIdle = 106 + UserInUINeverConnectedIdle = 107 + GameServerOnline = 200 + GameServerLocal = 201 + GameServerIdle = 202 + GameServerRelay = 203 + GameServerLocalUpload = 204 class EDOTAMatchPlayerTimeCustomStat(betterproto.Enum): - k_EDOTA_MatchPlayerTimeCustomStat_HPRegenUnderT1Towers = 1 - k_EDOTA_MatchPlayerTimeCustomStat_MagicDamageReducedWithNewFormula_Absolute = 2 - k_EDOTA_MatchPlayerTimeCustomStat_MagicDamageReducedWithNewFormula_PercentOfTotalHP = 3 - - -class DOTA_TournamentEvents(betterproto.Enum): - TE_FIRST_BLOOD = 0 - TE_GAME_END = 1 - TE_MULTI_KILL = 2 - TE_HERO_DENY = 3 - TE_AEGIS_DENY = 4 - TE_AEGIS_STOLEN = 5 - TE_GODLIKE = 6 - TE_COURIER_KILL = 7 - TE_ECHOSLAM = 8 - TE_RAPIER = 9 - TE_EARLY_ROSHAN = 10 - TE_BLACK_HOLE = 11 + HPRegenUnderT1Towers = 1 + MagicDamageReducedWithNewFormula_Absolute = 2 + MagicDamageReducedWithNewFormula_PercentOfTotalHP = 3 + + +class DOTATournamentEvents(betterproto.Enum): + FIRST_BLOOD = 0 + GAME_END = 1 + MULTI_KILL = 2 + HERO_DENY = 3 + AEGIS_DENY = 4 + AEGIS_STOLEN = 5 + GODLIKE = 6 + COURIER_KILL = 7 + ECHOSLAM = 8 + RAPIER = 9 + EARLY_ROSHAN = 10 + BLACK_HOLE = 11 class EBroadcastTimelineEvent(betterproto.Enum): - EBroadcastTimelineEvent_MatchStarted = 1 - EBroadcastTimelineEvent_GameStateChanged = 2 - EBroadcastTimelineEvent_TowerDeath = 3 - EBroadcastTimelineEvent_BarracksDeath = 4 - EBroadcastTimelineEvent_AncientDeath = 5 - EBroadcastTimelineEvent_RoshanDeath = 6 - EBroadcastTimelineEvent_HeroDeath = 7 - EBroadcastTimelineEvent_TeamFight = 8 - EBroadcastTimelineEvent_FirstBlood = 9 + MatchStarted = 1 + GameStateChanged = 2 + TowerDeath = 3 + BarracksDeath = 4 + AncientDeath = 5 + RoshanDeath = 6 + HeroDeath = 7 + TeamFight = 8 + FirstBlood = 9 class ECustomGameWhitelistState(betterproto.Enum): - CUSTOM_GAME_WHITELIST_STATE_UNKNOWN = 0 - CUSTOM_GAME_WHITELIST_STATE_APPROVED = 1 - CUSTOM_GAME_WHITELIST_STATE_REJECTED = 2 + UNKNOWN = 0 + APPROVED = 1 + REJECTED = 2 class EDOTATriviaQuestionCategory(betterproto.Enum): - k_EDOTATriviaQuestionCategory_AbilityIcon = 0 - k_EDOTATriviaQuestionCategory_AbilityCooldown = 1 - k_EDOTATriviaQuestionCategory_HeroAttributes = 2 - k_EDOTATriviaQuestionCategory_HeroMovementSpeed = 3 - k_EDOTATriviaQuestionCategory_TalentTree = 4 - k_EDOTATriviaQuestionCategory_HeroStats = 5 - k_EDOTATriviaQuestionCategory_ItemPrice = 6 - k_EDOTATriviaQuestionCategory_AbilitySound = 7 - k_EDOTATriviaQuestionCategory_InvokerSpells = 8 - k_EDOTATriviaQuestionCategory_AbilityManaCost = 9 - k_EDOTATriviaQuestionCategory_HeroAttackSound = 10 - k_EDOTATriviaQuestionCategory_AbilityName = 11 - k_EDOTATriviaQuestionCategory_ItemComponents = 12 - k_EDOTATriviaQuestionCategory_ItemLore = 13 - k_EDOTATriviaQuestionCategory_ItemPassives = 14 - k_EDOTATriviaQuestionCategory_STATIC_QUESTIONS_END = 15 - k_EDOTATriviaQuestionCategory_DYNAMIC_QUESTIONS_START = 99 - k_EDOTATriviaQuestionCategory_Dynamic_ItemBuild = 100 + AbilityIcon = 0 + AbilityCooldown = 1 + HeroAttributes = 2 + HeroMovementSpeed = 3 + TalentTree = 4 + HeroStats = 5 + ItemPrice = 6 + AbilitySound = 7 + InvokerSpells = 8 + AbilityManaCost = 9 + HeroAttackSound = 10 + AbilityName = 11 + ItemComponents = 12 + ItemLore = 13 + ItemPassives = 14 + STATIC_QUESTIONS_END = 15 + DYNAMIC_QUESTIONS_START = 99 + Dynamic_ItemBuild = 100 class EOverwatchConviction(betterproto.Enum): - k_EOverwatchConviction_None = 0 - k_EOverwatchConviction_NotGuilty = 1 - k_EOverwatchConviction_GuiltUnclear = 2 - k_EOverwatchConviction_Guilty = 3 + NONE = 0 + NotGuilty = 1 + GuiltUnclear = 2 + Guilty = 3 class EHeroRelicRarity(betterproto.Enum): - HERO_RELIC_RARITY_INVALID = -1 - HERO_RELIC_RARITY_COMMON = 0 - HERO_RELIC_RARITY_RARE = 1 + INVALID = -1 + COMMON = 0 + RARE = 1 class EStickerbookAuditAction(betterproto.Enum): - STICKERBOOK_AUDIT_CREATE_PAGE = 0 - STICKERBOOK_AUDIT_DELETE_PAGE = 1 - STICKERBOOK_AUDIT_STICK_STICKERS = 2 - STICKERBOOK_AUDIT_REPLACE_STICKERS = 3 - STICKERBOOK_AUDIT_HERO_STICKER = 4 + CREATE_PAGE = 0 + DELETE_PAGE = 1 + STICK_STICKERS = 2 + REPLACE_STICKERS = 3 + HERO_STICKER = 4 class EStickerbookPageType(betterproto.Enum): - STICKER_PAGE_GENERIC = 0 - STICKER_PAGE_TEAM = 1 - STICKER_PAGE_TALENT = 2 + GENERIC = 0 + TEAM = 1 + TALENT = 2 class CMsgDOTAProfileCardEStatID(betterproto.Enum): - k_eStat_Wins = 3 - k_eStat_Commends = 4 - k_eStat_GamesPlayed = 5 - k_eStat_FirstMatchDate = 6 - k_eStat_PreviousSeasonRank = 7 - k_eStat_GamesMVP = 8 + Wins = 3 + Commends = 4 + GamesPlayed = 5 + FirstMatchDate = 6 + PreviousSeasonRank = 7 + GamesMVP = 8 class CMsgGCRerollPlayerChallengeResponseEResult(betterproto.Enum): - eResult_Success = 0 - eResult_Dropped = 1 - eResult_NotFound = 2 - eResult_CantReroll = 3 - eResult_ServerError = 4 + Success = 0 + Dropped = 1 + NotFound = 2 + CantReroll = 3 + ServerError = 4 class CMsgDOTARealtimeGameStatsGraphDataeStat(betterproto.Enum): @@ -219,22 +219,22 @@ class CMsgDOTASeasonPredictionsPredictionEAnswerType(betterproto.Enum): class CMsgDOTAMatchReplayState(betterproto.Enum): - REPLAY_AVAILABLE = 0 - REPLAY_NOT_RECORDED = 1 - REPLAY_EXPIRED = 2 + AVAILABLE = 0 + NOT_RECORDED = 1 + EXPIRED = 2 class CMsgDOTAMatchPlayerHeroDamageType(betterproto.Enum): - HERO_DAMAGE_PHYSICAL = 0 - HERO_DAMAGE_MAGICAL = 1 - HERO_DAMAGE_PURE = 2 + PHYSICAL = 0 + MAGICAL = 1 + PURE = 2 class CMsgServerToGCRequestPlayerRecentAccomplishmentsResponseEResponse(betterproto.Enum): - k_eInternalError = 0 - k_eSuccess = 1 - k_eTooBusy = 2 - k_eDisabled = 3 + InternalError = 0 + Success = 1 + TooBusy = 2 + Disabled = 3 @dataclass @@ -1030,7 +1030,7 @@ class CMsgDOTAMatch(betterproto.Message): dire_team_logo_url: str = betterproto.string_field(55) radiant_team_complete: int = betterproto.uint32_field(27) dire_team_complete: int = betterproto.uint32_field(28) - game_mode: DOTA_GameMode = betterproto.enum_field(31) + game_mode: DOTAGameMode = betterproto.enum_field(31) picks_bans: list[CMatchHeroSelectEvent] = betterproto.message_field(32) match_seq_num: int = betterproto.uint64_field(33) replay_state: CMsgDOTAMatchReplayState = betterproto.enum_field(34) @@ -1127,7 +1127,7 @@ class CMsgDOTAMatchPlayer(betterproto.Message): lane_selection_flags: int = betterproto.uint32_field(75) bounty_runes: int = betterproto.uint32_field(77) outposts_captured: int = betterproto.uint32_field(78) - team_number: DOTA_GC_TEAM = betterproto.enum_field(80) + team_number: DOTAGCTeam = betterproto.enum_field(80) team_slot: int = betterproto.uint32_field(81) @@ -1281,7 +1281,7 @@ class CMsgSuccessfulHero(betterproto.Message): @dataclass class CMsgRecentMatchInfo(betterproto.Message): match_id: int = betterproto.uint64_field(1) - game_mode: DOTA_GameMode = betterproto.enum_field(2) + game_mode: DOTAGameMode = betterproto.enum_field(2) kills: int = betterproto.uint32_field(3) deaths: int = betterproto.uint32_field(4) assists: int = betterproto.uint32_field(5) @@ -1311,7 +1311,7 @@ class CMsgDOTAMatchMinimal(betterproto.Message): match_id: int = betterproto.uint64_field(1) start_time: float = betterproto.fixed32_field(2) duration: int = betterproto.uint32_field(3) - game_mode: DOTA_GameMode = betterproto.enum_field(4) + game_mode: DOTAGameMode = betterproto.enum_field(4) players: list[CMsgDOTAMatchMinimalPlayer] = betterproto.message_field(6) tourney: CMsgDOTAMatchMinimalTourney = betterproto.message_field(7) match_outcome: EMatchOutcome = betterproto.enum_field(8) @@ -1331,7 +1331,7 @@ class CMsgDOTAMatchMinimalPlayer(betterproto.Message): player_slot: int = betterproto.uint32_field(7) pro_name: str = betterproto.string_field(8) level: int = betterproto.uint32_field(9) - team_number: DOTA_GC_TEAM = betterproto.enum_field(10) + team_number: DOTAGCTeam = betterproto.enum_field(10) @dataclass diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py b/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py index fa1c6a94..de2cf0c8 100644 --- a/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py +++ b/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py @@ -6,891 +6,891 @@ class EDOTAGCMsg(betterproto.Enum): - k_EMsgGCDOTABase = 7000 - k_EMsgGCGameMatchSignOut = 7004 - k_EMsgGCGameMatchSignOutResponse = 7005 - k_EMsgGCJoinChatChannel = 7009 - k_EMsgGCJoinChatChannelResponse = 7010 - k_EMsgGCOtherJoinedChannel = 7013 - k_EMsgGCOtherLeftChannel = 7014 - k_EMsgServerToGCRequestStatus = 7026 - k_EMsgGCStartFindingMatch = 7033 - k_EMsgGCConnectedPlayers = 7034 - k_EMsgGCAbandonCurrentGame = 7035 - k_EMsgGCStopFindingMatch = 7036 - k_EMsgGCPracticeLobbyCreate = 7038 - k_EMsgGCPracticeLobbyLeave = 7040 - k_EMsgGCPracticeLobbyLaunch = 7041 - k_EMsgGCPracticeLobbyList = 7042 - k_EMsgGCPracticeLobbyListResponse = 7043 - k_EMsgGCPracticeLobbyJoin = 7044 - k_EMsgGCPracticeLobbySetDetails = 7046 - k_EMsgGCPracticeLobbySetTeamSlot = 7047 - k_EMsgGCInitialQuestionnaireResponse = 7049 - k_EMsgGCPracticeLobbyResponse = 7055 - k_EMsgGCBroadcastNotification = 7056 - k_EMsgGCLiveScoreboardUpdate = 7057 - k_EMsgGCRequestChatChannelList = 7060 - k_EMsgGCRequestChatChannelListResponse = 7061 - k_EMsgGCReadyUp = 7070 - k_EMsgGCKickedFromMatchmakingQueue = 7071 - k_EMsgGCLeaverDetected = 7072 - k_EMsgGCSpectateFriendGame = 7073 - k_EMsgGCSpectateFriendGameResponse = 7074 - k_EMsgGCReportsRemainingRequest = 7076 - k_EMsgGCReportsRemainingResponse = 7077 - k_EMsgGCSubmitPlayerReport = 7078 - k_EMsgGCSubmitPlayerReportResponse = 7079 - k_EMsgGCPracticeLobbyKick = 7081 - k_EMsgGCSubmitPlayerReportV2 = 7082 - k_EMsgGCSubmitPlayerReportResponseV2 = 7083 - k_EMsgGCRequestSaveGames = 7084 - k_EMsgGCRequestSaveGamesServer = 7085 - k_EMsgGCRequestSaveGamesResponse = 7086 - k_EMsgGCLeaverDetectedResponse = 7087 - k_EMsgGCPlayerFailedToConnect = 7088 - k_EMsgGCGCToRelayConnect = 7089 - k_EMsgGCGCToRelayConnectresponse = 7090 - k_EMsgGCWatchGame = 7091 - k_EMsgGCWatchGameResponse = 7092 - k_EMsgGCBanStatusRequest = 7093 - k_EMsgGCBanStatusResponse = 7094 - k_EMsgGCMatchDetailsRequest = 7095 - k_EMsgGCMatchDetailsResponse = 7096 - k_EMsgGCCancelWatchGame = 7097 - k_EMsgGCPopup = 7102 - k_EMsgGCFriendPracticeLobbyListRequest = 7111 - k_EMsgGCFriendPracticeLobbyListResponse = 7112 - k_EMsgGCPracticeLobbyJoinResponse = 7113 - k_EMsgGCCreateTeam = 7115 - k_EMsgGCCreateTeamResponse = 7116 - k_EMsgGCTeamInvite_InviterToGC = 7122 - k_EMsgGCTeamInvite_GCImmediateResponseToInviter = 7123 - k_EMsgGCTeamInvite_GCRequestToInvitee = 7124 - k_EMsgGCTeamInvite_InviteeResponseToGC = 7125 - k_EMsgGCTeamInvite_GCResponseToInviter = 7126 - k_EMsgGCTeamInvite_GCResponseToInvitee = 7127 - k_EMsgGCKickTeamMember = 7128 - k_EMsgGCKickTeamMemberResponse = 7129 - k_EMsgGCLeaveTeam = 7130 - k_EMsgGCLeaveTeamResponse = 7131 - k_EMsgGCApplyTeamToPracticeLobby = 7142 - k_EMsgGCTransferTeamAdmin = 7144 - k_EMsgGCPracticeLobbyJoinBroadcastChannel = 7149 - k_EMsgGC_TournamentItemEvent = 7150 - k_EMsgGC_TournamentItemEventResponse = 7151 - k_EMsgTeamFanfare = 7156 - k_EMsgResponseTeamFanfare = 7157 - k_EMsgGC_GameServerUploadSaveGame = 7158 - k_EMsgGC_GameServerSaveGameResult = 7159 - k_EMsgGC_GameServerGetLoadGame = 7160 - k_EMsgGC_GameServerGetLoadGameResult = 7161 - k_EMsgGCEditTeamDetails = 7166 - k_EMsgGCEditTeamDetailsResponse = 7167 - k_EMsgGCReadyUpStatus = 7170 - k_EMsgGCToGCMatchCompleted = 7186 - k_EMsgGCBalancedShuffleLobby = 7188 - k_EMsgGCMatchmakingStatsRequest = 7197 - k_EMsgGCMatchmakingStatsResponse = 7198 - k_EMsgGCBotGameCreate = 7199 - k_EMsgGCSetMatchHistoryAccess = 7200 - k_EMsgGCSetMatchHistoryAccessResponse = 7201 - k_EMsgUpgradeLeagueItem = 7203 - k_EMsgUpgradeLeagueItemResponse = 7204 - k_EMsgGCWatchDownloadedReplay = 7206 - k_EMsgClientsRejoinChatChannels = 7217 - k_EMsgGCToGCGetUserChatInfo = 7218 - k_EMsgGCToGCGetUserChatInfoResponse = 7219 - k_EMsgGCToGCLeaveAllChatChannels = 7220 - k_EMsgGCToGCUpdateAccountChatBan = 7221 - k_EMsgGCToGCCanInviteUserToTeam = 7234 - k_EMsgGCToGCCanInviteUserToTeamResponse = 7235 - k_EMsgGCToGCGetUserRank = 7236 - k_EMsgGCToGCGetUserRankResponse = 7237 - k_EMsgGCToGCAdjustUserRank = 7238 - k_EMsgGCToGCAdjustUserRankResponse = 7239 - k_EMsgGCToGCUpdateTeamStats = 7240 - k_EMsgGCToGCValidateTeam = 7241 - k_EMsgGCToGCValidateTeamResponse = 7242 - k_EMsgGCToGCGetLeagueAdmin = 7255 - k_EMsgGCToGCGetLeagueAdminResponse = 7256 - k_EMsgGCLeaveChatChannel = 7272 - k_EMsgGCChatMessage = 7273 - k_EMsgGCGetHeroStandings = 7274 - k_EMsgGCGetHeroStandingsResponse = 7275 - k_EMsgGCItemEditorReservationsRequest = 7283 - k_EMsgGCItemEditorReservationsResponse = 7284 - k_EMsgGCItemEditorReserveItemDef = 7285 - k_EMsgGCItemEditorReserveItemDefResponse = 7286 - k_EMsgGCItemEditorReleaseReservation = 7287 - k_EMsgGCItemEditorReleaseReservationResponse = 7288 - k_EMsgGCRewardTutorialPrizes = 7289 - k_EMsgGCFantasyLivePlayerStats = 7308 - k_EMsgGCFantasyFinalPlayerStats = 7309 - k_EMsgGCFlipLobbyTeams = 7320 - k_EMsgGCToGCEvaluateReportedPlayer = 7322 - k_EMsgGCToGCEvaluateReportedPlayerResponse = 7323 - k_EMsgGCToGCProcessPlayerReportForTarget = 7324 - k_EMsgGCToGCProcessReportSuccess = 7325 - k_EMsgGCNotifyAccountFlagsChange = 7326 - k_EMsgGCSetProfilePrivacy = 7327 - k_EMsgGCSetProfilePrivacyResponse = 7328 - k_EMsgGCClientSuspended = 7342 - k_EMsgGCPartyMemberSetCoach = 7343 - k_EMsgGCPracticeLobbySetCoach = 7346 - k_EMsgGCChatModeratorBan = 7359 - k_EMsgGCLobbyUpdateBroadcastChannelInfo = 7367 - k_EMsgGCToGCGrantTournamentItem = 7372 - k_EMsgGCToGCUpgradeTwitchViewerItems = 7375 - k_EMsgGCToGCGetLiveMatchAffiliates = 7376 - k_EMsgGCToGCGetLiveMatchAffiliatesResponse = 7377 - k_EMsgGCToGCUpdatePlayerPennantCounts = 7378 - k_EMsgGCToGCGetPlayerPennantCounts = 7379 - k_EMsgGCToGCGetPlayerPennantCountsResponse = 7380 - k_EMsgGCGameMatchSignOutPermissionRequest = 7381 - k_EMsgGCGameMatchSignOutPermissionResponse = 7382 - k_EMsgDOTAAwardEventPoints = 7384 - k_EMsgDOTAGetEventPoints = 7387 - k_EMsgDOTAGetEventPointsResponse = 7388 - k_EMsgGCPartyLeaderWatchGamePrompt = 7397 - k_EMsgGCCompendiumSetSelection = 7405 - k_EMsgGCCompendiumDataRequest = 7406 - k_EMsgGCCompendiumDataResponse = 7407 - k_EMsgDOTAGetPlayerMatchHistory = 7408 - k_EMsgDOTAGetPlayerMatchHistoryResponse = 7409 - k_EMsgGCToGCMatchmakingAddParty = 7410 - k_EMsgGCToGCMatchmakingRemoveParty = 7411 - k_EMsgGCToGCMatchmakingRemoveAllParties = 7412 - k_EMsgGCToGCMatchmakingMatchFound = 7413 - k_EMsgGCToGCUpdateMatchManagementStats = 7414 - k_EMsgGCToGCUpdateMatchmakingStats = 7415 - k_EMsgGCToServerPingRequest = 7416 - k_EMsgGCToServerPingResponse = 7417 - k_EMsgGCToServerEvaluateToxicChat = 7418 - k_EMsgServerToGCEvaluateToxicChat = 7419 - k_EMsgServerToGCEvaluateToxicChatResponse = 7420 - k_EMsgGCToGCProcessMatchLeaver = 7426 - k_EMsgGCNotificationsRequest = 7427 - k_EMsgGCNotificationsResponse = 7428 - k_EMsgGCToGCModifyNotification = 7429 - k_EMsgGCLeagueAdminList = 7434 - k_EMsgGCNotificationsMarkReadRequest = 7435 - k_EMsgServerToGCRequestBatchPlayerResources = 7450 - k_EMsgServerToGCRequestBatchPlayerResourcesResponse = 7451 - k_EMsgGCCompendiumSetSelectionResponse = 7453 - k_EMsgGCPlayerInfoSubmit = 7456 - k_EMsgGCPlayerInfoSubmitResponse = 7457 - k_EMsgGCToGCGetAccountLevel = 7458 - k_EMsgGCToGCGetAccountLevelResponse = 7459 - k_EMsgDOTAGetWeekendTourneySchedule = 7464 - k_EMsgDOTAWeekendTourneySchedule = 7465 - k_EMsgGCJoinableCustomGameModesRequest = 7466 - k_EMsgGCJoinableCustomGameModesResponse = 7467 - k_EMsgGCJoinableCustomLobbiesRequest = 7468 - k_EMsgGCJoinableCustomLobbiesResponse = 7469 - k_EMsgGCQuickJoinCustomLobby = 7470 - k_EMsgGCQuickJoinCustomLobbyResponse = 7471 - k_EMsgGCToGCGrantEventPointAction = 7472 - k_EMsgGCToGCSetCompendiumSelection = 7478 - k_EMsgGCHasItemQuery = 7484 - k_EMsgGCHasItemResponse = 7485 - k_EMsgGCToGCGrantEventPointActionMsg = 7488 - k_EMsgGCToGCGetCompendiumSelections = 7492 - k_EMsgGCToGCGetCompendiumSelectionsResponse = 7493 - k_EMsgServerToGCMatchConnectionStats = 7494 - k_EMsgGCToClientTournamentItemDrop = 7495 - k_EMsgSQLDelayedGrantLeagueDrop = 7496 - k_EMsgServerGCUpdateSpectatorCount = 7497 - k_EMsgGCToGCEmoticonUnlock = 7501 - k_EMsgSignOutDraftInfo = 7502 - k_EMsgClientToGCEmoticonDataRequest = 7503 - k_EMsgGCToClientEmoticonData = 7504 - k_EMsgGCPracticeLobbyToggleBroadcastChannelCameramanStatus = 7505 - k_EMsgDOTARedeemItem = 7518 - k_EMsgDOTARedeemItemResponse = 7519 - k_EMsgClientToGCGetAllHeroProgress = 7521 - k_EMsgClientToGCGetAllHeroProgressResponse = 7522 - k_EMsgGCToGCGetServerForClient = 7523 - k_EMsgGCToGCGetServerForClientResponse = 7524 - k_EMsgSQLProcessTournamentGameOutcome = 7525 - k_EMsgSQLGrantTrophyToAccount = 7526 - k_EMsgClientToGCGetTrophyList = 7527 - k_EMsgClientToGCGetTrophyListResponse = 7528 - k_EMsgGCToClientTrophyAwarded = 7529 - k_EMsgGCGameBotMatchSignOut = 7530 - k_EMsgGCGameBotMatchSignOutPermissionRequest = 7531 - k_EMsgSignOutBotInfo = 7532 - k_EMsgGCToGCUpdateProfileCards = 7533 - k_EMsgClientToGCGetProfileCard = 7534 - k_EMsgClientToGCGetProfileCardResponse = 7535 - k_EMsgClientToGCGetBattleReport = 7536 - k_EMsgClientToGCGetBattleReportResponse = 7537 - k_EMsgClientToGCSetProfileCardSlots = 7538 - k_EMsgGCToClientProfileCardUpdated = 7539 - k_EMsgServerToGCVictoryPredictions = 7540 - k_EMsgClientToGCGetBattleReportAggregateStats = 7541 - k_EMsgClientToGCGetBattleReportAggregateStatsResponse = 7542 - k_EMsgClientToGCGetBattleReportInfo = 7543 - k_EMsgClientToGCGetBattleReportInfoResponse = 7544 - k_EMsgSignOutCommunicationSummary = 7545 - k_EMsgServerToGCRequestStatus_Response = 7546 - k_EMsgClientToGCCreateHeroStatue = 7547 - k_EMsgGCToClientHeroStatueCreateResult = 7548 - k_EMsgGCGCToLANServerRelayConnect = 7549 - k_EMsgClientToGCAcknowledgeBattleReport = 7550 - k_EMsgClientToGCAcknowledgeBattleReportResponse = 7551 - k_EMsgClientToGCGetBattleReportMatchHistory = 7552 - k_EMsgClientToGCGetBattleReportMatchHistoryResponse = 7553 - k_EMsgServerToGCReportKillSummaries = 7554 - k_EMsgGCToGCUpdatePlayerPredictions = 7561 - k_EMsgGCToServerPredictionResult = 7562 - k_EMsgGCToGCReplayMonitorValidateReplay = 7569 - k_EMsgLobbyEventPoints = 7572 - k_EMsgGCToGCGetCustomGameTickets = 7573 - k_EMsgGCToGCGetCustomGameTicketsResponse = 7574 - k_EMsgGCToGCCustomGamePlayed = 7576 - k_EMsgGCToGCGrantEventPointsToUser = 7577 - k_EMsgGameserverCrashReport = 7579 - k_EMsgGameserverCrashReportResponse = 7580 - k_EMsgGCToClientSteamDatagramTicket = 7581 - k_EMsgGCToGCSendAccountsEventPoints = 7583 - k_EMsgClientToGCRerollPlayerChallenge = 7584 - k_EMsgServerToGCRerollPlayerChallenge = 7585 - k_EMsgGCRerollPlayerChallengeResponse = 7586 - k_EMsgSignOutUpdatePlayerChallenge = 7587 - k_EMsgClientToGCSetPartyLeader = 7588 - k_EMsgClientToGCCancelPartyInvites = 7589 - k_EMsgSQLGrantLeagueMatchToTicketHolders = 7592 - k_EMsgGCToGCEmoticonUnlockNoRollback = 7594 - k_EMsgClientToGCApplyGemCombiner = 7603 - k_EMsgClientToGCGetAllHeroOrder = 7606 - k_EMsgClientToGCGetAllHeroOrderResponse = 7607 - k_EMsgSQLGCToGCGrantBadgePoints = 7608 - k_EMsgGCToGCCheckOwnsEntireEmoticonRange = 7611 - k_EMsgGCToGCCheckOwnsEntireEmoticonRangeResponse = 7612 - k_EMsgGCToClientRequestLaneSelection = 7623 - k_EMsgGCToClientRequestLaneSelectionResponse = 7624 - k_EMsgServerToGCCavernCrawlIsHeroActive = 7625 - k_EMsgServerToGCCavernCrawlIsHeroActiveResponse = 7626 - k_EMsgClientToGCPlayerCardSpecificPurchaseRequest = 7627 - k_EMsgClientToGCPlayerCardSpecificPurchaseResponse = 7628 - k_EMsgGCtoServerTensorflowInstance = 7629 - k_EMsgSQLSetIsLeagueAdmin = 7630 - k_EMsgGCToGCGetLiveLeagueMatches = 7631 - k_EMsgGCToGCGetLiveLeagueMatchesResponse = 7632 - k_EMsgDOTALeagueInfoListAdminsRequest = 7633 - k_EMsgDOTALeagueInfoListAdminsReponse = 7634 - k_EMsgGCToGCLeagueMatchStarted = 7645 - k_EMsgGCToGCLeagueMatchCompleted = 7646 - k_EMsgGCToGCLeagueMatchStartedResponse = 7647 - k_EMsgDOTALeagueAvailableLobbyNodesRequest = 7650 - k_EMsgDOTALeagueAvailableLobbyNodes = 7651 - k_EMsgGCToGCLeagueRequest = 7652 - k_EMsgGCToGCLeagueResponse = 7653 - k_EMsgGCToGCLeagueNodeGroupRequest = 7654 - k_EMsgGCToGCLeagueNodeGroupResponse = 7655 - k_EMsgGCToGCLeagueNodeRequest = 7656 - k_EMsgGCToGCLeagueNodeResponse = 7657 - k_EMsgGCToGCRealtimeStatsTerseRequest = 7658 - k_EMsgGCToGCRealtimeStatsTerseResponse = 7659 - k_EMsgGCToGCGetTopMatchesRequest = 7660 - k_EMsgGCToGCGetTopMatchesResponse = 7661 - k_EMsgClientToGCGetFilteredPlayers = 7662 - k_EMsgGCToClientGetFilteredPlayersResponse = 7663 - k_EMsgClientToGCRemoveFilteredPlayer = 7664 - k_EMsgGCToClientRemoveFilteredPlayerResponse = 7665 - k_EMsgGCToClientPlayerBeaconState = 7666 - k_EMsgGCToClientPartyBeaconUpdate = 7667 - k_EMsgGCToClientPartySearchInvite = 7668 - k_EMsgClientToGCUpdatePartyBeacon = 7669 - k_EMsgClientToGCRequestActiveBeaconParties = 7670 - k_EMsgGCToClientRequestActiveBeaconPartiesResponse = 7671 - k_EMsgClientToGCManageFavorites = 7672 - k_EMsgGCToClientManageFavoritesResponse = 7673 - k_EMsgClientToGCJoinPartyFromBeacon = 7674 - k_EMsgGCToClientJoinPartyFromBeaconResponse = 7675 - k_EMsgClientToGCGetFavoritePlayers = 7676 - k_EMsgGCToClientGetFavoritePlayersResponse = 7677 - k_EMsgClientToGCVerifyFavoritePlayers = 7678 - k_EMsgGCToClientVerifyFavoritePlayersResponse = 7679 - k_EMsgGCToClientPartySearchInvites = 7680 - k_EMsgGCToClientRequestMMInfo = 7681 - k_EMsgClientToGCMMInfo = 7682 - k_EMsgSignOutTextMuteInfo = 7683 - k_EMsgClientToGCPurchaseLabyrinthBlessings = 7684 - k_EMsgClientToGCPurchaseLabyrinthBlessingsResponse = 7685 - k_EMsgClientToGCPurchaseFilteredPlayerSlot = 7686 - k_EMsgGCToClientPurchaseFilteredPlayerSlotResponse = 7687 - k_EMsgClientToGCUpdateFilteredPlayerNote = 7688 - k_EMsgGCToClientUpdateFilteredPlayerNoteResponse = 7689 - k_EMsgClientToGCClaimSwag = 7690 - k_EMsgGCToClientClaimSwagResponse = 7691 - k_EMsgServerToGCLockCharmTrading = 8004 - k_EMsgClientToGCPlayerStatsRequest = 8006 - k_EMsgGCToClientPlayerStatsResponse = 8007 - k_EMsgGCClearPracticeLobbyTeam = 8008 - k_EMsgClientToGCFindTopSourceTVGames = 8009 - k_EMsgGCToClientFindTopSourceTVGamesResponse = 8010 - k_EMsgGCLobbyList = 8011 - k_EMsgGCLobbyListResponse = 8012 - k_EMsgGCPlayerStatsMatchSignOut = 8013 - k_EMsgClientToGCSocialFeedPostCommentRequest = 8016 - k_EMsgGCToClientSocialFeedPostCommentResponse = 8017 - k_EMsgClientToGCCustomGamesFriendsPlayedRequest = 8018 - k_EMsgGCToClientCustomGamesFriendsPlayedResponse = 8019 - k_EMsgClientToGCFriendsPlayedCustomGameRequest = 8020 - k_EMsgGCToClientFriendsPlayedCustomGameResponse = 8021 - k_EMsgGCTopCustomGamesList = 8024 - k_EMsgClientToGCSetPartyOpen = 8029 - k_EMsgClientToGCMergePartyInvite = 8030 - k_EMsgGCToClientMergeGroupInviteReply = 8031 - k_EMsgClientToGCMergePartyResponse = 8032 - k_EMsgGCToClientMergePartyResponseReply = 8033 - k_EMsgClientToGCGetProfileCardStats = 8034 - k_EMsgClientToGCGetProfileCardStatsResponse = 8035 - k_EMsgClientToGCTopLeagueMatchesRequest = 8036 - k_EMsgClientToGCTopFriendMatchesRequest = 8037 - k_EMsgGCToClientProfileCardStatsUpdated = 8040 - k_EMsgServerToGCRealtimeStats = 8041 - k_EMsgGCToServerRealtimeStatsStartStop = 8042 - k_EMsgGCToGCGetServersForClients = 8045 - k_EMsgGCToGCGetServersForClientsResponse = 8046 - k_EMsgGCPracticeLobbyKickFromTeam = 8047 - k_EMsgDOTAChatGetMemberCount = 8048 - k_EMsgDOTAChatGetMemberCountResponse = 8049 - k_EMsgClientToGCSocialFeedPostMessageRequest = 8050 - k_EMsgGCToClientSocialFeedPostMessageResponse = 8051 - k_EMsgCustomGameListenServerStartedLoading = 8052 - k_EMsgCustomGameClientFinishedLoading = 8053 - k_EMsgGCPracticeLobbyCloseBroadcastChannel = 8054 - k_EMsgGCStartFindingMatchResponse = 8055 - k_EMsgSQLGCToGCGrantAccountFlag = 8057 - k_EMsgGCToClientTopLeagueMatchesResponse = 8061 - k_EMsgGCToClientTopFriendMatchesResponse = 8062 - k_EMsgClientToGCMatchesMinimalRequest = 8063 - k_EMsgClientToGCMatchesMinimalResponse = 8064 - k_EMsgGCToClientChatRegionsEnabled = 8067 - k_EMsgClientToGCPingData = 8068 - k_EMsgGCToGCEnsureAccountInParty = 8071 - k_EMsgGCToGCEnsureAccountInPartyResponse = 8072 - k_EMsgClientToGCGetProfileTickets = 8073 - k_EMsgClientToGCGetProfileTicketsResponse = 8074 - k_EMsgGCToClientMatchGroupsVersion = 8075 - k_EMsgClientToGCH264Unsupported = 8076 - k_EMsgClientToGCGetQuestProgress = 8078 - k_EMsgClientToGCGetQuestProgressResponse = 8079 - k_EMsgSignOutXPCoins = 8080 - k_EMsgGCToClientMatchSignedOut = 8081 - k_EMsgGCGetHeroStatsHistory = 8082 - k_EMsgGCGetHeroStatsHistoryResponse = 8083 - k_EMsgClientToGCPrivateChatInvite = 8084 - k_EMsgClientToGCPrivateChatKick = 8088 - k_EMsgClientToGCPrivateChatPromote = 8089 - k_EMsgClientToGCPrivateChatDemote = 8090 - k_EMsgGCToClientPrivateChatResponse = 8091 - k_EMsgClientToGCLatestConductScorecardRequest = 8095 - k_EMsgClientToGCLatestConductScorecard = 8096 - k_EMsgClientToGCWageringRequest = 8099 - k_EMsgGCToClientWageringResponse = 8100 - k_EMsgClientToGCEventGoalsRequest = 8103 - k_EMsgClientToGCEventGoalsResponse = 8104 - k_EMsgGCToGCLeaguePredictionsUpdate = 8108 - k_EMsgGCToGCAddUserToPostGameChat = 8110 - k_EMsgClientToGCHasPlayerVotedForMVP = 8111 - k_EMsgClientToGCHasPlayerVotedForMVPResponse = 8112 - k_EMsgClientToGCVoteForMVP = 8113 - k_EMsgClientToGCVoteForMVPResponse = 8114 - k_EMsgGCToGCGetEventOwnership = 8115 - k_EMsgGCToGCGetEventOwnershipResponse = 8116 - k_EMsgGCToClientAutomatedTournamentStateChange = 8117 - k_EMsgClientToGCWeekendTourneyOpts = 8118 - k_EMsgClientToGCWeekendTourneyOptsResponse = 8119 - k_EMsgClientToGCWeekendTourneyLeave = 8120 - k_EMsgClientToGCWeekendTourneyLeaveResponse = 8121 - k_EMsgClientToGCTeammateStatsRequest = 8124 - k_EMsgClientToGCTeammateStatsResponse = 8125 - k_EMsgClientToGCGetGiftPermissions = 8126 - k_EMsgClientToGCGetGiftPermissionsResponse = 8127 - k_EMsgClientToGCVoteForArcana = 8128 - k_EMsgClientToGCVoteForArcanaResponse = 8129 - k_EMsgClientToGCRequestArcanaVotesRemaining = 8130 - k_EMsgClientToGCRequestArcanaVotesRemainingResponse = 8131 - k_EMsgGCTransferTeamAdminResponse = 8132 - k_EMsgGCToClientTeamInfo = 8135 - k_EMsgGCToClientTeamsInfo = 8136 - k_EMsgClientToGCMyTeamInfoRequest = 8137 - k_EMsgClientToGCPublishUserStat = 8140 - k_EMsgGCToGCSignoutSpendWager = 8141 - k_EMsgGCSubmitLobbyMVPVote = 8144 - k_EMsgGCSubmitLobbyMVPVoteResponse = 8145 - k_EMsgSignOutCommunityGoalProgress = 8150 - k_EMsgGCToClientLobbyMVPAwarded = 8152 - k_EMsgGCToClientQuestProgressUpdated = 8153 - k_EMsgGCToClientWageringUpdate = 8154 - k_EMsgGCToClientArcanaVotesUpdate = 8155 - k_EMsgClientToGCSetSpectatorLobbyDetails = 8157 - k_EMsgClientToGCSetSpectatorLobbyDetailsResponse = 8158 - k_EMsgClientToGCCreateSpectatorLobby = 8159 - k_EMsgClientToGCCreateSpectatorLobbyResponse = 8160 - k_EMsgClientToGCSpectatorLobbyList = 8161 - k_EMsgClientToGCSpectatorLobbyListResponse = 8162 - k_EMsgSpectatorLobbyGameDetails = 8163 - k_EMsgServerToGCCompendiumInGamePredictionResults = 8166 - k_EMsgServerToGCCloseCompendiumInGamePredictionVoting = 8167 - k_EMsgClientToGCOpenPlayerCardPack = 8168 - k_EMsgClientToGCOpenPlayerCardPackResponse = 8169 - k_EMsgClientToGCSelectCompendiumInGamePrediction = 8170 - k_EMsgClientToGCSelectCompendiumInGamePredictionResponse = 8171 - k_EMsgClientToGCWeekendTourneyGetPlayerStats = 8172 - k_EMsgClientToGCWeekendTourneyGetPlayerStatsResponse = 8173 - k_EMsgClientToGCRecyclePlayerCard = 8174 - k_EMsgClientToGCRecyclePlayerCardResponse = 8175 - k_EMsgClientToGCCreatePlayerCardPack = 8176 - k_EMsgClientToGCCreatePlayerCardPackResponse = 8177 - k_EMsgClientToGCGetPlayerCardRosterRequest = 8178 - k_EMsgClientToGCGetPlayerCardRosterResponse = 8179 - k_EMsgClientToGCSetPlayerCardRosterRequest = 8180 - k_EMsgClientToGCSetPlayerCardRosterResponse = 8181 - k_EMsgServerToGCCloseCompendiumInGamePredictionVotingResponse = 8183 - k_EMsgLobbyBattleCupVictory = 8186 - k_EMsgGCGetPlayerCardItemInfo = 8187 - k_EMsgGCGetPlayerCardItemInfoResponse = 8188 - k_EMsgClientToGCRequestSteamDatagramTicket = 8189 - k_EMsgClientToGCRequestSteamDatagramTicketResponse = 8190 - k_EMsgGCToClientBattlePassRollupRequest = 8191 - k_EMsgGCToClientBattlePassRollupResponse = 8192 - k_EMsgClientToGCTransferSeasonalMMRRequest = 8193 - k_EMsgClientToGCTransferSeasonalMMRResponse = 8194 - k_EMsgGCToGCPublicChatCommunicationBan = 8195 - k_EMsgGCToGCUpdateAccountInfo = 8196 - k_EMsgGCChatReportPublicSpam = 8197 - k_EMsgClientToGCSetPartyBuilderOptions = 8198 - k_EMsgClientToGCSetPartyBuilderOptionsResponse = 8199 - k_EMsgGCToClientPlaytestStatus = 8200 - k_EMsgClientToGCJoinPlaytest = 8201 - k_EMsgClientToGCJoinPlaytestResponse = 8202 - k_EMsgLobbyPlaytestDetails = 8203 - k_EMsgDOTASetFavoriteTeam = 8204 - k_EMsgGCToClientBattlePassRollupListRequest = 8205 - k_EMsgGCToClientBattlePassRollupListResponse = 8206 - k_EMsgDOTAClaimEventAction = 8209 - k_EMsgDOTAClaimEventActionResponse = 8210 - k_EMsgDOTAGetPeriodicResource = 8211 - k_EMsgDOTAGetPeriodicResourceResponse = 8212 - k_EMsgDOTAPeriodicResourceUpdated = 8213 - k_EMsgServerToGCSpendWager = 8214 - k_EMsgGCToGCSignoutSpendWagerToken = 8215 - k_EMsgSubmitTriviaQuestionAnswer = 8216 - k_EMsgSubmitTriviaQuestionAnswerResponse = 8217 - k_EMsgClientToGCGiveTip = 8218 - k_EMsgClientToGCGiveTipResponse = 8219 - k_EMsgStartTriviaSession = 8220 - k_EMsgStartTriviaSessionResponse = 8221 - k_EMsgAnchorPhoneNumberRequest = 8222 - k_EMsgAnchorPhoneNumberResponse = 8223 - k_EMsgUnanchorPhoneNumberRequest = 8224 - k_EMsgUnanchorPhoneNumberResponse = 8225 - k_EMsgGCToGCSignoutSpendRankWager = 8229 - k_EMsgGCToGCGetFavoriteTeam = 8230 - k_EMsgGCToGCGetFavoriteTeamResponse = 8231 - k_EMsgSignOutEventGameData = 8232 - k_EMsgClientToGCQuickStatsRequest = 8238 - k_EMsgClientToGCQuickStatsResponse = 8239 - k_EMsgGCToGCSubtractEventPointsFromUser = 8240 - k_EMsgSelectionPriorityChoiceRequest = 8241 - k_EMsgSelectionPriorityChoiceResponse = 8242 - k_EMsgGCToGCCompendiumInGamePredictionResults = 8243 - k_EMsgGameAutographReward = 8244 - k_EMsgGameAutographRewardResponse = 8245 - k_EMsgDestroyLobbyRequest = 8246 - k_EMsgDestroyLobbyResponse = 8247 - k_EMsgPurchaseItemWithEventPoints = 8248 - k_EMsgPurchaseItemWithEventPointsResponse = 8249 - k_EMsgServerToGCMatchPlayerItemPurchaseHistory = 8250 - k_EMsgGCToGCGrantPlusHeroMatchResults = 8251 - k_EMsgServerToGCMatchStateHistory = 8255 - k_EMsgPurchaseHeroRandomRelic = 8258 - k_EMsgPurchaseHeroRandomRelicResponse = 8259 - k_EMsgClientToGCClaimEventActionUsingItem = 8260 - k_EMsgClientToGCClaimEventActionUsingItemResponse = 8261 - k_EMsgPartyReadyCheckRequest = 8262 - k_EMsgPartyReadyCheckResponse = 8263 - k_EMsgPartyReadyCheckAcknowledge = 8264 - k_EMsgGetRecentPlayTimeFriendsRequest = 8265 - k_EMsgGetRecentPlayTimeFriendsResponse = 8266 - k_EMsgGCToClientCommendNotification = 8267 - k_EMsgProfileRequest = 8268 - k_EMsgProfileResponse = 8269 - k_EMsgProfileUpdate = 8270 - k_EMsgProfileUpdateResponse = 8271 - k_EMsgHeroGlobalDataRequest = 8274 - k_EMsgHeroGlobalDataResponse = 8275 - k_EMsgClientToGCRequestPlusWeeklyChallengeResult = 8276 - k_EMsgClientToGCRequestPlusWeeklyChallengeResultResponse = 8277 - k_EMsgGCToGCGrantPlusPrepaidTime = 8278 - k_EMsgPrivateMetadataKeyRequest = 8279 - k_EMsgPrivateMetadataKeyResponse = 8280 - k_EMsgGCToGCReconcilePlusStatus = 8281 - k_EMsgGCToGCCheckPlusStatus = 8282 - k_EMsgGCToGCCheckPlusStatusResponse = 8283 - k_EMsgGCToGCReconcilePlusAutoGrantItems = 8284 - k_EMsgGCToGCReconcilePlusStatusUnreliable = 8285 - k_EMsgGCToClientCavernCrawlMapPathCompleted = 8288 - k_EMsgClientToGCCavernCrawlClaimRoom = 8289 - k_EMsgClientToGCCavernCrawlClaimRoomResponse = 8290 - k_EMsgClientToGCCavernCrawlUseItemOnRoom = 8291 - k_EMsgClientToGCCavernCrawlUseItemOnRoomResponse = 8292 - k_EMsgClientToGCCavernCrawlUseItemOnPath = 8293 - k_EMsgClientToGCCavernCrawlUseItemOnPathResponse = 8294 - k_EMsgClientToGCCavernCrawlRequestMapState = 8295 - k_EMsgClientToGCCavernCrawlRequestMapStateResponse = 8296 - k_EMsgSignOutTips = 8297 - k_EMsgClientToGCRequestEventPointLogV2 = 8298 - k_EMsgClientToGCRequestEventPointLogResponseV2 = 8299 - k_EMsgClientToGCRequestEventTipsSummary = 8300 - k_EMsgClientToGCRequestEventTipsSummaryResponse = 8301 - k_EMsgClientToGCRequestSocialFeed = 8303 - k_EMsgClientToGCRequestSocialFeedResponse = 8304 - k_EMsgClientToGCRequestSocialFeedComments = 8305 - k_EMsgClientToGCRequestSocialFeedCommentsResponse = 8306 - k_EMsgClientToGCCavernCrawlGetClaimedRoomCount = 8308 - k_EMsgClientToGCCavernCrawlGetClaimedRoomCountResponse = 8309 - k_EMsgGCToGCReconcilePlusAutoGrantItemsUnreliable = 8310 - k_EMsgServerToGCAddBroadcastTimelineEvent = 8311 - k_EMsgGCToServerUpdateSteamBroadcasting = 8312 - k_EMsgClientToGCRecordContestVote = 8313 - k_EMsgGCToClientRecordContestVoteResponse = 8314 - k_EMsgGCToGCGrantAutograph = 8315 - k_EMsgGCToGCGrantAutographResponse = 8316 - k_EMsgSignOutConsumableUsage = 8317 - k_EMsgLobbyEventGameDetails = 8318 - k_EMsgDevGrantEventPoints = 8319 - k_EMsgDevGrantEventPointsResponse = 8320 - k_EMsgDevGrantEventAction = 8321 - k_EMsgDevGrantEventActionResponse = 8322 - k_EMsgDevResetEventState = 8323 - k_EMsgDevResetEventStateResponse = 8324 - k_EMsgGCToGCReconcileEventOwnership = 8325 - k_EMsgConsumeEventSupportGrantItem = 8326 - k_EMsgConsumeEventSupportGrantItemResponse = 8327 - k_EMsgGCToClientClaimEventActionUsingItemCompleted = 8328 - k_EMsgGCToClientCavernCrawlMapUpdated = 8329 - k_EMsgServerToGCRequestPlayerRecentAccomplishments = 8330 - k_EMsgServerToGCRequestPlayerRecentAccomplishmentsResponse = 8331 - k_EMsgClientToGCRequestPlayerRecentAccomplishments = 8332 - k_EMsgClientToGCRequestPlayerRecentAccomplishmentsResponse = 8333 - k_EMsgClientToGCRequestPlayerHeroRecentAccomplishments = 8334 - k_EMsgClientToGCRequestPlayerHeroRecentAccomplishmentsResponse = 8335 - k_EMsgSignOutEventActionGrants = 8336 - k_EMsgClientToGCRequestPlayerCoachMatches = 8337 - k_EMsgClientToGCRequestPlayerCoachMatchesResponse = 8338 - k_EMsgClientToGCSubmitCoachTeammateRating = 8341 - k_EMsgClientToGCSubmitCoachTeammateRatingResponse = 8342 - k_EMsgGCToClientCoachTeammateRatingsChanged = 8343 - k_EMsgClientToGCRequestPlayerCoachMatch = 8345 - k_EMsgClientToGCRequestPlayerCoachMatchResponse = 8346 - k_EMsgClientToGCRequestContestVotes = 8347 - k_EMsgClientToGCRequestContestVotesResponse = 8348 - k_EMsgClientToGCMVPVoteTimeout = 8349 - k_EMsgClientToGCMVPVoteTimeoutResponse = 8350 - k_EMsgMatchMatchmakingStats = 8360 - k_EMsgClientToGCSubmitPlayerMatchSurvey = 8361 - k_EMsgClientToGCSubmitPlayerMatchSurveyResponse = 8362 - k_EMsgSQLGCToGCGrantAllHeroProgressAccount = 8363 - k_EMsgSQLGCToGCGrantAllHeroProgressVictory = 8364 - k_EMsgDevDeleteEventActions = 8365 - k_EMsgDevDeleteEventActionsResponse = 8366 - k_EMsgGCToGCGetAllHeroCurrent = 8635 - k_EMsgGCToGCGetAllHeroCurrentResponse = 8636 - k_EMsgGCSubmitPlayerAvoidRequest = 8637 - k_EMsgGCSubmitPlayerAvoidRequestResponse = 8638 - k_EMsgGCToClientNotificationsUpdated = 8639 - k_EMsgGCtoGCAssociatedExploiterAccountInfo = 8640 - k_EMsgGCtoGCAssociatedExploiterAccountInfoResponse = 8641 - k_EMsgGCtoGCRequestRecalibrationCheck = 8642 - k_EMsgGCToClientVACReminder = 8643 - k_EMsgClientToGCUnderDraftBuy = 8644 - k_EMsgClientToGCUnderDraftBuyResponse = 8645 - k_EMsgClientToGCUnderDraftReroll = 8646 - k_EMsgClientToGCUnderDraftRerollResponse = 8647 - k_EMsgNeutralItemStats = 8648 - k_EMsgClientToGCCreateGuild = 8649 - k_EMsgClientToGCCreateGuildResponse = 8650 - k_EMsgClientToGCSetGuildInfo = 8651 - k_EMsgClientToGCSetGuildInfoResponse = 8652 - k_EMsgClientToGCAddGuildRole = 8653 - k_EMsgClientToGCAddGuildRoleResponse = 8654 - k_EMsgClientToGCModifyGuildRole = 8655 - k_EMsgClientToGCModifyGuildRoleResponse = 8656 - k_EMsgClientToGCRemoveGuildRole = 8657 - k_EMsgClientToGCRemoveGuildRoleResponse = 8658 - k_EMsgClientToGCJoinGuild = 8659 - k_EMsgClientToGCJoinGuildResponse = 8660 - k_EMsgClientToGCLeaveGuild = 8661 - k_EMsgClientToGCLeaveGuildResponse = 8662 - k_EMsgClientToGCInviteToGuild = 8663 - k_EMsgClientToGCInviteToGuildResponse = 8664 - k_EMsgClientToGCDeclineInviteToGuild = 8665 - k_EMsgClientToGCDeclineInviteToGuildResponse = 8666 - k_EMsgClientToGCCancelInviteToGuild = 8667 - k_EMsgClientToGCCancelInviteToGuildResponse = 8668 - k_EMsgClientToGCKickGuildMember = 8669 - k_EMsgClientToGCKickGuildMemberResponse = 8670 - k_EMsgClientToGCSetGuildMemberRole = 8671 - k_EMsgClientToGCSetGuildMemberRoleResponse = 8672 - k_EMsgClientToGCRequestGuildData = 8673 - k_EMsgClientToGCRequestGuildDataResponse = 8674 - k_EMsgGCToClientGuildDataUpdated = 8675 - k_EMsgClientToGCRequestGuildMembership = 8676 - k_EMsgClientToGCRequestGuildMembershipResponse = 8677 - k_EMsgGCToClientGuildMembershipUpdated = 8678 - k_EMsgClientToGCAcceptInviteToGuild = 8681 - k_EMsgClientToGCAcceptInviteToGuildResponse = 8682 - k_EMsgClientToGCSetGuildRoleOrder = 8683 - k_EMsgClientToGCSetGuildRoleOrderResponse = 8684 - k_EMsgClientToGCRequestGuildFeed = 8685 - k_EMsgClientToGCRequestGuildFeedResponse = 8686 - k_EMsgClientToGCRequestAccountGuildEventData = 8687 - k_EMsgClientToGCRequestAccountGuildEventDataResponse = 8688 - k_EMsgGCToClientAccountGuildEventDataUpdated = 8689 - k_EMsgClientToGCRequestActiveGuildContracts = 8690 - k_EMsgClientToGCRequestActiveGuildContractsResponse = 8691 - k_EMsgGCToClientActiveGuildContractsUpdated = 8692 - k_EMsgGCToClientGuildFeedUpdated = 8693 - k_EMsgClientToGCSelectGuildContract = 8694 - k_EMsgClientToGCSelectGuildContractResponse = 8695 - k_EMsgGCToGCCompleteGuildContracts = 8696 - k_EMsgClientToGCAddPlayerToGuildChat = 8698 - k_EMsgClientToGCAddPlayerToGuildChatResponse = 8699 - k_EMsgClientToGCUnderDraftSell = 8700 - k_EMsgClientToGCUnderDraftSellResponse = 8701 - k_EMsgClientToGCUnderDraftRequest = 8702 - k_EMsgClientToGCUnderDraftResponse = 8703 - k_EMsgClientToGCUnderDraftRedeemReward = 8704 - k_EMsgClientToGCUnderDraftRedeemRewardResponse = 8705 - k_EMsgGCToServerLobbyHeroBanRates = 8708 - k_EMsgSignOutGuildContractProgress = 8711 - k_EMsgSignOutMVPStats = 8712 - k_EMsgClientToGCRequestActiveGuildChallenge = 8713 - k_EMsgClientToGCRequestActiveGuildChallengeResponse = 8714 - k_EMsgGCToClientActiveGuildChallengeUpdated = 8715 - k_EMsgClientToGCRequestReporterUpdates = 8716 - k_EMsgClientToGCRequestReporterUpdatesResponse = 8717 - k_EMsgClientToGCAcknowledgeReporterUpdates = 8718 - k_EMsgSignOutGuildChallengeProgress = 8720 - k_EMsgClientToGCRequestGuildEventMembers = 8721 - k_EMsgClientToGCRequestGuildEventMembersResponse = 8722 - k_EMsgClientToGCReportGuildContent = 8725 - k_EMsgClientToGCReportGuildContentResponse = 8726 - k_EMsgClientToGCRequestAccountGuildPersonaInfo = 8727 - k_EMsgClientToGCRequestAccountGuildPersonaInfoResponse = 8728 - k_EMsgClientToGCRequestAccountGuildPersonaInfoBatch = 8729 - k_EMsgClientToGCRequestAccountGuildPersonaInfoBatchResponse = 8730 - k_EMsgGCToClientUnderDraftGoldUpdated = 8731 - k_EMsgGCToServerRecordTrainingData = 8732 - k_EMsgSignOutBounties = 8733 - k_EMsgLobbyFeaturedGamemodeProgress = 8734 - k_EMsgLobbyGauntletProgress = 8735 - k_EMsgClientToGCSubmitDraftTriviaMatchAnswer = 8736 - k_EMsgClientToGCSubmitDraftTriviaMatchAnswerResponse = 8737 - k_EMsgGCToGCSignoutSpendBounty = 8738 - k_EMsgClientToGCApplyGauntletTicket = 8739 - k_EMsgClientToGCUnderDraftRollBackBench = 8740 - k_EMsgClientToGCUnderDraftRollBackBenchResponse = 8741 - k_EMsgGCToGCGetEventActionScore = 8742 - k_EMsgGCToGCGetEventActionScoreResponse = 8743 - k_EMsgServerToGCGetGuildContracts = 8744 - k_EMsgServerToGCGetGuildContractsResponse = 8745 - k_EMsgLobbyEventGameData = 8746 - k_EMsgGCToClientGuildMembersDataUpdated = 8747 - k_EMsgSignOutReportActivityMarkers = 8748 - k_EMsgSignOutDiretideCandy = 8749 - k_EMsgGCToClientPostGameItemAwardNotification = 8750 - k_EMsgClientToGCGetOWMatchDetails = 8751 - k_EMsgClientToGCGetOWMatchDetailsResponse = 8752 - k_EMsgClientToGCSubmitOWConviction = 8753 - k_EMsgClientToGCSubmitOWConvictionResponse = 8754 - k_EMsgGCToGCGetAccountSteamChina = 8755 - k_EMsgGCToGCGetAccountSteamChinaResponse = 8756 - k_EMsgClientToGCClaimLeaderboardRewards = 8757 - k_EMsgClientToGCClaimLeaderboardRewardsResponse = 8758 - k_EMsgClientToGCRecalibrateMMR = 8759 - k_EMsgClientToGCRecalibrateMMRResponse = 8760 - k_EMsgGCToGCGrantEventPointActionList = 8761 - k_EMsgClientToGCChinaSSAURLRequest = 8764 - k_EMsgClientToGCChinaSSAURLResponse = 8765 - k_EMsgClientToGCChinaSSAAcceptedRequest = 8766 - k_EMsgClientToGCChinaSSAAcceptedResponse = 8767 - k_EMsgSignOutOverwatchSuspicion = 8768 - k_EMsgServerToGCGetSuspicionConfig = 8769 - k_EMsgServerToGCGetSuspicionConfigResponse = 8770 - k_EMsgGCToGCGrantPlusHeroChallengeMatchResults = 8771 - k_EMsgGCToClientOverwatchCasesAvailable = 8772 - k_EMsgServerToGCAccountCheck = 8773 - k_EMsgClientToGCStartWatchingOverwatch = 8774 - k_EMsgClientToGCStopWatchingOverwatch = 8775 - k_EMsgSignOutPerfData = 8776 - k_EMsgClientToGCGetDPCFavorites = 8777 - k_EMsgClientToGCGetDPCFavoritesResponse = 8778 - k_EMsgClientToGCSetDPCFavoriteState = 8779 - k_EMsgClientToGCSetDPCFavoriteStateResponse = 8780 - k_EMsgClientToGCOverwatchReplayError = 8781 - k_EMsgServerToGCPlayerChallengeHistory = 8782 - k_EMsgSignOutBanData = 8783 - k_EMsgWebapiDPCSeasonResults = 8784 - k_EMsgClientToGCCoachFriend = 8785 - k_EMsgClientToGCCoachFriendResponse = 8786 - k_EMsgClientToGCRequestPrivateCoachingSession = 8787 - k_EMsgClientToGCRequestPrivateCoachingSessionResponse = 8788 - k_EMsgClientToGCAcceptPrivateCoachingSession = 8789 - k_EMsgClientToGCAcceptPrivateCoachingSessionResponse = 8790 - k_EMsgClientToGCLeavePrivateCoachingSession = 8791 - k_EMsgClientToGCLeavePrivateCoachingSessionResponse = 8792 - k_EMsgClientToGCGetCurrentPrivateCoachingSession = 8793 - k_EMsgClientToGCGetCurrentPrivateCoachingSessionResponse = 8794 - k_EMsgGCToClientPrivateCoachingSessionUpdated = 8795 - k_EMsgClientToGCSubmitPrivateCoachingSessionRating = 8796 - k_EMsgClientToGCSubmitPrivateCoachingSessionRatingResponse = 8797 - k_EMsgClientToGCGetAvailablePrivateCoachingSessions = 8798 - k_EMsgClientToGCGetAvailablePrivateCoachingSessionsResponse = 8799 - k_EMsgClientToGCGetAvailablePrivateCoachingSessionsSummary = 8800 - k_EMsgClientToGCGetAvailablePrivateCoachingSessionsSummaryResponse = 8801 - k_EMsgClientToGCJoinPrivateCoachingSessionLobby = 8802 - k_EMsgClientToGCJoinPrivateCoachingSessionLobbyResponse = 8803 - k_EMsgClientToGCRespondToCoachFriendRequest = 8804 - k_EMsgClientToGCRespondToCoachFriendRequestResponse = 8805 - k_EMsgClientToGCSetEventActiveSeasonID = 8806 - k_EMsgClientToGCSetEventActiveSeasonIDResponse = 8807 - k_EMsgServerToGCMatchPlayerNeutralItemEquipHistory = 8808 - k_EMsgServerToGCCompendiumChosenInGamePredictions = 8809 - k_EMsgClientToGCCreateTeamPlayerCardPack = 8810 - k_EMsgClientToGCCreateTeamPlayerCardPackResponse = 8811 - k_EMsgGCToServerSubmitCheerData = 8812 - k_EMsgGCToServerCheerConfig = 8813 - k_EMsgServerToGCGetCheerConfig = 8814 - k_EMsgServerToGCGetCheerConfigResponse = 8815 - k_EMsgGCToGCGrantAutographByID = 8816 - k_EMsgGCToServerCheerScalesOverride = 8817 - k_EMsgGCToServerGetCheerState = 8818 - k_EMsgServerToGCReportCheerState = 8819 - k_EMsgGCToServerScenarioSave = 8820 - k_EMsgGCToServerAbilityDraftLobbyData = 8821 - k_EMsgSignOutReportCommunications = 8822 - k_EMsgClientToGCBatchGetPlayerCardRosterRequest = 8823 - k_EMsgClientToGCBatchGetPlayerCardRosterResponse = 8824 - k_EMsgClientToGCGetStickerbookRequest = 8825 - k_EMsgClientToGCGetStickerbookResponse = 8826 - k_EMsgClientToGCCreateStickerbookPageRequest = 8827 - k_EMsgClientToGCCreateStickerbookPageResponse = 8828 - k_EMsgClientToGCDeleteStickerbookPageRequest = 8829 - k_EMsgClientToGCDeleteStickerbookPageResponse = 8830 - k_EMsgClientToGCPlaceStickersRequest = 8831 - k_EMsgClientToGCPlaceStickersResponse = 8832 - k_EMsgClientToGCPlaceCollectionStickersRequest = 8833 - k_EMsgClientToGCPlaceCollectionStickersResponse = 8834 - k_EMsgClientToGCOrderStickerbookTeamPageRequest = 8835 - k_EMsgClientToGCOrderStickerbookTeamPageResponse = 8836 - k_EMsgServerToGCGetStickerHeroes = 8837 - k_EMsgServerToGCGetStickerHeroesResponse = 8838 - k_EMsgClientToGCCandyShopGetUserData = 8840 - k_EMsgClientToGCCandyShopGetUserDataResponse = 8841 - k_EMsgGCToClientCandyShopUserDataUpdated = 8842 - k_EMsgClientToGCCandyShopPurchaseReward = 8843 - k_EMsgClientToGCCandyShopPurchaseRewardResponse = 8844 - k_EMsgClientToGCCandyShopDoExchange = 8845 - k_EMsgClientToGCCandyShopDoExchangeResponse = 8846 - k_EMsgClientToGCCandyShopDoVariableExchange = 8847 - k_EMsgClientToGCCandyShopDoVariableExchangeResponse = 8848 - k_EMsgClientToGCCandyShopRerollRewards = 8849 - k_EMsgClientToGCCandyShopRerollRewardsResponse = 8850 - k_EMsgClientToGCSetHeroSticker = 8851 - k_EMsgClientToGCSetHeroStickerResponse = 8852 - k_EMsgClientToGCGetHeroStickers = 8853 - k_EMsgClientToGCGetHeroStickersResponse = 8854 - k_EMsgClientToGCSetFavoritePage = 8855 - k_EMsgClientToGCSetFavoritePageResponse = 8856 - k_EMsgClientToGCCandyShopDevGrantCandy = 8857 - k_EMsgClientToGCCandyShopDevGrantCandyResponse = 8858 - k_EMsgClientToGCCandyShopDevClearInventory = 8859 - k_EMsgClientToGCCandyShopDevClearInventoryResponse = 8860 - k_EMsgClientToGCCandyShopOpenBags = 8861 - k_EMsgClientToGCCandyShopOpenBagsResponse = 8862 - k_EMsgClientToGCCandyShopDevGrantCandyBags = 8863 - k_EMsgClientToGCCandyShopDevGrantCandyBagsResponse = 8864 - k_EMsgClientToGCCandyShopDevShuffleExchange = 8865 - k_EMsgClientToGCCandyShopDevShuffleExchangeResponse = 8866 - k_EMsgClientToGCCandyShopDevGrantRerollCharges = 8867 - k_EMsgClientToGCCandyShopDevGrantRerollChargesResponse = 8868 - k_EMsgLobbyAdditionalAccountData = 8869 - k_EMsgServerToGCLobbyInitialized = 8870 - k_EMsgClientToGCCollectorsCacheAvailableDataRequest = 8871 - k_EMsgGCToClientCollectorsCacheAvailableDataResponse = 8872 - k_EMsgClientToGCUploadMatchClip = 8873 - k_EMsgGCToClientUploadMatchClipResponse = 8874 - k_EMsgGCToServerSetSteamLearnKeysChanged = 8876 - k_EMsgSignOutMuertaMinigame = 8877 - k_EMsgGCToServerLobbyHeroRoleStats = 8878 - k_EMsgClientToGCRankRequest = 8879 - k_EMsgGCToClientRankResponse = 8880 - k_EMsgGCToClientRankUpdate = 8881 - k_EMsgSignOutMapStats = 8882 - k_EMsgClientToGCMapStatsRequest = 8883 - k_EMsgGCToClientMapStatsResponse = 8884 - k_EMsgGCToServerSetSteamLearnInferencing = 8885 - k_EMsgClientToGCShowcaseGetUserData = 8886 - k_EMsgClientToGCShowcaseGetUserDataResponse = 8887 - k_EMsgClientToGCShowcaseSetUserData = 8888 - k_EMsgClientToGCShowcaseSetUserDataResponse = 8889 - k_EMsgClientToGCFantasyCraftingGetData = 8890 - k_EMsgClientToGCFantasyCraftingGetDataResponse = 8891 - k_EMsgClientToGCFantasyCraftingPerformOperation = 8892 - k_EMsgClientToGCFantasyCraftingPerformOperationResponse = 8893 - k_EMsgGCToClientFantasyCraftingGetDataUpdated = 8894 - k_EMsgClientToGCFantasyCraftingDevModifyTablet = 8895 - k_EMsgClientToGCFantasyCraftingDevModifyTabletResponse = 8896 - k_EMsgClientToGCRoadToTIGetQuests = 8897 - k_EMsgClientToGCRoadToTIGetQuestsResponse = 8898 - k_EMsgClientToGCRoadToTIGetActiveQuest = 8899 - k_EMsgClientToGCRoadToTIGetActiveQuestResponse = 8900 - k_EMsgClientToGCBingoGetUserData = 8901 - k_EMsgClientToGCBingoGetUserDataResponse = 8902 - k_EMsgClientToGCBingoClaimRow = 8903 - k_EMsgClientToGCBingoClaimRowResponse = 8904 - k_EMsgClientToGCBingoDevRerollCard = 8905 - k_EMsgClientToGCBingoDevRerollCardResponse = 8906 - k_EMsgClientToGCBingoGetStatsData = 8907 - k_EMsgClientToGCBingoGetStatsDataResponse = 8908 - k_EMsgGCToClientBingoUserDataUpdated = 8909 - k_EMsgGCToClientRoadToTIQuestDataUpdated = 8910 - k_EMsgClientToGCRoadToTIUseItem = 8911 - k_EMsgClientToGCRoadToTIUseItemResponse = 8912 - k_EMsgClientToGCShowcaseSubmitReport = 8913 - k_EMsgClientToGCShowcaseSubmitReportResponse = 8914 - k_EMsgClientToGCShowcaseAdminGetReportsRollupList = 8915 - k_EMsgClientToGCShowcaseAdminGetReportsRollupListResponse = 8916 - k_EMsgClientToGCShowcaseAdminGetReportsRollup = 8917 - k_EMsgClientToGCShowcaseAdminGetReportsRollupResponse = 8918 - k_EMsgClientToGCShowcaseAdminGetUserDetails = 8919 - k_EMsgClientToGCShowcaseAdminGetUserDetailsResponse = 8920 - k_EMsgClientToGCShowcaseAdminConvict = 8921 - k_EMsgClientToGCShowcaseAdminConvictResponse = 8922 - k_EMsgClientToGCShowcaseAdminExonerate = 8923 - k_EMsgClientToGCShowcaseAdminExonerateResponse = 8924 - k_EMsgClientToGCShowcaseAdminReset = 8925 - k_EMsgClientToGCShowcaseAdminResetResponse = 8926 - k_EMsgClientToGCShowcaseAdminLockAccount = 8927 - k_EMsgClientToGCShowcaseAdminLockAccountResponse = 8928 - k_EMsgClientToGCFantasyCraftingSelectPlayer = 8929 - k_EMsgClientToGCFantasyCraftingSelectPlayerResponse = 8930 - k_EMsgClientToGCFantasyCraftingGenerateTablets = 8931 - k_EMsgClientToGCFantasyCraftingGenerateTabletsResponse = 8932 - k_EMsgClientToGcFantasyCraftingUpgradeTablets = 8933 - k_EMsgClientToGcFantasyCraftingUpgradeTabletsResponse = 8934 - k_EMsgClientToGCFantasyCraftingRerollOptions = 8936 - k_EMsgClientToGCFantasyCraftingRerollOptionsResponse = 8937 - k_EMsgClientToGCRoadToTIDevForceQuest = 8935 - k_EMsgLobbyRoadToTIMatchQuestData = 8939 - k_EMsgClientToGCShowcaseModerationGetQueue = 8940 - k_EMsgClientToGCShowcaseModerationGetQueueResponse = 8941 - k_EMsgClientToGCShowcaseModerationApplyModeration = 8942 - k_EMsgClientToGCShowcaseModerationApplyModerationResponse = 8943 + GCDOTABase = 7000 + GCGameMatchSignOut = 7004 + GCGameMatchSignOutResponse = 7005 + GCJoinChatChannel = 7009 + GCJoinChatChannelResponse = 7010 + GCOtherJoinedChannel = 7013 + GCOtherLeftChannel = 7014 + ServerToGCRequestStatus = 7026 + GCStartFindingMatch = 7033 + GCConnectedPlayers = 7034 + GCAbandonCurrentGame = 7035 + GCStopFindingMatch = 7036 + GCPracticeLobbyCreate = 7038 + GCPracticeLobbyLeave = 7040 + GCPracticeLobbyLaunch = 7041 + GCPracticeLobbyList = 7042 + GCPracticeLobbyListResponse = 7043 + GCPracticeLobbyJoin = 7044 + GCPracticeLobbySetDetails = 7046 + GCPracticeLobbySetTeamSlot = 7047 + GCInitialQuestionnaireResponse = 7049 + GCPracticeLobbyResponse = 7055 + GCBroadcastNotification = 7056 + GCLiveScoreboardUpdate = 7057 + GCRequestChatChannelList = 7060 + GCRequestChatChannelListResponse = 7061 + GCReadyUp = 7070 + GCKickedFromMatchmakingQueue = 7071 + GCLeaverDetected = 7072 + GCSpectateFriendGame = 7073 + GCSpectateFriendGameResponse = 7074 + GCReportsRemainingRequest = 7076 + GCReportsRemainingResponse = 7077 + GCSubmitPlayerReport = 7078 + GCSubmitPlayerReportResponse = 7079 + GCPracticeLobbyKick = 7081 + GCSubmitPlayerReportV2 = 7082 + GCSubmitPlayerReportResponseV2 = 7083 + GCRequestSaveGames = 7084 + GCRequestSaveGamesServer = 7085 + GCRequestSaveGamesResponse = 7086 + GCLeaverDetectedResponse = 7087 + GCPlayerFailedToConnect = 7088 + GCGCToRelayConnect = 7089 + GCGCToRelayConnectresponse = 7090 + GCWatchGame = 7091 + GCWatchGameResponse = 7092 + GCBanStatusRequest = 7093 + GCBanStatusResponse = 7094 + GCMatchDetailsRequest = 7095 + GCMatchDetailsResponse = 7096 + GCCancelWatchGame = 7097 + GCPopup = 7102 + GCFriendPracticeLobbyListRequest = 7111 + GCFriendPracticeLobbyListResponse = 7112 + GCPracticeLobbyJoinResponse = 7113 + GCCreateTeam = 7115 + GCCreateTeamResponse = 7116 + GCTeamInvite_InviterToGC = 7122 + GCTeamInvite_GCImmediateResponseToInviter = 7123 + GCTeamInvite_GCRequestToInvitee = 7124 + GCTeamInvite_InviteeResponseToGC = 7125 + GCTeamInvite_GCResponseToInviter = 7126 + GCTeamInvite_GCResponseToInvitee = 7127 + GCKickTeamMember = 7128 + GCKickTeamMemberResponse = 7129 + GCLeaveTeam = 7130 + GCLeaveTeamResponse = 7131 + GCApplyTeamToPracticeLobby = 7142 + GCTransferTeamAdmin = 7144 + GCPracticeLobbyJoinBroadcastChannel = 7149 + GC_TournamentItemEvent = 7150 + GC_TournamentItemEventResponse = 7151 + TeamFanfare = 7156 + ResponseTeamFanfare = 7157 + GC_GameServerUploadSaveGame = 7158 + GC_GameServerSaveGameResult = 7159 + GC_GameServerGetLoadGame = 7160 + GC_GameServerGetLoadGameResult = 7161 + GCEditTeamDetails = 7166 + GCEditTeamDetailsResponse = 7167 + GCReadyUpStatus = 7170 + GCToGCMatchCompleted = 7186 + GCBalancedShuffleLobby = 7188 + GCMatchmakingStatsRequest = 7197 + GCMatchmakingStatsResponse = 7198 + GCBotGameCreate = 7199 + GCSetMatchHistoryAccess = 7200 + GCSetMatchHistoryAccessResponse = 7201 + UpgradeLeagueItem = 7203 + UpgradeLeagueItemResponse = 7204 + GCWatchDownloadedReplay = 7206 + ClientsRejoinChatChannels = 7217 + GCToGCGetUserChatInfo = 7218 + GCToGCGetUserChatInfoResponse = 7219 + GCToGCLeaveAllChatChannels = 7220 + GCToGCUpdateAccountChatBan = 7221 + GCToGCCanInviteUserToTeam = 7234 + GCToGCCanInviteUserToTeamResponse = 7235 + GCToGCGetUserRank = 7236 + GCToGCGetUserRankResponse = 7237 + GCToGCAdjustUserRank = 7238 + GCToGCAdjustUserRankResponse = 7239 + GCToGCUpdateTeamStats = 7240 + GCToGCValidateTeam = 7241 + GCToGCValidateTeamResponse = 7242 + GCToGCGetLeagueAdmin = 7255 + GCToGCGetLeagueAdminResponse = 7256 + GCLeaveChatChannel = 7272 + GCChatMessage = 7273 + GCGetHeroStandings = 7274 + GCGetHeroStandingsResponse = 7275 + GCItemEditorReservationsRequest = 7283 + GCItemEditorReservationsResponse = 7284 + GCItemEditorReserveItemDef = 7285 + GCItemEditorReserveItemDefResponse = 7286 + GCItemEditorReleaseReservation = 7287 + GCItemEditorReleaseReservationResponse = 7288 + GCRewardTutorialPrizes = 7289 + GCFantasyLivePlayerStats = 7308 + GCFantasyFinalPlayerStats = 7309 + GCFlipLobbyTeams = 7320 + GCToGCEvaluateReportedPlayer = 7322 + GCToGCEvaluateReportedPlayerResponse = 7323 + GCToGCProcessPlayerReportForTarget = 7324 + GCToGCProcessReportSuccess = 7325 + GCNotifyAccountFlagsChange = 7326 + GCSetProfilePrivacy = 7327 + GCSetProfilePrivacyResponse = 7328 + GCClientSuspended = 7342 + GCPartyMemberSetCoach = 7343 + GCPracticeLobbySetCoach = 7346 + GCChatModeratorBan = 7359 + GCLobbyUpdateBroadcastChannelInfo = 7367 + GCToGCGrantTournamentItem = 7372 + GCToGCUpgradeTwitchViewerItems = 7375 + GCToGCGetLiveMatchAffiliates = 7376 + GCToGCGetLiveMatchAffiliatesResponse = 7377 + GCToGCUpdatePlayerPennantCounts = 7378 + GCToGCGetPlayerPennantCounts = 7379 + GCToGCGetPlayerPennantCountsResponse = 7380 + GCGameMatchSignOutPermissionRequest = 7381 + GCGameMatchSignOutPermissionResponse = 7382 + DOTAAwardEventPoints = 7384 + DOTAGetEventPoints = 7387 + DOTAGetEventPointsResponse = 7388 + GCPartyLeaderWatchGamePrompt = 7397 + GCCompendiumSetSelection = 7405 + GCCompendiumDataRequest = 7406 + GCCompendiumDataResponse = 7407 + DOTAGetPlayerMatchHistory = 7408 + DOTAGetPlayerMatchHistoryResponse = 7409 + GCToGCMatchmakingAddParty = 7410 + GCToGCMatchmakingRemoveParty = 7411 + GCToGCMatchmakingRemoveAllParties = 7412 + GCToGCMatchmakingMatchFound = 7413 + GCToGCUpdateMatchManagementStats = 7414 + GCToGCUpdateMatchmakingStats = 7415 + GCToServerPingRequest = 7416 + GCToServerPingResponse = 7417 + GCToServerEvaluateToxicChat = 7418 + ServerToGCEvaluateToxicChat = 7419 + ServerToGCEvaluateToxicChatResponse = 7420 + GCToGCProcessMatchLeaver = 7426 + GCNotificationsRequest = 7427 + GCNotificationsResponse = 7428 + GCToGCModifyNotification = 7429 + GCLeagueAdminList = 7434 + GCNotificationsMarkReadRequest = 7435 + ServerToGCRequestBatchPlayerResources = 7450 + ServerToGCRequestBatchPlayerResourcesResponse = 7451 + GCCompendiumSetSelectionResponse = 7453 + GCPlayerInfoSubmit = 7456 + GCPlayerInfoSubmitResponse = 7457 + GCToGCGetAccountLevel = 7458 + GCToGCGetAccountLevelResponse = 7459 + DOTAGetWeekendTourneySchedule = 7464 + DOTAWeekendTourneySchedule = 7465 + GCJoinableCustomGameModesRequest = 7466 + GCJoinableCustomGameModesResponse = 7467 + GCJoinableCustomLobbiesRequest = 7468 + GCJoinableCustomLobbiesResponse = 7469 + GCQuickJoinCustomLobby = 7470 + GCQuickJoinCustomLobbyResponse = 7471 + GCToGCGrantEventPointAction = 7472 + GCToGCSetCompendiumSelection = 7478 + GCHasItemQuery = 7484 + GCHasItemResponse = 7485 + GCToGCGrantEventPointActionMsg = 7488 + GCToGCGetCompendiumSelections = 7492 + GCToGCGetCompendiumSelectionsResponse = 7493 + ServerToGCMatchConnectionStats = 7494 + GCToClientTournamentItemDrop = 7495 + SQLDelayedGrantLeagueDrop = 7496 + ServerGCUpdateSpectatorCount = 7497 + GCToGCEmoticonUnlock = 7501 + SignOutDraftInfo = 7502 + ClientToGCEmoticonDataRequest = 7503 + GCToClientEmoticonData = 7504 + GCPracticeLobbyToggleBroadcastChannelCameramanStatus = 7505 + DOTARedeemItem = 7518 + DOTARedeemItemResponse = 7519 + ClientToGCGetAllHeroProgress = 7521 + ClientToGCGetAllHeroProgressResponse = 7522 + GCToGCGetServerForClient = 7523 + GCToGCGetServerForClientResponse = 7524 + SQLProcessTournamentGameOutcome = 7525 + SQLGrantTrophyToAccount = 7526 + ClientToGCGetTrophyList = 7527 + ClientToGCGetTrophyListResponse = 7528 + GCToClientTrophyAwarded = 7529 + GCGameBotMatchSignOut = 7530 + GCGameBotMatchSignOutPermissionRequest = 7531 + SignOutBotInfo = 7532 + GCToGCUpdateProfileCards = 7533 + ClientToGCGetProfileCard = 7534 + ClientToGCGetProfileCardResponse = 7535 + ClientToGCGetBattleReport = 7536 + ClientToGCGetBattleReportResponse = 7537 + ClientToGCSetProfileCardSlots = 7538 + GCToClientProfileCardUpdated = 7539 + ServerToGCVictoryPredictions = 7540 + ClientToGCGetBattleReportAggregateStats = 7541 + ClientToGCGetBattleReportAggregateStatsResponse = 7542 + ClientToGCGetBattleReportInfo = 7543 + ClientToGCGetBattleReportInfoResponse = 7544 + SignOutCommunicationSummary = 7545 + ServerToGCRequestStatus_Response = 7546 + ClientToGCCreateHeroStatue = 7547 + GCToClientHeroStatueCreateResult = 7548 + GCGCToLANServerRelayConnect = 7549 + ClientToGCAcknowledgeBattleReport = 7550 + ClientToGCAcknowledgeBattleReportResponse = 7551 + ClientToGCGetBattleReportMatchHistory = 7552 + ClientToGCGetBattleReportMatchHistoryResponse = 7553 + ServerToGCReportKillSummaries = 7554 + GCToGCUpdatePlayerPredictions = 7561 + GCToServerPredictionResult = 7562 + GCToGCReplayMonitorValidateReplay = 7569 + LobbyEventPoints = 7572 + GCToGCGetCustomGameTickets = 7573 + GCToGCGetCustomGameTicketsResponse = 7574 + GCToGCCustomGamePlayed = 7576 + GCToGCGrantEventPointsToUser = 7577 + GameserverCrashReport = 7579 + GameserverCrashReportResponse = 7580 + GCToClientSteamDatagramTicket = 7581 + GCToGCSendAccountsEventPoints = 7583 + ClientToGCRerollPlayerChallenge = 7584 + ServerToGCRerollPlayerChallenge = 7585 + GCRerollPlayerChallengeResponse = 7586 + SignOutUpdatePlayerChallenge = 7587 + ClientToGCSetPartyLeader = 7588 + ClientToGCCancelPartyInvites = 7589 + SQLGrantLeagueMatchToTicketHolders = 7592 + GCToGCEmoticonUnlockNoRollback = 7594 + ClientToGCApplyGemCombiner = 7603 + ClientToGCGetAllHeroOrder = 7606 + ClientToGCGetAllHeroOrderResponse = 7607 + SQLGCToGCGrantBadgePoints = 7608 + GCToGCCheckOwnsEntireEmoticonRange = 7611 + GCToGCCheckOwnsEntireEmoticonRangeResponse = 7612 + GCToClientRequestLaneSelection = 7623 + GCToClientRequestLaneSelectionResponse = 7624 + ServerToGCCavernCrawlIsHeroActive = 7625 + ServerToGCCavernCrawlIsHeroActiveResponse = 7626 + ClientToGCPlayerCardSpecificPurchaseRequest = 7627 + ClientToGCPlayerCardSpecificPurchaseResponse = 7628 + GCtoServerTensorflowInstance = 7629 + SQLSetIsLeagueAdmin = 7630 + GCToGCGetLiveLeagueMatches = 7631 + GCToGCGetLiveLeagueMatchesResponse = 7632 + DOTALeagueInfoListAdminsRequest = 7633 + DOTALeagueInfoListAdminsReponse = 7634 + GCToGCLeagueMatchStarted = 7645 + GCToGCLeagueMatchCompleted = 7646 + GCToGCLeagueMatchStartedResponse = 7647 + DOTALeagueAvailableLobbyNodesRequest = 7650 + DOTALeagueAvailableLobbyNodes = 7651 + GCToGCLeagueRequest = 7652 + GCToGCLeagueResponse = 7653 + GCToGCLeagueNodeGroupRequest = 7654 + GCToGCLeagueNodeGroupResponse = 7655 + GCToGCLeagueNodeRequest = 7656 + GCToGCLeagueNodeResponse = 7657 + GCToGCRealtimeStatsTerseRequest = 7658 + GCToGCRealtimeStatsTerseResponse = 7659 + GCToGCGetTopMatchesRequest = 7660 + GCToGCGetTopMatchesResponse = 7661 + ClientToGCGetFilteredPlayers = 7662 + GCToClientGetFilteredPlayersResponse = 7663 + ClientToGCRemoveFilteredPlayer = 7664 + GCToClientRemoveFilteredPlayerResponse = 7665 + GCToClientPlayerBeaconState = 7666 + GCToClientPartyBeaconUpdate = 7667 + GCToClientPartySearchInvite = 7668 + ClientToGCUpdatePartyBeacon = 7669 + ClientToGCRequestActiveBeaconParties = 7670 + GCToClientRequestActiveBeaconPartiesResponse = 7671 + ClientToGCManageFavorites = 7672 + GCToClientManageFavoritesResponse = 7673 + ClientToGCJoinPartyFromBeacon = 7674 + GCToClientJoinPartyFromBeaconResponse = 7675 + ClientToGCGetFavoritePlayers = 7676 + GCToClientGetFavoritePlayersResponse = 7677 + ClientToGCVerifyFavoritePlayers = 7678 + GCToClientVerifyFavoritePlayersResponse = 7679 + GCToClientPartySearchInvites = 7680 + GCToClientRequestMMInfo = 7681 + ClientToGCMMInfo = 7682 + SignOutTextMuteInfo = 7683 + ClientToGCPurchaseLabyrinthBlessings = 7684 + ClientToGCPurchaseLabyrinthBlessingsResponse = 7685 + ClientToGCPurchaseFilteredPlayerSlot = 7686 + GCToClientPurchaseFilteredPlayerSlotResponse = 7687 + ClientToGCUpdateFilteredPlayerNote = 7688 + GCToClientUpdateFilteredPlayerNoteResponse = 7689 + ClientToGCClaimSwag = 7690 + GCToClientClaimSwagResponse = 7691 + ServerToGCLockCharmTrading = 8004 + ClientToGCPlayerStatsRequest = 8006 + GCToClientPlayerStatsResponse = 8007 + GCClearPracticeLobbyTeam = 8008 + ClientToGCFindTopSourceTVGames = 8009 + GCToClientFindTopSourceTVGamesResponse = 8010 + GCLobbyList = 8011 + GCLobbyListResponse = 8012 + GCPlayerStatsMatchSignOut = 8013 + ClientToGCSocialFeedPostCommentRequest = 8016 + GCToClientSocialFeedPostCommentResponse = 8017 + ClientToGCCustomGamesFriendsPlayedRequest = 8018 + GCToClientCustomGamesFriendsPlayedResponse = 8019 + ClientToGCFriendsPlayedCustomGameRequest = 8020 + GCToClientFriendsPlayedCustomGameResponse = 8021 + GCTopCustomGamesList = 8024 + ClientToGCSetPartyOpen = 8029 + ClientToGCMergePartyInvite = 8030 + GCToClientMergeGroupInviteReply = 8031 + ClientToGCMergePartyResponse = 8032 + GCToClientMergePartyResponseReply = 8033 + ClientToGCGetProfileCardStats = 8034 + ClientToGCGetProfileCardStatsResponse = 8035 + ClientToGCTopLeagueMatchesRequest = 8036 + ClientToGCTopFriendMatchesRequest = 8037 + GCToClientProfileCardStatsUpdated = 8040 + ServerToGCRealtimeStats = 8041 + GCToServerRealtimeStatsStartStop = 8042 + GCToGCGetServersForClients = 8045 + GCToGCGetServersForClientsResponse = 8046 + GCPracticeLobbyKickFromTeam = 8047 + DOTAChatGetMemberCount = 8048 + DOTAChatGetMemberCountResponse = 8049 + ClientToGCSocialFeedPostMessageRequest = 8050 + GCToClientSocialFeedPostMessageResponse = 8051 + CustomGameListenServerStartedLoading = 8052 + CustomGameClientFinishedLoading = 8053 + GCPracticeLobbyCloseBroadcastChannel = 8054 + GCStartFindingMatchResponse = 8055 + SQLGCToGCGrantAccountFlag = 8057 + GCToClientTopLeagueMatchesResponse = 8061 + GCToClientTopFriendMatchesResponse = 8062 + ClientToGCMatchesMinimalRequest = 8063 + ClientToGCMatchesMinimalResponse = 8064 + GCToClientChatRegionsEnabled = 8067 + ClientToGCPingData = 8068 + GCToGCEnsureAccountInParty = 8071 + GCToGCEnsureAccountInPartyResponse = 8072 + ClientToGCGetProfileTickets = 8073 + ClientToGCGetProfileTicketsResponse = 8074 + GCToClientMatchGroupsVersion = 8075 + ClientToGCH264Unsupported = 8076 + ClientToGCGetQuestProgress = 8078 + ClientToGCGetQuestProgressResponse = 8079 + SignOutXPCoins = 8080 + GCToClientMatchSignedOut = 8081 + GCGetHeroStatsHistory = 8082 + GCGetHeroStatsHistoryResponse = 8083 + ClientToGCPrivateChatInvite = 8084 + ClientToGCPrivateChatKick = 8088 + ClientToGCPrivateChatPromote = 8089 + ClientToGCPrivateChatDemote = 8090 + GCToClientPrivateChatResponse = 8091 + ClientToGCLatestConductScorecardRequest = 8095 + ClientToGCLatestConductScorecard = 8096 + ClientToGCWageringRequest = 8099 + GCToClientWageringResponse = 8100 + ClientToGCEventGoalsRequest = 8103 + ClientToGCEventGoalsResponse = 8104 + GCToGCLeaguePredictionsUpdate = 8108 + GCToGCAddUserToPostGameChat = 8110 + ClientToGCHasPlayerVotedForMVP = 8111 + ClientToGCHasPlayerVotedForMVPResponse = 8112 + ClientToGCVoteForMVP = 8113 + ClientToGCVoteForMVPResponse = 8114 + GCToGCGetEventOwnership = 8115 + GCToGCGetEventOwnershipResponse = 8116 + GCToClientAutomatedTournamentStateChange = 8117 + ClientToGCWeekendTourneyOpts = 8118 + ClientToGCWeekendTourneyOptsResponse = 8119 + ClientToGCWeekendTourneyLeave = 8120 + ClientToGCWeekendTourneyLeaveResponse = 8121 + ClientToGCTeammateStatsRequest = 8124 + ClientToGCTeammateStatsResponse = 8125 + ClientToGCGetGiftPermissions = 8126 + ClientToGCGetGiftPermissionsResponse = 8127 + ClientToGCVoteForArcana = 8128 + ClientToGCVoteForArcanaResponse = 8129 + ClientToGCRequestArcanaVotesRemaining = 8130 + ClientToGCRequestArcanaVotesRemainingResponse = 8131 + GCTransferTeamAdminResponse = 8132 + GCToClientTeamInfo = 8135 + GCToClientTeamsInfo = 8136 + ClientToGCMyTeamInfoRequest = 8137 + ClientToGCPublishUserStat = 8140 + GCToGCSignoutSpendWager = 8141 + GCSubmitLobbyMVPVote = 8144 + GCSubmitLobbyMVPVoteResponse = 8145 + SignOutCommunityGoalProgress = 8150 + GCToClientLobbyMVPAwarded = 8152 + GCToClientQuestProgressUpdated = 8153 + GCToClientWageringUpdate = 8154 + GCToClientArcanaVotesUpdate = 8155 + ClientToGCSetSpectatorLobbyDetails = 8157 + ClientToGCSetSpectatorLobbyDetailsResponse = 8158 + ClientToGCCreateSpectatorLobby = 8159 + ClientToGCCreateSpectatorLobbyResponse = 8160 + ClientToGCSpectatorLobbyList = 8161 + ClientToGCSpectatorLobbyListResponse = 8162 + SpectatorLobbyGameDetails = 8163 + ServerToGCCompendiumInGamePredictionResults = 8166 + ServerToGCCloseCompendiumInGamePredictionVoting = 8167 + ClientToGCOpenPlayerCardPack = 8168 + ClientToGCOpenPlayerCardPackResponse = 8169 + ClientToGCSelectCompendiumInGamePrediction = 8170 + ClientToGCSelectCompendiumInGamePredictionResponse = 8171 + ClientToGCWeekendTourneyGetPlayerStats = 8172 + ClientToGCWeekendTourneyGetPlayerStatsResponse = 8173 + ClientToGCRecyclePlayerCard = 8174 + ClientToGCRecyclePlayerCardResponse = 8175 + ClientToGCCreatePlayerCardPack = 8176 + ClientToGCCreatePlayerCardPackResponse = 8177 + ClientToGCGetPlayerCardRosterRequest = 8178 + ClientToGCGetPlayerCardRosterResponse = 8179 + ClientToGCSetPlayerCardRosterRequest = 8180 + ClientToGCSetPlayerCardRosterResponse = 8181 + ServerToGCCloseCompendiumInGamePredictionVotingResponse = 8183 + LobbyBattleCupVictory = 8186 + GCGetPlayerCardItemInfo = 8187 + GCGetPlayerCardItemInfoResponse = 8188 + ClientToGCRequestSteamDatagramTicket = 8189 + ClientToGCRequestSteamDatagramTicketResponse = 8190 + GCToClientBattlePassRollupRequest = 8191 + GCToClientBattlePassRollupResponse = 8192 + ClientToGCTransferSeasonalMMRRequest = 8193 + ClientToGCTransferSeasonalMMRResponse = 8194 + GCToGCPublicChatCommunicationBan = 8195 + GCToGCUpdateAccountInfo = 8196 + GCChatReportPublicSpam = 8197 + ClientToGCSetPartyBuilderOptions = 8198 + ClientToGCSetPartyBuilderOptionsResponse = 8199 + GCToClientPlaytestStatus = 8200 + ClientToGCJoinPlaytest = 8201 + ClientToGCJoinPlaytestResponse = 8202 + LobbyPlaytestDetails = 8203 + DOTASetFavoriteTeam = 8204 + GCToClientBattlePassRollupListRequest = 8205 + GCToClientBattlePassRollupListResponse = 8206 + DOTAClaimEventAction = 8209 + DOTAClaimEventActionResponse = 8210 + DOTAGetPeriodicResource = 8211 + DOTAGetPeriodicResourceResponse = 8212 + DOTAPeriodicResourceUpdated = 8213 + ServerToGCSpendWager = 8214 + GCToGCSignoutSpendWagerToken = 8215 + SubmitTriviaQuestionAnswer = 8216 + SubmitTriviaQuestionAnswerResponse = 8217 + ClientToGCGiveTip = 8218 + ClientToGCGiveTipResponse = 8219 + StartTriviaSession = 8220 + StartTriviaSessionResponse = 8221 + AnchorPhoneNumberRequest = 8222 + AnchorPhoneNumberResponse = 8223 + UnanchorPhoneNumberRequest = 8224 + UnanchorPhoneNumberResponse = 8225 + GCToGCSignoutSpendRankWager = 8229 + GCToGCGetFavoriteTeam = 8230 + GCToGCGetFavoriteTeamResponse = 8231 + SignOutEventGameData = 8232 + ClientToGCQuickStatsRequest = 8238 + ClientToGCQuickStatsResponse = 8239 + GCToGCSubtractEventPointsFromUser = 8240 + SelectionPriorityChoiceRequest = 8241 + SelectionPriorityChoiceResponse = 8242 + GCToGCCompendiumInGamePredictionResults = 8243 + GameAutographReward = 8244 + GameAutographRewardResponse = 8245 + DestroyLobbyRequest = 8246 + DestroyLobbyResponse = 8247 + PurchaseItemWithEventPoints = 8248 + PurchaseItemWithEventPointsResponse = 8249 + ServerToGCMatchPlayerItemPurchaseHistory = 8250 + GCToGCGrantPlusHeroMatchResults = 8251 + ServerToGCMatchStateHistory = 8255 + PurchaseHeroRandomRelic = 8258 + PurchaseHeroRandomRelicResponse = 8259 + ClientToGCClaimEventActionUsingItem = 8260 + ClientToGCClaimEventActionUsingItemResponse = 8261 + PartyReadyCheckRequest = 8262 + PartyReadyCheckResponse = 8263 + PartyReadyCheckAcknowledge = 8264 + GetRecentPlayTimeFriendsRequest = 8265 + GetRecentPlayTimeFriendsResponse = 8266 + GCToClientCommendNotification = 8267 + ProfileRequest = 8268 + ProfileResponse = 8269 + ProfileUpdate = 8270 + ProfileUpdateResponse = 8271 + HeroGlobalDataRequest = 8274 + HeroGlobalDataResponse = 8275 + ClientToGCRequestPlusWeeklyChallengeResult = 8276 + ClientToGCRequestPlusWeeklyChallengeResultResponse = 8277 + GCToGCGrantPlusPrepaidTime = 8278 + PrivateMetadataKeyRequest = 8279 + PrivateMetadataKeyResponse = 8280 + GCToGCReconcilePlusStatus = 8281 + GCToGCCheckPlusStatus = 8282 + GCToGCCheckPlusStatusResponse = 8283 + GCToGCReconcilePlusAutoGrantItems = 8284 + GCToGCReconcilePlusStatusUnreliable = 8285 + GCToClientCavernCrawlMapPathCompleted = 8288 + ClientToGCCavernCrawlClaimRoom = 8289 + ClientToGCCavernCrawlClaimRoomResponse = 8290 + ClientToGCCavernCrawlUseItemOnRoom = 8291 + ClientToGCCavernCrawlUseItemOnRoomResponse = 8292 + ClientToGCCavernCrawlUseItemOnPath = 8293 + ClientToGCCavernCrawlUseItemOnPathResponse = 8294 + ClientToGCCavernCrawlRequestMapState = 8295 + ClientToGCCavernCrawlRequestMapStateResponse = 8296 + SignOutTips = 8297 + ClientToGCRequestEventPointLogV2 = 8298 + ClientToGCRequestEventPointLogResponseV2 = 8299 + ClientToGCRequestEventTipsSummary = 8300 + ClientToGCRequestEventTipsSummaryResponse = 8301 + ClientToGCRequestSocialFeed = 8303 + ClientToGCRequestSocialFeedResponse = 8304 + ClientToGCRequestSocialFeedComments = 8305 + ClientToGCRequestSocialFeedCommentsResponse = 8306 + ClientToGCCavernCrawlGetClaimedRoomCount = 8308 + ClientToGCCavernCrawlGetClaimedRoomCountResponse = 8309 + GCToGCReconcilePlusAutoGrantItemsUnreliable = 8310 + ServerToGCAddBroadcastTimelineEvent = 8311 + GCToServerUpdateSteamBroadcasting = 8312 + ClientToGCRecordContestVote = 8313 + GCToClientRecordContestVoteResponse = 8314 + GCToGCGrantAutograph = 8315 + GCToGCGrantAutographResponse = 8316 + SignOutConsumableUsage = 8317 + LobbyEventGameDetails = 8318 + DevGrantEventPoints = 8319 + DevGrantEventPointsResponse = 8320 + DevGrantEventAction = 8321 + DevGrantEventActionResponse = 8322 + DevResetEventState = 8323 + DevResetEventStateResponse = 8324 + GCToGCReconcileEventOwnership = 8325 + ConsumeEventSupportGrantItem = 8326 + ConsumeEventSupportGrantItemResponse = 8327 + GCToClientClaimEventActionUsingItemCompleted = 8328 + GCToClientCavernCrawlMapUpdated = 8329 + ServerToGCRequestPlayerRecentAccomplishments = 8330 + ServerToGCRequestPlayerRecentAccomplishmentsResponse = 8331 + ClientToGCRequestPlayerRecentAccomplishments = 8332 + ClientToGCRequestPlayerRecentAccomplishmentsResponse = 8333 + ClientToGCRequestPlayerHeroRecentAccomplishments = 8334 + ClientToGCRequestPlayerHeroRecentAccomplishmentsResponse = 8335 + SignOutEventActionGrants = 8336 + ClientToGCRequestPlayerCoachMatches = 8337 + ClientToGCRequestPlayerCoachMatchesResponse = 8338 + ClientToGCSubmitCoachTeammateRating = 8341 + ClientToGCSubmitCoachTeammateRatingResponse = 8342 + GCToClientCoachTeammateRatingsChanged = 8343 + ClientToGCRequestPlayerCoachMatch = 8345 + ClientToGCRequestPlayerCoachMatchResponse = 8346 + ClientToGCRequestContestVotes = 8347 + ClientToGCRequestContestVotesResponse = 8348 + ClientToGCMVPVoteTimeout = 8349 + ClientToGCMVPVoteTimeoutResponse = 8350 + MatchMatchmakingStats = 8360 + ClientToGCSubmitPlayerMatchSurvey = 8361 + ClientToGCSubmitPlayerMatchSurveyResponse = 8362 + SQLGCToGCGrantAllHeroProgressAccount = 8363 + SQLGCToGCGrantAllHeroProgressVictory = 8364 + DevDeleteEventActions = 8365 + DevDeleteEventActionsResponse = 8366 + GCToGCGetAllHeroCurrent = 8635 + GCToGCGetAllHeroCurrentResponse = 8636 + GCSubmitPlayerAvoidRequest = 8637 + GCSubmitPlayerAvoidRequestResponse = 8638 + GCToClientNotificationsUpdated = 8639 + GCtoGCAssociatedExploiterAccountInfo = 8640 + GCtoGCAssociatedExploiterAccountInfoResponse = 8641 + GCtoGCRequestRecalibrationCheck = 8642 + GCToClientVACReminder = 8643 + ClientToGCUnderDraftBuy = 8644 + ClientToGCUnderDraftBuyResponse = 8645 + ClientToGCUnderDraftReroll = 8646 + ClientToGCUnderDraftRerollResponse = 8647 + NeutralItemStats = 8648 + ClientToGCCreateGuild = 8649 + ClientToGCCreateGuildResponse = 8650 + ClientToGCSetGuildInfo = 8651 + ClientToGCSetGuildInfoResponse = 8652 + ClientToGCAddGuildRole = 8653 + ClientToGCAddGuildRoleResponse = 8654 + ClientToGCModifyGuildRole = 8655 + ClientToGCModifyGuildRoleResponse = 8656 + ClientToGCRemoveGuildRole = 8657 + ClientToGCRemoveGuildRoleResponse = 8658 + ClientToGCJoinGuild = 8659 + ClientToGCJoinGuildResponse = 8660 + ClientToGCLeaveGuild = 8661 + ClientToGCLeaveGuildResponse = 8662 + ClientToGCInviteToGuild = 8663 + ClientToGCInviteToGuildResponse = 8664 + ClientToGCDeclineInviteToGuild = 8665 + ClientToGCDeclineInviteToGuildResponse = 8666 + ClientToGCCancelInviteToGuild = 8667 + ClientToGCCancelInviteToGuildResponse = 8668 + ClientToGCKickGuildMember = 8669 + ClientToGCKickGuildMemberResponse = 8670 + ClientToGCSetGuildMemberRole = 8671 + ClientToGCSetGuildMemberRoleResponse = 8672 + ClientToGCRequestGuildData = 8673 + ClientToGCRequestGuildDataResponse = 8674 + GCToClientGuildDataUpdated = 8675 + ClientToGCRequestGuildMembership = 8676 + ClientToGCRequestGuildMembershipResponse = 8677 + GCToClientGuildMembershipUpdated = 8678 + ClientToGCAcceptInviteToGuild = 8681 + ClientToGCAcceptInviteToGuildResponse = 8682 + ClientToGCSetGuildRoleOrder = 8683 + ClientToGCSetGuildRoleOrderResponse = 8684 + ClientToGCRequestGuildFeed = 8685 + ClientToGCRequestGuildFeedResponse = 8686 + ClientToGCRequestAccountGuildEventData = 8687 + ClientToGCRequestAccountGuildEventDataResponse = 8688 + GCToClientAccountGuildEventDataUpdated = 8689 + ClientToGCRequestActiveGuildContracts = 8690 + ClientToGCRequestActiveGuildContractsResponse = 8691 + GCToClientActiveGuildContractsUpdated = 8692 + GCToClientGuildFeedUpdated = 8693 + ClientToGCSelectGuildContract = 8694 + ClientToGCSelectGuildContractResponse = 8695 + GCToGCCompleteGuildContracts = 8696 + ClientToGCAddPlayerToGuildChat = 8698 + ClientToGCAddPlayerToGuildChatResponse = 8699 + ClientToGCUnderDraftSell = 8700 + ClientToGCUnderDraftSellResponse = 8701 + ClientToGCUnderDraftRequest = 8702 + ClientToGCUnderDraftResponse = 8703 + ClientToGCUnderDraftRedeemReward = 8704 + ClientToGCUnderDraftRedeemRewardResponse = 8705 + GCToServerLobbyHeroBanRates = 8708 + SignOutGuildContractProgress = 8711 + SignOutMVPStats = 8712 + ClientToGCRequestActiveGuildChallenge = 8713 + ClientToGCRequestActiveGuildChallengeResponse = 8714 + GCToClientActiveGuildChallengeUpdated = 8715 + ClientToGCRequestReporterUpdates = 8716 + ClientToGCRequestReporterUpdatesResponse = 8717 + ClientToGCAcknowledgeReporterUpdates = 8718 + SignOutGuildChallengeProgress = 8720 + ClientToGCRequestGuildEventMembers = 8721 + ClientToGCRequestGuildEventMembersResponse = 8722 + ClientToGCReportGuildContent = 8725 + ClientToGCReportGuildContentResponse = 8726 + ClientToGCRequestAccountGuildPersonaInfo = 8727 + ClientToGCRequestAccountGuildPersonaInfoResponse = 8728 + ClientToGCRequestAccountGuildPersonaInfoBatch = 8729 + ClientToGCRequestAccountGuildPersonaInfoBatchResponse = 8730 + GCToClientUnderDraftGoldUpdated = 8731 + GCToServerRecordTrainingData = 8732 + SignOutBounties = 8733 + LobbyFeaturedGamemodeProgress = 8734 + LobbyGauntletProgress = 8735 + ClientToGCSubmitDraftTriviaMatchAnswer = 8736 + ClientToGCSubmitDraftTriviaMatchAnswerResponse = 8737 + GCToGCSignoutSpendBounty = 8738 + ClientToGCApplyGauntletTicket = 8739 + ClientToGCUnderDraftRollBackBench = 8740 + ClientToGCUnderDraftRollBackBenchResponse = 8741 + GCToGCGetEventActionScore = 8742 + GCToGCGetEventActionScoreResponse = 8743 + ServerToGCGetGuildContracts = 8744 + ServerToGCGetGuildContractsResponse = 8745 + LobbyEventGameData = 8746 + GCToClientGuildMembersDataUpdated = 8747 + SignOutReportActivityMarkers = 8748 + SignOutDiretideCandy = 8749 + GCToClientPostGameItemAwardNotification = 8750 + ClientToGCGetOWMatchDetails = 8751 + ClientToGCGetOWMatchDetailsResponse = 8752 + ClientToGCSubmitOWConviction = 8753 + ClientToGCSubmitOWConvictionResponse = 8754 + GCToGCGetAccountSteamChina = 8755 + GCToGCGetAccountSteamChinaResponse = 8756 + ClientToGCClaimLeaderboardRewards = 8757 + ClientToGCClaimLeaderboardRewardsResponse = 8758 + ClientToGCRecalibrateMMR = 8759 + ClientToGCRecalibrateMMRResponse = 8760 + GCToGCGrantEventPointActionList = 8761 + ClientToGCChinaSSAURLRequest = 8764 + ClientToGCChinaSSAURLResponse = 8765 + ClientToGCChinaSSAAcceptedRequest = 8766 + ClientToGCChinaSSAAcceptedResponse = 8767 + SignOutOverwatchSuspicion = 8768 + ServerToGCGetSuspicionConfig = 8769 + ServerToGCGetSuspicionConfigResponse = 8770 + GCToGCGrantPlusHeroChallengeMatchResults = 8771 + GCToClientOverwatchCasesAvailable = 8772 + ServerToGCAccountCheck = 8773 + ClientToGCStartWatchingOverwatch = 8774 + ClientToGCStopWatchingOverwatch = 8775 + SignOutPerfData = 8776 + ClientToGCGetDPCFavorites = 8777 + ClientToGCGetDPCFavoritesResponse = 8778 + ClientToGCSetDPCFavoriteState = 8779 + ClientToGCSetDPCFavoriteStateResponse = 8780 + ClientToGCOverwatchReplayError = 8781 + ServerToGCPlayerChallengeHistory = 8782 + SignOutBanData = 8783 + WebapiDPCSeasonResults = 8784 + ClientToGCCoachFriend = 8785 + ClientToGCCoachFriendResponse = 8786 + ClientToGCRequestPrivateCoachingSession = 8787 + ClientToGCRequestPrivateCoachingSessionResponse = 8788 + ClientToGCAcceptPrivateCoachingSession = 8789 + ClientToGCAcceptPrivateCoachingSessionResponse = 8790 + ClientToGCLeavePrivateCoachingSession = 8791 + ClientToGCLeavePrivateCoachingSessionResponse = 8792 + ClientToGCGetCurrentPrivateCoachingSession = 8793 + ClientToGCGetCurrentPrivateCoachingSessionResponse = 8794 + GCToClientPrivateCoachingSessionUpdated = 8795 + ClientToGCSubmitPrivateCoachingSessionRating = 8796 + ClientToGCSubmitPrivateCoachingSessionRatingResponse = 8797 + ClientToGCGetAvailablePrivateCoachingSessions = 8798 + ClientToGCGetAvailablePrivateCoachingSessionsResponse = 8799 + ClientToGCGetAvailablePrivateCoachingSessionsSummary = 8800 + ClientToGCGetAvailablePrivateCoachingSessionsSummaryResponse = 8801 + ClientToGCJoinPrivateCoachingSessionLobby = 8802 + ClientToGCJoinPrivateCoachingSessionLobbyResponse = 8803 + ClientToGCRespondToCoachFriendRequest = 8804 + ClientToGCRespondToCoachFriendRequestResponse = 8805 + ClientToGCSetEventActiveSeasonID = 8806 + ClientToGCSetEventActiveSeasonIDResponse = 8807 + ServerToGCMatchPlayerNeutralItemEquipHistory = 8808 + ServerToGCCompendiumChosenInGamePredictions = 8809 + ClientToGCCreateTeamPlayerCardPack = 8810 + ClientToGCCreateTeamPlayerCardPackResponse = 8811 + GCToServerSubmitCheerData = 8812 + GCToServerCheerConfig = 8813 + ServerToGCGetCheerConfig = 8814 + ServerToGCGetCheerConfigResponse = 8815 + GCToGCGrantAutographByID = 8816 + GCToServerCheerScalesOverride = 8817 + GCToServerGetCheerState = 8818 + ServerToGCReportCheerState = 8819 + GCToServerScenarioSave = 8820 + GCToServerAbilityDraftLobbyData = 8821 + SignOutReportCommunications = 8822 + ClientToGCBatchGetPlayerCardRosterRequest = 8823 + ClientToGCBatchGetPlayerCardRosterResponse = 8824 + ClientToGCGetStickerbookRequest = 8825 + ClientToGCGetStickerbookResponse = 8826 + ClientToGCCreateStickerbookPageRequest = 8827 + ClientToGCCreateStickerbookPageResponse = 8828 + ClientToGCDeleteStickerbookPageRequest = 8829 + ClientToGCDeleteStickerbookPageResponse = 8830 + ClientToGCPlaceStickersRequest = 8831 + ClientToGCPlaceStickersResponse = 8832 + ClientToGCPlaceCollectionStickersRequest = 8833 + ClientToGCPlaceCollectionStickersResponse = 8834 + ClientToGCOrderStickerbookTeamPageRequest = 8835 + ClientToGCOrderStickerbookTeamPageResponse = 8836 + ServerToGCGetStickerHeroes = 8837 + ServerToGCGetStickerHeroesResponse = 8838 + ClientToGCCandyShopGetUserData = 8840 + ClientToGCCandyShopGetUserDataResponse = 8841 + GCToClientCandyShopUserDataUpdated = 8842 + ClientToGCCandyShopPurchaseReward = 8843 + ClientToGCCandyShopPurchaseRewardResponse = 8844 + ClientToGCCandyShopDoExchange = 8845 + ClientToGCCandyShopDoExchangeResponse = 8846 + ClientToGCCandyShopDoVariableExchange = 8847 + ClientToGCCandyShopDoVariableExchangeResponse = 8848 + ClientToGCCandyShopRerollRewards = 8849 + ClientToGCCandyShopRerollRewardsResponse = 8850 + ClientToGCSetHeroSticker = 8851 + ClientToGCSetHeroStickerResponse = 8852 + ClientToGCGetHeroStickers = 8853 + ClientToGCGetHeroStickersResponse = 8854 + ClientToGCSetFavoritePage = 8855 + ClientToGCSetFavoritePageResponse = 8856 + ClientToGCCandyShopDevGrantCandy = 8857 + ClientToGCCandyShopDevGrantCandyResponse = 8858 + ClientToGCCandyShopDevClearInventory = 8859 + ClientToGCCandyShopDevClearInventoryResponse = 8860 + ClientToGCCandyShopOpenBags = 8861 + ClientToGCCandyShopOpenBagsResponse = 8862 + ClientToGCCandyShopDevGrantCandyBags = 8863 + ClientToGCCandyShopDevGrantCandyBagsResponse = 8864 + ClientToGCCandyShopDevShuffleExchange = 8865 + ClientToGCCandyShopDevShuffleExchangeResponse = 8866 + ClientToGCCandyShopDevGrantRerollCharges = 8867 + ClientToGCCandyShopDevGrantRerollChargesResponse = 8868 + LobbyAdditionalAccountData = 8869 + ServerToGCLobbyInitialized = 8870 + ClientToGCCollectorsCacheAvailableDataRequest = 8871 + GCToClientCollectorsCacheAvailableDataResponse = 8872 + ClientToGCUploadMatchClip = 8873 + GCToClientUploadMatchClipResponse = 8874 + GCToServerSetSteamLearnKeysChanged = 8876 + SignOutMuertaMinigame = 8877 + GCToServerLobbyHeroRoleStats = 8878 + ClientToGCRankRequest = 8879 + GCToClientRankResponse = 8880 + GCToClientRankUpdate = 8881 + SignOutMapStats = 8882 + ClientToGCMapStatsRequest = 8883 + GCToClientMapStatsResponse = 8884 + GCToServerSetSteamLearnInferencing = 8885 + ClientToGCShowcaseGetUserData = 8886 + ClientToGCShowcaseGetUserDataResponse = 8887 + ClientToGCShowcaseSetUserData = 8888 + ClientToGCShowcaseSetUserDataResponse = 8889 + ClientToGCFantasyCraftingGetData = 8890 + ClientToGCFantasyCraftingGetDataResponse = 8891 + ClientToGCFantasyCraftingPerformOperation = 8892 + ClientToGCFantasyCraftingPerformOperationResponse = 8893 + GCToClientFantasyCraftingGetDataUpdated = 8894 + ClientToGCFantasyCraftingDevModifyTablet = 8895 + ClientToGCFantasyCraftingDevModifyTabletResponse = 8896 + ClientToGCRoadToTIGetQuests = 8897 + ClientToGCRoadToTIGetQuestsResponse = 8898 + ClientToGCRoadToTIGetActiveQuest = 8899 + ClientToGCRoadToTIGetActiveQuestResponse = 8900 + ClientToGCBingoGetUserData = 8901 + ClientToGCBingoGetUserDataResponse = 8902 + ClientToGCBingoClaimRow = 8903 + ClientToGCBingoClaimRowResponse = 8904 + ClientToGCBingoDevRerollCard = 8905 + ClientToGCBingoDevRerollCardResponse = 8906 + ClientToGCBingoGetStatsData = 8907 + ClientToGCBingoGetStatsDataResponse = 8908 + GCToClientBingoUserDataUpdated = 8909 + GCToClientRoadToTIQuestDataUpdated = 8910 + ClientToGCRoadToTIUseItem = 8911 + ClientToGCRoadToTIUseItemResponse = 8912 + ClientToGCShowcaseSubmitReport = 8913 + ClientToGCShowcaseSubmitReportResponse = 8914 + ClientToGCShowcaseAdminGetReportsRollupList = 8915 + ClientToGCShowcaseAdminGetReportsRollupListResponse = 8916 + ClientToGCShowcaseAdminGetReportsRollup = 8917 + ClientToGCShowcaseAdminGetReportsRollupResponse = 8918 + ClientToGCShowcaseAdminGetUserDetails = 8919 + ClientToGCShowcaseAdminGetUserDetailsResponse = 8920 + ClientToGCShowcaseAdminConvict = 8921 + ClientToGCShowcaseAdminConvictResponse = 8922 + ClientToGCShowcaseAdminExonerate = 8923 + ClientToGCShowcaseAdminExonerateResponse = 8924 + ClientToGCShowcaseAdminReset = 8925 + ClientToGCShowcaseAdminResetResponse = 8926 + ClientToGCShowcaseAdminLockAccount = 8927 + ClientToGCShowcaseAdminLockAccountResponse = 8928 + ClientToGCFantasyCraftingSelectPlayer = 8929 + ClientToGCFantasyCraftingSelectPlayerResponse = 8930 + ClientToGCFantasyCraftingGenerateTablets = 8931 + ClientToGCFantasyCraftingGenerateTabletsResponse = 8932 + ClientToGcFantasyCraftingUpgradeTablets = 8933 + ClientToGcFantasyCraftingUpgradeTabletsResponse = 8934 + ClientToGCFantasyCraftingRerollOptions = 8936 + ClientToGCFantasyCraftingRerollOptionsResponse = 8937 + ClientToGCRoadToTIDevForceQuest = 8935 + LobbyRoadToTIMatchQuestData = 8939 + ClientToGCShowcaseModerationGetQueue = 8940 + ClientToGCShowcaseModerationGetQueueResponse = 8941 + ClientToGCShowcaseModerationApplyModeration = 8942 + ClientToGCShowcaseModerationApplyModerationResponse = 8943 diff --git a/steam/ext/dota2/protobufs/dota_shared_enums.py b/steam/ext/dota2/protobufs/dota_shared_enums.py index f8885218..71fd9b07 100644 --- a/steam/ext/dota2/protobufs/dota_shared_enums.py +++ b/steam/ext/dota2/protobufs/dota_shared_enums.py @@ -8,697 +8,697 @@ import betterproto -class DOTA_GameMode(betterproto.Enum): - DOTA_GAMEMODE_NONE = 0 - DOTA_GAMEMODE_AP = 1 - DOTA_GAMEMODE_CM = 2 - DOTA_GAMEMODE_RD = 3 - DOTA_GAMEMODE_SD = 4 - DOTA_GAMEMODE_AR = 5 - DOTA_GAMEMODE_INTRO = 6 - DOTA_GAMEMODE_HW = 7 - DOTA_GAMEMODE_REVERSE_CM = 8 - DOTA_GAMEMODE_XMAS = 9 - DOTA_GAMEMODE_TUTORIAL = 10 - DOTA_GAMEMODE_MO = 11 - DOTA_GAMEMODE_LP = 12 - DOTA_GAMEMODE_POOL1 = 13 - DOTA_GAMEMODE_FH = 14 - DOTA_GAMEMODE_CUSTOM = 15 - DOTA_GAMEMODE_CD = 16 - DOTA_GAMEMODE_BD = 17 - DOTA_GAMEMODE_ABILITY_DRAFT = 18 - DOTA_GAMEMODE_EVENT = 19 - DOTA_GAMEMODE_ARDM = 20 - DOTA_GAMEMODE_1V1MID = 21 - DOTA_GAMEMODE_ALL_DRAFT = 22 - DOTA_GAMEMODE_TURBO = 23 - DOTA_GAMEMODE_MUTATION = 24 - DOTA_GAMEMODE_COACHES_CHALLENGE = 25 - - -class DOTA_GameState(betterproto.Enum): - DOTA_GAMERULES_STATE_INIT = 0 - DOTA_GAMERULES_STATE_WAIT_FOR_PLAYERS_TO_LOAD = 1 - DOTA_GAMERULES_STATE_HERO_SELECTION = 2 - DOTA_GAMERULES_STATE_STRATEGY_TIME = 3 - DOTA_GAMERULES_STATE_PRE_GAME = 4 - DOTA_GAMERULES_STATE_GAME_IN_PROGRESS = 5 - DOTA_GAMERULES_STATE_POST_GAME = 6 - DOTA_GAMERULES_STATE_DISCONNECT = 7 - DOTA_GAMERULES_STATE_TEAM_SHOWCASE = 8 - DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP = 9 - DOTA_GAMERULES_STATE_WAIT_FOR_MAP_TO_LOAD = 10 - DOTA_GAMERULES_STATE_SCENARIO_SETUP = 11 - DOTA_GAMERULES_STATE_PLAYER_DRAFT = 12 - DOTA_GAMERULES_STATE_LAST = 13 - - -class DOTA_GC_TEAM(betterproto.Enum): - DOTA_GC_TEAM_GOOD_GUYS = 0 - DOTA_GC_TEAM_BAD_GUYS = 1 - DOTA_GC_TEAM_BROADCASTER = 2 - DOTA_GC_TEAM_SPECTATOR = 3 - DOTA_GC_TEAM_PLAYER_POOL = 4 - DOTA_GC_TEAM_NOTEAM = 5 - DOTA_GC_TEAM_CUSTOM_1 = 6 - DOTA_GC_TEAM_CUSTOM_2 = 7 - DOTA_GC_TEAM_CUSTOM_3 = 8 - DOTA_GC_TEAM_CUSTOM_4 = 9 - DOTA_GC_TEAM_CUSTOM_5 = 10 - DOTA_GC_TEAM_CUSTOM_6 = 11 - DOTA_GC_TEAM_CUSTOM_7 = 12 - DOTA_GC_TEAM_CUSTOM_8 = 13 - DOTA_GC_TEAM_NEUTRALS = 14 +class DOTAGameMode(betterproto.Enum): + NONE = 0 + AP = 1 + CM = 2 + RD = 3 + SD = 4 + AR = 5 + INTRO = 6 + HW = 7 + REVERSE_CM = 8 + XMAS = 9 + TUTORIAL = 10 + MO = 11 + LP = 12 + POOL1 = 13 + FH = 14 + CUSTOM = 15 + CD = 16 + BD = 17 + ABILITY_DRAFT = 18 + EVENT = 19 + ARDM = 20 + MID1V1 = 21 + ALL_DRAFT = 22 + TURBO = 23 + MUTATION = 24 + COACHES_CHALLENGE = 25 + + +class DOTAGameState(betterproto.Enum): + INIT = 0 + WAIT_FOR_PLAYERS_TO_LOAD = 1 + HERO_SELECTION = 2 + STRATEGY_TIME = 3 + PRE_GAME = 4 + GAME_IN_PROGRESS = 5 + POST_GAME = 6 + DISCONNECT = 7 + TEAM_SHOWCASE = 8 + CUSTOM_GAME_SETUP = 9 + WAIT_FOR_MAP_TO_LOAD = 10 + SCENARIO_SETUP = 11 + PLAYER_DRAFT = 12 + LAST = 13 + + +class DOTAGCTeam(betterproto.Enum): + GOOD_GUYS = 0 + BAD_GUYS = 1 + BROADCASTER = 2 + SPECTATOR = 3 + PLAYER_POOL = 4 + NOTEAM = 5 + CUSTOM_1 = 6 + CUSTOM_2 = 7 + CUSTOM_3 = 8 + CUSTOM_4 = 9 + CUSTOM_5 = 10 + CUSTOM_6 = 11 + CUSTOM_7 = 12 + CUSTOM_8 = 13 + NEUTRALS = 14 class EEvent(betterproto.Enum): - EVENT_ID_NONE = 0 - EVENT_ID_DIRETIDE = 1 - EVENT_ID_SPRING_FESTIVAL = 2 - EVENT_ID_FROSTIVUS_2013 = 3 - EVENT_ID_COMPENDIUM_2014 = 4 - EVENT_ID_NEXON_PC_BANG = 5 - EVENT_ID_PWRD_DAC_2015 = 6 - EVENT_ID_NEW_BLOOM_2015 = 7 - EVENT_ID_INTERNATIONAL_2015 = 8 - EVENT_ID_FALL_MAJOR_2015 = 9 - EVENT_ID_ORACLE_PA = 10 - EVENT_ID_NEW_BLOOM_2015_PREBEAST = 11 - EVENT_ID_FROSTIVUS = 12 - EVENT_ID_WINTER_MAJOR_2016 = 13 - EVENT_ID_INTERNATIONAL_2016 = 14 - EVENT_ID_FALL_MAJOR_2016 = 15 - EVENT_ID_WINTER_MAJOR_2017 = 16 - EVENT_ID_NEW_BLOOM_2017 = 17 - EVENT_ID_INTERNATIONAL_2017 = 18 - EVENT_ID_PLUS_SUBSCRIPTION = 19 - EVENT_ID_SINGLES_DAY_2017 = 20 - EVENT_ID_FROSTIVUS_2017 = 21 - EVENT_ID_INTERNATIONAL_2018 = 22 - EVENT_ID_FROSTIVUS_2018 = 23 - EVENT_ID_NEW_BLOOM_2019 = 24 - EVENT_ID_INTERNATIONAL_2019 = 25 - EVENT_ID_NEW_PLAYER_EXPERIENCE = 26 - EVENT_ID_FROSTIVUS_2019 = 27 - EVENT_ID_NEW_BLOOM_2020 = 28 - EVENT_ID_INTERNATIONAL_2020 = 29 - EVENT_ID_TEAM_FANDOM = 30 - EVENT_ID_DIRETIDE_2020 = 31 - EVENT_ID_SPRING_2021 = 32 - EVENT_ID_FALL_2021 = 33 - EVENT_ID_TEAM_FANDOM_FALL_2021 = 34 - EVENT_ID_TEAM_2021_2022_TOUR2 = 35 - EVENT_ID_INTERNATIONAL_2022 = 36 - EVENT_ID_TEAM_2021_2022_TOUR3 = 37 - EVENT_ID_TEAM_INTERNATIONAL_2022 = 38 - EVENT_ID_PERMANENT_GRANTS = 39 - EVENT_ID_MUERTA_RELEASE_SPRING2023 = 40 - EVENT_ID_TEAM_2023_TOUR1 = 41 - EVENT_ID_TEAM_2023_TOUR2 = 42 - EVENT_ID_TEAM_2023_TOUR3 = 43 - EVENT_ID_INTERNATIONAL_2023 = 45 - EVENT_ID_10TH_ANNIVERSARY = 46 - EVENT_ID_FROSTIVUS_2023 = 48 + NONE = 0 + DIRETIDE = 1 + SPRING_FESTIVAL = 2 + FROSTIVUS_2013 = 3 + COMPENDIUM_2014 = 4 + NEXON_PC_BANG = 5 + PWRD_DAC_2015 = 6 + NEW_BLOOM_2015 = 7 + INTERNATIONAL_2015 = 8 + FALL_MAJOR_2015 = 9 + ORACLE_PA = 10 + NEW_BLOOM_2015_PREBEAST = 11 + FROSTIVUS = 12 + WINTER_MAJOR_2016 = 13 + INTERNATIONAL_2016 = 14 + FALL_MAJOR_2016 = 15 + WINTER_MAJOR_2017 = 16 + NEW_BLOOM_2017 = 17 + INTERNATIONAL_2017 = 18 + PLUS_SUBSCRIPTION = 19 + SINGLES_DAY_2017 = 20 + FROSTIVUS_2017 = 21 + INTERNATIONAL_2018 = 22 + FROSTIVUS_2018 = 23 + NEW_BLOOM_2019 = 24 + INTERNATIONAL_2019 = 25 + NEW_PLAYER_EXPERIENCE = 26 + FROSTIVUS_2019 = 27 + NEW_BLOOM_2020 = 28 + INTERNATIONAL_2020 = 29 + TEAM_FANDOM = 30 + DIRETIDE_2020 = 31 + SPRING_2021 = 32 + FALL_2021 = 33 + TEAM_FANDOM_FALL_2021 = 34 + TEAM_2021_2022_TOUR2 = 35 + INTERNATIONAL_2022 = 36 + TEAM_2021_2022_TOUR3 = 37 + TEAM_INTERNATIONAL_2022 = 38 + PERMANENT_GRANTS = 39 + MUERTA_RELEASE_SPRING2023 = 40 + TEAM_2023_TOUR1 = 41 + TEAM_2023_TOUR2 = 42 + TEAM_2023_TOUR3 = 43 + INTERNATIONAL_2023 = 45 + TENTH_ANNIVERSARY = 46 + FROSTIVUS_2023 = 48 class ERankType(betterproto.Enum): - k_ERankType_Invalid = 0 - k_ERankType_Casual = 1 - k_ERankType_Ranked = 2 - k_ERankType_CasualLegacy = 3 - k_ERankType_RankedLegacy = 4 - k_ERankType_CasualGlicko = 5 - k_ERankType_RankedGlicko = 6 - k_ERankType_RankMax = 7 - k_ERankType_BehaviorPrivate = 100 - k_ERankType_BehaviorPublic = 101 - k_ERankType_Max = 102 + Invalid = 0 + Casual = 1 + Ranked = 2 + CasualLegacy = 3 + RankedLegacy = 4 + CasualGlicko = 5 + RankedGlicko = 6 + RankMax = 7 + BehaviorPrivate = 100 + BehaviorPublic = 101 + Max = 102 class DOTALeaverStatusT(betterproto.Enum): - DOTA_LEAVER_NONE = 0 - DOTA_LEAVER_DISCONNECTED = 1 - DOTA_LEAVER_DISCONNECTED_TOO_LONG = 2 - DOTA_LEAVER_ABANDONED = 3 - DOTA_LEAVER_AFK = 4 - DOTA_LEAVER_NEVER_CONNECTED = 5 - DOTA_LEAVER_NEVER_CONNECTED_TOO_LONG = 6 - DOTA_LEAVER_FAILED_TO_READY_UP = 7 - DOTA_LEAVER_DECLINED = 8 + NONE = 0 + DISCONNECTED = 1 + DISCONNECTED_TOO_LONG = 2 + ABANDONED = 3 + AFK = 4 + NEVER_CONNECTED = 5 + NEVER_CONNECTED_TOO_LONG = 6 + FAILED_TO_READY_UP = 7 + DECLINED = 8 class DOTAConnectionStateT(betterproto.Enum): - DOTA_CONNECTION_STATE_UNKNOWN = 0 - DOTA_CONNECTION_STATE_NOT_YET_CONNECTED = 1 - DOTA_CONNECTION_STATE_CONNECTED = 2 - DOTA_CONNECTION_STATE_DISCONNECTED = 3 - DOTA_CONNECTION_STATE_ABANDONED = 4 - DOTA_CONNECTION_STATE_LOADING = 5 - DOTA_CONNECTION_STATE_FAILED = 6 - - -class Fantasy_Roles(betterproto.Enum): - FANTASY_ROLE_UNDEFINED = 0 - FANTASY_ROLE_CORE = 1 - FANTASY_ROLE_SUPPORT = 2 - FANTASY_ROLE_OFFLANE = 3 - FANTASY_ROLE_MID = 4 - - -class Fantasy_Scoring(betterproto.Enum): - FANTASY_SCORING_KILLS = 0 - FANTASY_SCORING_DEATHS = 1 - FANTASY_SCORING_CS = 2 - FANTASY_SCORING_GPM = 3 - FANTASY_SCORING_TOWER_KILLS = 4 - FANTASY_SCORING_ROSHAN_KILLS = 5 - FANTASY_SCORING_TEAMFIGHT_PARTICIPATION = 6 - FANTASY_SCORING_WARDS_PLANTED = 7 - FANTASY_SCORING_CAMPS_STACKED = 8 - FANTASY_SCORING_RUNES_GRABBED = 9 - FANTASY_SCORING_FIRST_BLOOD = 10 - FANTASY_SCORING_STUNS = 11 - FANTASY_SCORING_SMOKES_USED = 12 - FANTASY_SCORING_NEUTRAL_TOKENS_FOUND = 13 - FANTASY_SCORING_WATCHERS_TAKEN = 14 - FANTASY_SCORING_LOTUSES_GAINED = 15 - FANTASY_SCORING_TORMENTOR_KILLS = 16 - FANTASY_SCORING_COURIER_KILLS = 17 - FANTASY_SCORING_TYPES = 18 - FANTASY_SCORING_INVALID = 19 - - -class Fantasy_Team_Slots(betterproto.Enum): - FANTASY_SLOT_NONE = 0 - FANTASY_SLOT_CORE = 1 - FANTASY_SLOT_SUPPORT = 2 - FANTASY_SLOT_ANY = 3 - FANTASY_SLOT_BENCH = 4 - - -class Fantasy_Selection_Mode(betterproto.Enum): - FANTASY_SELECTION_INVALID = 0 - FANTASY_SELECTION_LOCKED = 1 - FANTASY_SELECTION_SHUFFLE = 2 - FANTASY_SELECTION_FREE_PICK = 3 - FANTASY_SELECTION_ENDED = 4 - FANTASY_SELECTION_PRE_SEASON = 5 - FANTASY_SELECTION_PRE_DRAFT = 6 - FANTASY_SELECTION_DRAFTING = 7 - FANTASY_SELECTION_REGULAR_SEASON = 8 - FANTASY_SELECTION_CARD_BASED = 9 - - -class Fantasy_Gem_Type(betterproto.Enum): - FANTASY_GEM_TYPE_RUBY = 0 - FANTASY_GEM_TYPE_SAPPHIRE = 1 - FANTASY_GEM_TYPE_EMERALD = 2 + UNKNOWN = 0 + NOT_YET_CONNECTED = 1 + CONNECTED = 2 + DISCONNECTED = 3 + ABANDONED = 4 + LOADING = 5 + FAILED = 6 + + +class FantasyRoles(betterproto.Enum): + UNDEFINED = 0 + CORE = 1 + SUPPORT = 2 + OFFLANE = 3 + MID = 4 + + +class FantasyScoring(betterproto.Enum): + KILLS = 0 + DEATHS = 1 + CS = 2 + GPM = 3 + TOWER_KILLS = 4 + ROSHAN_KILLS = 5 + TEAMFIGHT_PARTICIPATION = 6 + WARDS_PLANTED = 7 + CAMPS_STACKED = 8 + RUNES_GRABBED = 9 + FIRST_BLOOD = 10 + STUNS = 11 + SMOKES_USED = 12 + NEUTRAL_TOKENS_FOUND = 13 + WATCHERS_TAKEN = 14 + LOTUSES_GAINED = 15 + TORMENTOR_KILLS = 16 + COURIER_KILLS = 17 + TYPES = 18 + INVALID = 19 + + +class FantasyTeamSlots(betterproto.Enum): + NONE = 0 + CORE = 1 + SUPPORT = 2 + ANY = 3 + BENCH = 4 + + +class FantasySelectionMode(betterproto.Enum): + INVALID = 0 + LOCKED = 1 + SHUFFLE = 2 + FREE_PICK = 3 + ENDED = 4 + PRE_SEASON = 5 + PRE_DRAFT = 6 + DRAFTING = 7 + REGULAR_SEASON = 8 + CARD_BASED = 9 + + +class FantasyGemType(betterproto.Enum): + RUBY = 0 + SAPPHIRE = 1 + EMERALD = 2 class DOTAChatChannelTypeT(betterproto.Enum): - DOTAChannelType_Regional = 0 - DOTAChannelType_Custom = 1 - DOTAChannelType_Party = 2 - DOTAChannelType_Lobby = 3 - DOTAChannelType_Team = 4 - DOTAChannelType_Guild = 5 - DOTAChannelType_Fantasy = 6 - DOTAChannelType_Whisper = 7 - DOTAChannelType_Console = 8 - DOTAChannelType_Tab = 9 - DOTAChannelType_Invalid = 10 - DOTAChannelType_GameAll = 11 - DOTAChannelType_GameAllies = 12 - DOTAChannelType_GameSpectator = 13 - DOTAChannelType_GameCoaching = 14 - DOTAChannelType_Cafe = 15 - DOTAChannelType_CustomGame = 16 - DOTAChannelType_Private = 17 - DOTAChannelType_PostGame = 18 - DOTAChannelType_BattleCup = 19 - DOTAChannelType_HLTVSpectator = 20 - DOTAChannelType_GameEvents = 21 - DOTAChannelType_Trivia = 22 - DOTAChannelType_NewPlayer = 23 - DOTAChannelType_PrivateCoaching = 24 + Regional = 0 + Custom = 1 + Party = 2 + Lobby = 3 + Team = 4 + Guild = 5 + Fantasy = 6 + Whisper = 7 + Console = 8 + Tab = 9 + Invalid = 10 + GameAll = 11 + GameAllies = 12 + GameSpectator = 13 + GameCoaching = 14 + Cafe = 15 + CustomGame = 16 + Private = 17 + PostGame = 18 + BattleCup = 19 + HLTVSpectator = 20 + GameEvents = 21 + Trivia = 22 + NewPlayer = 23 + PrivateCoaching = 24 class EChatSpecialPrivileges(betterproto.Enum): - k_EChatSpecialPrivileges_None = 0 - k_EChatSpecialPrivileges_Moderator = 1 - k_EChatSpecialPrivileges_SuperModerator = 2 + NONE = 0 + Moderator = 1 + SuperModerator = 2 class DOTACommTypeT(betterproto.Enum): - DOTA_COMM_TYPE_NONE = 0 - DOTA_COMM_TYPE_PING = 1 - DOTA_COMM_TYPE_CHATWHEEL = 2 - DOTA_COMM_TYPE_TIP = 3 - DOTA_COMM_TYPE_TEXT = 4 - DOTA_COMM_TYPE_SHOWCASE = 5 - DOTA_COMM_TYPE_VOICE = 6 - DOTA_COMM_TYPE_ALLY_ABILITY = 7 - DOTA_COMM_TYPE_PAUSE = 8 - DOTA_COMM_TYPE_COACHING = 9 - DOTA_COMM_TYPE_NOCOOLDOWN = 10 - DOTA_COMM_TYPE_RANKEDMATCHMAKE = 11 - DOTA_COMM_TYPE_DROPS = 12 - DOTA_COMM_TYPE_NEWPLAYER_EXPERT = 13 - DOTA_COMM_TYPE_COACHED = 14 - DOTA_COMM_TYPE_MAPDRAWING = 15 + NONE = 0 + PING = 1 + CHATWHEEL = 2 + TIP = 3 + TEXT = 4 + SHOWCASE = 5 + VOICE = 6 + ALLY_ABILITY = 7 + PAUSE = 8 + COACHING = 9 + NOCOOLDOWN = 10 + RANKEDMATCHMAKE = 11 + DROPS = 12 + NEWPLAYER_EXPERT = 13 + COACHED = 14 + MAPDRAWING = 15 class DOTACommLevelT(betterproto.Enum): - DOTA_COMM_LEVEL_NONE = 0 - DOTA_COMM_LEVEL_COOLDOWN = 1 - DOTA_COMM_LEVEL_PINGS = 2 - DOTA_COMM_LEVEL_MAPDRAWING = 3 - DOTA_COMM_LEVEL_CHAT = 4 - DOTA_COMM_LEVEL_TIPPING = 5 - DOTA_COMM_LEVEL_VOICE = 6 - DOTA_COMM_LEVEL_ALLIED_ABILITY = 7 + NONE = 0 + COOLDOWN = 1 + PINGS = 2 + MAPDRAWING = 3 + CHAT = 4 + TIPPING = 5 + VOICE = 6 + ALLIED_ABILITY = 7 class DOTABehaviorLevelT(betterproto.Enum): - DOTA_BEHAVIOR_LEVEL_NONE = 0 - DOTA_BEHAVIOR_LEVEL_RANKED_ALLOWED = 1 - DOTA_BEHAVIOR_LEVEL_PAUSING = 2 - DOTA_BEHAVIOR_LEVEL_DROPS = 3 - DOTA_BEHAVIOR_LEVEL_COACHING = 4 + NONE = 0 + RANKED_ALLOWED = 1 + PAUSING = 2 + DROPS = 3 + COACHING = 4 class EProfileCardSlotType(betterproto.Enum): - k_EProfileCardSlotType_Empty = 0 - k_EProfileCardSlotType_Stat = 1 - k_EProfileCardSlotType_Trophy = 2 - k_EProfileCardSlotType_Item = 3 - k_EProfileCardSlotType_Hero = 4 - k_EProfileCardSlotType_Emoticon = 5 - k_EProfileCardSlotType_Team = 6 + Empty = 0 + Stat = 1 + Trophy = 2 + Item = 3 + Hero = 4 + Emoticon = 5 + Team = 6 class EMatchGroupServerStatus(betterproto.Enum): - k_EMatchGroupServerStatus_OK = 0 - k_EMatchGroupServerStatus_LimitedAvailability = 1 - k_EMatchGroupServerStatus_Offline = 2 + OK = 0 + LimitedAvailability = 1 + Offline = 2 -class DOTA_CM_PICK(betterproto.Enum): - DOTA_CM_RANDOM = 0 - DOTA_CM_GOOD_GUYS = 1 - DOTA_CM_BAD_GUYS = 2 +class DOTACMPICK(betterproto.Enum): + RANDOM = 0 + GOOD_GUYS = 1 + BAD_GUYS = 2 class DOTALowPriorityBanType(betterproto.Enum): - DOTA_LOW_PRIORITY_BAN_ABANDON = 0 - DOTA_LOW_PRIORITY_BAN_REPORTS = 1 - DOTA_LOW_PRIORITY_BAN_SECONDARY_ABANDON = 2 - DOTA_LOW_PRIORITY_BAN_PRE_GAME_ROLE = 3 + ABANDON = 0 + REPORTS = 1 + SECONDARY_ABANDON = 2 + PRE_GAME_ROLE = 3 class DOTALobbyReadyState(betterproto.Enum): - DOTALobbyReadyState_UNDECLARED = 0 - DOTALobbyReadyState_ACCEPTED = 1 - DOTALobbyReadyState_DECLINED = 2 + UNDECLARED = 0 + ACCEPTED = 1 + DECLINED = 2 class DOTAJoinLobbyResult(betterproto.Enum): - DOTA_JOIN_RESULT_SUCCESS = 0 - DOTA_JOIN_RESULT_ALREADY_IN_GAME = 1 - DOTA_JOIN_RESULT_INVALID_LOBBY = 2 - DOTA_JOIN_RESULT_INCORRECT_PASSWORD = 3 - DOTA_JOIN_RESULT_ACCESS_DENIED = 4 - DOTA_JOIN_RESULT_GENERIC_ERROR = 5 - DOTA_JOIN_RESULT_INCORRECT_VERSION = 6 - DOTA_JOIN_RESULT_IN_TEAM_PARTY = 7 - DOTA_JOIN_RESULT_NO_LOBBY_FOUND = 8 - DOTA_JOIN_RESULT_LOBBY_FULL = 9 - DOTA_JOIN_RESULT_CUSTOM_GAME_INCORRECT_VERSION = 10 - DOTA_JOIN_RESULT_TIMEOUT = 11 - DOTA_JOIN_RESULT_CUSTOM_GAME_COOLDOWN = 12 - DOTA_JOIN_RESULT_BUSY = 13 - DOTA_JOIN_RESULT_NO_PLAYTIME = 14 + SUCCESS = 0 + ALREADY_IN_GAME = 1 + INVALID_LOBBY = 2 + INCORRECT_PASSWORD = 3 + ACCESS_DENIED = 4 + GENERIC_ERROR = 5 + INCORRECT_VERSION = 6 + IN_TEAM_PARTY = 7 + NO_LOBBY_FOUND = 8 + LOBBY_FULL = 9 + CUSTOM_GAME_INCORRECT_VERSION = 10 + TIMEOUT = 11 + CUSTOM_GAME_COOLDOWN = 12 + BUSY = 13 + NO_PLAYTIME = 14 class DOTASelectionPriorityRules(betterproto.Enum): - k_DOTASelectionPriorityRules_Manual = 0 - k_DOTASelectionPriorityRules_Automatic = 1 + Manual = 0 + Automatic = 1 class DOTASelectionPriorityChoice(betterproto.Enum): - k_DOTASelectionPriorityChoice_Invalid = 0 - k_DOTASelectionPriorityChoice_FirstPick = 1 - k_DOTASelectionPriorityChoice_SecondPick = 2 - k_DOTASelectionPriorityChoice_Radiant = 3 - k_DOTASelectionPriorityChoice_Dire = 4 + Invalid = 0 + FirstPick = 1 + SecondPick = 2 + Radiant = 3 + Dire = 4 class DOTAMatchVote(betterproto.Enum): - DOTAMatchVote_INVALID = 0 - DOTAMatchVote_POSITIVE = 1 - DOTAMatchVote_NEGATIVE = 2 + INVALID = 0 + POSITIVE = 1 + NEGATIVE = 2 class DOTALobbyVisibility(betterproto.Enum): - DOTALobbyVisibility_Public = 0 - DOTALobbyVisibility_Friends = 1 - DOTALobbyVisibility_Unlisted = 2 + Public = 0 + Friends = 1 + Unlisted = 2 class EDOTAPlayerMMRType(betterproto.Enum): - k_EDOTAPlayerMMRType_Invalid = 0 - k_EDOTAPlayerMMRType_GeneralHidden = 1 - k_EDOTAPlayerMMRType_GeneralCompetitive = 3 + Invalid = 0 + GeneralHidden = 1 + GeneralCompetitive = 3 class EDOTAMMRBoostType(betterproto.Enum): - k_EDOTAMMRBoostType_None = 0 - k_EDOTAMMRBoostType_Leader = 1 - k_EDOTAMMRBoostType_Follower = 2 + NONE = 0 + Leader = 1 + Follower = 2 class MatchType(betterproto.Enum): - MATCH_TYPE_CASUAL = 0 - MATCH_TYPE_COOP_BOTS = 1 - MATCH_TYPE_COMPETITIVE = 4 - MATCH_TYPE_WEEKEND_TOURNEY = 5 - MATCH_TYPE_EVENT = 7 - MATCH_TYPE_COACHES_CHALLENGE = 12 - MATCH_TYPE_NEW_PLAYER_POOL = 14 + CASUAL = 0 + COOP_BOTS = 1 + COMPETITIVE = 4 + WEEKEND_TOURNEY = 5 + EVENT = 7 + COACHES_CHALLENGE = 12 + NEW_PLAYER_POOL = 14 class DOTABotDifficulty(betterproto.Enum): - BOT_DIFFICULTY_PASSIVE = 0 - BOT_DIFFICULTY_EASY = 1 - BOT_DIFFICULTY_MEDIUM = 2 - BOT_DIFFICULTY_HARD = 3 - BOT_DIFFICULTY_UNFAIR = 4 - BOT_DIFFICULTY_INVALID = 5 - BOT_DIFFICULTY_EXTRA1 = 6 - BOT_DIFFICULTY_EXTRA2 = 7 - BOT_DIFFICULTY_EXTRA3 = 8 - BOT_DIFFICULTY_NPX = 9 - - -class DOTA_BOT_MODE(betterproto.Enum): - DOTA_BOT_MODE_NONE = 0 - DOTA_BOT_MODE_LANING = 1 - DOTA_BOT_MODE_ATTACK = 2 - DOTA_BOT_MODE_ROAM = 3 - DOTA_BOT_MODE_RETREAT = 4 - DOTA_BOT_MODE_SECRET_SHOP = 5 - DOTA_BOT_MODE_SIDE_SHOP = 6 - DOTA_BOT_MODE_RUNE = 7 - DOTA_BOT_MODE_PUSH_TOWER_TOP = 8 - DOTA_BOT_MODE_PUSH_TOWER_MID = 9 - DOTA_BOT_MODE_PUSH_TOWER_BOT = 10 - DOTA_BOT_MODE_DEFEND_TOWER_TOP = 11 - DOTA_BOT_MODE_DEFEND_TOWER_MID = 12 - DOTA_BOT_MODE_DEFEND_TOWER_BOT = 13 - DOTA_BOT_MODE_ASSEMBLE = 14 - DOTA_BOT_MODE_ASSEMBLE_WITH_HUMANS = 15 - DOTA_BOT_MODE_TEAM_ROAM = 16 - DOTA_BOT_MODE_FARM = 17 - DOTA_BOT_MODE_DEFEND_ALLY = 18 - DOTA_BOT_MODE_EVASIVE_MANEUVERS = 19 - DOTA_BOT_MODE_ROSHAN = 20 - DOTA_BOT_MODE_ITEM = 21 - DOTA_BOT_MODE_WARD = 22 - DOTA_BOT_MODE_COMPANION = 23 - DOTA_BOT_MODE_TUTORIAL_BOSS = 24 - DOTA_BOT_MODE_MINION = 25 - DOTA_BOT_MODE_OUTPOST = 26 + PASSIVE = 0 + EASY = 1 + MEDIUM = 2 + HARD = 3 + UNFAIR = 4 + INVALID = 5 + EXTRA1 = 6 + EXTRA2 = 7 + EXTRA3 = 8 + NPX = 9 + + +class DOTABotMode(betterproto.Enum): + NONE = 0 + LANING = 1 + ATTACK = 2 + ROAM = 3 + RETREAT = 4 + SECRET_SHOP = 5 + SIDE_SHOP = 6 + RUNE = 7 + PUSH_TOWER_TOP = 8 + PUSH_TOWER_MID = 9 + PUSH_TOWER_BOT = 10 + DEFEND_TOWER_TOP = 11 + DEFEND_TOWER_MID = 12 + DEFEND_TOWER_BOT = 13 + ASSEMBLE = 14 + ASSEMBLE_WITH_HUMANS = 15 + TEAM_ROAM = 16 + FARM = 17 + DEFEND_ALLY = 18 + EVASIVE_MANEUVERS = 19 + ROSHAN = 20 + ITEM = 21 + WARD = 22 + COMPANION = 23 + TUTORIAL_BOSS = 24 + MINION = 25 + OUTPOST = 26 class MatchLanguages(betterproto.Enum): - MATCH_LANGUAGE_INVALID = 0 - MATCH_LANGUAGE_ENGLISH = 1 - MATCH_LANGUAGE_RUSSIAN = 2 - MATCH_LANGUAGE_CHINESE = 3 - MATCH_LANGUAGE_KOREAN = 4 - MATCH_LANGUAGE_SPANISH = 5 - MATCH_LANGUAGE_PORTUGUESE = 6 - MATCH_LANGUAGE_ENGLISH2 = 7 + INVALID = 0 + ENGLISH = 1 + RUSSIAN = 2 + CHINESE = 3 + KOREAN = 4 + SPANISH = 5 + PORTUGUESE = 6 + ENGLISH2 = 7 class ETourneyQueueDeadlineState(betterproto.Enum): - k_ETourneyQueueDeadlineState_Normal = 0 - k_ETourneyQueueDeadlineState_Missed = 1 - k_ETourneyQueueDeadlineState_ExpiredOK = 2 - k_ETourneyQueueDeadlineState_SeekingBye = 3 - k_ETourneyQueueDeadlineState_EligibleForRefund = 4 - k_ETourneyQueueDeadlineState_NA = -1 - k_ETourneyQueueDeadlineState_ExpiringSoon = 101 + Normal = 0 + Missed = 1 + ExpiredOK = 2 + SeekingBye = 3 + EligibleForRefund = 4 + NA = -1 + ExpiringSoon = 101 class EMatchOutcome(betterproto.Enum): - k_EMatchOutcome_Unknown = 0 - k_EMatchOutcome_RadVictory = 2 - k_EMatchOutcome_DireVictory = 3 - k_EMatchOutcome_NeutralVictory = 4 - k_EMatchOutcome_NoTeamWinner = 5 - k_EMatchOutcome_Custom1Victory = 6 - k_EMatchOutcome_Custom2Victory = 7 - k_EMatchOutcome_Custom3Victory = 8 - k_EMatchOutcome_Custom4Victory = 9 - k_EMatchOutcome_Custom5Victory = 10 - k_EMatchOutcome_Custom6Victory = 11 - k_EMatchOutcome_Custom7Victory = 12 - k_EMatchOutcome_Custom8Victory = 13 - k_EMatchOutcome_NotScored_PoorNetworkConditions = 64 - k_EMatchOutcome_NotScored_Leaver = 65 - k_EMatchOutcome_NotScored_ServerCrash = 66 - k_EMatchOutcome_NotScored_NeverStarted = 67 - k_EMatchOutcome_NotScored_Canceled = 68 - k_EMatchOutcome_NotScored_Suspicious = 69 + Unknown = 0 + RadVictory = 2 + DireVictory = 3 + NeutralVictory = 4 + NoTeamWinner = 5 + Custom1Victory = 6 + Custom2Victory = 7 + Custom3Victory = 8 + Custom4Victory = 9 + Custom5Victory = 10 + Custom6Victory = 11 + Custom7Victory = 12 + Custom8Victory = 13 + NotScored_PoorNetworkConditions = 64 + NotScored_Leaver = 65 + NotScored_ServerCrash = 66 + NotScored_NeverStarted = 67 + NotScored_Canceled = 68 + NotScored_Suspicious = 69 class ELaneType(betterproto.Enum): - LANE_TYPE_UNKNOWN = 0 - LANE_TYPE_SAFE = 1 - LANE_TYPE_OFF = 2 - LANE_TYPE_MID = 3 - LANE_TYPE_JUNGLE = 4 - LANE_TYPE_ROAM = 5 + UNKNOWN = 0 + SAFE = 1 + OFF = 2 + MID = 3 + JUNGLE = 4 + ROAM = 5 class EBadgeType(betterproto.Enum): - k_EBadgeType_Invalid = 0 - k_EBadgeType_TI7_Midweek = 1 - k_EBadgeType_TI7_Finals = 2 - k_EBadgeType_TI7_AllEvent = 3 - k_EBadgeType_TI8_Midweek = 4 - k_EBadgeType_TI8_Finals = 5 - k_EBadgeType_TI8_AllEvent = 6 - k_EBadgeType_TI10 = 7 - k_EBadgeType_TI11_PlayoffsDay1 = 8 - k_EBadgeType_TI11_PlayoffsDay2 = 9 - k_EBadgeType_TI11_PlayoffsDay3 = 10 - k_EBadgeType_TI11_PlayoffsDay4 = 11 - k_EBadgeType_TI11_FinalsWeekend = 12 - k_EBadgeType_TI12_PlayoffsDay1 = 13 - k_EBadgeType_TI12_PlayoffsDay2 = 14 - k_EBadgeType_TI12_PlayoffsDay3 = 15 - k_EBadgeType_TI12_FinalsWeekend = 16 - k_EBadgeType_TI12_Special = 17 + Invalid = 0 + TI7_Midweek = 1 + TI7_Finals = 2 + TI7_AllEvent = 3 + TI8_Midweek = 4 + TI8_Finals = 5 + TI8_AllEvent = 6 + TI10 = 7 + TI11_PlayoffsDay1 = 8 + TI11_PlayoffsDay2 = 9 + TI11_PlayoffsDay3 = 10 + TI11_PlayoffsDay4 = 11 + TI11_FinalsWeekend = 12 + TI12_PlayoffsDay1 = 13 + TI12_PlayoffsDay2 = 14 + TI12_PlayoffsDay3 = 15 + TI12_FinalsWeekend = 16 + TI12_Special = 17 class ELeagueStatus(betterproto.Enum): - LEAGUE_STATUS_UNSET = 0 - LEAGUE_STATUS_UNSUBMITTED = 1 - LEAGUE_STATUS_SUBMITTED = 2 - LEAGUE_STATUS_ACCEPTED = 3 - LEAGUE_STATUS_REJECTED = 4 - LEAGUE_STATUS_CONCLUDED = 5 - LEAGUE_STATUS_DELETED = 6 + UNSET = 0 + UNSUBMITTED = 1 + SUBMITTED = 2 + ACCEPTED = 3 + REJECTED = 4 + CONCLUDED = 5 + DELETED = 6 class ELeagueRegion(betterproto.Enum): - LEAGUE_REGION_UNSET = 0 - LEAGUE_REGION_NA = 1 - LEAGUE_REGION_SA = 2 - LEAGUE_REGION_WEU = 3 - LEAGUE_REGION_EEU = 4 - LEAGUE_REGION_CHINA = 5 - LEAGUE_REGION_SEA = 6 + UNSET = 0 + NA = 1 + SA = 2 + WEU = 3 + EEU = 4 + CHINA = 5 + SEA = 6 class ELeagueTier(betterproto.Enum): - LEAGUE_TIER_UNSET = 0 - LEAGUE_TIER_AMATEUR = 1 - LEAGUE_TIER_PROFESSIONAL = 2 - LEAGUE_TIER_MINOR = 3 - LEAGUE_TIER_MAJOR = 4 - LEAGUE_TIER_INTERNATIONAL = 5 - LEAGUE_TIER_DPC_QUALIFIER = 6 - LEAGUE_TIER_DPC_LEAGUE_QUALIFIER = 7 - LEAGUE_TIER_DPC_LEAGUE = 8 - LEAGUE_TIER_DPC_LEAGUE_FINALS = 9 + UNSET = 0 + AMATEUR = 1 + PROFESSIONAL = 2 + MINOR = 3 + MAJOR = 4 + INTERNATIONAL = 5 + DPC_QUALIFIER = 6 + DPC_LEAGUE_QUALIFIER = 7 + DPC_LEAGUE = 8 + DPC_LEAGUE_FINALS = 9 class ELeagueTierCategory(betterproto.Enum): - LEAGUE_TIER_CATEGORY_AMATEUR = 1 - LEAGUE_TIER_CATEGORY_PROFESSIONAL = 2 - LEAGUE_TIER_CATEGORY_DPC = 3 + AMATEUR = 1 + PROFESSIONAL = 2 + DPC = 3 class ELeagueDivision(betterproto.Enum): - LEAGUE_DIVISION_UNSET = 0 - LEAGUE_DIVISION_I = 1 - LEAGUE_DIVISION_II = 2 + UNSET = 0 + I = 1 + II = 2 class ELeagueBroadcastProvider(betterproto.Enum): - LEAGUE_BROADCAST_UNKNOWN = 0 - LEAGUE_BROADCAST_STEAM = 1 - LEAGUE_BROADCAST_TWITCH = 2 - LEAGUE_BROADCAST_YOUTUBE = 3 - LEAGUE_BROADCAST_OTHER = 100 + UNKNOWN = 0 + STEAM = 1 + TWITCH = 2 + YOUTUBE = 3 + OTHER = 100 class ELeaguePhase(betterproto.Enum): - LEAGUE_PHASE_UNSET = 0 - LEAGUE_PHASE_REGIONAL_QUALIFIER = 1 - LEAGUE_PHASE_GROUP_STAGE = 2 - LEAGUE_PHASE_MAIN_EVENT = 3 + UNSET = 0 + REGIONAL_QUALIFIER = 1 + GROUP_STAGE = 2 + MAIN_EVENT = 3 class ELeagueAuditAction(betterproto.Enum): - LEAGUE_AUDIT_ACTION_INVALID = 0 - LEAGUE_AUDIT_ACTION_LEAGUE_CREATE = 1 - LEAGUE_AUDIT_ACTION_LEAGUE_EDIT = 2 - LEAGUE_AUDIT_ACTION_LEAGUE_DELETE = 3 - LEAGUE_AUDIT_ACTION_LEAGUE_ADMIN_ADD = 4 - LEAGUE_AUDIT_ACTION_LEAGUE_ADMIN_REVOKE = 5 - LEAGUE_AUDIT_ACTION_LEAGUE_ADMIN_PROMOTE = 6 - LEAGUE_AUDIT_ACTION_LEAGUE_STREAM_ADD = 7 - LEAGUE_AUDIT_ACTION_LEAGUE_STREAM_REMOVE = 8 - LEAGUE_AUDIT_ACTION_LEAGUE_IMAGE_UPDATED = 9 - LEAGUE_AUDIT_ACTION_LEAGUE_MESSAGE_ADDED = 10 - LEAGUE_AUDIT_ACTION_LEAGUE_SUBMITTED = 11 - LEAGUE_AUDIT_ACTION_LEAGUE_SET_PRIZE_POOL = 12 - LEAGUE_AUDIT_ACTION_LEAGUE_ADD_PRIZE_POOL_ITEM = 13 - LEAGUE_AUDIT_ACTION_LEAGUE_REMOVE_PRIZE_POOL_ITEM = 14 - LEAGUE_AUDIT_ACTION_LEAGUE_MATCH_START = 15 - LEAGUE_AUDIT_ACTION_LEAGUE_MATCH_END = 16 - LEAGUE_AUDIT_ACTION_LEAGUE_ADD_INVITED_TEAM = 17 - LEAGUE_AUDIT_ACTION_LEAGUE_REMOVE_INVITED_TEAM = 18 - LEAGUE_AUDIT_ACTION_LEAGUE_STATUS_CHANGED = 19 - LEAGUE_AUDIT_ACTION_LEAGUE_STREAM_EDIT = 20 - LEAGUE_AUDIT_ACTION_LEAGUE_TEAM_SWAP = 21 - LEAGUE_AUDIT_ACTION_NODEGROUP_CREATE = 100 - LEAGUE_AUDIT_ACTION_NODEGROUP_DESTROY = 101 - LEAGUE_AUDIT_ACTION_NODEGROUP_ADD_TEAM = 102 - LEAGUE_AUDIT_ACTION_NODEGROUP_REMOVE_TEAM = 103 - LEAGUE_AUDIT_ACTION_NODEGROUP_SET_ADVANCING = 104 - LEAGUE_AUDIT_ACTION_NODEGROUP_EDIT = 105 - LEAGUE_AUDIT_ACTION_NODEGROUP_POPULATE = 106 - LEAGUE_AUDIT_ACTION_NODEGROUP_COMPLETED = 107 - LEAGUE_AUDIT_ACTION_NODEGROUP_SET_SECONDARY_ADVANCING = 108 - LEAGUE_AUDIT_ACTION_NODEGROUP_SET_TERTIARY_ADVANCING = 109 - LEAGUE_AUDIT_ACTION_NODE_CREATE = 200 - LEAGUE_AUDIT_ACTION_NODE_DESTROY = 201 - LEAGUE_AUDIT_ACTION_NODE_AUTOCREATE = 202 - LEAGUE_AUDIT_ACTION_NODE_SET_TEAM = 203 - LEAGUE_AUDIT_ACTION_NODE_SET_SERIES_ID = 204 - LEAGUE_AUDIT_ACTION_NODE_SET_ADVANCING = 205 - LEAGUE_AUDIT_ACTION_NODE_SET_TIME = 206 - LEAGUE_AUDIT_ACTION_NODE_MATCH_COMPLETED = 207 - LEAGUE_AUDIT_ACTION_NODE_COMPLETED = 208 - LEAGUE_AUDIT_ACTION_NODE_EDIT = 209 - - -class DOTA_COMBATLOG_TYPES(betterproto.Enum): - DOTA_COMBATLOG_INVALID = -1 - DOTA_COMBATLOG_DAMAGE = 0 - DOTA_COMBATLOG_HEAL = 1 - DOTA_COMBATLOG_MODIFIER_ADD = 2 - DOTA_COMBATLOG_MODIFIER_REMOVE = 3 - DOTA_COMBATLOG_DEATH = 4 - DOTA_COMBATLOG_ABILITY = 5 - DOTA_COMBATLOG_ITEM = 6 - DOTA_COMBATLOG_LOCATION = 7 - DOTA_COMBATLOG_GOLD = 8 - DOTA_COMBATLOG_GAME_STATE = 9 - DOTA_COMBATLOG_XP = 10 - DOTA_COMBATLOG_PURCHASE = 11 - DOTA_COMBATLOG_BUYBACK = 12 - DOTA_COMBATLOG_ABILITY_TRIGGER = 13 - DOTA_COMBATLOG_PLAYERSTATS = 14 - DOTA_COMBATLOG_MULTIKILL = 15 - DOTA_COMBATLOG_KILLSTREAK = 16 - DOTA_COMBATLOG_TEAM_BUILDING_KILL = 17 - DOTA_COMBATLOG_FIRST_BLOOD = 18 - DOTA_COMBATLOG_MODIFIER_STACK_EVENT = 19 - DOTA_COMBATLOG_NEUTRAL_CAMP_STACK = 20 - DOTA_COMBATLOG_PICKUP_RUNE = 21 - DOTA_COMBATLOG_REVEALED_INVISIBLE = 22 - DOTA_COMBATLOG_HERO_SAVED = 23 - DOTA_COMBATLOG_MANA_RESTORED = 24 - DOTA_COMBATLOG_HERO_LEVELUP = 25 - DOTA_COMBATLOG_BOTTLE_HEAL_ALLY = 26 - DOTA_COMBATLOG_ENDGAME_STATS = 27 - DOTA_COMBATLOG_INTERRUPT_CHANNEL = 28 - DOTA_COMBATLOG_ALLIED_GOLD = 29 - DOTA_COMBATLOG_AEGIS_TAKEN = 30 - DOTA_COMBATLOG_MANA_DAMAGE = 31 - DOTA_COMBATLOG_PHYSICAL_DAMAGE_PREVENTED = 32 - DOTA_COMBATLOG_UNIT_SUMMONED = 33 - DOTA_COMBATLOG_ATTACK_EVADE = 34 - DOTA_COMBATLOG_TREE_CUT = 35 - DOTA_COMBATLOG_SUCCESSFUL_SCAN = 36 - DOTA_COMBATLOG_END_KILLSTREAK = 37 - DOTA_COMBATLOG_BLOODSTONE_CHARGE = 38 - DOTA_COMBATLOG_CRITICAL_DAMAGE = 39 - DOTA_COMBATLOG_SPELL_ABSORB = 40 - DOTA_COMBATLOG_UNIT_TELEPORTED = 41 - DOTA_COMBATLOG_KILL_EATER_EVENT = 42 - DOTA_COMBATLOG_NEUTRAL_ITEM_EARNED = 43 + INVALID = 0 + LEAGUE_CREATE = 1 + LEAGUE_EDIT = 2 + LEAGUE_DELETE = 3 + LEAGUE_ADMIN_ADD = 4 + LEAGUE_ADMIN_REVOKE = 5 + LEAGUE_ADMIN_PROMOTE = 6 + LEAGUE_STREAM_ADD = 7 + LEAGUE_STREAM_REMOVE = 8 + LEAGUE_IMAGE_UPDATED = 9 + LEAGUE_MESSAGE_ADDED = 10 + LEAGUE_SUBMITTED = 11 + LEAGUE_SET_PRIZE_POOL = 12 + LEAGUE_ADD_PRIZE_POOL_ITEM = 13 + LEAGUE_REMOVE_PRIZE_POOL_ITEM = 14 + LEAGUE_MATCH_START = 15 + LEAGUE_MATCH_END = 16 + LEAGUE_ADD_INVITED_TEAM = 17 + LEAGUE_REMOVE_INVITED_TEAM = 18 + LEAGUE_STATUS_CHANGED = 19 + LEAGUE_STREAM_EDIT = 20 + LEAGUE_TEAM_SWAP = 21 + NODEGROUP_CREATE = 100 + NODEGROUP_DESTROY = 101 + NODEGROUP_ADD_TEAM = 102 + NODEGROUP_REMOVE_TEAM = 103 + NODEGROUP_SET_ADVANCING = 104 + NODEGROUP_EDIT = 105 + NODEGROUP_POPULATE = 106 + NODEGROUP_COMPLETED = 107 + NODEGROUP_SET_SECONDARY_ADVANCING = 108 + NODEGROUP_SET_TERTIARY_ADVANCING = 109 + NODE_CREATE = 200 + NODE_DESTROY = 201 + NODE_AUTOCREATE = 202 + NODE_SET_TEAM = 203 + NODE_SET_SERIES_ID = 204 + NODE_SET_ADVANCING = 205 + NODE_SET_TIME = 206 + NODE_MATCH_COMPLETED = 207 + NODE_COMPLETED = 208 + NODE_EDIT = 209 + + +class DOTACombatLogTypes(betterproto.Enum): + INVALID = -1 + DAMAGE = 0 + HEAL = 1 + MODIFIER_ADD = 2 + MODIFIER_REMOVE = 3 + DEATH = 4 + ABILITY = 5 + ITEM = 6 + LOCATION = 7 + GOLD = 8 + GAME_STATE = 9 + XP = 10 + PURCHASE = 11 + BUYBACK = 12 + ABILITY_TRIGGER = 13 + PLAYERSTATS = 14 + MULTIKILL = 15 + KILLSTREAK = 16 + TEAM_BUILDING_KILL = 17 + FIRST_BLOOD = 18 + MODIFIER_STACK_EVENT = 19 + NEUTRAL_CAMP_STACK = 20 + PICKUP_RUNE = 21 + REVEALED_INVISIBLE = 22 + HERO_SAVED = 23 + MANA_RESTORED = 24 + HERO_LEVELUP = 25 + BOTTLE_HEAL_ALLY = 26 + ENDGAME_STATS = 27 + INTERRUPT_CHANNEL = 28 + ALLIED_GOLD = 29 + AEGIS_TAKEN = 30 + MANA_DAMAGE = 31 + PHYSICAL_DAMAGE_PREVENTED = 32 + UNIT_SUMMONED = 33 + ATTACK_EVADE = 34 + TREE_CUT = 35 + SUCCESSFUL_SCAN = 36 + END_KILLSTREAK = 37 + BLOODSTONE_CHARGE = 38 + CRITICAL_DAMAGE = 39 + SPELL_ABSORB = 40 + UNIT_TELEPORTED = 41 + KILL_EATER_EVENT = 42 + NEUTRAL_ITEM_EARNED = 43 class EDPCFavoriteType(betterproto.Enum): - FAVORITE_TYPE_ALL = 0 - FAVORITE_TYPE_PLAYER = 1 - FAVORITE_TYPE_TEAM = 2 - FAVORITE_TYPE_LEAGUE = 3 + ALL = 0 + PLAYER = 1 + TEAM = 2 + LEAGUE = 3 class EDPCPushNotification(betterproto.Enum): - DPC_PUSH_NOTIFICATION_MATCH_STARTING = 1 - DPC_PUSH_NOTIFICATION_PLAYER_LEFT_TEAM = 10 - DPC_PUSH_NOTIFICATION_PLAYER_JOINED_TEAM = 11 - DPC_PUSH_NOTIFICATION_PLAYER_JOINED_TEAM_AS_COACH = 12 - DPC_PUSH_NOTIFICATION_PLAYER_LEFT_TEAM_AS_COACH = 13 - DPC_PUSH_NOTIFICATION_LEAGUE_RESULT = 20 - DPC_PUSH_NOTIFICATION_PREDICTION_MATCHES_AVAILABLE = 30 - DPC_PUSH_NOTIFICATION_PREDICTION_RESULT = 31 - DPC_PUSH_NOTIFICATION_FANTASY_PLAYER_CLEARED = 40 - DPC_PUSH_NOTIFICATION_FANTASY_DAILY_SUMMARY = 41 - DPC_PUSH_NOTIFICATION_FANTASY_FINAL_RESULTS = 42 + MATCH_STARTING = 1 + PLAYER_LEFT_TEAM = 10 + PLAYER_JOINED_TEAM = 11 + PLAYER_JOINED_TEAM_AS_COACH = 12 + PLAYER_LEFT_TEAM_AS_COACH = 13 + LEAGUE_RESULT = 20 + PREDICTION_MATCHES_AVAILABLE = 30 + PREDICTION_RESULT = 31 + FANTASY_PLAYER_CLEARED = 40 + FANTASY_DAILY_SUMMARY = 41 + FANTASY_FINAL_RESULTS = 42 class EEventActionScoreMode(betterproto.Enum): - k_eEventActionScoreMode_Add = 0 - k_eEventActionScoreMode_Min = 1 + Add = 0 + Min = 1 class EPlayerChallengeHistoryType(betterproto.Enum): - k_EPlayerChallengeHistoryType_Invalid = 0 - k_EPlayerChallengeHistoryType_KillEater = 1 - k_EPlayerChallengeHistoryType_DotaPlusRelic = 2 - k_EPlayerChallengeHistoryType_DotaPlusHeroPlayerChallenge = 3 - k_EPlayerChallengeHistoryType_InGameEventChallenge = 4 - k_EPlayerChallengeHistoryType_GuildContract = 5 + Invalid = 0 + KillEater = 1 + DotaPlusRelic = 2 + DotaPlusHeroPlayerChallenge = 3 + InGameEventChallenge = 4 + GuildContract = 5 class EOverwatchReportReason(betterproto.Enum): - k_EOverwatchReportReason_Unknown = 0 - k_EOverwatchReportReason_Cheating = 1 - k_EOverwatchReportReason_Feeding = 2 - k_EOverwatchReportReason_Griefing = 3 - k_EOverwatchReportReason_Suspicious = 4 - k_EOverwatchReportReason_AbilityAbuse = 5 + Unknown = 0 + Cheating = 1 + Feeding = 2 + Griefing = 3 + Suspicious = 4 + AbilityAbuse = 5 @dataclass @@ -722,7 +722,7 @@ class CDOTASaveGame(betterproto.Message): @dataclass class CDOTASaveGamePlayer(betterproto.Message): - team: DOTA_GC_TEAM = betterproto.enum_field(1) + team: DOTAGCTeam = betterproto.enum_field(1) name: str = betterproto.string_field(2) hero: str = betterproto.string_field(3) @@ -745,7 +745,7 @@ class CDOTASaveGameSaveInstancePlayerPositions(betterproto.Message): @dataclass class CMsgDOTACombatLogEntry(betterproto.Message): - type: DOTA_COMBATLOG_TYPES = betterproto.enum_field(1) + type: DOTACombatLogTypes = betterproto.enum_field(1) target_name: int = betterproto.uint32_field(2) target_source_name: int = betterproto.uint32_field(3) attacker_name: int = betterproto.uint32_field(4) diff --git a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py index 69c3fea0..508f1eb2 100644 --- a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py +++ b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py @@ -13,28 +13,27 @@ if TYPE_CHECKING: from .steammessages import CGCSystemMsg_GetAccountDetails_Response - from .steammessages_steamlearn.steamworkssdk import CMsgSteamLearnHMACKeys class ESourceEngine(betterproto.Enum): - k_ESE_Source1 = 0 - k_ESE_Source2 = 1 + Source1 = 0 + Source2 = 1 class PartnerAccountType(betterproto.Enum): - PARTNER_NONE = 0 - PARTNER_PERFECT_WORLD = 1 - PARTNER_INVALID = 3 + NONE = 0 + PERFECT_WORLD = 1 + INVALID = 3 class GCConnectionStatus(betterproto.Enum): - GCConnectionStatus_HAVE_SESSION = 0 - GCConnectionStatus_GC_GOING_DOWN = 1 - GCConnectionStatus_NO_SESSION = 2 - GCConnectionStatus_NO_SESSION_IN_LOGON_QUEUE = 3 - GCConnectionStatus_NO_STEAM = 4 - GCConnectionStatus_SUSPENDED = 5 - GCConnectionStatus_STEAM_GOING_DOWN = 6 + HAVE_SESSION = 0 + GC_GOING_DOWN = 1 + NO_SESSION = 2 + NO_SESSION_IN_LOGON_QUEUE = 3 + NO_STEAM = 4 + SUSPENDED = 5 + STEAM_GOING_DOWN = 6 @dataclass @@ -246,7 +245,7 @@ class CMsgSOCacheHaveVersion(betterproto.Message): cached_file_version: int = betterproto.uint32_field(4) -class CMsgClientHello(GCProtobufMessage, msg=EGCBaseClientMsg.k_EMsgGCClientHello): +class CMsgClientHello(GCProtobufMessage, msg=EGCBaseClientMsg.GCClientHello): version: int = betterproto.uint32_field(1) socache_have_versions: list[CMsgSOCacheHaveVersion] = betterproto.message_field(2) client_session_need: int = betterproto.uint32_field(3) diff --git a/steam/ext/dota2/protobufs/gcsystemmsgs.py b/steam/ext/dota2/protobufs/gcsystemmsgs.py index ef2e7921..871f5cd1 100644 --- a/steam/ext/dota2/protobufs/gcsystemmsgs.py +++ b/steam/ext/dota2/protobufs/gcsystemmsgs.py @@ -6,27 +6,27 @@ class ESOMsg(betterproto.Enum): - k_ESOMsg_Create = 21 - k_ESOMsg_Update = 22 - k_ESOMsg_Destroy = 23 - k_ESOMsg_CacheSubscribed = 24 - k_ESOMsg_CacheUnsubscribed = 25 - k_ESOMsg_UpdateMultiple = 26 - k_ESOMsg_CacheSubscriptionRefresh = 28 - k_ESOMsg_CacheSubscribedUpToDate = 29 + Create = 21 + Update = 22 + Destroy = 23 + CacheSubscribed = 24 + CacheUnsubscribed = 25 + UpdateMultiple = 26 + CacheSubscriptionRefresh = 28 + CacheSubscribedUpToDate = 29 class EGCBaseClientMsg(betterproto.Enum): - k_EMsgGCPingRequest = 3001 - k_EMsgGCPingResponse = 3002 - k_EMsgGCToClientPollConvarRequest = 3003 - k_EMsgGCToClientPollConvarResponse = 3004 - k_EMsgGCCompressedMsgToClient = 3005 - k_EMsgGCCompressedMsgToClient_Legacy = 523 - k_EMsgGCToClientRequestDropped = 3006 - k_EMsgGCClientWelcome = 4004 - k_EMsgGCServerWelcome = 4005 - k_EMsgGCClientHello = 4006 - k_EMsgGCServerHello = 4007 - k_EMsgGCClientConnectionStatus = 4009 - k_EMsgGCServerConnectionStatus = 4010 + GCPingRequest = 3001 + GCPingResponse = 3002 + GCToClientPollConvarRequest = 3003 + GCToClientPollConvarResponse = 3004 + GCCompressedMsgToClient = 3005 + GCCompressedMsgToClient_Legacy = 523 + GCToClientRequestDropped = 3006 + GCClientWelcome = 4004 + GCServerWelcome = 4005 + GCClientHello = 4006 + GCServerHello = 4007 + GCClientConnectionStatus = 4009 + GCServerConnectionStatus = 4010 diff --git a/steam/ext/dota2/protobufs/steammessages.py b/steam/ext/dota2/protobufs/steammessages.py index e04b2575..da0bb776 100644 --- a/steam/ext/dota2/protobufs/steammessages.py +++ b/steam/ext/dota2/protobufs/steammessages.py @@ -9,21 +9,21 @@ class EGCPlatform(betterproto.Enum): - k_eGCPlatform_None = 0 - k_eGCPlatform_PC = 1 - k_eGCPlatform_Mac = 2 - k_eGCPlatform_Linux = 3 - k_eGCPlatform_Android = 4 - k_eGCPlatform_iOS = 5 + NONE = 0 + PC = 1 + Mac = 2 + Linux = 3 + Android = 4 + iOS = 5 class GCProtoBufMsgSrc(betterproto.Enum): - GCProtoBufMsgSrc_Unspecified = 0 - GCProtoBufMsgSrc_FromSystem = 1 - GCProtoBufMsgSrc_FromSteamID = 2 - GCProtoBufMsgSrc_FromGC = 3 - GCProtoBufMsgSrc_ReplySystem = 4 - GCProtoBufMsgSrc_SpoofedSteamID = 5 + Unspecified = 0 + FromSystem = 1 + FromSteamID = 2 + FromGC = 3 + ReplySystem = 4 + SpoofedSteamID = 5 @dataclass From 494bd5cafe88472715593466b1f99d28e03a7429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 01:26:39 +0300 Subject: [PATCH 12/50] =?UTF-8?q?=F0=9F=AA=93=20Total=20Overhaul=20of=20th?= =?UTF-8?q?e=20PR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 161 +- steam/ext/dota2/enums.py | 1191 +++++++++++ steam/ext/dota2/models.py | 196 ++ steam/ext/dota2/protobufs/__init__.py | 9 +- steam/ext/dota2/protobufs/client_messages.py | 14 + steam/ext/dota2/protobufs/common.py | 101 + .../protobufs/dota_gcmessages_client_watch.py | 246 --- .../dota2/protobufs/dota_gcmessages_common.py | 1838 ----------------- .../dota2/protobufs/dota_gcmessages_msgid.py | 896 -------- .../ext/dota2/protobufs/dota_shared_enums.py | 836 -------- steam/ext/dota2/protobufs/gcsdk_gcmessages.py | 573 ----- steam/ext/dota2/protobufs/gcsystemmsgs.py | 32 - steam/ext/dota2/protobufs/lobby.py | 50 + steam/ext/dota2/protobufs/sdk.py | 66 + steam/ext/dota2/protobufs/shared_enums.py | 81 + steam/ext/dota2/protobufs/steammessages.py | 102 - steam/ext/dota2/protobufs/watch.py | 76 + steam/ext/dota2/state.py | 11 +- tests/unit/test_ext_dota2.py | 5 + 19 files changed, 1908 insertions(+), 4576 deletions(-) create mode 100644 steam/ext/dota2/enums.py create mode 100644 steam/ext/dota2/models.py create mode 100644 steam/ext/dota2/protobufs/client_messages.py create mode 100644 steam/ext/dota2/protobufs/common.py delete mode 100644 steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py delete mode 100644 steam/ext/dota2/protobufs/dota_gcmessages_common.py delete mode 100644 steam/ext/dota2/protobufs/dota_gcmessages_msgid.py delete mode 100644 steam/ext/dota2/protobufs/dota_shared_enums.py delete mode 100644 steam/ext/dota2/protobufs/gcsdk_gcmessages.py delete mode 100644 steam/ext/dota2/protobufs/gcsystemmsgs.py create mode 100644 steam/ext/dota2/protobufs/lobby.py create mode 100644 steam/ext/dota2/protobufs/sdk.py create mode 100644 steam/ext/dota2/protobufs/shared_enums.py delete mode 100644 steam/ext/dota2/protobufs/steammessages.py create mode 100644 steam/ext/dota2/protobufs/watch.py create mode 100644 tests/unit/test_ext_dota2.py diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 36f400c7..ffa3b933 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -3,18 +3,21 @@ from __future__ import annotations import asyncio -from typing import Final, Literal +from functools import partial +from typing import Final from ..._const import timeout from ..._gc import Client as Client_ from ...app import DOTA2 from ...ext import commands from ...utils import MISSING -from .protobufs.dota_gcmessages_client_watch import ( +from .models import LiveMatch +from .protobufs.watch import ( CMsgClientToGCFindTopSourceTVGames, CMsgGCToClientFindTopSourceTVGamesResponse, ) from .state import GCState # noqa: TCH001 +from .enums import Hero __all__ = ( "Client", @@ -33,80 +36,136 @@ class Client(Client_): _APP: Final = DOTA2 _state: GCState # type: ignore # PEP 705 - async def top_source_tv_games( + async def top_live_matches( self, - *, - search_key: str = MISSING, - league_id: int = MISSING, - hero_id: int = MISSING, - start_game: Literal[0, 10, 20, 30, 40, 50, 60, 70, 80, 90] = 0, - game_list_index: int = MISSING, - lobby_ids: list[int] = MISSING, - ) -> list[CMsgGCToClientFindTopSourceTVGamesResponse]: - """Fetch Top Source TV Games. - - This functionality is similar to game list in the Watch Tab of Dota 2 game application. - It fetches summary data for the currently on-going Dota 2 matches from the following categories: - - * tournament games - * highest average mmr games - * specific lobbies, like friends' games by their lobby_ids - - Note - ------- - Note that the following documentation for keyword arguments to query against is rather observant - than from official. So, please, if you know more or description is incorrect, contact us. + hero: Hero = MISSING, + max_matches: int = 100, + ) -> list[LiveMatch]: + """Fetch top live matches + + This is similar to game list in the Watch Tab of Dota 2 game app. + "Top matches" in this context means + + * tournament matches + * highest average MMR matches Parameters ---------- - league_id - The league ID for the professional tournament. hero_id - `hero_id` to filter results by which can be found in the client Watch Tab feature. - start_game - This argument controls how many responses the game coordinator should return. - For example, `start_game=0` returns a list with 1 Response, - `start_game=90` returns a list of 10 Responses. - The GC fills each response in consequent manner with games that satisfy keyword arguments - or with currently live highest average MMR games in case no other argument was given. - game_list_index - Only get responses matching `game_list_index`. Responses from GC change - from time to time. The `game_list_index` indicates that those responses belong to the same chunk. - lobby_ids - The lobby IDs of the games to fetch. + Filter matches by Hero. + Note, in this case Game Coordinator will still use only current top100 live matches, i.e. requesting + "filter by Muerta" will return only subset of those matches in which Muerta is currently being played. + It will not look into lower MMR games than top100. + max_matches + Maximum amount of matches to be fetched. Returns ------- - The responses from the GC. They are grouped into grouped into chunks of 10. games. + List of currently live top matches. Raises ------ + ValueError + `max_games` value should be between 1 and 100 inclusively. asyncio.TimeoutError - Request time-outed. The reason for this might be inappropriate combination of keyword arguments, - inappropriate argument values or simply Dota 2 Game Coordinator being down. + Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ - kwargs = locals() - kwargs.pop("self") - kwargs = {key: value for key, value in kwargs.items() if value is not MISSING} - def start_game_check(start_game: int): - def predicate(msg: CMsgGCToClientFindTopSourceTVGamesResponse) -> bool: - return msg.start_game == start_game + if max_matches < 1 or 100 < max_matches: + raise ValueError("max_games value should be between 1 and 100.") + + # mini-math: max_matches 100 -> start_game 90, 91 -> 90, 90 -> 80 + start_game = (max_matches - 1) // 10 * 10 - return predicate + def callback(start_game: int, msg: CMsgGCToClientFindTopSourceTVGamesResponse) -> bool: + return msg.start_game == start_game futures = [ self._state.ws.gc_wait_for( CMsgGCToClientFindTopSourceTVGamesResponse, - check=partial(lambda start_game, msg: msg.start_game == start_game, start_game), + check=partial(callback, start_game), ) for start_game in range(0, start_game + 1, 10) ] - await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(**kwargs)) + if hero is MISSING: + await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(start_game=start_game)) + else: + await self._state.ws.send_gc_message( + CMsgClientToGCFindTopSourceTVGames(start_game=start_game, hero_id=hero.value) + ) + + async with timeout(30.0): + responses = await asyncio.gather(*futures) + live_matches = [ + LiveMatch(self._state, match_info) for response in responses for match_info in response.game_list + ] + # still need to slice the list, i.e. in case user asks for 85 games, but live_matches above will have 90 matches + return live_matches[:max_matches] + + async def tournament_live_games( + self, + # todo: league_id as integer is not human-readable/gettable thing, introduce methods to easily find those + league_id: int, + ) -> list[LiveMatch]: + """Fetch currently live tournament matches + + Parameters + ---------- + league_id + Tournament league_id + + Returns + ------- + List of currently live tournament matches. + + Raises + ------ + asyncio.TimeoutError + Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. + """ + + future = self._state.ws.gc_wait_for( + CMsgGCToClientFindTopSourceTVGamesResponse, + check=lambda msg: msg.league_id == league_id, + ) + await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(league_id=league_id)) + + async with timeout(30.0): + response = await future + return [LiveMatch(self._state, match_info) for match_info in response.game_list] + + async def live_matches( + self, + # todo: lobby_ids is not easy to get by the user. Introduce methods to get it, i.e. from Rich Presence + lobby_ids: list[int], + ) -> list[LiveMatch]: + """Fetch currently live matches by lobby_ids + + Parameters + ---------- + lobby_ids + Lobby IDs + + Returns + ------- + List of live matches. + + Raises + ------ + asyncio.TimeoutError + Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. + """ + future = self._state.ws.gc_wait_for( + CMsgGCToClientFindTopSourceTVGamesResponse, + check=lambda msg: msg.specific_games == True, + ) + await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(lobby_ids=lobby_ids)) async with timeout(30.0): - return await asyncio.gather(*futures) + response = await future + # todo: test with more than 10 lobby_ids, Game Coordinator will probably chunk it wrongly or fail at all + return [LiveMatch(self._state, match_info) for match_info in response.game_list] class Bot(commands.Bot, Client): diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py new file mode 100644 index 00000000..42624239 --- /dev/null +++ b/steam/ext/dota2/enums.py @@ -0,0 +1,1191 @@ +"""Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from ...enums import IntEnum, classproperty + +if TYPE_CHECKING: + from collections.abc import Mapping + + from typing_extensions import Self + + +# fmt: off +class Hero(IntEnum): + """Enum representing Dota 2 hero. + + Primarily, mapping hero_id to hero name. + """ + NONE = 0 + AntiMage = 1 + Axe = 2 + Bane = 3 + Bloodseeker = 4 + CrystalMaiden = 5 + DrowRanger = 6 + Earthshaker = 7 + Juggernaut = 8 + Mirana = 9 + Morphling = 10 + ShadowFiend = 11 + PhantomLancer = 12 + Puck = 13 + Pudge = 14 + Razor = 15 + SandKing = 16 + StormSpirit = 17 + Sven = 18 + Tiny = 19 + VengefulSpirit = 20 + Windranger = 21 + Zeus = 22 + Kunkka = 23 + Lina = 25 + Lion = 26 + ShadowShaman = 27 + Slardar = 28 + Tidehunter = 29 + WitchDoctor = 30 + Lich = 31 + Riki = 32 + Enigma = 33 + Tinker = 34 + Sniper = 35 + Necrophos = 36 + Warlock = 37 + Beastmaster = 38 + QueenOfPain = 39 + Venomancer = 40 + FacelessVoid = 41 + WraithKing = 42 + DeathProphet = 43 + PhantomAssassin = 44 + Pugna = 45 + TemplarAssassin = 46 + Viper = 47 + Luna = 48 + DragonKnight = 49 + Dazzle = 50 + Clockwerk = 51 + Leshrac = 52 + NaturesProphet = 53 + Lifestealer = 54 + DarkSeer = 55 + Clinkz = 56 + Omniknight = 57 + Enchantress = 58 + Huskar = 59 + NightStalker = 60 + Broodmother = 61 + BountyHunter = 62 + Weaver = 63 + Jakiro = 64 + Batrider = 65 + Chen = 66 + Spectre = 67 + AncientApparition = 68 + Doom = 69 + Ursa = 70 + SpiritBreaker = 71 + Gyrocopter = 72 + Alchemist = 73 + Invoker = 74 + Silencer = 75 + OutworldDevourer = 76 + Lycan = 77 + Brewmaster = 78 + ShadowDemon = 79 + LoneDruid = 80 + ChaosKnight = 81 + Meepo = 82 + TreantProtector = 83 + OgreMagi = 84 + Undying = 85 + Rubick = 86 + Disruptor = 87 + NyxAssassin = 88 + NagaSiren = 89 + KeeperOfTheLight = 90 + Io = 91 + Visage = 92 + Slark = 93 + Medusa = 94 + TrollWarlord = 95 + CentaurWarrunner = 96 + Magnus = 97 + Timbersaw = 98 + Bristleback = 99 + Tusk = 100 + SkywrathMage = 101 + Abaddon = 102 + ElderTitan = 103 + LegionCommander = 104 + Techies = 105 + EmberSpirit = 106 + EarthSpirit = 107 + Underlord = 108 + Terrorblade = 109 + Phoenix = 110 + Oracle = 111 + WinterWyvern = 112 + ArcWarden = 113 + MonkeyKing = 114 + DarkWillow = 119 + Pangolier = 120 + Grimstroke = 121 + Hoodwink = 123 + VoidSpirit = 126 + Snapfire = 128 + Mars = 129 + Dawnbreaker = 135 + Marci = 136 + PrimalBeast = 137 + Muerta = 138 + + @classproperty + def DISPLAY_NAMES(cls: type[Self]) -> Mapping[Hero, str]: # type: ignore + return { + cls.NONE : "None", # happens when player disconnects or hasn't picked yet. + cls.AntiMage : "Anti-Mage", + cls.Axe : "Axe", + cls.Bane : "Bane", + cls.Bloodseeker : "Bloodseeker", + cls.CrystalMaiden : "Crystal Maiden", + cls.DrowRanger : "Drow Ranger", + cls.Earthshaker : "Earthshaker", + cls.Juggernaut : "Juggernaut", + cls.Mirana : "Mirana", + cls.Morphling : "Morphling", + cls.ShadowFiend : "Shadow Fiend", + cls.PhantomLancer : "Phantom Lancer", + cls.Puck : "Puck", + cls.Pudge : "Pudge", + cls.Razor : "Razor", + cls.SandKing : "Sand King", + cls.StormSpirit : "Storm Spirit", + cls.Sven : "Sven", + cls.Tiny : "Tiny", + cls.VengefulSpirit : "Vengeful Spirit", + cls.Windranger : "Windranger", + cls.Zeus : "Zeus", + cls.Kunkka : "Kunkka", + cls.Lina : "Lina", + cls.Lion : "Lion", + cls.ShadowShaman : "Shadow Shaman", + cls.Slardar : "Slardar", + cls.Tidehunter : "Tidehunter", + cls.WitchDoctor : "Witch Doctor", + cls.Lich : "Lich", + cls.Riki : "Riki", + cls.Enigma : "Enigma", + cls.Tinker : "Tinker", + cls.Sniper : "Sniper", + cls.Necrophos : "Necrophos", + cls.Warlock : "Warlock", + cls.Beastmaster : "Beastmaster", + cls.QueenOfPain : "Queen of Pain", + cls.Venomancer : "Venomancer", + cls.FacelessVoid : "Faceless Void", + cls.WraithKing : "Wraith King", + cls.DeathProphet : "Death Prophet", + cls.PhantomAssassin : "Phantom Assassin", + cls.Pugna : "Pugna", + cls.TemplarAssassin : "Templar Assassin", + cls.Viper : "Viper", + cls.Luna : "Luna", + cls.DragonKnight : "Dragon Knight", + cls.Dazzle : "Dazzle", + cls.Clockwerk : "Clockwerk", + cls.Leshrac : "Leshrac", + cls.NaturesProphet : "Nature's Prophet", + cls.Lifestealer : "Lifestealer", + cls.DarkSeer : "Dark Seer", + cls.Clinkz : "Clinkz", + cls.Omniknight : "Omniknight", + cls.Enchantress : "Enchantress", + cls.Huskar : "Huskar", + cls.NightStalker : "Night Stalker", + cls.Broodmother : "Broodmother", + cls.BountyHunter : "Bounty Hunter", + cls.Weaver : "Weaver", + cls.Jakiro : "Jakiro", + cls.Batrider : "Batrider", + cls.Chen : "Chen", + cls.Spectre : "Spectre", + cls.AncientApparition: "Ancient Apparition", + cls.Doom : "Doom", + cls.Ursa : "Ursa", + cls.SpiritBreaker : "Spirit Breaker", + cls.Gyrocopter : "Gyrocopter", + cls.Alchemist : "Alchemist", + cls.Invoker : "Invoker", + cls.Silencer : "Silencer", + cls.OutworldDevourer : "Outworld Devourer", + cls.Lycan : "Lycan", + cls.Brewmaster : "Brewmaster", + cls.ShadowDemon : "Shadow Demon", + cls.LoneDruid : "Lone Druid", + cls.ChaosKnight : "Chaos Knight", + cls.Meepo : "Meepo", + cls.TreantProtector : "Treant Protector", + cls.OgreMagi : "Ogre Magi", + cls.Undying : "Undying", + cls.Rubick : "Rubick", + cls.Disruptor : "Disruptor", + cls.NyxAssassin : "Nyx Assassin", + cls.NagaSiren : "Naga Siren", + cls.KeeperOfTheLight : "Keeper of the Light", + cls.Io : "Io", + cls.Visage : "Visage", + cls.Slark : "Slark", + cls.Medusa : "Medusa", + cls.TrollWarlord : "Troll Warlord", + cls.CentaurWarrunner : "Centaur Warrunner", + cls.Magnus : "Magnus", + cls.Timbersaw : "Timbersaw", + cls.Bristleback : "Bristleback", + cls.Tusk : "Tusk", + cls.SkywrathMage : "Skywrath Mage", + cls.Abaddon : "Abaddon", + cls.ElderTitan : "Elder Titan", + cls.LegionCommander : "Legion Commander", + cls.Techies : "Techies", + cls.EmberSpirit : "Ember Spirit", + cls.EarthSpirit : "Earth Spirit", + cls.Underlord : "Underlord", + cls.Terrorblade : "Terrorblade", + cls.Phoenix : "Phoenix", + cls.Oracle : "Oracle", + cls.WinterWyvern : "Winter Wyvern", + cls.ArcWarden : "Arc Warden", + cls.MonkeyKing : "Monkey King", + cls.DarkWillow : "Dark Willow", + cls.Pangolier : "Pangolier", + cls.Grimstroke : "Grimstroke", + cls.Hoodwink : "Hoodwink", + cls.VoidSpirit : "Void Spirit", + cls.Snapfire : "Snapfire", + cls.Mars : "Mars", + cls.Dawnbreaker : "Dawnbreaker", + cls.Marci : "Marci", + cls.PrimalBeast : "Primal Beast", + cls.Muerta : "Muerta", + } + + @property + def display_name(self) -> str: + return self.DISPLAY_NAMES[self] + + @property + def hero_id(self) -> int: + return self.value + + +class EMsg(IntEnum): + # EGCBaseClientMsg - gcsystemmsgs.proto + GCPingRequest = 3001 + GCPingResponse = 3002 + GCToClientPollConvarRequest = 3003 + GCToClientPollConvarResponse = 3004 + GCCompressedMsgToClient = 3005 + GCCompressedMsgToClient_Legacy = 523 + GCToClientRequestDropped = 3006 + GCClientWelcome = 4004 + GCServerWelcome = 4005 + GCClientHello = 4006 + GCServerHello = 4007 + GCClientConnectionStatus = 4009 + GCServerConnectionStatus = 4010 + + # EDOTAGCMsg - dota_gcmessages_msgid.proto + GCDOTABase = 7000 + GCGameMatchSignOut = 7004 + GCGameMatchSignOutResponse = 7005 + GCJoinChatChannel = 7009 + GCJoinChatChannelResponse = 7010 + GCOtherJoinedChannel = 7013 + GCOtherLeftChannel = 7014 + ServerToGCRequestStatus = 7026 + GCStartFindingMatch = 7033 + GCConnectedPlayers = 7034 + GCAbandonCurrentGame = 7035 + GCStopFindingMatch = 7036 + GCPracticeLobbyCreate = 7038 + GCPracticeLobbyLeave = 7040 + GCPracticeLobbyLaunch = 7041 + GCPracticeLobbyList = 7042 + GCPracticeLobbyListResponse = 7043 + GCPracticeLobbyJoin = 7044 + GCPracticeLobbySetDetails = 7046 + GCPracticeLobbySetTeamSlot = 7047 + GCInitialQuestionnaireResponse = 7049 + GCPracticeLobbyResponse = 7055 + GCBroadcastNotification = 7056 + GCLiveScoreboardUpdate = 7057 + GCRequestChatChannelList = 7060 + GCRequestChatChannelListResponse = 7061 + GCReadyUp = 7070 + GCKickedFromMatchmakingQueue = 7071 + GCLeaverDetected = 7072 + GCSpectateFriendGame = 7073 + GCSpectateFriendGameResponse = 7074 + GCReportsRemainingRequest = 7076 + GCReportsRemainingResponse = 7077 + GCSubmitPlayerReport = 7078 + GCSubmitPlayerReportResponse = 7079 + GCPracticeLobbyKick = 7081 + GCSubmitPlayerReportV2 = 7082 + GCSubmitPlayerReportResponseV2 = 7083 + GCRequestSaveGames = 7084 + GCRequestSaveGamesServer = 7085 + GCRequestSaveGamesResponse = 7086 + GCLeaverDetectedResponse = 7087 + GCPlayerFailedToConnect = 7088 + GCGCToRelayConnect = 7089 + GCGCToRelayConnectresponse = 7090 + GCWatchGame = 7091 + GCWatchGameResponse = 7092 + GCBanStatusRequest = 7093 + GCBanStatusResponse = 7094 + GCMatchDetailsRequest = 7095 + GCMatchDetailsResponse = 7096 + GCCancelWatchGame = 7097 + GCPopup = 7102 + GCFriendPracticeLobbyListRequest = 7111 + GCFriendPracticeLobbyListResponse = 7112 + GCPracticeLobbyJoinResponse = 7113 + GCCreateTeam = 7115 + GCCreateTeamResponse = 7116 + GCTeamInvite_InviterToGC = 7122 + GCTeamInvite_GCImmediateResponseToInviter = 7123 + GCTeamInvite_GCRequestToInvitee = 7124 + GCTeamInvite_InviteeResponseToGC = 7125 + GCTeamInvite_GCResponseToInviter = 7126 + GCTeamInvite_GCResponseToInvitee = 7127 + GCKickTeamMember = 7128 + GCKickTeamMemberResponse = 7129 + GCLeaveTeam = 7130 + GCLeaveTeamResponse = 7131 + GCApplyTeamToPracticeLobby = 7142 + GCTransferTeamAdmin = 7144 + GCPracticeLobbyJoinBroadcastChannel = 7149 + GC_TournamentItemEvent = 7150 + GC_TournamentItemEventResponse = 7151 + TeamFanfare = 7156 + ResponseTeamFanfare = 7157 + GC_GameServerUploadSaveGame = 7158 + GC_GameServerSaveGameResult = 7159 + GC_GameServerGetLoadGame = 7160 + GC_GameServerGetLoadGameResult = 7161 + GCEditTeamDetails = 7166 + GCEditTeamDetailsResponse = 7167 + GCReadyUpStatus = 7170 + GCToGCMatchCompleted = 7186 + GCBalancedShuffleLobby = 7188 + GCMatchmakingStatsRequest = 7197 + GCMatchmakingStatsResponse = 7198 + GCBotGameCreate = 7199 + GCSetMatchHistoryAccess = 7200 + GCSetMatchHistoryAccessResponse = 7201 + UpgradeLeagueItem = 7203 + UpgradeLeagueItemResponse = 7204 + GCWatchDownloadedReplay = 7206 + ClientsRejoinChatChannels = 7217 + GCToGCGetUserChatInfo = 7218 + GCToGCGetUserChatInfoResponse = 7219 + GCToGCLeaveAllChatChannels = 7220 + GCToGCUpdateAccountChatBan = 7221 + GCToGCCanInviteUserToTeam = 7234 + GCToGCCanInviteUserToTeamResponse = 7235 + GCToGCGetUserRank = 7236 + GCToGCGetUserRankResponse = 7237 + GCToGCAdjustUserRank = 7238 + GCToGCAdjustUserRankResponse = 7239 + GCToGCUpdateTeamStats = 7240 + GCToGCValidateTeam = 7241 + GCToGCValidateTeamResponse = 7242 + GCToGCGetLeagueAdmin = 7255 + GCToGCGetLeagueAdminResponse = 7256 + GCLeaveChatChannel = 7272 + GCChatMessage = 7273 + GCGetHeroStandings = 7274 + GCGetHeroStandingsResponse = 7275 + GCItemEditorReservationsRequest = 7283 + GCItemEditorReservationsResponse = 7284 + GCItemEditorReserveItemDef = 7285 + GCItemEditorReserveItemDefResponse = 7286 + GCItemEditorReleaseReservation = 7287 + GCItemEditorReleaseReservationResponse = 7288 + GCRewardTutorialPrizes = 7289 + GCFantasyLivePlayerStats = 7308 + GCFantasyFinalPlayerStats = 7309 + GCFlipLobbyTeams = 7320 + GCToGCEvaluateReportedPlayer = 7322 + GCToGCEvaluateReportedPlayerResponse = 7323 + GCToGCProcessPlayerReportForTarget = 7324 + GCToGCProcessReportSuccess = 7325 + GCNotifyAccountFlagsChange = 7326 + GCSetProfilePrivacy = 7327 + GCSetProfilePrivacyResponse = 7328 + GCClientSuspended = 7342 + GCPartyMemberSetCoach = 7343 + GCPracticeLobbySetCoach = 7346 + GCChatModeratorBan = 7359 + GCLobbyUpdateBroadcastChannelInfo = 7367 + GCToGCGrantTournamentItem = 7372 + GCToGCUpgradeTwitchViewerItems = 7375 + GCToGCGetLiveMatchAffiliates = 7376 + GCToGCGetLiveMatchAffiliatesResponse = 7377 + GCToGCUpdatePlayerPennantCounts = 7378 + GCToGCGetPlayerPennantCounts = 7379 + GCToGCGetPlayerPennantCountsResponse = 7380 + GCGameMatchSignOutPermissionRequest = 7381 + GCGameMatchSignOutPermissionResponse = 7382 + DOTAAwardEventPoints = 7384 + DOTAGetEventPoints = 7387 + DOTAGetEventPointsResponse = 7388 + GCPartyLeaderWatchGamePrompt = 7397 + GCCompendiumSetSelection = 7405 + GCCompendiumDataRequest = 7406 + GCCompendiumDataResponse = 7407 + DOTAGetPlayerMatchHistory = 7408 + DOTAGetPlayerMatchHistoryResponse = 7409 + GCToGCMatchmakingAddParty = 7410 + GCToGCMatchmakingRemoveParty = 7411 + GCToGCMatchmakingRemoveAllParties = 7412 + GCToGCMatchmakingMatchFound = 7413 + GCToGCUpdateMatchManagementStats = 7414 + GCToGCUpdateMatchmakingStats = 7415 + GCToServerPingRequest = 7416 + GCToServerPingResponse = 7417 + GCToServerEvaluateToxicChat = 7418 + ServerToGCEvaluateToxicChat = 7419 + ServerToGCEvaluateToxicChatResponse = 7420 + GCToGCProcessMatchLeaver = 7426 + GCNotificationsRequest = 7427 + GCNotificationsResponse = 7428 + GCToGCModifyNotification = 7429 + GCLeagueAdminList = 7434 + GCNotificationsMarkReadRequest = 7435 + ServerToGCRequestBatchPlayerResources = 7450 + ServerToGCRequestBatchPlayerResourcesResponse = 7451 + GCCompendiumSetSelectionResponse = 7453 + GCPlayerInfoSubmit = 7456 + GCPlayerInfoSubmitResponse = 7457 + GCToGCGetAccountLevel = 7458 + GCToGCGetAccountLevelResponse = 7459 + DOTAGetWeekendTourneySchedule = 7464 + DOTAWeekendTourneySchedule = 7465 + GCJoinableCustomGameModesRequest = 7466 + GCJoinableCustomGameModesResponse = 7467 + GCJoinableCustomLobbiesRequest = 7468 + GCJoinableCustomLobbiesResponse = 7469 + GCQuickJoinCustomLobby = 7470 + GCQuickJoinCustomLobbyResponse = 7471 + GCToGCGrantEventPointAction = 7472 + GCToGCSetCompendiumSelection = 7478 + GCHasItemQuery = 7484 + GCHasItemResponse = 7485 + GCToGCGrantEventPointActionMsg = 7488 + GCToGCGetCompendiumSelections = 7492 + GCToGCGetCompendiumSelectionsResponse = 7493 + ServerToGCMatchConnectionStats = 7494 + GCToClientTournamentItemDrop = 7495 + SQLDelayedGrantLeagueDrop = 7496 + ServerGCUpdateSpectatorCount = 7497 + GCToGCEmoticonUnlock = 7501 + SignOutDraftInfo = 7502 + ClientToGCEmoticonDataRequest = 7503 + GCToClientEmoticonData = 7504 + GCPracticeLobbyToggleBroadcastChannelCameramanStatus = 7505 + DOTARedeemItem = 7518 + DOTARedeemItemResponse = 7519 + ClientToGCGetAllHeroProgress = 7521 + ClientToGCGetAllHeroProgressResponse = 7522 + GCToGCGetServerForClient = 7523 + GCToGCGetServerForClientResponse = 7524 + SQLProcessTournamentGameOutcome = 7525 + SQLGrantTrophyToAccount = 7526 + ClientToGCGetTrophyList = 7527 + ClientToGCGetTrophyListResponse = 7528 + GCToClientTrophyAwarded = 7529 + GCGameBotMatchSignOut = 7530 + GCGameBotMatchSignOutPermissionRequest = 7531 + SignOutBotInfo = 7532 + GCToGCUpdateProfileCards = 7533 + ClientToGCGetProfileCard = 7534 + ClientToGCGetProfileCardResponse = 7535 + ClientToGCGetBattleReport = 7536 + ClientToGCGetBattleReportResponse = 7537 + ClientToGCSetProfileCardSlots = 7538 + GCToClientProfileCardUpdated = 7539 + ServerToGCVictoryPredictions = 7540 + ClientToGCGetBattleReportAggregateStats = 7541 + ClientToGCGetBattleReportAggregateStatsResponse = 7542 + ClientToGCGetBattleReportInfo = 7543 + ClientToGCGetBattleReportInfoResponse = 7544 + SignOutCommunicationSummary = 7545 + ServerToGCRequestStatus_Response = 7546 + ClientToGCCreateHeroStatue = 7547 + GCToClientHeroStatueCreateResult = 7548 + GCGCToLANServerRelayConnect = 7549 + ClientToGCAcknowledgeBattleReport = 7550 + ClientToGCAcknowledgeBattleReportResponse = 7551 + ClientToGCGetBattleReportMatchHistory = 7552 + ClientToGCGetBattleReportMatchHistoryResponse = 7553 + ServerToGCReportKillSummaries = 7554 + GCToGCUpdatePlayerPredictions = 7561 + GCToServerPredictionResult = 7562 + GCToGCReplayMonitorValidateReplay = 7569 + LobbyEventPoints = 7572 + GCToGCGetCustomGameTickets = 7573 + GCToGCGetCustomGameTicketsResponse = 7574 + GCToGCCustomGamePlayed = 7576 + GCToGCGrantEventPointsToUser = 7577 + GameserverCrashReport = 7579 + GameserverCrashReportResponse = 7580 + GCToClientSteamDatagramTicket = 7581 + GCToGCSendAccountsEventPoints = 7583 + ClientToGCRerollPlayerChallenge = 7584 + ServerToGCRerollPlayerChallenge = 7585 + GCRerollPlayerChallengeResponse = 7586 + SignOutUpdatePlayerChallenge = 7587 + ClientToGCSetPartyLeader = 7588 + ClientToGCCancelPartyInvites = 7589 + SQLGrantLeagueMatchToTicketHolders = 7592 + GCToGCEmoticonUnlockNoRollback = 7594 + ClientToGCApplyGemCombiner = 7603 + ClientToGCGetAllHeroOrder = 7606 + ClientToGCGetAllHeroOrderResponse = 7607 + SQLGCToGCGrantBadgePoints = 7608 + GCToGCCheckOwnsEntireEmoticonRange = 7611 + GCToGCCheckOwnsEntireEmoticonRangeResponse = 7612 + GCToClientRequestLaneSelection = 7623 + GCToClientRequestLaneSelectionResponse = 7624 + ServerToGCCavernCrawlIsHeroActive = 7625 + ServerToGCCavernCrawlIsHeroActiveResponse = 7626 + ClientToGCPlayerCardSpecificPurchaseRequest = 7627 + ClientToGCPlayerCardSpecificPurchaseResponse = 7628 + GCtoServerTensorflowInstance = 7629 + SQLSetIsLeagueAdmin = 7630 + GCToGCGetLiveLeagueMatches = 7631 + GCToGCGetLiveLeagueMatchesResponse = 7632 + DOTALeagueInfoListAdminsRequest = 7633 + DOTALeagueInfoListAdminsReponse = 7634 + GCToGCLeagueMatchStarted = 7645 + GCToGCLeagueMatchCompleted = 7646 + GCToGCLeagueMatchStartedResponse = 7647 + DOTALeagueAvailableLobbyNodesRequest = 7650 + DOTALeagueAvailableLobbyNodes = 7651 + GCToGCLeagueRequest = 7652 + GCToGCLeagueResponse = 7653 + GCToGCLeagueNodeGroupRequest = 7654 + GCToGCLeagueNodeGroupResponse = 7655 + GCToGCLeagueNodeRequest = 7656 + GCToGCLeagueNodeResponse = 7657 + GCToGCRealtimeStatsTerseRequest = 7658 + GCToGCRealtimeStatsTerseResponse = 7659 + GCToGCGetTopMatchesRequest = 7660 + GCToGCGetTopMatchesResponse = 7661 + ClientToGCGetFilteredPlayers = 7662 + GCToClientGetFilteredPlayersResponse = 7663 + ClientToGCRemoveFilteredPlayer = 7664 + GCToClientRemoveFilteredPlayerResponse = 7665 + GCToClientPlayerBeaconState = 7666 + GCToClientPartyBeaconUpdate = 7667 + GCToClientPartySearchInvite = 7668 + ClientToGCUpdatePartyBeacon = 7669 + ClientToGCRequestActiveBeaconParties = 7670 + GCToClientRequestActiveBeaconPartiesResponse = 7671 + ClientToGCManageFavorites = 7672 + GCToClientManageFavoritesResponse = 7673 + ClientToGCJoinPartyFromBeacon = 7674 + GCToClientJoinPartyFromBeaconResponse = 7675 + ClientToGCGetFavoritePlayers = 7676 + GCToClientGetFavoritePlayersResponse = 7677 + ClientToGCVerifyFavoritePlayers = 7678 + GCToClientVerifyFavoritePlayersResponse = 7679 + GCToClientPartySearchInvites = 7680 + GCToClientRequestMMInfo = 7681 + ClientToGCMMInfo = 7682 + SignOutTextMuteInfo = 7683 + ClientToGCPurchaseLabyrinthBlessings = 7684 + ClientToGCPurchaseLabyrinthBlessingsResponse = 7685 + ClientToGCPurchaseFilteredPlayerSlot = 7686 + GCToClientPurchaseFilteredPlayerSlotResponse = 7687 + ClientToGCUpdateFilteredPlayerNote = 7688 + GCToClientUpdateFilteredPlayerNoteResponse = 7689 + ClientToGCClaimSwag = 7690 + GCToClientClaimSwagResponse = 7691 + ServerToGCLockCharmTrading = 8004 + ClientToGCPlayerStatsRequest = 8006 + GCToClientPlayerStatsResponse = 8007 + GCClearPracticeLobbyTeam = 8008 + ClientToGCFindTopSourceTVGames = 8009 + GCToClientFindTopSourceTVGamesResponse = 8010 + GCLobbyList = 8011 + GCLobbyListResponse = 8012 + GCPlayerStatsMatchSignOut = 8013 + ClientToGCSocialFeedPostCommentRequest = 8016 + GCToClientSocialFeedPostCommentResponse = 8017 + ClientToGCCustomGamesFriendsPlayedRequest = 8018 + GCToClientCustomGamesFriendsPlayedResponse = 8019 + ClientToGCFriendsPlayedCustomGameRequest = 8020 + GCToClientFriendsPlayedCustomGameResponse = 8021 + GCTopCustomGamesList = 8024 + ClientToGCSetPartyOpen = 8029 + ClientToGCMergePartyInvite = 8030 + GCToClientMergeGroupInviteReply = 8031 + ClientToGCMergePartyResponse = 8032 + GCToClientMergePartyResponseReply = 8033 + ClientToGCGetProfileCardStats = 8034 + ClientToGCGetProfileCardStatsResponse = 8035 + ClientToGCTopLeagueMatchesRequest = 8036 + ClientToGCTopFriendMatchesRequest = 8037 + GCToClientProfileCardStatsUpdated = 8040 + ServerToGCRealtimeStats = 8041 + GCToServerRealtimeStatsStartStop = 8042 + GCToGCGetServersForClients = 8045 + GCToGCGetServersForClientsResponse = 8046 + GCPracticeLobbyKickFromTeam = 8047 + DOTAChatGetMemberCount = 8048 + DOTAChatGetMemberCountResponse = 8049 + ClientToGCSocialFeedPostMessageRequest = 8050 + GCToClientSocialFeedPostMessageResponse = 8051 + CustomGameListenServerStartedLoading = 8052 + CustomGameClientFinishedLoading = 8053 + GCPracticeLobbyCloseBroadcastChannel = 8054 + GCStartFindingMatchResponse = 8055 + SQLGCToGCGrantAccountFlag = 8057 + GCToClientTopLeagueMatchesResponse = 8061 + GCToClientTopFriendMatchesResponse = 8062 + ClientToGCMatchesMinimalRequest = 8063 + ClientToGCMatchesMinimalResponse = 8064 + GCToClientChatRegionsEnabled = 8067 + ClientToGCPingData = 8068 + GCToGCEnsureAccountInParty = 8071 + GCToGCEnsureAccountInPartyResponse = 8072 + ClientToGCGetProfileTickets = 8073 + ClientToGCGetProfileTicketsResponse = 8074 + GCToClientMatchGroupsVersion = 8075 + ClientToGCH264Unsupported = 8076 + ClientToGCGetQuestProgress = 8078 + ClientToGCGetQuestProgressResponse = 8079 + SignOutXPCoins = 8080 + GCToClientMatchSignedOut = 8081 + GCGetHeroStatsHistory = 8082 + GCGetHeroStatsHistoryResponse = 8083 + ClientToGCPrivateChatInvite = 8084 + ClientToGCPrivateChatKick = 8088 + ClientToGCPrivateChatPromote = 8089 + ClientToGCPrivateChatDemote = 8090 + GCToClientPrivateChatResponse = 8091 + ClientToGCLatestConductScorecardRequest = 8095 + ClientToGCLatestConductScorecard = 8096 + ClientToGCWageringRequest = 8099 + GCToClientWageringResponse = 8100 + ClientToGCEventGoalsRequest = 8103 + ClientToGCEventGoalsResponse = 8104 + GCToGCLeaguePredictionsUpdate = 8108 + GCToGCAddUserToPostGameChat = 8110 + ClientToGCHasPlayerVotedForMVP = 8111 + ClientToGCHasPlayerVotedForMVPResponse = 8112 + ClientToGCVoteForMVP = 8113 + ClientToGCVoteForMVPResponse = 8114 + GCToGCGetEventOwnership = 8115 + GCToGCGetEventOwnershipResponse = 8116 + GCToClientAutomatedTournamentStateChange = 8117 + ClientToGCWeekendTourneyOpts = 8118 + ClientToGCWeekendTourneyOptsResponse = 8119 + ClientToGCWeekendTourneyLeave = 8120 + ClientToGCWeekendTourneyLeaveResponse = 8121 + ClientToGCTeammateStatsRequest = 8124 + ClientToGCTeammateStatsResponse = 8125 + ClientToGCGetGiftPermissions = 8126 + ClientToGCGetGiftPermissionsResponse = 8127 + ClientToGCVoteForArcana = 8128 + ClientToGCVoteForArcanaResponse = 8129 + ClientToGCRequestArcanaVotesRemaining = 8130 + ClientToGCRequestArcanaVotesRemainingResponse = 8131 + GCTransferTeamAdminResponse = 8132 + GCToClientTeamInfo = 8135 + GCToClientTeamsInfo = 8136 + ClientToGCMyTeamInfoRequest = 8137 + ClientToGCPublishUserStat = 8140 + GCToGCSignoutSpendWager = 8141 + GCSubmitLobbyMVPVote = 8144 + GCSubmitLobbyMVPVoteResponse = 8145 + SignOutCommunityGoalProgress = 8150 + GCToClientLobbyMVPAwarded = 8152 + GCToClientQuestProgressUpdated = 8153 + GCToClientWageringUpdate = 8154 + GCToClientArcanaVotesUpdate = 8155 + ClientToGCSetSpectatorLobbyDetails = 8157 + ClientToGCSetSpectatorLobbyDetailsResponse = 8158 + ClientToGCCreateSpectatorLobby = 8159 + ClientToGCCreateSpectatorLobbyResponse = 8160 + ClientToGCSpectatorLobbyList = 8161 + ClientToGCSpectatorLobbyListResponse = 8162 + SpectatorLobbyGameDetails = 8163 + ServerToGCCompendiumInGamePredictionResults = 8166 + ServerToGCCloseCompendiumInGamePredictionVoting = 8167 + ClientToGCOpenPlayerCardPack = 8168 + ClientToGCOpenPlayerCardPackResponse = 8169 + ClientToGCSelectCompendiumInGamePrediction = 8170 + ClientToGCSelectCompendiumInGamePredictionResponse = 8171 + ClientToGCWeekendTourneyGetPlayerStats = 8172 + ClientToGCWeekendTourneyGetPlayerStatsResponse = 8173 + ClientToGCRecyclePlayerCard = 8174 + ClientToGCRecyclePlayerCardResponse = 8175 + ClientToGCCreatePlayerCardPack = 8176 + ClientToGCCreatePlayerCardPackResponse = 8177 + ClientToGCGetPlayerCardRosterRequest = 8178 + ClientToGCGetPlayerCardRosterResponse = 8179 + ClientToGCSetPlayerCardRosterRequest = 8180 + ClientToGCSetPlayerCardRosterResponse = 8181 + ServerToGCCloseCompendiumInGamePredictionVotingResponse = 8183 + LobbyBattleCupVictory = 8186 + GCGetPlayerCardItemInfo = 8187 + GCGetPlayerCardItemInfoResponse = 8188 + ClientToGCRequestSteamDatagramTicket = 8189 + ClientToGCRequestSteamDatagramTicketResponse = 8190 + GCToClientBattlePassRollupRequest = 8191 + GCToClientBattlePassRollupResponse = 8192 + ClientToGCTransferSeasonalMMRRequest = 8193 + ClientToGCTransferSeasonalMMRResponse = 8194 + GCToGCPublicChatCommunicationBan = 8195 + GCToGCUpdateAccountInfo = 8196 + GCChatReportPublicSpam = 8197 + ClientToGCSetPartyBuilderOptions = 8198 + ClientToGCSetPartyBuilderOptionsResponse = 8199 + GCToClientPlaytestStatus = 8200 + ClientToGCJoinPlaytest = 8201 + ClientToGCJoinPlaytestResponse = 8202 + LobbyPlaytestDetails = 8203 + DOTASetFavoriteTeam = 8204 + GCToClientBattlePassRollupListRequest = 8205 + GCToClientBattlePassRollupListResponse = 8206 + DOTAClaimEventAction = 8209 + DOTAClaimEventActionResponse = 8210 + DOTAGetPeriodicResource = 8211 + DOTAGetPeriodicResourceResponse = 8212 + DOTAPeriodicResourceUpdated = 8213 + ServerToGCSpendWager = 8214 + GCToGCSignoutSpendWagerToken = 8215 + SubmitTriviaQuestionAnswer = 8216 + SubmitTriviaQuestionAnswerResponse = 8217 + ClientToGCGiveTip = 8218 + ClientToGCGiveTipResponse = 8219 + StartTriviaSession = 8220 + StartTriviaSessionResponse = 8221 + AnchorPhoneNumberRequest = 8222 + AnchorPhoneNumberResponse = 8223 + UnanchorPhoneNumberRequest = 8224 + UnanchorPhoneNumberResponse = 8225 + GCToGCSignoutSpendRankWager = 8229 + GCToGCGetFavoriteTeam = 8230 + GCToGCGetFavoriteTeamResponse = 8231 + SignOutEventGameData = 8232 + ClientToGCQuickStatsRequest = 8238 + ClientToGCQuickStatsResponse = 8239 + GCToGCSubtractEventPointsFromUser = 8240 + SelectionPriorityChoiceRequest = 8241 + SelectionPriorityChoiceResponse = 8242 + GCToGCCompendiumInGamePredictionResults = 8243 + GameAutographReward = 8244 + GameAutographRewardResponse = 8245 + DestroyLobbyRequest = 8246 + DestroyLobbyResponse = 8247 + PurchaseItemWithEventPoints = 8248 + PurchaseItemWithEventPointsResponse = 8249 + ServerToGCMatchPlayerItemPurchaseHistory = 8250 + GCToGCGrantPlusHeroMatchResults = 8251 + ServerToGCMatchStateHistory = 8255 + PurchaseHeroRandomRelic = 8258 + PurchaseHeroRandomRelicResponse = 8259 + ClientToGCClaimEventActionUsingItem = 8260 + ClientToGCClaimEventActionUsingItemResponse = 8261 + PartyReadyCheckRequest = 8262 + PartyReadyCheckResponse = 8263 + PartyReadyCheckAcknowledge = 8264 + GetRecentPlayTimeFriendsRequest = 8265 + GetRecentPlayTimeFriendsResponse = 8266 + GCToClientCommendNotification = 8267 + ProfileRequest = 8268 + ProfileResponse = 8269 + ProfileUpdate = 8270 + ProfileUpdateResponse = 8271 + HeroGlobalDataRequest = 8274 + HeroGlobalDataResponse = 8275 + ClientToGCRequestPlusWeeklyChallengeResult = 8276 + ClientToGCRequestPlusWeeklyChallengeResultResponse = 8277 + GCToGCGrantPlusPrepaidTime = 8278 + PrivateMetadataKeyRequest = 8279 + PrivateMetadataKeyResponse = 8280 + GCToGCReconcilePlusStatus = 8281 + GCToGCCheckPlusStatus = 8282 + GCToGCCheckPlusStatusResponse = 8283 + GCToGCReconcilePlusAutoGrantItems = 8284 + GCToGCReconcilePlusStatusUnreliable = 8285 + GCToClientCavernCrawlMapPathCompleted = 8288 + ClientToGCCavernCrawlClaimRoom = 8289 + ClientToGCCavernCrawlClaimRoomResponse = 8290 + ClientToGCCavernCrawlUseItemOnRoom = 8291 + ClientToGCCavernCrawlUseItemOnRoomResponse = 8292 + ClientToGCCavernCrawlUseItemOnPath = 8293 + ClientToGCCavernCrawlUseItemOnPathResponse = 8294 + ClientToGCCavernCrawlRequestMapState = 8295 + ClientToGCCavernCrawlRequestMapStateResponse = 8296 + SignOutTips = 8297 + ClientToGCRequestEventPointLogV2 = 8298 + ClientToGCRequestEventPointLogResponseV2 = 8299 + ClientToGCRequestEventTipsSummary = 8300 + ClientToGCRequestEventTipsSummaryResponse = 8301 + ClientToGCRequestSocialFeed = 8303 + ClientToGCRequestSocialFeedResponse = 8304 + ClientToGCRequestSocialFeedComments = 8305 + ClientToGCRequestSocialFeedCommentsResponse = 8306 + ClientToGCCavernCrawlGetClaimedRoomCount = 8308 + ClientToGCCavernCrawlGetClaimedRoomCountResponse = 8309 + GCToGCReconcilePlusAutoGrantItemsUnreliable = 8310 + ServerToGCAddBroadcastTimelineEvent = 8311 + GCToServerUpdateSteamBroadcasting = 8312 + ClientToGCRecordContestVote = 8313 + GCToClientRecordContestVoteResponse = 8314 + GCToGCGrantAutograph = 8315 + GCToGCGrantAutographResponse = 8316 + SignOutConsumableUsage = 8317 + LobbyEventGameDetails = 8318 + DevGrantEventPoints = 8319 + DevGrantEventPointsResponse = 8320 + DevGrantEventAction = 8321 + DevGrantEventActionResponse = 8322 + DevResetEventState = 8323 + DevResetEventStateResponse = 8324 + GCToGCReconcileEventOwnership = 8325 + ConsumeEventSupportGrantItem = 8326 + ConsumeEventSupportGrantItemResponse = 8327 + GCToClientClaimEventActionUsingItemCompleted = 8328 + GCToClientCavernCrawlMapUpdated = 8329 + ServerToGCRequestPlayerRecentAccomplishments = 8330 + ServerToGCRequestPlayerRecentAccomplishmentsResponse = 8331 + ClientToGCRequestPlayerRecentAccomplishments = 8332 + ClientToGCRequestPlayerRecentAccomplishmentsResponse = 8333 + ClientToGCRequestPlayerHeroRecentAccomplishments = 8334 + ClientToGCRequestPlayerHeroRecentAccomplishmentsResponse = 8335 + SignOutEventActionGrants = 8336 + ClientToGCRequestPlayerCoachMatches = 8337 + ClientToGCRequestPlayerCoachMatchesResponse = 8338 + ClientToGCSubmitCoachTeammateRating = 8341 + ClientToGCSubmitCoachTeammateRatingResponse = 8342 + GCToClientCoachTeammateRatingsChanged = 8343 + ClientToGCRequestPlayerCoachMatch = 8345 + ClientToGCRequestPlayerCoachMatchResponse = 8346 + ClientToGCRequestContestVotes = 8347 + ClientToGCRequestContestVotesResponse = 8348 + ClientToGCMVPVoteTimeout = 8349 + ClientToGCMVPVoteTimeoutResponse = 8350 + MatchMatchmakingStats = 8360 + ClientToGCSubmitPlayerMatchSurvey = 8361 + ClientToGCSubmitPlayerMatchSurveyResponse = 8362 + SQLGCToGCGrantAllHeroProgressAccount = 8363 + SQLGCToGCGrantAllHeroProgressVictory = 8364 + DevDeleteEventActions = 8365 + DevDeleteEventActionsResponse = 8366 + GCToGCGetAllHeroCurrent = 8635 + GCToGCGetAllHeroCurrentResponse = 8636 + GCSubmitPlayerAvoidRequest = 8637 + GCSubmitPlayerAvoidRequestResponse = 8638 + GCToClientNotificationsUpdated = 8639 + GCtoGCAssociatedExploiterAccountInfo = 8640 + GCtoGCAssociatedExploiterAccountInfoResponse = 8641 + GCtoGCRequestRecalibrationCheck = 8642 + GCToClientVACReminder = 8643 + ClientToGCUnderDraftBuy = 8644 + ClientToGCUnderDraftBuyResponse = 8645 + ClientToGCUnderDraftReroll = 8646 + ClientToGCUnderDraftRerollResponse = 8647 + NeutralItemStats = 8648 + ClientToGCCreateGuild = 8649 + ClientToGCCreateGuildResponse = 8650 + ClientToGCSetGuildInfo = 8651 + ClientToGCSetGuildInfoResponse = 8652 + ClientToGCAddGuildRole = 8653 + ClientToGCAddGuildRoleResponse = 8654 + ClientToGCModifyGuildRole = 8655 + ClientToGCModifyGuildRoleResponse = 8656 + ClientToGCRemoveGuildRole = 8657 + ClientToGCRemoveGuildRoleResponse = 8658 + ClientToGCJoinGuild = 8659 + ClientToGCJoinGuildResponse = 8660 + ClientToGCLeaveGuild = 8661 + ClientToGCLeaveGuildResponse = 8662 + ClientToGCInviteToGuild = 8663 + ClientToGCInviteToGuildResponse = 8664 + ClientToGCDeclineInviteToGuild = 8665 + ClientToGCDeclineInviteToGuildResponse = 8666 + ClientToGCCancelInviteToGuild = 8667 + ClientToGCCancelInviteToGuildResponse = 8668 + ClientToGCKickGuildMember = 8669 + ClientToGCKickGuildMemberResponse = 8670 + ClientToGCSetGuildMemberRole = 8671 + ClientToGCSetGuildMemberRoleResponse = 8672 + ClientToGCRequestGuildData = 8673 + ClientToGCRequestGuildDataResponse = 8674 + GCToClientGuildDataUpdated = 8675 + ClientToGCRequestGuildMembership = 8676 + ClientToGCRequestGuildMembershipResponse = 8677 + GCToClientGuildMembershipUpdated = 8678 + ClientToGCAcceptInviteToGuild = 8681 + ClientToGCAcceptInviteToGuildResponse = 8682 + ClientToGCSetGuildRoleOrder = 8683 + ClientToGCSetGuildRoleOrderResponse = 8684 + ClientToGCRequestGuildFeed = 8685 + ClientToGCRequestGuildFeedResponse = 8686 + ClientToGCRequestAccountGuildEventData = 8687 + ClientToGCRequestAccountGuildEventDataResponse = 8688 + GCToClientAccountGuildEventDataUpdated = 8689 + ClientToGCRequestActiveGuildContracts = 8690 + ClientToGCRequestActiveGuildContractsResponse = 8691 + GCToClientActiveGuildContractsUpdated = 8692 + GCToClientGuildFeedUpdated = 8693 + ClientToGCSelectGuildContract = 8694 + ClientToGCSelectGuildContractResponse = 8695 + GCToGCCompleteGuildContracts = 8696 + ClientToGCAddPlayerToGuildChat = 8698 + ClientToGCAddPlayerToGuildChatResponse = 8699 + ClientToGCUnderDraftSell = 8700 + ClientToGCUnderDraftSellResponse = 8701 + ClientToGCUnderDraftRequest = 8702 + ClientToGCUnderDraftResponse = 8703 + ClientToGCUnderDraftRedeemReward = 8704 + ClientToGCUnderDraftRedeemRewardResponse = 8705 + GCToServerLobbyHeroBanRates = 8708 + SignOutGuildContractProgress = 8711 + SignOutMVPStats = 8712 + ClientToGCRequestActiveGuildChallenge = 8713 + ClientToGCRequestActiveGuildChallengeResponse = 8714 + GCToClientActiveGuildChallengeUpdated = 8715 + ClientToGCRequestReporterUpdates = 8716 + ClientToGCRequestReporterUpdatesResponse = 8717 + ClientToGCAcknowledgeReporterUpdates = 8718 + SignOutGuildChallengeProgress = 8720 + ClientToGCRequestGuildEventMembers = 8721 + ClientToGCRequestGuildEventMembersResponse = 8722 + ClientToGCReportGuildContent = 8725 + ClientToGCReportGuildContentResponse = 8726 + ClientToGCRequestAccountGuildPersonaInfo = 8727 + ClientToGCRequestAccountGuildPersonaInfoResponse = 8728 + ClientToGCRequestAccountGuildPersonaInfoBatch = 8729 + ClientToGCRequestAccountGuildPersonaInfoBatchResponse = 8730 + GCToClientUnderDraftGoldUpdated = 8731 + GCToServerRecordTrainingData = 8732 + SignOutBounties = 8733 + LobbyFeaturedGamemodeProgress = 8734 + LobbyGauntletProgress = 8735 + ClientToGCSubmitDraftTriviaMatchAnswer = 8736 + ClientToGCSubmitDraftTriviaMatchAnswerResponse = 8737 + GCToGCSignoutSpendBounty = 8738 + ClientToGCApplyGauntletTicket = 8739 + ClientToGCUnderDraftRollBackBench = 8740 + ClientToGCUnderDraftRollBackBenchResponse = 8741 + GCToGCGetEventActionScore = 8742 + GCToGCGetEventActionScoreResponse = 8743 + ServerToGCGetGuildContracts = 8744 + ServerToGCGetGuildContractsResponse = 8745 + LobbyEventGameData = 8746 + GCToClientGuildMembersDataUpdated = 8747 + SignOutReportActivityMarkers = 8748 + SignOutDiretideCandy = 8749 + GCToClientPostGameItemAwardNotification = 8750 + ClientToGCGetOWMatchDetails = 8751 + ClientToGCGetOWMatchDetailsResponse = 8752 + ClientToGCSubmitOWConviction = 8753 + ClientToGCSubmitOWConvictionResponse = 8754 + GCToGCGetAccountSteamChina = 8755 + GCToGCGetAccountSteamChinaResponse = 8756 + ClientToGCClaimLeaderboardRewards = 8757 + ClientToGCClaimLeaderboardRewardsResponse = 8758 + ClientToGCRecalibrateMMR = 8759 + ClientToGCRecalibrateMMRResponse = 8760 + GCToGCGrantEventPointActionList = 8761 + ClientToGCChinaSSAURLRequest = 8764 + ClientToGCChinaSSAURLResponse = 8765 + ClientToGCChinaSSAAcceptedRequest = 8766 + ClientToGCChinaSSAAcceptedResponse = 8767 + SignOutOverwatchSuspicion = 8768 + ServerToGCGetSuspicionConfig = 8769 + ServerToGCGetSuspicionConfigResponse = 8770 + GCToGCGrantPlusHeroChallengeMatchResults = 8771 + GCToClientOverwatchCasesAvailable = 8772 + ServerToGCAccountCheck = 8773 + ClientToGCStartWatchingOverwatch = 8774 + ClientToGCStopWatchingOverwatch = 8775 + SignOutPerfData = 8776 + ClientToGCGetDPCFavorites = 8777 + ClientToGCGetDPCFavoritesResponse = 8778 + ClientToGCSetDPCFavoriteState = 8779 + ClientToGCSetDPCFavoriteStateResponse = 8780 + ClientToGCOverwatchReplayError = 8781 + ServerToGCPlayerChallengeHistory = 8782 + SignOutBanData = 8783 + WebapiDPCSeasonResults = 8784 + ClientToGCCoachFriend = 8785 + ClientToGCCoachFriendResponse = 8786 + ClientToGCRequestPrivateCoachingSession = 8787 + ClientToGCRequestPrivateCoachingSessionResponse = 8788 + ClientToGCAcceptPrivateCoachingSession = 8789 + ClientToGCAcceptPrivateCoachingSessionResponse = 8790 + ClientToGCLeavePrivateCoachingSession = 8791 + ClientToGCLeavePrivateCoachingSessionResponse = 8792 + ClientToGCGetCurrentPrivateCoachingSession = 8793 + ClientToGCGetCurrentPrivateCoachingSessionResponse = 8794 + GCToClientPrivateCoachingSessionUpdated = 8795 + ClientToGCSubmitPrivateCoachingSessionRating = 8796 + ClientToGCSubmitPrivateCoachingSessionRatingResponse = 8797 + ClientToGCGetAvailablePrivateCoachingSessions = 8798 + ClientToGCGetAvailablePrivateCoachingSessionsResponse = 8799 + ClientToGCGetAvailablePrivateCoachingSessionsSummary = 8800 + ClientToGCGetAvailablePrivateCoachingSessionsSummaryResponse = 8801 + ClientToGCJoinPrivateCoachingSessionLobby = 8802 + ClientToGCJoinPrivateCoachingSessionLobbyResponse = 8803 + ClientToGCRespondToCoachFriendRequest = 8804 + ClientToGCRespondToCoachFriendRequestResponse = 8805 + ClientToGCSetEventActiveSeasonID = 8806 + ClientToGCSetEventActiveSeasonIDResponse = 8807 + ServerToGCMatchPlayerNeutralItemEquipHistory = 8808 + ServerToGCCompendiumChosenInGamePredictions = 8809 + ClientToGCCreateTeamPlayerCardPack = 8810 + ClientToGCCreateTeamPlayerCardPackResponse = 8811 + GCToServerSubmitCheerData = 8812 + GCToServerCheerConfig = 8813 + ServerToGCGetCheerConfig = 8814 + ServerToGCGetCheerConfigResponse = 8815 + GCToGCGrantAutographByID = 8816 + GCToServerCheerScalesOverride = 8817 + GCToServerGetCheerState = 8818 + ServerToGCReportCheerState = 8819 + GCToServerScenarioSave = 8820 + GCToServerAbilityDraftLobbyData = 8821 + SignOutReportCommunications = 8822 + ClientToGCBatchGetPlayerCardRosterRequest = 8823 + ClientToGCBatchGetPlayerCardRosterResponse = 8824 + ClientToGCGetStickerbookRequest = 8825 + ClientToGCGetStickerbookResponse = 8826 + ClientToGCCreateStickerbookPageRequest = 8827 + ClientToGCCreateStickerbookPageResponse = 8828 + ClientToGCDeleteStickerbookPageRequest = 8829 + ClientToGCDeleteStickerbookPageResponse = 8830 + ClientToGCPlaceStickersRequest = 8831 + ClientToGCPlaceStickersResponse = 8832 + ClientToGCPlaceCollectionStickersRequest = 8833 + ClientToGCPlaceCollectionStickersResponse = 8834 + ClientToGCOrderStickerbookTeamPageRequest = 8835 + ClientToGCOrderStickerbookTeamPageResponse = 8836 + ServerToGCGetStickerHeroes = 8837 + ServerToGCGetStickerHeroesResponse = 8838 + ClientToGCCandyShopGetUserData = 8840 + ClientToGCCandyShopGetUserDataResponse = 8841 + GCToClientCandyShopUserDataUpdated = 8842 + ClientToGCCandyShopPurchaseReward = 8843 + ClientToGCCandyShopPurchaseRewardResponse = 8844 + ClientToGCCandyShopDoExchange = 8845 + ClientToGCCandyShopDoExchangeResponse = 8846 + ClientToGCCandyShopDoVariableExchange = 8847 + ClientToGCCandyShopDoVariableExchangeResponse = 8848 + ClientToGCCandyShopRerollRewards = 8849 + ClientToGCCandyShopRerollRewardsResponse = 8850 + ClientToGCSetHeroSticker = 8851 + ClientToGCSetHeroStickerResponse = 8852 + ClientToGCGetHeroStickers = 8853 + ClientToGCGetHeroStickersResponse = 8854 + ClientToGCSetFavoritePage = 8855 + ClientToGCSetFavoritePageResponse = 8856 + ClientToGCCandyShopDevGrantCandy = 8857 + ClientToGCCandyShopDevGrantCandyResponse = 8858 + ClientToGCCandyShopDevClearInventory = 8859 + ClientToGCCandyShopDevClearInventoryResponse = 8860 + ClientToGCCandyShopOpenBags = 8861 + ClientToGCCandyShopOpenBagsResponse = 8862 + ClientToGCCandyShopDevGrantCandyBags = 8863 + ClientToGCCandyShopDevGrantCandyBagsResponse = 8864 + ClientToGCCandyShopDevShuffleExchange = 8865 + ClientToGCCandyShopDevShuffleExchangeResponse = 8866 + ClientToGCCandyShopDevGrantRerollCharges = 8867 + ClientToGCCandyShopDevGrantRerollChargesResponse = 8868 + LobbyAdditionalAccountData = 8869 + ServerToGCLobbyInitialized = 8870 + ClientToGCCollectorsCacheAvailableDataRequest = 8871 + GCToClientCollectorsCacheAvailableDataResponse = 8872 + ClientToGCUploadMatchClip = 8873 + GCToClientUploadMatchClipResponse = 8874 + GCToServerSetSteamLearnKeysChanged = 8876 + SignOutMuertaMinigame = 8877 + GCToServerLobbyHeroRoleStats = 8878 + ClientToGCRankRequest = 8879 + GCToClientRankResponse = 8880 + GCToClientRankUpdate = 8881 + SignOutMapStats = 8882 + ClientToGCMapStatsRequest = 8883 + GCToClientMapStatsResponse = 8884 + GCToServerSetSteamLearnInferencing = 8885 + ClientToGCShowcaseGetUserData = 8886 + ClientToGCShowcaseGetUserDataResponse = 8887 + ClientToGCShowcaseSetUserData = 8888 + ClientToGCShowcaseSetUserDataResponse = 8889 + ClientToGCFantasyCraftingGetData = 8890 + ClientToGCFantasyCraftingGetDataResponse = 8891 + ClientToGCFantasyCraftingPerformOperation = 8892 + ClientToGCFantasyCraftingPerformOperationResponse = 8893 + GCToClientFantasyCraftingGetDataUpdated = 8894 + ClientToGCFantasyCraftingDevModifyTablet = 8895 + ClientToGCFantasyCraftingDevModifyTabletResponse = 8896 + ClientToGCRoadToTIGetQuests = 8897 + ClientToGCRoadToTIGetQuestsResponse = 8898 + ClientToGCRoadToTIGetActiveQuest = 8899 + ClientToGCRoadToTIGetActiveQuestResponse = 8900 + ClientToGCBingoGetUserData = 8901 + ClientToGCBingoGetUserDataResponse = 8902 + ClientToGCBingoClaimRow = 8903 + ClientToGCBingoClaimRowResponse = 8904 + ClientToGCBingoDevRerollCard = 8905 + ClientToGCBingoDevRerollCardResponse = 8906 + ClientToGCBingoGetStatsData = 8907 + ClientToGCBingoGetStatsDataResponse = 8908 + GCToClientBingoUserDataUpdated = 8909 + GCToClientRoadToTIQuestDataUpdated = 8910 + ClientToGCRoadToTIUseItem = 8911 + ClientToGCRoadToTIUseItemResponse = 8912 + ClientToGCShowcaseSubmitReport = 8913 + ClientToGCShowcaseSubmitReportResponse = 8914 + ClientToGCShowcaseAdminGetReportsRollupList = 8915 + ClientToGCShowcaseAdminGetReportsRollupListResponse = 8916 + ClientToGCShowcaseAdminGetReportsRollup = 8917 + ClientToGCShowcaseAdminGetReportsRollupResponse = 8918 + ClientToGCShowcaseAdminGetUserDetails = 8919 + ClientToGCShowcaseAdminGetUserDetailsResponse = 8920 + ClientToGCShowcaseAdminConvict = 8921 + ClientToGCShowcaseAdminConvictResponse = 8922 + ClientToGCShowcaseAdminExonerate = 8923 + ClientToGCShowcaseAdminExonerateResponse = 8924 + ClientToGCShowcaseAdminReset = 8925 + ClientToGCShowcaseAdminResetResponse = 8926 + ClientToGCShowcaseAdminLockAccount = 8927 + ClientToGCShowcaseAdminLockAccountResponse = 8928 + ClientToGCFantasyCraftingSelectPlayer = 8929 + ClientToGCFantasyCraftingSelectPlayerResponse = 8930 + ClientToGCFantasyCraftingGenerateTablets = 8931 + ClientToGCFantasyCraftingGenerateTabletsResponse = 8932 + ClientToGcFantasyCraftingUpgradeTablets = 8933 + ClientToGcFantasyCraftingUpgradeTabletsResponse = 8934 + ClientToGCFantasyCraftingRerollOptions = 8936 + ClientToGCFantasyCraftingRerollOptionsResponse = 8937 + ClientToGCRoadToTIDevForceQuest = 8935 + LobbyRoadToTIMatchQuestData = 8939 + ClientToGCShowcaseModerationGetQueue = 8940 + ClientToGCShowcaseModerationGetQueueResponse = 8941 + ClientToGCShowcaseModerationApplyModeration = 8942 + ClientToGCShowcaseModerationApplyModerationResponse = 8943 +# fmt: on diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py new file mode 100644 index 00000000..afdb2c10 --- /dev/null +++ b/steam/ext/dota2/models.py @@ -0,0 +1,196 @@ +"""Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE""" + +from __future__ import annotations + +import datetime +from dataclasses import dataclass +from typing import TYPE_CHECKING, TypeVar, Generic, Self + +from .enums import Hero +from ... import abc +from .protobufs.shared_enums import DOTAGameMode +from .protobufs.lobby import CSODOTALobbyLobbyType + +if TYPE_CHECKING: + from .protobufs.watch import CSourceTVGameSmall + from .state import GCState + from .protobufs.common import CMsgDOTAProfileCard + +__all__ = ("LiveMatch",) + +UserT = TypeVar("UserT", bound=abc.PartialUser) + + +@dataclass(slots=True) +class LivePlayer: + user: PartialUser + hero: Hero + + +@dataclass(slots=True) +class BattleCup: + tournament_id: int + division: int + skill_level: int + bracket_round: int + + +@dataclass(slots=True) +class TournamentTeam: + id: int + name: str + logo: float # todo: can I get more info on logo than float nonsense ? + + +@dataclass(slots=True) +class TournamentMatch: + league_id: int + series_id: int + teams: list[TournamentTeam] + battle_cup_info: BattleCup | None + + +class LiveMatch: + """Represents a live match of Dota 2 + + Attributes + ----------- + match_id + Match ID. + server_steam_id + Server Steam ID. + lobby_id + Lobby ID. + lobby_type + Lobby Type. i.e. Ranked, Unranked. + game_mode + Game mode, i.e. All Pick, Captains Mode. + players + List of players in this match. This is sorted with team slot order (or commonly referred as player's colour). + Radiant team players first, i.e. "blue", "teal", "purple", ... Then Dire team players. + average_mmr + Average MMR. + sort_score + Number for in-game's Watch Tab to sort the game list in descending order with. + spectators: + Amount of people currently watching this match live in the Dota 2 application. + start_time: + Datetime in UTC for when the match started, including pre-draft stage. + end_time: + Datetime in UTC for when the match is finished. 0 if match is currently live. + game_time: + Timedelta representing in-game timer. + Draft stage and time before runes (0:00 mark) have this as non-positive timedelta. + delay + Time delay for the match if watching in the Dota 2 application. + Similarly, the data in attributes of this class is also behind the present by this delay. + last_update_time: + Time the data was updated last by the Game Coordinator. + tournament + Tournament information, if the match is a tournament game. + radiant_lead + Amount of gold lead Radiant team has. Negative value in case Dire is leading. + radiant_score + Amount of kills Radiant team has + dire_score + Amount of kills Dire team has + building_state + Bitmask. An integer that represents a binary of which buildings are still standing. + custom_game_difficulty + Custom Game Difficulty + """ + + def __init__(self, state: GCState, proto: CSourceTVGameSmall) -> None: + self._state: GCState = state + + self.match_id: int = proto.match_id + self.server_steam_id: int = proto.match_id + self.lobby_id: int = proto.lobby_id + + self.lobby_type = CSODOTALobbyLobbyType.try_value(proto.lobby_type) + self.game_mode = DOTAGameMode.try_value(proto.game_mode) + self.average_mmr: int = proto.average_mmr + self.sort_score: int = proto.sort_score + self.spectators: int = proto.spectators + + self.start_time = datetime.datetime.fromtimestamp(proto.activate_time, datetime.timezone.utc) + self.game_time = datetime.timedelta(seconds=proto.game_time) + self.end_time = datetime.timedelta(seconds=proto.deactivate_time) + self.delay = datetime.timedelta(seconds=proto.delay) + self.last_update_time = datetime.datetime.fromtimestamp(proto.last_update_time, datetime.timezone.utc) + + self.tournament: TournamentMatch | None = None + if proto.league_id: # if it is 0 then all tournament related fields are going to be 0 as well + battle_cup = None + if proto.weekend_tourney_tournament_id: # if it is 0 then all battle cup related fields are going to be 0 + battle_cup = BattleCup( + proto.weekend_tourney_tournament_id, + proto.weekend_tourney_division, + proto.weekend_tourney_skill_level, + proto.weekend_tourney_bracket_round, + ) + self.tournament = TournamentMatch( + proto.league_id, + proto.series_id, + [ + TournamentTeam(proto.team_id_radiant, proto.team_name_radiant, proto.team_logo_radiant), + TournamentTeam(proto.team_id_dire, proto.team_name_dire, proto.team_logo_dire), + ], + battle_cup, + ) + + self.radiant_lead: int = proto.radiant_lead + self.radiant_score: int = proto.radiant_score + self.dire_score: int = proto.dire_score + self.building_state: float = proto.building_state # todo: helper function to decode this into human-readable + + self.custom_game_difficulty: int = proto.custom_game_difficulty + + # Since Immortal Draft update, players come from the proto message in a wrong order + # which can be fixed back with extra fields that they introduced later: `team`, `team_slot` + # why valve chose to introduce extra bytes fields instead of resorting it once after player selection - no clue + sorted_players = [p for p in sorted(proto.players, key=lambda player: (player.team, player.team_slot))] + + self.players = [ + LivePlayer( + user=PartialUser(self._state, p.account_id), + hero=Hero.try_value(p.hero_id), + ) + for p in sorted_players + ] + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} match_id={self.match_id} server_steam_id={self.server_steam_id}>" + + +class PartialUser(abc.PartialUser): + __slots__ = () + _state: GCState + + async def dota2_profile_card(self) -> ProfileCard[Self]: + """Fetches this users Dota 2 profile card.""" + msg = await self._state.fetch_user_dota2_profile_card(self.id) + return ProfileCard(self, msg) + + +class ProfileCard(Generic[UserT]): + def __init__(self, user: UserT, proto: CMsgDOTAProfileCard): + print(proto) + self.user = user + self.slots = proto.slots + self.badge_points = proto.badge_points + self.event_points = proto.event_points + self.event_id = proto.event_id + self.recent_battle_cup_victory = proto.recent_battle_cup_victory + self.rank_tier = proto.rank_tier + self.leaderboard_rank = proto.leaderboard_rank + self.is_plus_subscriber = proto.is_plus_subscriber + self.plus_original_start_date = proto.plus_original_start_date + self.rank_tier_score = proto.rank_tier_score + self.leaderboard_rank_core = proto.leaderboard_rank_core + self.title = proto.title + self.favorite_team_packed = proto.favorite_team_packed + self.lifetime_games = proto.lifetime_games + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} user={self.user!r}>" diff --git a/steam/ext/dota2/protobufs/__init__.py b/steam/ext/dota2/protobufs/__init__.py index bea50577..9bc38b26 100644 --- a/steam/ext/dota2/protobufs/__init__.py +++ b/steam/ext/dota2/protobufs/__init__.py @@ -5,6 +5,13 @@ APP_ID: Final = 570 from ....protobufs.msg import GCProtobufMessage -from . import dota_gcmessages_client_watch as dota_gcmessages_client_watch, gcsdk_gcmessages as gcsdk_gcmessages +from . import ( + client_messages as client_messages, + common as common, + lobby as lobby, + sdk as sdk, + shared_enums as shared_enums, + watch as watch, +) [setattr(cls, "_betterproto", betterproto.ProtoClassMetadata(cls)) for cls in GCProtobufMessage.__subclasses__()] diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py new file mode 100644 index 00000000..6ada0f2e --- /dev/null +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -0,0 +1,14 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_gcmessages_client.proto +# plugin: python-betterproto + +from __future__ import annotations + + +import betterproto +from ....protobufs.msg import GCProtobufMessage +from ..enums import EMsg + + +class CMsgClientToGCGetProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCard): + account_id: int = betterproto.uint32_field(1) diff --git a/steam/ext/dota2/protobufs/common.py b/steam/ext/dota2/protobufs/common.py new file mode 100644 index 00000000..51c3d3b5 --- /dev/null +++ b/steam/ext/dota2/protobufs/common.py @@ -0,0 +1,101 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_gcmessages_common.proto +# plugin: python-betterproto + +from __future__ import annotations + +from dataclasses import dataclass + + +import betterproto + +from ....protobufs.msg import GCProtobufMessage +from ..enums import EMsg + + +# fmt: off +class CMsgDOTAProfileCardEStatID(betterproto.Enum): + Wins = 3 + Commends = 4 + GamesPlayed = 5 + FirstMatchDate = 6 + PreviousSeasonRank = 7 + GamesMVP = 8 +# fmt: on + + +@dataclass +class CMsgBattleCupVictory(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + win_date: int = betterproto.uint32_field(2) + valid_until: int = betterproto.uint32_field(3) + skill_level: int = betterproto.uint32_field(4) + tournament_id: int = betterproto.uint32_field(5) + division_id: int = betterproto.uint32_field(6) + team_id: int = betterproto.uint32_field(7) + streak: int = betterproto.uint32_field(8) + trophy_id: int = betterproto.uint32_field(9) + + +@dataclass +class CMsgDOTAProfileCardSlot(betterproto.Message): + slot_id: int = betterproto.uint32_field(1) + trophy: CMsgDOTAProfileCardSlotTrophy = betterproto.message_field(2) + stat: CMsgDOTAProfileCardSlotStat = betterproto.message_field(3) + item: CMsgDOTAProfileCardSlotItem = betterproto.message_field(4) + hero: CMsgDOTAProfileCardSlotHero = betterproto.message_field(5) + emoticon: CMsgDOTAProfileCardSlotEmoticon = betterproto.message_field(6) + team: CMsgDOTAProfileCardSlotTeam = betterproto.message_field(7) + + +@dataclass +class CMsgDOTAProfileCardSlotTrophy(betterproto.Message): + trophy_id: int = betterproto.uint32_field(1) + trophy_score: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgDOTAProfileCardSlotStat(betterproto.Message): + stat_id: CMsgDOTAProfileCardEStatID = betterproto.enum_field(1) + stat_score: int = betterproto.uint32_field(2) + + +@dataclass +class CMsgDOTAProfileCardSlotItem(betterproto.Message): + serialized_item: bytes = betterproto.bytes_field(1) + item_id: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgDOTAProfileCardSlotHero(betterproto.Message): + hero_id: int = betterproto.uint32_field(1) + hero_wins: int = betterproto.uint32_field(2) + hero_losses: int = betterproto.uint32_field(3) + + +@dataclass +class CMsgDOTAProfileCardSlotEmoticon(betterproto.Message): + emoticon_id: int = betterproto.uint32_field(1) + + +@dataclass +class CMsgDOTAProfileCardSlotTeam(betterproto.Message): + team_id: int = betterproto.uint32_field(1) + + +class CMsgDOTAProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCardResponse): + account_id: int = betterproto.uint32_field(1) + slots: list[CMsgDOTAProfileCardSlot] = betterproto.message_field(3) + badge_points: int = betterproto.uint32_field(4) + event_points: int = betterproto.uint32_field(5) + event_id: int = betterproto.uint32_field(6) + recent_battle_cup_victory: CMsgBattleCupVictory = betterproto.message_field(7) + rank_tier: int = betterproto.uint32_field(8) + leaderboard_rank: int = betterproto.uint32_field(9) + is_plus_subscriber: bool = betterproto.bool_field(10) + plus_original_start_date: int = betterproto.uint32_field(11) + rank_tier_score: int = betterproto.uint32_field(12) + leaderboard_rank_core: int = betterproto.uint32_field(17) + title: int = betterproto.uint32_field(23) + favorite_team_packed: int = betterproto.uint64_field(24) + lifetime_games: int = betterproto.uint32_field(25) diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py b/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py deleted file mode 100644 index 428d99cc..00000000 --- a/steam/ext/dota2/protobufs/dota_gcmessages_client_watch.py +++ /dev/null @@ -1,246 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: dota_gcmessages_client_watch.proto -# plugin: python-betterproto - -from __future__ import annotations - -from dataclasses import dataclass -from typing import TYPE_CHECKING - -import betterproto - -from ....protobufs.msg import GCProtobufMessage -from .dota_gcmessages_msgid import EDOTAGCMsg - -if TYPE_CHECKING: - from dota_gcmessages_common import CMsgDOTAMatchMinimal - - -class CMsgSpectateFriendGameResponseEWatchLiveResult(betterproto.Enum): - SUCCESS = 0 - ERROR_GENERIC = 1 - ERROR_NO_PLUS = 2 - ERROR_NOT_FRIENDS = 3 - ERROR_LOBBY_NOT_FOUND = 4 - ERROR_SPECTATOR_IN_A_LOBBY = 5 - ERROR_LOBBY_IS_LAN = 6 - ERROR_WRONG_LOBBY_TYPE = 7 - ERROR_WRONG_LOBBY_STATE = 8 - ERROR_PLAYER_NOT_PLAYER = 9 - ERROR_TOO_MANY_SPECTATORS = 10 - ERROR_SPECTATOR_SWITCHED_TEAMS = 11 - ERROR_FRIENDS_ON_BOTH_SIDES = 12 - ERROR_SPECTATOR_IN_THIS_LOBBY = 13 - ERROR_LOBBY_IS_LEAGUE = 14 - - -class CMsgWatchGameResponseWatchGameResult(betterproto.Enum): - PENDING = 0 - READY = 1 - GAMESERVERNOTFOUND = 2 - UNAVAILABLE = 3 - CANCELLED = 4 - INCOMPATIBLEVERSION = 5 - MISSINGLEAGUESUBSCRIPTION = 6 - LOBBYNOTFOUND = 7 - - -@dataclass -class CSourceTVGameSmall(betterproto.Message): - activate_time: int = betterproto.uint32_field(1) - deactivate_time: int = betterproto.uint32_field(2) - server_steam_id: int = betterproto.uint64_field(3) - lobby_id: int = betterproto.uint64_field(4) - league_id: int = betterproto.uint32_field(5) - lobby_type: int = betterproto.uint32_field(6) - game_time: int = betterproto.int32_field(7) - delay: int = betterproto.uint32_field(8) - spectators: int = betterproto.uint32_field(9) - game_mode: int = betterproto.uint32_field(10) - average_mmr: int = betterproto.uint32_field(11) - match_id: int = betterproto.uint64_field(12) - series_id: int = betterproto.uint32_field(13) - team_name_radiant: str = betterproto.string_field(15) - team_name_dire: str = betterproto.string_field(16) - team_logo_radiant: float = betterproto.fixed64_field(24) - team_logo_dire: float = betterproto.fixed64_field(25) - team_id_radiant: int = betterproto.uint32_field(30) - team_id_dire: int = betterproto.uint32_field(31) - sort_score: int = betterproto.uint32_field(17) - last_update_time: float = betterproto.float_field(18) - radiant_lead: int = betterproto.int32_field(19) - radiant_score: int = betterproto.uint32_field(20) - dire_score: int = betterproto.uint32_field(21) - players: list[CSourceTVGameSmallPlayer] = betterproto.message_field(22) - building_state: float = betterproto.fixed32_field(23) - weekend_tourney_tournament_id: int = betterproto.uint32_field(26) - weekend_tourney_division: int = betterproto.uint32_field(27) - weekend_tourney_skill_level: int = betterproto.uint32_field(28) - weekend_tourney_bracket_round: int = betterproto.uint32_field(29) - custom_game_difficulty: int = betterproto.uint32_field(32) - - -@dataclass -class CSourceTVGameSmallPlayer(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - hero_id: int = betterproto.uint32_field(2) - team_slot: int = betterproto.uint32_field(3) - team: int = betterproto.uint32_field(4) - - -class CMsgClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EDOTAGCMsg.ClientToGCFindTopSourceTVGames): - search_key: str = betterproto.string_field(1) - league_id: int = betterproto.uint32_field(2) - hero_id: int = betterproto.uint32_field(3) - start_game: int = betterproto.uint32_field(4) - game_list_index: int = betterproto.uint32_field(5) - lobby_ids: list[int] = betterproto.uint64_field(6) - - -class CMsgGCToClientFindTopSourceTVGamesResponse( - GCProtobufMessage, msg=EDOTAGCMsg.GCToClientFindTopSourceTVGamesResponse -): - search_key: str = betterproto.string_field(1) - league_id: int = betterproto.uint32_field(2) - hero_id: int = betterproto.uint32_field(3) - start_game: int = betterproto.uint32_field(4) - num_games: int = betterproto.uint32_field(5) - game_list_index: int = betterproto.uint32_field(6) - game_list: list[CSourceTVGameSmall] = betterproto.message_field(7) - specific_games: bool = betterproto.bool_field(8) - bot_game: CSourceTVGameSmall = betterproto.message_field(9) - - -@dataclass -class CMsgGCToClientTopWeekendTourneyGames(betterproto.Message): - live_games: list[CSourceTVGameSmall] = betterproto.message_field(1) - - -@dataclass -class CMsgClientToGCTopLeagueMatchesRequest(betterproto.Message): - pass - - -@dataclass -class CMsgClientToGCTopFriendMatchesRequest(betterproto.Message): - pass - - -@dataclass -class CMsgClientToGCMatchesMinimalRequest(betterproto.Message): - match_ids: list[int] = betterproto.uint64_field(1) - - -@dataclass -class CMsgClientToGCMatchesMinimalResponse(betterproto.Message): - matches: list[CMsgDOTAMatchMinimal] = betterproto.message_field(1) - last_match: bool = betterproto.bool_field(2) - - -@dataclass -class CMsgGCToClientTopLeagueMatchesResponse(betterproto.Message): - matches: list[CMsgDOTAMatchMinimal] = betterproto.message_field(2) - - -@dataclass -class CMsgGCToClientTopFriendMatchesResponse(betterproto.Message): - matches: list[CMsgDOTAMatchMinimal] = betterproto.message_field(1) - - -@dataclass -class CMsgSpectateFriendGame(betterproto.Message): - steam_id: float = betterproto.fixed64_field(1) - live: bool = betterproto.bool_field(2) - - -@dataclass -class CMsgSpectateFriendGameResponse(betterproto.Message): - server_steamid: float = betterproto.fixed64_field(4) - watch_live_result: CMsgSpectateFriendGameResponseEWatchLiveResult = betterproto.enum_field(5) - - -@dataclass -class CDOTAReplayDownloadInfo(betterproto.Message): - match: CMsgDOTAMatchMinimal = betterproto.message_field(1) - title: str = betterproto.string_field(2) - description: str = betterproto.string_field(3) - size: int = betterproto.uint32_field(4) - tags: list[str] = betterproto.string_field(5) - exists_on_disk: bool = betterproto.bool_field(6) - - -@dataclass -class CDOTAReplayDownloadInfoHighlight(betterproto.Message): - timestamp: int = betterproto.uint32_field(1) - description: str = betterproto.string_field(2) - - -@dataclass -class CMsgWatchGame(betterproto.Message): - server_steamid: float = betterproto.fixed64_field(1) - client_version: int = betterproto.uint32_field(2) - watch_server_steamid: float = betterproto.fixed64_field(3) - lobby_id: int = betterproto.uint64_field(4) - regions: list[int] = betterproto.uint32_field(5) - - -@dataclass -class CMsgCancelWatchGame(betterproto.Message): - pass - - -@dataclass -class CMsgWatchGameResponse(betterproto.Message): - watch_game_result: CMsgWatchGameResponseWatchGameResult = betterproto.enum_field(1) - source_tv_public_addr: int = betterproto.uint32_field(2) - source_tv_private_addr: int = betterproto.uint32_field(3) - source_tv_port: int = betterproto.uint32_field(4) - game_server_steamid: float = betterproto.fixed64_field(5) - watch_server_steamid: float = betterproto.fixed64_field(6) - watch_tv_unique_secret_code: float = betterproto.fixed64_field(7) - - -@dataclass -class CMsgPartyLeaderWatchGamePrompt(betterproto.Message): - game_server_steamid: float = betterproto.fixed64_field(5) - - -@dataclass -class CDOTABroadcasterInfo(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - server_steam_id: float = betterproto.fixed64_field(2) - live: bool = betterproto.bool_field(3) - team_name_radiant: str = betterproto.string_field(4) - team_name_dire: str = betterproto.string_field(5) - series_game: int = betterproto.uint32_field(7) - upcoming_broadcast_timestamp: int = betterproto.uint32_field(9) - allow_live_video: bool = betterproto.bool_field(10) - node_type: int = betterproto.uint32_field(11) - node_name: str = betterproto.string_field(12) - - -@dataclass -class CMsgDOTASeries(betterproto.Message): - series_id: int = betterproto.uint32_field(1) - series_type: int = betterproto.uint32_field(2) - team_1: CMsgDOTASeriesTeamInfo = betterproto.message_field(3) - team_2: CMsgDOTASeriesTeamInfo = betterproto.message_field(4) - match_minimal: list[CMsgDOTAMatchMinimal] = betterproto.message_field(5) - live_game: CMsgDOTASeriesLiveGame = betterproto.message_field(6) - - -@dataclass -class CMsgDOTASeriesTeamInfo(betterproto.Message): - team_id: int = betterproto.uint32_field(1) - team_name: str = betterproto.string_field(2) - team_logo_url: str = betterproto.string_field(3) - wager_count: int = betterproto.uint32_field(4) - - -@dataclass -class CMsgDOTASeriesLiveGame(betterproto.Message): - server_steam_id: float = betterproto.fixed64_field(1) - team_radiant: CMsgDOTASeriesTeamInfo = betterproto.message_field(2) - team_dire: CMsgDOTASeriesTeamInfo = betterproto.message_field(3) - team_radiant_score: int = betterproto.uint32_field(4) - team_dire_score: int = betterproto.uint32_field(5) diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_common.py b/steam/ext/dota2/protobufs/dota_gcmessages_common.py deleted file mode 100644 index fe85f5cf..00000000 --- a/steam/ext/dota2/protobufs/dota_gcmessages_common.py +++ /dev/null @@ -1,1838 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: dota_gcmessages_common.proto -# plugin: python-betterproto -from __future__ import annotations - -from dataclasses import dataclass -from typing import TYPE_CHECKING - -import betterproto - -if TYPE_CHECKING: - from .dota_shared_enums import ( - CMsgPendingEventAward, - DOTAGameMode, - DOTAGCTeam, - EEvent, - ELeaguePhase, - ELeagueRegion, - EMatchOutcome, - ) - - -class ESpecialPingValue(betterproto.Enum): - NoData = 16382 - Failed = 16383 - - -class EDOTAGCSessionNeed(betterproto.Enum): - Unknown = 0 - UserNoSessionNeeded = 100 - UserInOnlineGame = 101 - UserInLocalGame = 102 - UserInUIWasConnected = 103 - UserInUINeverConnected = 104 - UserTutorials = 105 - UserInUIWasConnectedIdle = 106 - UserInUINeverConnectedIdle = 107 - GameServerOnline = 200 - GameServerLocal = 201 - GameServerIdle = 202 - GameServerRelay = 203 - GameServerLocalUpload = 204 - - -class EDOTAMatchPlayerTimeCustomStat(betterproto.Enum): - HPRegenUnderT1Towers = 1 - MagicDamageReducedWithNewFormula_Absolute = 2 - MagicDamageReducedWithNewFormula_PercentOfTotalHP = 3 - - -class DOTATournamentEvents(betterproto.Enum): - FIRST_BLOOD = 0 - GAME_END = 1 - MULTI_KILL = 2 - HERO_DENY = 3 - AEGIS_DENY = 4 - AEGIS_STOLEN = 5 - GODLIKE = 6 - COURIER_KILL = 7 - ECHOSLAM = 8 - RAPIER = 9 - EARLY_ROSHAN = 10 - BLACK_HOLE = 11 - - -class EBroadcastTimelineEvent(betterproto.Enum): - MatchStarted = 1 - GameStateChanged = 2 - TowerDeath = 3 - BarracksDeath = 4 - AncientDeath = 5 - RoshanDeath = 6 - HeroDeath = 7 - TeamFight = 8 - FirstBlood = 9 - - -class ECustomGameWhitelistState(betterproto.Enum): - UNKNOWN = 0 - APPROVED = 1 - REJECTED = 2 - - -class EDOTATriviaQuestionCategory(betterproto.Enum): - AbilityIcon = 0 - AbilityCooldown = 1 - HeroAttributes = 2 - HeroMovementSpeed = 3 - TalentTree = 4 - HeroStats = 5 - ItemPrice = 6 - AbilitySound = 7 - InvokerSpells = 8 - AbilityManaCost = 9 - HeroAttackSound = 10 - AbilityName = 11 - ItemComponents = 12 - ItemLore = 13 - ItemPassives = 14 - STATIC_QUESTIONS_END = 15 - DYNAMIC_QUESTIONS_START = 99 - Dynamic_ItemBuild = 100 - - -class EOverwatchConviction(betterproto.Enum): - NONE = 0 - NotGuilty = 1 - GuiltUnclear = 2 - Guilty = 3 - - -class EHeroRelicRarity(betterproto.Enum): - INVALID = -1 - COMMON = 0 - RARE = 1 - - -class EStickerbookAuditAction(betterproto.Enum): - CREATE_PAGE = 0 - DELETE_PAGE = 1 - STICK_STICKERS = 2 - REPLACE_STICKERS = 3 - HERO_STICKER = 4 - - -class EStickerbookPageType(betterproto.Enum): - GENERIC = 0 - TEAM = 1 - TALENT = 2 - - -class CMsgDOTAProfileCardEStatID(betterproto.Enum): - Wins = 3 - Commends = 4 - GamesPlayed = 5 - FirstMatchDate = 6 - PreviousSeasonRank = 7 - GamesMVP = 8 - - -class CMsgGCRerollPlayerChallengeResponseEResult(betterproto.Enum): - Success = 0 - Dropped = 1 - NotFound = 2 - CantReroll = 3 - ServerError = 4 - - -class CMsgDOTARealtimeGameStatsGraphDataeStat(betterproto.Enum): - CreepGoldEarned = 0 - KillGoldEarned = 1 - DeathAndBuybackGoldLost = 2 - XPEarned = 3 - - -class CMsgDOTARealtimeGameStatsGraphDataeLocation(betterproto.Enum): - BotLane = 0 - MidLane = 1 - TopLane = 2 - Jungle = 3 - Ancients = 4 - Other = 5 - - -class CMsgInGamePredictionERawValueTypeT(betterproto.Enum): - Number = 0 - Time = 1 - - -class CMsgInGamePredictionEPredictionType(betterproto.Enum): - Generic = 0 - Hero = 1 - Team = 2 - Player = 3 - Special = 4 - YesNo = 5 - QualifiersTeam = 6 - - -class CMsgInGamePredictionEResolutionTypeT(betterproto.Enum): - InvalidQuery = 0 - FirstToPassQuery = 1 - LastToPassQuery = 2 - LastRemainingQuery = 3 - MaxToPassQuery = 4 - MinToPassQuery = 5 - SumQuery = 6 - MaxTeamSumToPassQuery = 7 - MinTeamSumToPassQuery = 8 - - -class CMsgInGamePredictionERandomSelectionGroupT(betterproto.Enum): - EarlyGame = 0 - MidGame = 1 - LateGame = 2 - Count = 3 - - -class CMsgDOTASeasonPredictionsPredictionEPredictionType(betterproto.Enum): - Generic = 0 - Hero = 1 - Team = 2 - Player = 3 - Special = 4 - YesNo = 5 - QualifiersTeam = 6 - LastChanceTeam = 7 - - -class CMsgDOTASeasonPredictionsPredictionEAnswerType(betterproto.Enum): - SingleInt = 0 - SingleFloat = 1 - MultipleInt = 2 - MultipleFloat = 3 - AnswerTeam = 4 - SingleTime = 5 - MultipleTime = 6 - NoAnswer = 7 - - -class CMsgDOTAMatchReplayState(betterproto.Enum): - AVAILABLE = 0 - NOT_RECORDED = 1 - EXPIRED = 2 - - -class CMsgDOTAMatchPlayerHeroDamageType(betterproto.Enum): - PHYSICAL = 0 - MAGICAL = 1 - PURE = 2 - - -class CMsgServerToGCRequestPlayerRecentAccomplishmentsResponseEResponse(betterproto.Enum): - InternalError = 0 - Success = 1 - TooBusy = 2 - Disabled = 3 - - -@dataclass -class CSODOTAGameAccountClient(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - wins: int = betterproto.uint32_field(3) - losses: int = betterproto.uint32_field(4) - xp: int = betterproto.uint32_field(12) - level: int = betterproto.uint32_field(13) - initial_skill: int = betterproto.uint32_field(14) - leaver_count: int = betterproto.uint32_field(15) - secondary_leaver_count: int = betterproto.uint32_field(58) - low_priority_until_date: int = betterproto.uint32_field(18) - prevent_text_chat_until_date: int = betterproto.uint32_field(20) - prevent_voice_until_date: int = betterproto.uint32_field(21) - prevent_public_text_chat_until_date: int = betterproto.uint32_field(86) - prevent_new_player_chat_until_date: int = betterproto.uint32_field(122) - last_abandoned_game_date: int = betterproto.uint32_field(22) - last_secondary_abandoned_game_date: int = betterproto.uint32_field(59) - leaver_penalty_count: int = betterproto.uint32_field(23) - completed_game_streak: int = betterproto.uint32_field(24) - account_disabled_until_date: int = betterproto.uint32_field(38) - account_disabled_count: int = betterproto.uint32_field(39) - match_disabled_until_date: int = betterproto.uint32_field(41) - match_disabled_count: int = betterproto.uint32_field(42) - shutdownlawterminatetimestamp: int = betterproto.uint32_field(47) - low_priority_games_remaining: int = betterproto.uint32_field(48) - recruitment_level: int = betterproto.uint32_field(55) - has_new_notifications: bool = betterproto.bool_field(56) - is_league_admin: bool = betterproto.bool_field(57) - casual_games_played: int = betterproto.uint32_field(60) - solo_competitive_games_played: int = betterproto.uint32_field(61) - party_competitive_games_played: int = betterproto.uint32_field(62) - casual_1v1_games_played: int = betterproto.uint32_field(65) - curr_all_hero_challenge_id: int = betterproto.uint32_field(67) - play_time_points: int = betterproto.uint32_field(68) - account_flags: int = betterproto.uint32_field(69) - play_time_level: int = betterproto.uint32_field(70) - player_behavior_seq_num_last_report: int = betterproto.uint32_field(71) - player_behavior_score_last_report: int = betterproto.uint32_field(72) - player_behavior_report_old_data: bool = betterproto.bool_field(73) - tourney_skill_level: int = betterproto.uint32_field(74) - tourney_recent_participation_date: int = betterproto.uint32_field(85) - anchored_phone_number_id: int = betterproto.uint64_field(88) - ranked_matchmaking_ban_until_date: int = betterproto.uint32_field(89) - recent_game_time_1: int = betterproto.uint32_field(90) - recent_game_time_2: int = betterproto.uint32_field(91) - recent_game_time_3: int = betterproto.uint32_field(92) - favorite_team_packed: int = betterproto.uint64_field(103) - recent_report_time: int = betterproto.uint32_field(104) - custom_game_disabled_until_date: int = betterproto.uint32_field(105) - recent_win_time_1: int = betterproto.uint32_field(106) - recent_win_time_2: int = betterproto.uint32_field(107) - recent_win_time_3: int = betterproto.uint32_field(108) - coach_rating: int = betterproto.uint32_field(109) - queue_points: int = betterproto.uint32_field(114) - role_handicaps: list[CSODOTAGameAccountClientRoleHandicap] = betterproto.message_field(115) - event_mode_recent_time: int = betterproto.uint32_field(120) - mmr_recalibration_time: int = betterproto.uint32_field(121) - - -@dataclass -class CSODOTAGameAccountClientRoleHandicap(betterproto.Message): - role: int = betterproto.uint32_field(1) - handicap: float = betterproto.float_field(2) - - -@dataclass -class CSODOTAGameAccountPlus(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - original_start_date: int = betterproto.uint32_field(2) - plus_flags: int = betterproto.uint32_field(3) - plus_status: int = betterproto.uint32_field(4) - prepaid_time_start: int = betterproto.uint32_field(5) - prepaid_time_balance: int = betterproto.uint32_field(6) - next_payment_date: float = betterproto.fixed32_field(7) - steam_agreement_id: float = betterproto.fixed64_field(8) - - -@dataclass -class CSODOTAChatWheel(betterproto.Message): - message_id: int = betterproto.uint32_field(1) - - -@dataclass -class CMsgLobbyFeaturedGamemodeProgress(betterproto.Message): - accounts: list[CMsgLobbyFeaturedGamemodeProgressAccountProgress] = betterproto.message_field(1) - - -@dataclass -class CMsgLobbyFeaturedGamemodeProgressAccountProgress(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - current_value: int = betterproto.uint32_field(2) - max_value: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgBattleCupVictory(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - win_date: int = betterproto.uint32_field(2) - valid_until: int = betterproto.uint32_field(3) - skill_level: int = betterproto.uint32_field(4) - tournament_id: int = betterproto.uint32_field(5) - division_id: int = betterproto.uint32_field(6) - team_id: int = betterproto.uint32_field(7) - streak: int = betterproto.uint32_field(8) - trophy_id: int = betterproto.uint32_field(9) - - -@dataclass -class CMsgLobbyBattleCupVictoryList(betterproto.Message): - winners: list[CMsgBattleCupVictory] = betterproto.message_field(1) - - -@dataclass -class CMsgDOTABroadcastNotification(betterproto.Message): - message: str = betterproto.string_field(1) - - -@dataclass -class CProtoItemHeroStatue(betterproto.Message): - hero_id: int = betterproto.uint32_field(1) - status_effect_index: int = betterproto.uint32_field(2) - sequence_name: str = betterproto.string_field(3) - cycle: float = betterproto.float_field(4) - wearable: list[int] = betterproto.uint32_field(5) - inscription: str = betterproto.string_field(6) - style: list[int] = betterproto.uint32_field(7) - tournament_drop: bool = betterproto.bool_field(8) - - -@dataclass -class CMatchPlayerAbilityUpgrade(betterproto.Message): - ability: int = betterproto.int32_field(1) - time: int = betterproto.uint32_field(2) - - -@dataclass -class CMatchPlayerTimedCustomStat(betterproto.Message): - stat: EDOTAMatchPlayerTimeCustomStat = betterproto.enum_field(2) - value: float = betterproto.float_field(3) - - -@dataclass -class CMatchPlayerTimedStats(betterproto.Message): - time: int = betterproto.uint32_field(1) - kills: int = betterproto.uint32_field(2) - deaths: int = betterproto.uint32_field(3) - assists: int = betterproto.uint32_field(4) - net_worth: int = betterproto.uint32_field(5) - xp: int = betterproto.uint32_field(6) - last_hits: int = betterproto.uint32_field(7) - denies: int = betterproto.uint32_field(8) - bounty_rune_gold: int = betterproto.uint32_field(9) - range_creep_upgrade_gold: int = betterproto.uint32_field(10) - observer_wards_dewarded: int = betterproto.uint32_field(11) - reliable_gold_earned: int = betterproto.uint32_field(12) - gold_loss_prevented: int = betterproto.uint32_field(13) - hero_kill_gold: int = betterproto.uint32_field(14) - creep_kill_gold: int = betterproto.uint32_field(15) - building_gold: int = betterproto.uint32_field(16) - other_gold: int = betterproto.uint32_field(17) - comeback_gold: int = betterproto.uint32_field(18) - experimental_gold: int = betterproto.uint32_field(19) - experimental2_gold: int = betterproto.uint32_field(20) - creep_deny_gold: int = betterproto.uint32_field(21) - tp_scrolls_purchased_1: int = betterproto.uint32_field(22) - tp_scrolls_purchased_2: int = betterproto.uint32_field(23) - tp_scrolls_purchased_3: int = betterproto.uint32_field(24) - tp_scrolls_purchased_4: int = betterproto.uint32_field(25) - tp_scrolls_purchased_5: int = betterproto.uint32_field(26) - neutral_gold: int = betterproto.uint32_field(27) - courier_gold: int = betterproto.uint32_field(28) - roshan_gold: int = betterproto.uint32_field(29) - income_gold: int = betterproto.uint32_field(30) - item_value: int = betterproto.uint32_field(36) - support_gold_spent: int = betterproto.uint32_field(37) - camps_stacked: int = betterproto.uint32_field(38) - wards_placed: int = betterproto.uint32_field(39) - triple_kills: int = betterproto.uint32_field(40) - rampages: int = betterproto.uint32_field(41) - custom_stats: list[CMatchPlayerTimedCustomStat] = betterproto.message_field(42) - - -@dataclass -class CMatchTeamTimedStats(betterproto.Message): - time: int = betterproto.uint32_field(1) - enemy_towers_killed: int = betterproto.uint32_field(2) - enemy_barracks_killed: int = betterproto.uint32_field(3) - enemy_towers_status: int = betterproto.uint32_field(4) - enemy_barracks_status: int = betterproto.uint32_field(5) - - -@dataclass -class CMatchAdditionalUnitInventory(betterproto.Message): - unit_name: str = betterproto.string_field(1) - items: list[int] = betterproto.int32_field(2) - - -@dataclass -class CMatchPlayerPermanentBuff(betterproto.Message): - permanent_buff: int = betterproto.uint32_field(1) - stack_count: int = betterproto.uint32_field(2) - grant_time: int = betterproto.uint32_field(3) - - -@dataclass -class CMatchHeroSelectEvent(betterproto.Message): - is_pick: bool = betterproto.bool_field(1) - team: int = betterproto.uint32_field(2) - hero_id: int = betterproto.uint32_field(3) - - -@dataclass -class CMatchClip(betterproto.Message): - match_id: int = betterproto.uint64_field(1) - player_account_id: int = betterproto.uint32_field(2) - game_time_seconds: int = betterproto.uint32_field(3) - duration_seconds: int = betterproto.uint32_field(4) - player_id: int = betterproto.uint32_field(5) - hero_id: int = betterproto.uint32_field(6) - ability_id: int = betterproto.int32_field(7) - camera_mode: int = betterproto.uint32_field(8) - comment: str = betterproto.string_field(9) - - -@dataclass -class CPartySearchClientParty(betterproto.Message): - party_id: float = betterproto.fixed64_field(1) - beacon_type: int = betterproto.int32_field(2) - party_members: list[float] = betterproto.fixed32_field(3) - - -@dataclass -class CMsgDOTAHasItemQuery(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - item_id: int = betterproto.uint64_field(2) - - -@dataclass -class CMsgDOTAHasItemResponse(betterproto.Message): - has_item: bool = betterproto.bool_field(1) - - -@dataclass -class CMsgGCGetPlayerCardItemInfo(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - player_card_item_ids: list[int] = betterproto.uint64_field(2) - all_for_event: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgGCGetPlayerCardItemInfoResponse(betterproto.Message): - player_card_infos: list[CMsgGCGetPlayerCardItemInfoResponsePlayerCardInfo] = betterproto.message_field(1) - - -@dataclass -class CMsgGCGetPlayerCardItemInfoResponsePlayerCardInfo(betterproto.Message): - player_card_item_id: int = betterproto.uint64_field(1) - account_id: int = betterproto.uint32_field(2) - packed_bonuses: int = betterproto.uint64_field(3) - - -@dataclass -class CSODOTAMapLocationState(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - location_id: int = betterproto.int32_field(2) - completed: bool = betterproto.bool_field(3) - - -@dataclass -class CMsgLeagueAdminList(betterproto.Message): - account_ids: list[int] = betterproto.uint32_field(1) - - -@dataclass -class CMsgDOTAProfileCard(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - slots: list[CMsgDOTAProfileCardSlot] = betterproto.message_field(3) - badge_points: int = betterproto.uint32_field(4) - event_points: int = betterproto.uint32_field(5) - event_id: int = betterproto.uint32_field(6) - recent_battle_cup_victory: CMsgBattleCupVictory = betterproto.message_field(7) - rank_tier: int = betterproto.uint32_field(8) - leaderboard_rank: int = betterproto.uint32_field(9) - is_plus_subscriber: bool = betterproto.bool_field(10) - plus_original_start_date: int = betterproto.uint32_field(11) - rank_tier_score: int = betterproto.uint32_field(12) - leaderboard_rank_core: int = betterproto.uint32_field(17) - title: int = betterproto.uint32_field(23) - favorite_team_packed: int = betterproto.uint64_field(24) - lifetime_games: int = betterproto.uint32_field(25) - - -@dataclass -class CMsgDOTAProfileCardSlot(betterproto.Message): - slot_id: int = betterproto.uint32_field(1) - trophy: CMsgDOTAProfileCardSlotTrophy = betterproto.message_field(2) - stat: CMsgDOTAProfileCardSlotStat = betterproto.message_field(3) - item: CMsgDOTAProfileCardSlotItem = betterproto.message_field(4) - hero: CMsgDOTAProfileCardSlotHero = betterproto.message_field(5) - emoticon: CMsgDOTAProfileCardSlotEmoticon = betterproto.message_field(6) - team: CMsgDOTAProfileCardSlotTeam = betterproto.message_field(7) - - -@dataclass -class CMsgDOTAProfileCardSlotTrophy(betterproto.Message): - trophy_id: int = betterproto.uint32_field(1) - trophy_score: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgDOTAProfileCardSlotStat(betterproto.Message): - stat_id: CMsgDOTAProfileCardEStatID = betterproto.enum_field(1) - stat_score: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgDOTAProfileCardSlotItem(betterproto.Message): - serialized_item: bytes = betterproto.bytes_field(1) - item_id: int = betterproto.uint64_field(2) - - -@dataclass -class CMsgDOTAProfileCardSlotHero(betterproto.Message): - hero_id: int = betterproto.uint32_field(1) - hero_wins: int = betterproto.uint32_field(2) - hero_losses: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgDOTAProfileCardSlotEmoticon(betterproto.Message): - emoticon_id: int = betterproto.uint32_field(1) - - -@dataclass -class CMsgDOTAProfileCardSlotTeam(betterproto.Message): - team_id: int = betterproto.uint32_field(1) - - -@dataclass -class CSODOTAPlayerChallenge(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - event_id: int = betterproto.uint32_field(2) - slot_id: int = betterproto.uint32_field(3) - int_param_0: int = betterproto.uint32_field(5) - int_param_1: int = betterproto.uint32_field(6) - created_time: int = betterproto.uint32_field(7) - completed: int = betterproto.uint32_field(8) - sequence_id: int = betterproto.uint32_field(9) - challenge_tier: int = betterproto.uint32_field(10) - flags: int = betterproto.uint32_field(11) - attempts: int = betterproto.uint32_field(12) - complete_limit: int = betterproto.uint32_field(13) - quest_rank: int = betterproto.uint32_field(14) - max_quest_rank: int = betterproto.uint32_field(15) - instance_id: int = betterproto.uint32_field(16) - hero_id: int = betterproto.uint32_field(17) - template_id: int = betterproto.uint32_field(18) - - -@dataclass -class CMsgClientToGCRerollPlayerChallenge(betterproto.Message): - event_id: EEvent = betterproto.enum_field(1) - sequence_id: int = betterproto.uint32_field(3) - hero_id: int = betterproto.uint32_field(4) - - -@dataclass -class CMsgGCRerollPlayerChallengeResponse(betterproto.Message): - result: CMsgGCRerollPlayerChallengeResponseEResult = betterproto.enum_field(1) - - -@dataclass -class CMsgGCTopCustomGamesList(betterproto.Message): - top_custom_games: list[int] = betterproto.uint64_field(1) - game_of_the_day: int = betterproto.uint64_field(2) - - -@dataclass -class CMsgDOTARealtimeGameStats(betterproto.Message): - match: CMsgDOTARealtimeGameStatsMatchDetails = betterproto.message_field(1) - teams: list[CMsgDOTARealtimeGameStatsTeamDetails] = betterproto.message_field(2) - buildings: list[CMsgDOTARealtimeGameStatsBuildingDetails] = betterproto.message_field(3) - graph_data: CMsgDOTARealtimeGameStatsGraphData = betterproto.message_field(4) - delta_frame: bool = betterproto.bool_field(5) - - -@dataclass -class CMsgDOTARealtimeGameStatsTeamDetails(betterproto.Message): - team_number: int = betterproto.uint32_field(1) - team_id: int = betterproto.uint32_field(2) - team_name: str = betterproto.string_field(3) - team_logo: float = betterproto.fixed64_field(4) - team_tag: str = betterproto.string_field(10) - score: int = betterproto.uint32_field(5) - net_worth: int = betterproto.uint32_field(9) - players: list[CMsgDOTARealtimeGameStatsPlayerDetails] = betterproto.message_field(6) - only_team: bool = betterproto.bool_field(7) - cheers: int = betterproto.uint32_field(8) - team_logo_url: str = betterproto.string_field(11) - - -@dataclass -class CMsgDOTARealtimeGameStatsItemDetails(betterproto.Message): - item_ability_id: int = betterproto.int32_field(1) - name: str = betterproto.string_field(2) - time: int = betterproto.int32_field(3) - sold: bool = betterproto.bool_field(4) - stackcount: int = betterproto.uint32_field(5) - - -@dataclass -class CMsgDOTARealtimeGameStatsAbilityDetails(betterproto.Message): - id: int = betterproto.int32_field(1) - name: str = betterproto.string_field(2) - level: int = betterproto.uint32_field(3) - cooldown: float = betterproto.float_field(4) - cooldown_max: float = betterproto.float_field(5) - - -@dataclass -class CMsgDOTARealtimeGameStatsHeroToHeroStats(betterproto.Message): - victimid: int = betterproto.int32_field(1) - kills: int = betterproto.uint32_field(2) - assists: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgDOTARealtimeGameStatsAbilityList(betterproto.Message): - id: list[int] = betterproto.int32_field(1) - - -@dataclass -class CMsgDOTARealtimeGameStatsPlayerDetails(betterproto.Message): - accountid: int = betterproto.uint32_field(1) - playerid: int = betterproto.int32_field(2) - name: str = betterproto.string_field(3) - team: int = betterproto.uint32_field(4) - heroid: int = betterproto.uint32_field(5) - healthpoints: int = betterproto.uint32_field(6) - maxhealthpoints: int = betterproto.uint32_field(7) - healthregenrate: float = betterproto.float_field(8) - manapoints: int = betterproto.uint32_field(9) - maxmanapoints: int = betterproto.uint32_field(10) - manaregenrate: float = betterproto.float_field(11) - base_strength: int = betterproto.uint32_field(12) - base_agility: int = betterproto.uint32_field(13) - base_intelligence: int = betterproto.uint32_field(14) - base_armor: int = betterproto.int32_field(15) - base_movespeed: int = betterproto.uint32_field(16) - base_damage: int = betterproto.uint32_field(17) - strength: int = betterproto.uint32_field(18) - agility: int = betterproto.uint32_field(19) - intelligence: int = betterproto.uint32_field(20) - armor: int = betterproto.int32_field(21) - movespeed: int = betterproto.uint32_field(22) - damage: int = betterproto.uint32_field(23) - hero_damage: int = betterproto.uint32_field(24) - tower_damage: int = betterproto.uint32_field(25) - abilities: list[CMsgDOTARealtimeGameStatsAbilityDetails] = betterproto.message_field(26) - level: int = betterproto.uint32_field(27) - kill_count: int = betterproto.uint32_field(28) - death_count: int = betterproto.uint32_field(29) - assists_count: int = betterproto.uint32_field(30) - denies_count: int = betterproto.uint32_field(31) - lh_count: int = betterproto.uint32_field(32) - hero_healing: int = betterproto.uint32_field(33) - gold_per_min: int = betterproto.uint32_field(34) - xp_per_min: int = betterproto.uint32_field(35) - net_gold: int = betterproto.uint32_field(36) - gold: int = betterproto.uint32_field(37) - x: float = betterproto.float_field(38) - y: float = betterproto.float_field(39) - respawn_time: int = betterproto.int32_field(40) - ultimate_cooldown: int = betterproto.uint32_field(41) - has_buyback: bool = betterproto.bool_field(42) - items: list[CMsgDOTARealtimeGameStatsItemDetails] = betterproto.message_field(43) - stashitems: list[CMsgDOTARealtimeGameStatsItemDetails] = betterproto.message_field(44) - itemshoppinglist: list[CMsgDOTARealtimeGameStatsItemDetails] = betterproto.message_field(45) - levelpoints: list[CMsgDOTARealtimeGameStatsAbilityList] = betterproto.message_field(46) - hero_to_hero_stats: list[CMsgDOTARealtimeGameStatsHeroToHeroStats] = betterproto.message_field(47) - has_ultimate: bool = betterproto.bool_field(48) - has_ultimate_mana: bool = betterproto.bool_field(49) - team_slot: int = betterproto.uint32_field(50) - - -@dataclass -class CMsgDOTARealtimeGameStatsBuildingDetails(betterproto.Message): - team: int = betterproto.uint32_field(2) - heading: float = betterproto.float_field(3) - lane: int = betterproto.uint32_field(4) - tier: int = betterproto.uint32_field(5) - type: int = betterproto.uint32_field(6) - x: float = betterproto.float_field(7) - y: float = betterproto.float_field(8) - destroyed: bool = betterproto.bool_field(9) - - -@dataclass -class CMsgDOTARealtimeGameStatsKillDetails(betterproto.Message): - player_id: int = betterproto.int32_field(1) - death_time: int = betterproto.int32_field(2) - killer_player_id: int = betterproto.int32_field(3) - - -@dataclass -class CMsgDOTARealtimeGameStatsBroadcasterDetails(betterproto.Message): - player_id: int = betterproto.int32_field(1) - - -@dataclass -class CMsgDOTARealtimeGameStatsPickBanDetails(betterproto.Message): - hero: int = betterproto.uint32_field(1) - team: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgDOTARealtimeGameStatsMatchDetails(betterproto.Message): - server_steam_id: float = betterproto.fixed64_field(1) - match_id: int = betterproto.uint64_field(2) - timestamp: int = betterproto.uint32_field(3) - time_of_day: float = betterproto.float_field(4) - is_nightstalker_night: bool = betterproto.bool_field(5) - game_time: int = betterproto.int32_field(6) - game_state: int = betterproto.uint32_field(19) - teamid_radiant: int = betterproto.uint32_field(8) - teamid_dire: int = betterproto.uint32_field(9) - picks: list[CMsgDOTARealtimeGameStatsPickBanDetails] = betterproto.message_field(10) - bans: list[CMsgDOTARealtimeGameStatsPickBanDetails] = betterproto.message_field(11) - kills: list[CMsgDOTARealtimeGameStatsKillDetails] = betterproto.message_field(12) - broadcasters: list[CMsgDOTARealtimeGameStatsBroadcasterDetails] = betterproto.message_field(13) - game_mode: int = betterproto.uint32_field(14) - league_id: int = betterproto.uint32_field(15) - league_node_id: int = betterproto.uint32_field(18) - single_team: bool = betterproto.bool_field(16) - cheers_peak: int = betterproto.uint32_field(17) - lobby_type: int = betterproto.uint32_field(20) - start_timestamp: int = betterproto.uint32_field(21) - - -@dataclass -class CMsgDOTARealtimeGameStatsGraphData(betterproto.Message): - graph_gold: list[int] = betterproto.int32_field(1) - graph_xp: list[int] = betterproto.int32_field(2) - graph_kill: list[int] = betterproto.int32_field(3) - graph_tower: list[int] = betterproto.int32_field(4) - graph_rax: list[int] = betterproto.int32_field(5) - team_loc_stats: list[CMsgDOTARealtimeGameStatsGraphDataTeamLocationStats] = betterproto.message_field(6) - - -@dataclass -class CMsgDOTARealtimeGameStatsGraphDataLocationStats(betterproto.Message): - stats: list[int] = betterproto.int32_field(1) - - -@dataclass -class CMsgDOTARealtimeGameStatsGraphDataTeamLocationStats(betterproto.Message): - loc_stats: list[CMsgDOTARealtimeGameStatsGraphDataLocationStats] = betterproto.message_field(1) - - -@dataclass -class CMsgDOTARealtimeGameStatsTerse(betterproto.Message): - match: CMsgDOTARealtimeGameStatsTerseMatchDetails = betterproto.message_field(1) - teams: list[CMsgDOTARealtimeGameStatsTerseTeamDetails] = betterproto.message_field(2) - buildings: list[CMsgDOTARealtimeGameStatsTerseBuildingDetails] = betterproto.message_field(3) - graph_data: CMsgDOTARealtimeGameStatsTerseGraphData = betterproto.message_field(4) - delta_frame: bool = betterproto.bool_field(5) - - -@dataclass -class CMsgDOTARealtimeGameStatsTerseTeamDetails(betterproto.Message): - team_number: int = betterproto.uint32_field(1) - team_id: int = betterproto.uint32_field(2) - team_name: str = betterproto.string_field(3) - team_tag: str = betterproto.string_field(8) - team_logo: float = betterproto.fixed64_field(4) - score: int = betterproto.uint32_field(5) - net_worth: int = betterproto.uint32_field(7) - team_logo_url: str = betterproto.string_field(9) - players: list[CMsgDOTARealtimeGameStatsTersePlayerDetails] = betterproto.message_field(6) - - -@dataclass -class CMsgDOTARealtimeGameStatsTersePlayerDetails(betterproto.Message): - accountid: int = betterproto.uint32_field(1) - playerid: int = betterproto.int32_field(2) - name: str = betterproto.string_field(3) - team: int = betterproto.uint32_field(4) - heroid: int = betterproto.uint32_field(5) - level: int = betterproto.uint32_field(6) - kill_count: int = betterproto.uint32_field(7) - death_count: int = betterproto.uint32_field(8) - assists_count: int = betterproto.uint32_field(9) - denies_count: int = betterproto.uint32_field(10) - lh_count: int = betterproto.uint32_field(11) - gold: int = betterproto.uint32_field(12) - x: float = betterproto.float_field(13) - y: float = betterproto.float_field(14) - net_worth: int = betterproto.uint32_field(15) - abilities: list[int] = betterproto.int32_field(16) - items: list[int] = betterproto.int32_field(17) - team_slot: int = betterproto.uint32_field(18) - - -@dataclass -class CMsgDOTARealtimeGameStatsTerseBuildingDetails(betterproto.Message): - team: int = betterproto.uint32_field(1) - heading: float = betterproto.float_field(2) - type: int = betterproto.uint32_field(3) - lane: int = betterproto.uint32_field(4) - tier: int = betterproto.uint32_field(5) - x: float = betterproto.float_field(6) - y: float = betterproto.float_field(7) - destroyed: bool = betterproto.bool_field(8) - - -@dataclass -class CMsgDOTARealtimeGameStatsTersePickBanDetails(betterproto.Message): - hero: int = betterproto.uint32_field(1) - team: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgDOTARealtimeGameStatsTerseMatchDetails(betterproto.Message): - server_steam_id: float = betterproto.fixed64_field(1) - match_id: int = betterproto.uint64_field(2) - timestamp: int = betterproto.uint32_field(3) - game_time: int = betterproto.int32_field(4) - steam_broadcaster_account_ids: list[int] = betterproto.uint32_field(6) - game_mode: int = betterproto.uint32_field(7) - league_id: int = betterproto.uint32_field(8) - league_node_id: int = betterproto.uint32_field(9) - game_state: int = betterproto.uint32_field(10) - picks: list[CMsgDOTARealtimeGameStatsTersePickBanDetails] = betterproto.message_field(11) - bans: list[CMsgDOTARealtimeGameStatsTersePickBanDetails] = betterproto.message_field(12) - lobby_type: int = betterproto.uint32_field(13) - start_timestamp: int = betterproto.uint32_field(14) - - -@dataclass -class CMsgDOTARealtimeGameStatsTerseGraphData(betterproto.Message): - graph_gold: list[int] = betterproto.int32_field(1) - - -@dataclass -class CMsgDOTABroadcastTimelineEvent(betterproto.Message): - event: EBroadcastTimelineEvent = betterproto.enum_field(1) - timestamp: float = betterproto.fixed32_field(2) - data: int = betterproto.uint32_field(3) - string_data: str = betterproto.string_field(4) - - -@dataclass -class CMsgGCToClientMatchGroupsVersion(betterproto.Message): - matchgroups_version: int = betterproto.uint32_field(1) - - -@dataclass -class CMsgDOTASDOHeroStatsHistory(betterproto.Message): - match_id: int = betterproto.uint64_field(1) - game_mode: int = betterproto.uint32_field(2) - lobby_type: int = betterproto.uint32_field(3) - start_time: int = betterproto.uint32_field(4) - won: bool = betterproto.bool_field(5) - gpm: int = betterproto.uint32_field(6) - xpm: int = betterproto.uint32_field(7) - kills: int = betterproto.uint32_field(8) - deaths: int = betterproto.uint32_field(9) - assists: int = betterproto.uint32_field(10) - - -@dataclass -class CMsgPredictionChoice(betterproto.Message): - value: int = betterproto.uint32_field(1) - name: str = betterproto.string_field(2) - min_raw_value: int = betterproto.uint32_field(3) - max_raw_value: int = betterproto.uint32_field(4) - - -@dataclass -class CMsgInGamePrediction(betterproto.Message): - id: int = betterproto.uint32_field(1) - name: str = betterproto.string_field(2) - type: CMsgInGamePredictionEPredictionType = betterproto.enum_field(3) - group: CMsgInGamePredictionERandomSelectionGroupT = betterproto.enum_field(4) - question: str = betterproto.string_field(5) - choices: list[CMsgPredictionChoice] = betterproto.message_field(6) - required_heroes: list[str] = betterproto.string_field(7) - query_name: str = betterproto.string_field(8) - query_values: list[CMsgInGamePredictionQueryKeyValues] = betterproto.message_field(9) - answer_resolution_type: CMsgInGamePredictionEResolutionTypeT = betterproto.enum_field(10) - points_to_grant: int = betterproto.uint32_field(11) - reward_action: int = betterproto.uint32_field(12) - debug_force_selection: int = betterproto.uint32_field(13) - raw_value_type: CMsgInGamePredictionERawValueTypeT = betterproto.enum_field(14) - - -@dataclass -class CMsgInGamePredictionQueryKeyValues(betterproto.Message): - name: str = betterproto.string_field(1) - value: str = betterproto.string_field(2) - - -@dataclass -class CMsgDOTASeasonPredictions(betterproto.Message): - predictions: list[CMsgDOTASeasonPredictionsPrediction] = betterproto.message_field(1) - in_game_predictions: list[CMsgInGamePrediction] = betterproto.message_field(2) - in_game_prediction_count_per_game: int = betterproto.uint32_field(3) - in_game_prediction_voting_period_minutes: int = betterproto.uint32_field(4) - - -@dataclass -class CMsgDOTASeasonPredictionsPrediction(betterproto.Message): - type: CMsgDOTASeasonPredictionsPredictionEPredictionType = betterproto.enum_field(1) - question: str = betterproto.string_field(2) - choices: list[CMsgPredictionChoice] = betterproto.message_field(3) - selection_id: int = betterproto.uint32_field(4) - start_date: int = betterproto.uint32_field(5) - lock_date: int = betterproto.uint32_field(6) - reward: int = betterproto.uint32_field(7) - answer_type: CMsgDOTASeasonPredictionsPredictionEAnswerType = betterproto.enum_field(8) - answer_id: int = betterproto.uint32_field(9) - answers: list[CMsgDOTASeasonPredictionsPredictionAnswers] = betterproto.message_field(10) - query_name: str = betterproto.string_field(11) - lock_on_selection_id: int = betterproto.uint32_field(13) - lock_on_selection_value: int = betterproto.uint32_field(14) - lock_on_selection_set: bool = betterproto.bool_field(15) - use_answer_value_ranges: bool = betterproto.bool_field(16) - region: ELeagueRegion = betterproto.enum_field(17) - phases: list[ELeaguePhase] = betterproto.enum_field(18) - reward_event: EEvent = betterproto.enum_field(19) - - -@dataclass -class CMsgDOTASeasonPredictionsPredictionAnswers(betterproto.Message): - answer_id: int = betterproto.uint32_field(1) - - -@dataclass -class CMsgAvailablePredictions(betterproto.Message): - match_predictions: list[CMsgAvailablePredictionsMatchPrediction] = betterproto.message_field(1) - - -@dataclass -class CMsgAvailablePredictionsMatchPrediction(betterproto.Message): - match_id: int = betterproto.uint64_field(1) - predictions: list[CMsgInGamePrediction] = betterproto.message_field(2) - - -@dataclass -class CMsgLeagueWatchedGames(betterproto.Message): - leagues: list[CMsgLeagueWatchedGamesLeague] = betterproto.message_field(1) - - -@dataclass -class CMsgLeagueWatchedGamesSeries(betterproto.Message): - node_id: int = betterproto.uint32_field(1) - game: list[int] = betterproto.uint32_field(2) - - -@dataclass -class CMsgLeagueWatchedGamesLeague(betterproto.Message): - league_id: int = betterproto.uint32_field(1) - series: list[CMsgLeagueWatchedGamesSeries] = betterproto.message_field(2) - - -@dataclass -class CMsgDOTAMatch(betterproto.Message): - duration: int = betterproto.uint32_field(3) - starttime: float = betterproto.fixed32_field(4) - players: list[CMsgDOTAMatchPlayer] = betterproto.message_field(5) - match_id: int = betterproto.uint64_field(6) - tower_status: list[int] = betterproto.uint32_field(8) - barracks_status: list[int] = betterproto.uint32_field(9) - cluster: int = betterproto.uint32_field(10) - first_blood_time: int = betterproto.uint32_field(12) - replay_salt: float = betterproto.fixed32_field(13) - server_ip: float = betterproto.fixed32_field(14) - server_port: int = betterproto.uint32_field(15) - lobby_type: int = betterproto.uint32_field(16) - human_players: int = betterproto.uint32_field(17) - average_skill: int = betterproto.uint32_field(18) - game_balance: float = betterproto.float_field(19) - radiant_team_id: int = betterproto.uint32_field(20) - dire_team_id: int = betterproto.uint32_field(21) - leagueid: int = betterproto.uint32_field(22) - radiant_team_name: str = betterproto.string_field(23) - dire_team_name: str = betterproto.string_field(24) - radiant_team_logo: int = betterproto.uint64_field(25) - dire_team_logo: int = betterproto.uint64_field(26) - radiant_team_logo_url: str = betterproto.string_field(54) - dire_team_logo_url: str = betterproto.string_field(55) - radiant_team_complete: int = betterproto.uint32_field(27) - dire_team_complete: int = betterproto.uint32_field(28) - game_mode: DOTAGameMode = betterproto.enum_field(31) - picks_bans: list[CMatchHeroSelectEvent] = betterproto.message_field(32) - match_seq_num: int = betterproto.uint64_field(33) - replay_state: CMsgDOTAMatchReplayState = betterproto.enum_field(34) - radiant_guild_id: int = betterproto.uint32_field(35) - dire_guild_id: int = betterproto.uint32_field(36) - radiant_team_tag: str = betterproto.string_field(37) - dire_team_tag: str = betterproto.string_field(38) - series_id: int = betterproto.uint32_field(39) - series_type: int = betterproto.uint32_field(40) - broadcaster_channels: list[CMsgDOTAMatchBroadcasterChannel] = betterproto.message_field(43) - engine: int = betterproto.uint32_field(44) - custom_game_data: CMsgDOTAMatchCustomGameData = betterproto.message_field(45) - match_flags: int = betterproto.uint32_field(46) - private_metadata_key: float = betterproto.fixed32_field(47) - radiant_team_score: int = betterproto.uint32_field(48) - dire_team_score: int = betterproto.uint32_field(49) - match_outcome: EMatchOutcome = betterproto.enum_field(50) - tournament_id: int = betterproto.uint32_field(51) - tournament_round: int = betterproto.uint32_field(52) - pre_game_duration: int = betterproto.uint32_field(53) - coaches: list[CMsgDOTAMatchCoach] = betterproto.message_field(57) - - -@dataclass -class CMsgDOTAMatchPlayer(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - player_slot: int = betterproto.uint32_field(2) - hero_id: int = betterproto.uint32_field(3) - item_0: int = betterproto.int32_field(4) - item_1: int = betterproto.int32_field(5) - item_2: int = betterproto.int32_field(6) - item_3: int = betterproto.int32_field(7) - item_4: int = betterproto.int32_field(8) - item_5: int = betterproto.int32_field(9) - item_6: int = betterproto.int32_field(59) - item_7: int = betterproto.int32_field(60) - item_8: int = betterproto.int32_field(61) - item_9: int = betterproto.int32_field(76) - expected_team_contribution: float = betterproto.float_field(10) - scaled_metric: float = betterproto.float_field(11) - previous_rank: int = betterproto.uint32_field(12) - rank_change: int = betterproto.sint32_field(13) - mmr_type: int = betterproto.uint32_field(74) - kills: int = betterproto.uint32_field(14) - deaths: int = betterproto.uint32_field(15) - assists: int = betterproto.uint32_field(16) - leaver_status: int = betterproto.uint32_field(17) - gold: int = betterproto.uint32_field(18) - last_hits: int = betterproto.uint32_field(19) - denies: int = betterproto.uint32_field(20) - gold_per_min: int = betterproto.uint32_field(21) - xp_per_min: int = betterproto.uint32_field(22) - gold_spent: int = betterproto.uint32_field(23) - hero_damage: int = betterproto.uint32_field(24) - tower_damage: int = betterproto.uint32_field(25) - hero_healing: int = betterproto.uint32_field(26) - level: int = betterproto.uint32_field(27) - time_last_seen: int = betterproto.uint32_field(28) - player_name: str = betterproto.string_field(29) - support_ability_value: int = betterproto.uint32_field(30) - feeding_detected: bool = betterproto.bool_field(32) - search_rank: int = betterproto.uint32_field(34) - search_rank_uncertainty: int = betterproto.uint32_field(35) - rank_uncertainty_change: int = betterproto.int32_field(36) - hero_play_count: int = betterproto.uint32_field(37) - party_id: float = betterproto.fixed64_field(38) - scaled_hero_damage: int = betterproto.uint32_field(54) - scaled_tower_damage: int = betterproto.uint32_field(55) - scaled_hero_healing: int = betterproto.uint32_field(56) - scaled_kills: float = betterproto.float_field(39) - scaled_deaths: float = betterproto.float_field(40) - scaled_assists: float = betterproto.float_field(41) - claimed_farm_gold: int = betterproto.uint32_field(42) - support_gold: int = betterproto.uint32_field(43) - claimed_denies: int = betterproto.uint32_field(44) - claimed_misses: int = betterproto.uint32_field(45) - misses: int = betterproto.uint32_field(46) - ability_upgrades: list[CMatchPlayerAbilityUpgrade] = betterproto.message_field(47) - additional_units_inventory: list[CMatchAdditionalUnitInventory] = betterproto.message_field(48) - permanent_buffs: list[CMatchPlayerPermanentBuff] = betterproto.message_field(57) - pro_name: str = betterproto.string_field(72) - real_name: str = betterproto.string_field(73) - custom_game_data: CMsgDOTAMatchPlayerCustomGameData = betterproto.message_field(50) - active_plus_subscription: bool = betterproto.bool_field(51) - net_worth: int = betterproto.uint32_field(52) - bot_difficulty: int = betterproto.uint32_field(58) - hero_pick_order: int = betterproto.uint32_field(63) - hero_was_randomed: bool = betterproto.bool_field(64) - hero_was_dota_plus_suggestion: bool = betterproto.bool_field(69) - hero_damage_received: list[CMsgDOTAMatchPlayerHeroDamageReceived] = betterproto.message_field(67) - hero_damage_dealt: list[CMsgDOTAMatchPlayerHeroDamageReceived] = betterproto.message_field(79) - seconds_dead: int = betterproto.uint32_field(70) - gold_lost_to_death: int = betterproto.uint32_field(71) - lane_selection_flags: int = betterproto.uint32_field(75) - bounty_runes: int = betterproto.uint32_field(77) - outposts_captured: int = betterproto.uint32_field(78) - team_number: DOTAGCTeam = betterproto.enum_field(80) - team_slot: int = betterproto.uint32_field(81) - - -@dataclass -class CMsgDOTAMatchPlayerCustomGameData(betterproto.Message): - dota_team: int = betterproto.uint32_field(1) - winner: bool = betterproto.bool_field(2) - - -@dataclass -class CMsgDOTAMatchPlayerHeroDamageReceived(betterproto.Message): - pre_reduction: int = betterproto.uint32_field(1) - post_reduction: int = betterproto.uint32_field(2) - damage_type: CMsgDOTAMatchPlayerHeroDamageType = betterproto.enum_field(3) - - -@dataclass -class CMsgDOTAMatchBroadcasterInfo(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - name: str = betterproto.string_field(2) - - -@dataclass -class CMsgDOTAMatchBroadcasterChannel(betterproto.Message): - country_code: str = betterproto.string_field(1) - description: str = betterproto.string_field(2) - broadcaster_infos: list[CMsgDOTAMatchBroadcasterInfo] = betterproto.message_field(3) - language_code: str = betterproto.string_field(4) - - -@dataclass -class CMsgDOTAMatchCoach(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - coach_name: str = betterproto.string_field(2) - coach_rating: int = betterproto.uint32_field(3) - coach_team: int = betterproto.uint32_field(4) - coach_party_id: int = betterproto.uint64_field(5) - is_private_coach: bool = betterproto.bool_field(6) - - -@dataclass -class CMsgDOTAMatchCustomGameData(betterproto.Message): - custom_game_id: int = betterproto.uint64_field(1) - map_name: str = betterproto.string_field(2) - - -@dataclass -class CMsgPlayerCard(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - stat_modifier: list[CMsgPlayerCardStatModifier] = betterproto.message_field(2) - - -@dataclass -class CMsgPlayerCardStatModifier(betterproto.Message): - stat: int = betterproto.uint32_field(1) - value: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgDOTAFantasyPlayerStats(betterproto.Message): - player_account_id: int = betterproto.uint32_field(1) - match_id: int = betterproto.uint64_field(2) - match_completed: bool = betterproto.bool_field(3) - team_id: int = betterproto.uint32_field(4) - league_id: int = betterproto.uint32_field(5) - delay: int = betterproto.uint32_field(6) - series_id: int = betterproto.uint32_field(7) - series_type: int = betterproto.uint32_field(8) - kills: int = betterproto.uint32_field(10) - deaths: int = betterproto.uint32_field(11) - cs: int = betterproto.uint32_field(12) - gpm: float = betterproto.float_field(13) - tower_kills: int = betterproto.uint32_field(14) - roshan_kills: int = betterproto.uint32_field(15) - teamfight_participation: float = betterproto.float_field(16) - wards_placed: int = betterproto.uint32_field(17) - camps_stacked: int = betterproto.uint32_field(18) - runes_grabbed: int = betterproto.uint32_field(19) - first_blood: int = betterproto.uint32_field(20) - stuns: float = betterproto.float_field(21) - smokes: int = betterproto.uint32_field(22) - neutral_tokens: int = betterproto.uint32_field(23) - watchers: int = betterproto.uint32_field(24) - lotuses: int = betterproto.uint32_field(25) - tormentors: int = betterproto.uint32_field(26) - courier_kills: int = betterproto.uint32_field(27) - title_stats: float = betterproto.fixed64_field(28) - - -@dataclass -class CMsgDOTAFantasyPlayerMatchStats(betterproto.Message): - matches: list[CMsgDOTAFantasyPlayerStats] = betterproto.message_field(1) - - -@dataclass -class CMsgDOTABotDebugInfo(betterproto.Message): - bots: list[CMsgDOTABotDebugInfoBot] = betterproto.message_field(1) - desire_push_lane_top: float = betterproto.float_field(2) - desire_push_lane_mid: float = betterproto.float_field(3) - desire_push_lane_bot: float = betterproto.float_field(4) - desire_defend_lane_top: float = betterproto.float_field(5) - desire_defend_lane_mid: float = betterproto.float_field(6) - desire_defend_lane_bot: float = betterproto.float_field(7) - desire_farm_lane_top: float = betterproto.float_field(8) - desire_farm_lane_mid: float = betterproto.float_field(9) - desire_farm_lane_bot: float = betterproto.float_field(10) - desire_farm_roshan: float = betterproto.float_field(11) - execution_time: float = betterproto.float_field(12) - rune_status: list[int] = betterproto.uint32_field(13) - - -@dataclass -class CMsgDOTABotDebugInfoBot(betterproto.Message): - player_owner_id: int = betterproto.int32_field(1) - hero_id: int = betterproto.uint32_field(2) - difficulty: int = betterproto.uint32_field(3) - power_current: int = betterproto.uint32_field(4) - power_max: int = betterproto.uint32_field(5) - move_target_x: int = betterproto.uint32_field(6) - move_target_y: int = betterproto.uint32_field(7) - move_target_z: int = betterproto.uint32_field(8) - active_mode_id: int = betterproto.uint32_field(9) - execution_time: float = betterproto.float_field(10) - modes: list[CMsgDOTABotDebugInfoBotMode] = betterproto.message_field(11) - action: CMsgDOTABotDebugInfoBotAction = betterproto.message_field(12) - - -@dataclass -class CMsgDOTABotDebugInfoBotMode(betterproto.Message): - mode_id: int = betterproto.uint32_field(1) - desire: float = betterproto.float_field(2) - target_entity: int = betterproto.int32_field(3) - target_x: int = betterproto.uint32_field(4) - target_y: int = betterproto.uint32_field(5) - target_z: int = betterproto.uint32_field(6) - - -@dataclass -class CMsgDOTABotDebugInfoBotAction(betterproto.Message): - action_id: int = betterproto.uint32_field(1) - action_target: str = betterproto.string_field(2) - - -@dataclass -class CMsgSuccessfulHero(betterproto.Message): - hero_id: int = betterproto.uint32_field(1) - win_percent: float = betterproto.float_field(2) - longest_streak: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgRecentMatchInfo(betterproto.Message): - match_id: int = betterproto.uint64_field(1) - game_mode: DOTAGameMode = betterproto.enum_field(2) - kills: int = betterproto.uint32_field(3) - deaths: int = betterproto.uint32_field(4) - assists: int = betterproto.uint32_field(5) - duration: int = betterproto.uint32_field(6) - player_slot: int = betterproto.uint32_field(7) - match_outcome: EMatchOutcome = betterproto.enum_field(8) - timestamp: int = betterproto.uint32_field(9) - lobby_type: int = betterproto.uint32_field(10) - team_number: int = betterproto.uint32_field(11) - - -@dataclass -class CMsgMatchTips(betterproto.Message): - tips: list[CMsgMatchTipsSingleTip] = betterproto.message_field(2) - - -@dataclass -class CMsgMatchTipsSingleTip(betterproto.Message): - source_account_id: int = betterproto.uint32_field(1) - target_account_id: int = betterproto.uint32_field(2) - tip_amount: int = betterproto.uint32_field(3) - event_id: EEvent = betterproto.enum_field(4) - - -@dataclass -class CMsgDOTAMatchMinimal(betterproto.Message): - match_id: int = betterproto.uint64_field(1) - start_time: float = betterproto.fixed32_field(2) - duration: int = betterproto.uint32_field(3) - game_mode: DOTAGameMode = betterproto.enum_field(4) - players: list[CMsgDOTAMatchMinimalPlayer] = betterproto.message_field(6) - tourney: CMsgDOTAMatchMinimalTourney = betterproto.message_field(7) - match_outcome: EMatchOutcome = betterproto.enum_field(8) - radiant_score: int = betterproto.uint32_field(9) - dire_score: int = betterproto.uint32_field(10) - lobby_type: int = betterproto.uint32_field(11) - - -@dataclass -class CMsgDOTAMatchMinimalPlayer(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - hero_id: int = betterproto.uint32_field(2) - kills: int = betterproto.uint32_field(3) - deaths: int = betterproto.uint32_field(4) - assists: int = betterproto.uint32_field(5) - items: list[int] = betterproto.int32_field(6) - player_slot: int = betterproto.uint32_field(7) - pro_name: str = betterproto.string_field(8) - level: int = betterproto.uint32_field(9) - team_number: DOTAGCTeam = betterproto.enum_field(10) - - -@dataclass -class CMsgDOTAMatchMinimalTourney(betterproto.Message): - league_id: int = betterproto.uint32_field(1) - series_type: int = betterproto.uint32_field(8) - series_game: int = betterproto.uint32_field(9) - weekend_tourney_tournament_id: int = betterproto.uint32_field(10) - weekend_tourney_season_trophy_id: int = betterproto.uint32_field(11) - weekend_tourney_division: int = betterproto.uint32_field(12) - weekend_tourney_skill_level: int = betterproto.uint32_field(13) - radiant_team_id: int = betterproto.uint32_field(2) - radiant_team_name: str = betterproto.string_field(3) - radiant_team_logo: float = betterproto.fixed64_field(4) - radiant_team_logo_url: str = betterproto.string_field(14) - dire_team_id: int = betterproto.uint32_field(5) - dire_team_name: str = betterproto.string_field(6) - dire_team_logo: float = betterproto.fixed64_field(7) - dire_team_logo_url: str = betterproto.string_field(15) - - -@dataclass -class CMsgConsumableUsage(betterproto.Message): - item_def: int = betterproto.uint32_field(1) - quantity_change: int = betterproto.int32_field(2) - - -@dataclass -class CMsgMatchConsumableUsage(betterproto.Message): - player_consumables_used: list[CMsgMatchConsumableUsagePlayerUsage] = betterproto.message_field(1) - - -@dataclass -class CMsgMatchConsumableUsagePlayerUsage(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - consumables_used: list[CMsgConsumableUsage] = betterproto.message_field(2) - - -@dataclass -class CMsgMatchEventActionGrants(betterproto.Message): - player_grants: list[CMsgMatchEventActionGrantsPlayerGrants] = betterproto.message_field(1) - - -@dataclass -class CMsgMatchEventActionGrantsPlayerGrants(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - actions_granted: list[CMsgPendingEventAward] = betterproto.message_field(3) - - -@dataclass -class CMsgCustomGameWhitelist(betterproto.Message): - version: int = betterproto.uint32_field(1) - custom_games_whitelist: list[int] = betterproto.uint64_field(2) - disable_whitelist: bool = betterproto.bool_field(3) - - -@dataclass -class CMsgCustomGameWhitelistForEdit(betterproto.Message): - whitelist_entries: list[CMsgCustomGameWhitelistForEditWhitelistEntry] = betterproto.message_field(1) - - -@dataclass -class CMsgCustomGameWhitelistForEditWhitelistEntry(betterproto.Message): - custom_game_id: int = betterproto.uint64_field(1) - whitelist_state: ECustomGameWhitelistState = betterproto.enum_field(2) - - -@dataclass -class CMsgPlayerRecentMatchInfo(betterproto.Message): - match_id: int = betterproto.uint64_field(1) - timestamp: int = betterproto.uint32_field(2) - duration: int = betterproto.uint32_field(3) - win: bool = betterproto.bool_field(4) - hero_id: int = betterproto.uint32_field(5) - kills: int = betterproto.uint32_field(6) - deaths: int = betterproto.uint32_field(7) - assists: int = betterproto.uint32_field(8) - - -@dataclass -class CMsgPlayerMatchRecord(betterproto.Message): - wins: int = betterproto.uint32_field(1) - losses: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgPlayerRecentMatchOutcomes(betterproto.Message): - outcomes: int = betterproto.uint32_field(1) - match_count: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgPlayerRecentCommends(betterproto.Message): - commends: int = betterproto.uint32_field(1) - match_count: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgPlayerRecentAccomplishments(betterproto.Message): - recent_outcomes: CMsgPlayerRecentMatchOutcomes = betterproto.message_field(1) - total_record: CMsgPlayerMatchRecord = betterproto.message_field(2) - prediction_streak: int = betterproto.uint32_field(3) - plus_prediction_streak: int = betterproto.uint32_field(4) - recent_commends: CMsgPlayerRecentCommends = betterproto.message_field(5) - first_match_timestamp: int = betterproto.uint32_field(6) - last_match: CMsgPlayerRecentMatchInfo = betterproto.message_field(7) - recent_mvps: CMsgPlayerRecentMatchOutcomes = betterproto.message_field(8) - - -@dataclass -class CMsgPlayerHeroRecentAccomplishments(betterproto.Message): - recent_outcomes: CMsgPlayerRecentMatchOutcomes = betterproto.message_field(1) - total_record: CMsgPlayerMatchRecord = betterproto.message_field(2) - last_match: CMsgPlayerRecentMatchInfo = betterproto.message_field(3) - - -@dataclass -class CMsgRecentAccomplishments(betterproto.Message): - player_accomplishments: CMsgPlayerRecentAccomplishments = betterproto.message_field(1) - hero_accomplishments: CMsgPlayerHeroRecentAccomplishments = betterproto.message_field(2) - - -@dataclass -class CMsgServerToGCRequestPlayerRecentAccomplishments(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - hero_id: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgServerToGCRequestPlayerRecentAccomplishmentsResponse(betterproto.Message): - result: CMsgServerToGCRequestPlayerRecentAccomplishmentsResponseEResponse = betterproto.enum_field(1) - player_accomplishments: CMsgRecentAccomplishments = betterproto.message_field(2) - - -@dataclass -class CMsgArcanaVoteMatchVotes(betterproto.Message): - match_id: int = betterproto.uint32_field(1) - hero_id: int = betterproto.uint32_field(2) - vote_count: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgGCtoGCAssociatedExploiterAccountInfo(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - num_matches_to_search: int = betterproto.uint32_field(2) - min_shared_match_count: int = betterproto.uint32_field(3) - num_additional_players: int = betterproto.uint32_field(4) - - -@dataclass -class CMsgGCtoGCAssociatedExploiterAccountInfoResponse(betterproto.Message): - accounts: list[CMsgGCtoGCAssociatedExploiterAccountInfoResponseAccount] = betterproto.message_field(1) - - -@dataclass -class CMsgGCtoGCAssociatedExploiterAccountInfoResponseAccount(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - num_common_matches: int = betterproto.uint32_field(2) - earliest_common_match: int = betterproto.uint32_field(3) - latest_common_match: int = betterproto.uint32_field(4) - generation: int = betterproto.uint32_field(5) - persona: str = betterproto.string_field(6) - already_banned: bool = betterproto.bool_field(7) - - -@dataclass -class CMsgPullTabsData(betterproto.Message): - slots: list[CMsgPullTabsDataSlot] = betterproto.message_field(1) - jackpots: list[CMsgPullTabsDataJackpot] = betterproto.message_field(2) - last_board: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgPullTabsDataSlot(betterproto.Message): - event_id: int = betterproto.uint32_field(1) - board_id: int = betterproto.uint32_field(2) - hero_id: int = betterproto.uint32_field(3) - action_id: int = betterproto.uint32_field(4) - redeemed: bool = betterproto.bool_field(5) - - -@dataclass -class CMsgPullTabsDataJackpot(betterproto.Message): - board_id: int = betterproto.uint32_field(1) - action_id: int = betterproto.uint32_field(2) - hero_id: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgUnderDraftData(betterproto.Message): - bench_slots: list[CMsgUnderDraftDataBenchSlot] = betterproto.message_field(1) - shop_slots: list[CMsgUnderDraftDataShopSlot] = betterproto.message_field(2) - gold: int = betterproto.uint32_field(3) - total_gold: int = betterproto.uint32_field(4) - not_restorable: bool = betterproto.bool_field(5) - - -@dataclass -class CMsgUnderDraftDataBenchSlot(betterproto.Message): - slot_id: int = betterproto.uint32_field(1) - hero_id: int = betterproto.uint32_field(2) - stars: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgUnderDraftDataShopSlot(betterproto.Message): - slot_id: int = betterproto.uint32_field(1) - hero_id: int = betterproto.uint32_field(2) - is_special_reward: bool = betterproto.bool_field(3) - - -@dataclass -class CMsgPlayerTitleData(betterproto.Message): - title: list[int] = betterproto.uint32_field(1) - event_id: list[int] = betterproto.uint32_field(2) - active: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgDOTATriviaQuestion(betterproto.Message): - question_id: int = betterproto.uint32_field(1) - category: EDOTATriviaQuestionCategory = betterproto.enum_field(2) - timestamp: int = betterproto.uint32_field(3) - question_value: str = betterproto.string_field(4) - answer_values: list[str] = betterproto.string_field(5) - correct_answer_index: int = betterproto.uint32_field(6) - - -@dataclass -class CMsgDOTATriviaQuestionAnswersSummary(betterproto.Message): - summary_available: bool = betterproto.bool_field(1) - picked_count: list[int] = betterproto.uint32_field(2) - - -@dataclass -class CMsgGameDataSpecialValueBonus(betterproto.Message): - name: str = betterproto.string_field(1) - value: float = betterproto.float_field(2) - operation: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgGameDataSpecialValues(betterproto.Message): - name: str = betterproto.string_field(1) - values_float: list[float] = betterproto.float_field(2) - is_percentage: bool = betterproto.bool_field(4) - heading_loc: str = betterproto.string_field(5) - bonuses: list[CMsgGameDataSpecialValueBonus] = betterproto.message_field(6) - values_shard: list[float] = betterproto.float_field(7) - values_scepter: list[float] = betterproto.float_field(8) - - -@dataclass -class CMsgGameDataAbilityOrItem(betterproto.Message): - id: int = betterproto.int32_field(1) - name: str = betterproto.string_field(2) - name_loc: str = betterproto.string_field(5) - desc_loc: str = betterproto.string_field(6) - lore_loc: str = betterproto.string_field(7) - notes_loc: list[str] = betterproto.string_field(8) - shard_loc: str = betterproto.string_field(9) - scepter_loc: str = betterproto.string_field(10) - type: int = betterproto.uint32_field(20) - behavior: int = betterproto.uint64_field(21) - target_team: int = betterproto.uint32_field(22) - target_type: int = betterproto.uint32_field(23) - flags: int = betterproto.uint32_field(24) - damage: int = betterproto.uint32_field(25) - immunity: int = betterproto.uint32_field(26) - dispellable: int = betterproto.uint32_field(27) - max_level: int = betterproto.uint32_field(28) - cast_ranges: list[int] = betterproto.uint32_field(30) - cast_points: list[float] = betterproto.float_field(31) - channel_times: list[float] = betterproto.float_field(32) - cooldowns: list[float] = betterproto.float_field(33) - durations: list[float] = betterproto.float_field(34) - damages: list[int] = betterproto.uint32_field(35) - mana_costs: list[int] = betterproto.uint32_field(36) - gold_costs: list[int] = betterproto.uint32_field(37) - health_costs: list[int] = betterproto.uint32_field(38) - special_values: list[CMsgGameDataSpecialValues] = betterproto.message_field(40) - is_item: bool = betterproto.bool_field(50) - ability_has_scepter: bool = betterproto.bool_field(60) - ability_has_shard: bool = betterproto.bool_field(61) - ability_is_granted_by_scepter: bool = betterproto.bool_field(62) - ability_is_granted_by_shard: bool = betterproto.bool_field(63) - item_cost: int = betterproto.uint32_field(70) - item_initial_charges: int = betterproto.uint32_field(71) - item_neutral_tier: int = betterproto.uint32_field(72) - item_stock_max: int = betterproto.uint32_field(73) - item_stock_time: float = betterproto.float_field(74) - item_quality: int = betterproto.uint32_field(85) - - -@dataclass -class CMsgGameDataHero(betterproto.Message): - id: int = betterproto.uint32_field(1) - name: str = betterproto.string_field(2) - order_id: int = betterproto.uint32_field(3) - name_loc: str = betterproto.string_field(5) - bio_loc: str = betterproto.string_field(6) - hype_loc: str = betterproto.string_field(7) - npe_desc_loc: str = betterproto.string_field(8) - str_base: int = betterproto.uint32_field(10) - str_gain: float = betterproto.float_field(11) - agi_base: int = betterproto.uint32_field(12) - agi_gain: float = betterproto.float_field(13) - int_base: int = betterproto.uint32_field(14) - int_gain: float = betterproto.float_field(15) - primary_attr: int = betterproto.uint32_field(20) - complexity: int = betterproto.uint32_field(21) - attack_capability: int = betterproto.uint32_field(22) - role_levels: list[int] = betterproto.uint32_field(23) - damage_min: int = betterproto.int32_field(24) - damage_max: int = betterproto.int32_field(25) - attack_rate: float = betterproto.float_field(26) - attack_range: int = betterproto.uint32_field(27) - projectile_speed: int = betterproto.uint32_field(28) - armor: float = betterproto.float_field(29) - magic_resistance: int = betterproto.uint32_field(30) - movement_speed: int = betterproto.uint32_field(31) - turn_rate: float = betterproto.float_field(32) - sight_range_day: int = betterproto.uint32_field(33) - sight_range_night: int = betterproto.uint32_field(34) - max_health: int = betterproto.uint32_field(35) - health_regen: float = betterproto.float_field(36) - max_mana: int = betterproto.uint32_field(37) - mana_regen: float = betterproto.float_field(38) - abilities: list[CMsgGameDataAbilityOrItem] = betterproto.message_field(40) - talents: list[CMsgGameDataAbilityOrItem] = betterproto.message_field(41) - - -@dataclass -class CMsgGameDataAbilities(betterproto.Message): - abilities: list[CMsgGameDataAbilityOrItem] = betterproto.message_field(1) - - -@dataclass -class CMsgGameDataItems(betterproto.Message): - items: list[CMsgGameDataAbilityOrItem] = betterproto.message_field(1) - - -@dataclass -class CMsgGameDataHeroes(betterproto.Message): - heroes: list[CMsgGameDataHero] = betterproto.message_field(1) - - -@dataclass -class CMsgGameDataHeroList(betterproto.Message): - heroes: list[CMsgGameDataHeroListHeroInfo] = betterproto.message_field(1) - - -@dataclass -class CMsgGameDataHeroListHeroInfo(betterproto.Message): - id: int = betterproto.uint32_field(1) - name: str = betterproto.string_field(2) - name_loc: str = betterproto.string_field(3) - name_english_loc: str = betterproto.string_field(4) - primary_attr: int = betterproto.uint32_field(5) - complexity: int = betterproto.uint32_field(6) - - -@dataclass -class CMsgGameDataItemAbilityList(betterproto.Message): - itemabilities: list[CMsgGameDataItemAbilityListItemAbilityInfo] = betterproto.message_field(1) - - -@dataclass -class CMsgGameDataItemAbilityListItemAbilityInfo(betterproto.Message): - id: int = betterproto.int32_field(1) - name: str = betterproto.string_field(2) - name_loc: str = betterproto.string_field(3) - name_english_loc: str = betterproto.string_field(4) - neutral_item_tier: int = betterproto.int32_field(5) - - -@dataclass -class CMsgLobbyAbilityDraftData(betterproto.Message): - shuffle_draft_order: bool = betterproto.bool_field(1) - - -@dataclass -class CSOEconItemDropRateBonus(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - expiration_date: float = betterproto.fixed32_field(2) - bonus: float = betterproto.float_field(3) - bonus_count: int = betterproto.uint32_field(4) - item_id: int = betterproto.uint64_field(5) - def_index: int = betterproto.uint32_field(6) - seconds_left: int = betterproto.uint32_field(7) - booster_type: int = betterproto.uint32_field(8) - - -@dataclass -class CSOEconItemTournamentPassport(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - league_id: int = betterproto.uint32_field(2) - item_id: int = betterproto.uint64_field(3) - original_purchaser_id: int = betterproto.uint32_field(4) - passports_bought: int = betterproto.uint32_field(5) - version: int = betterproto.uint32_field(6) - def_index: int = betterproto.uint32_field(7) - reward_flags: int = betterproto.uint32_field(8) - - -@dataclass -class CMsgStickerbookSticker(betterproto.Message): - item_def_id: int = betterproto.uint32_field(1) - sticker_num: int = betterproto.uint32_field(2) - quality: int = betterproto.uint32_field(3) - position_x: float = betterproto.float_field(4) - position_y: float = betterproto.float_field(5) - position_z: float = betterproto.float_field(8) - rotation: float = betterproto.float_field(6) - scale: float = betterproto.float_field(7) - source_item_id: int = betterproto.uint64_field(9) - depth_bias: int = betterproto.uint32_field(10) - - -@dataclass -class CMsgStickerbookPage(betterproto.Message): - page_num: int = betterproto.uint32_field(1) - event_id: EEvent = betterproto.enum_field(2) - team_id: int = betterproto.uint32_field(3) - stickers: list[CMsgStickerbookSticker] = betterproto.message_field(4) - page_type: EStickerbookPageType = betterproto.enum_field(5) - - -@dataclass -class CMsgStickerbookTeamPageOrderSequence(betterproto.Message): - page_numbers: list[int] = betterproto.uint32_field(1) - - -@dataclass -class CMsgStickerbook(betterproto.Message): - pages: list[CMsgStickerbookPage] = betterproto.message_field(1) - team_page_order_sequence: CMsgStickerbookTeamPageOrderSequence = betterproto.message_field(2) - favorite_page_num: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgStickerHero(betterproto.Message): - hero_id: int = betterproto.uint32_field(1) - item_def_id: int = betterproto.uint32_field(2) - quality: int = betterproto.uint32_field(3) - source_item_id: int = betterproto.uint64_field(4) - - -@dataclass -class CMsgStickerHeroes(betterproto.Message): - heroes: list[CMsgStickerHero] = betterproto.message_field(1) - - -@dataclass -class CMsgHeroRoleStats(betterproto.Message): - lane_selection_flags: int = betterproto.uint32_field(1) - match_count: int = betterproto.uint32_field(2) - win_count: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgHeroRoleHeroStats(betterproto.Message): - hero_id: int = betterproto.uint32_field(1) - role_stats: list[CMsgHeroRoleStats] = betterproto.message_field(2) - - -@dataclass -class CMsgHeroRoleRankStats(betterproto.Message): - rank_tier: int = betterproto.uint32_field(1) - hero_stats: list[CMsgHeroRoleHeroStats] = betterproto.message_field(2) - - -@dataclass -class CMsgHeroRoleAllRanksStats(betterproto.Message): - start_timestamp: int = betterproto.uint32_field(1) - end_timestamp: int = betterproto.uint32_field(2) - rank_stats: list[CMsgHeroRoleRankStats] = betterproto.message_field(3) - - -@dataclass -class CMsgMapStatsSnapshot(betterproto.Message): - timestamp: int = betterproto.uint32_field(1) - lotuses_gained: int = betterproto.uint64_field(2) - wisdom_runes_gained: int = betterproto.uint64_field(3) - roshan_kills_day: int = betterproto.uint64_field(4) - roshan_kills_night: int = betterproto.uint64_field(5) - portals_used: int = betterproto.uint64_field(6) - watchers_taken: int = betterproto.uint64_field(7) - tormentor_kills: int = betterproto.uint64_field(8) - outposts_captured: int = betterproto.uint64_field(9) - shield_runes_gained: int = betterproto.uint64_field(10) - - -@dataclass -class CMsgGlobalMapStats(betterproto.Message): - current: CMsgMapStatsSnapshot = betterproto.message_field(1) - window_start: CMsgMapStatsSnapshot = betterproto.message_field(2) - window_end: CMsgMapStatsSnapshot = betterproto.message_field(3) - - -@dataclass -class CMsgTrackedStat(betterproto.Message): - tracked_stat_id: int = betterproto.uint32_field(1) - tracked_stat_value: int = betterproto.int32_field(2) diff --git a/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py b/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py deleted file mode 100644 index de2cf0c8..00000000 --- a/steam/ext/dota2/protobufs/dota_gcmessages_msgid.py +++ /dev/null @@ -1,896 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: dota_gcmessages_msgid.proto -# plugin: python-betterproto - -import betterproto - - -class EDOTAGCMsg(betterproto.Enum): - GCDOTABase = 7000 - GCGameMatchSignOut = 7004 - GCGameMatchSignOutResponse = 7005 - GCJoinChatChannel = 7009 - GCJoinChatChannelResponse = 7010 - GCOtherJoinedChannel = 7013 - GCOtherLeftChannel = 7014 - ServerToGCRequestStatus = 7026 - GCStartFindingMatch = 7033 - GCConnectedPlayers = 7034 - GCAbandonCurrentGame = 7035 - GCStopFindingMatch = 7036 - GCPracticeLobbyCreate = 7038 - GCPracticeLobbyLeave = 7040 - GCPracticeLobbyLaunch = 7041 - GCPracticeLobbyList = 7042 - GCPracticeLobbyListResponse = 7043 - GCPracticeLobbyJoin = 7044 - GCPracticeLobbySetDetails = 7046 - GCPracticeLobbySetTeamSlot = 7047 - GCInitialQuestionnaireResponse = 7049 - GCPracticeLobbyResponse = 7055 - GCBroadcastNotification = 7056 - GCLiveScoreboardUpdate = 7057 - GCRequestChatChannelList = 7060 - GCRequestChatChannelListResponse = 7061 - GCReadyUp = 7070 - GCKickedFromMatchmakingQueue = 7071 - GCLeaverDetected = 7072 - GCSpectateFriendGame = 7073 - GCSpectateFriendGameResponse = 7074 - GCReportsRemainingRequest = 7076 - GCReportsRemainingResponse = 7077 - GCSubmitPlayerReport = 7078 - GCSubmitPlayerReportResponse = 7079 - GCPracticeLobbyKick = 7081 - GCSubmitPlayerReportV2 = 7082 - GCSubmitPlayerReportResponseV2 = 7083 - GCRequestSaveGames = 7084 - GCRequestSaveGamesServer = 7085 - GCRequestSaveGamesResponse = 7086 - GCLeaverDetectedResponse = 7087 - GCPlayerFailedToConnect = 7088 - GCGCToRelayConnect = 7089 - GCGCToRelayConnectresponse = 7090 - GCWatchGame = 7091 - GCWatchGameResponse = 7092 - GCBanStatusRequest = 7093 - GCBanStatusResponse = 7094 - GCMatchDetailsRequest = 7095 - GCMatchDetailsResponse = 7096 - GCCancelWatchGame = 7097 - GCPopup = 7102 - GCFriendPracticeLobbyListRequest = 7111 - GCFriendPracticeLobbyListResponse = 7112 - GCPracticeLobbyJoinResponse = 7113 - GCCreateTeam = 7115 - GCCreateTeamResponse = 7116 - GCTeamInvite_InviterToGC = 7122 - GCTeamInvite_GCImmediateResponseToInviter = 7123 - GCTeamInvite_GCRequestToInvitee = 7124 - GCTeamInvite_InviteeResponseToGC = 7125 - GCTeamInvite_GCResponseToInviter = 7126 - GCTeamInvite_GCResponseToInvitee = 7127 - GCKickTeamMember = 7128 - GCKickTeamMemberResponse = 7129 - GCLeaveTeam = 7130 - GCLeaveTeamResponse = 7131 - GCApplyTeamToPracticeLobby = 7142 - GCTransferTeamAdmin = 7144 - GCPracticeLobbyJoinBroadcastChannel = 7149 - GC_TournamentItemEvent = 7150 - GC_TournamentItemEventResponse = 7151 - TeamFanfare = 7156 - ResponseTeamFanfare = 7157 - GC_GameServerUploadSaveGame = 7158 - GC_GameServerSaveGameResult = 7159 - GC_GameServerGetLoadGame = 7160 - GC_GameServerGetLoadGameResult = 7161 - GCEditTeamDetails = 7166 - GCEditTeamDetailsResponse = 7167 - GCReadyUpStatus = 7170 - GCToGCMatchCompleted = 7186 - GCBalancedShuffleLobby = 7188 - GCMatchmakingStatsRequest = 7197 - GCMatchmakingStatsResponse = 7198 - GCBotGameCreate = 7199 - GCSetMatchHistoryAccess = 7200 - GCSetMatchHistoryAccessResponse = 7201 - UpgradeLeagueItem = 7203 - UpgradeLeagueItemResponse = 7204 - GCWatchDownloadedReplay = 7206 - ClientsRejoinChatChannels = 7217 - GCToGCGetUserChatInfo = 7218 - GCToGCGetUserChatInfoResponse = 7219 - GCToGCLeaveAllChatChannels = 7220 - GCToGCUpdateAccountChatBan = 7221 - GCToGCCanInviteUserToTeam = 7234 - GCToGCCanInviteUserToTeamResponse = 7235 - GCToGCGetUserRank = 7236 - GCToGCGetUserRankResponse = 7237 - GCToGCAdjustUserRank = 7238 - GCToGCAdjustUserRankResponse = 7239 - GCToGCUpdateTeamStats = 7240 - GCToGCValidateTeam = 7241 - GCToGCValidateTeamResponse = 7242 - GCToGCGetLeagueAdmin = 7255 - GCToGCGetLeagueAdminResponse = 7256 - GCLeaveChatChannel = 7272 - GCChatMessage = 7273 - GCGetHeroStandings = 7274 - GCGetHeroStandingsResponse = 7275 - GCItemEditorReservationsRequest = 7283 - GCItemEditorReservationsResponse = 7284 - GCItemEditorReserveItemDef = 7285 - GCItemEditorReserveItemDefResponse = 7286 - GCItemEditorReleaseReservation = 7287 - GCItemEditorReleaseReservationResponse = 7288 - GCRewardTutorialPrizes = 7289 - GCFantasyLivePlayerStats = 7308 - GCFantasyFinalPlayerStats = 7309 - GCFlipLobbyTeams = 7320 - GCToGCEvaluateReportedPlayer = 7322 - GCToGCEvaluateReportedPlayerResponse = 7323 - GCToGCProcessPlayerReportForTarget = 7324 - GCToGCProcessReportSuccess = 7325 - GCNotifyAccountFlagsChange = 7326 - GCSetProfilePrivacy = 7327 - GCSetProfilePrivacyResponse = 7328 - GCClientSuspended = 7342 - GCPartyMemberSetCoach = 7343 - GCPracticeLobbySetCoach = 7346 - GCChatModeratorBan = 7359 - GCLobbyUpdateBroadcastChannelInfo = 7367 - GCToGCGrantTournamentItem = 7372 - GCToGCUpgradeTwitchViewerItems = 7375 - GCToGCGetLiveMatchAffiliates = 7376 - GCToGCGetLiveMatchAffiliatesResponse = 7377 - GCToGCUpdatePlayerPennantCounts = 7378 - GCToGCGetPlayerPennantCounts = 7379 - GCToGCGetPlayerPennantCountsResponse = 7380 - GCGameMatchSignOutPermissionRequest = 7381 - GCGameMatchSignOutPermissionResponse = 7382 - DOTAAwardEventPoints = 7384 - DOTAGetEventPoints = 7387 - DOTAGetEventPointsResponse = 7388 - GCPartyLeaderWatchGamePrompt = 7397 - GCCompendiumSetSelection = 7405 - GCCompendiumDataRequest = 7406 - GCCompendiumDataResponse = 7407 - DOTAGetPlayerMatchHistory = 7408 - DOTAGetPlayerMatchHistoryResponse = 7409 - GCToGCMatchmakingAddParty = 7410 - GCToGCMatchmakingRemoveParty = 7411 - GCToGCMatchmakingRemoveAllParties = 7412 - GCToGCMatchmakingMatchFound = 7413 - GCToGCUpdateMatchManagementStats = 7414 - GCToGCUpdateMatchmakingStats = 7415 - GCToServerPingRequest = 7416 - GCToServerPingResponse = 7417 - GCToServerEvaluateToxicChat = 7418 - ServerToGCEvaluateToxicChat = 7419 - ServerToGCEvaluateToxicChatResponse = 7420 - GCToGCProcessMatchLeaver = 7426 - GCNotificationsRequest = 7427 - GCNotificationsResponse = 7428 - GCToGCModifyNotification = 7429 - GCLeagueAdminList = 7434 - GCNotificationsMarkReadRequest = 7435 - ServerToGCRequestBatchPlayerResources = 7450 - ServerToGCRequestBatchPlayerResourcesResponse = 7451 - GCCompendiumSetSelectionResponse = 7453 - GCPlayerInfoSubmit = 7456 - GCPlayerInfoSubmitResponse = 7457 - GCToGCGetAccountLevel = 7458 - GCToGCGetAccountLevelResponse = 7459 - DOTAGetWeekendTourneySchedule = 7464 - DOTAWeekendTourneySchedule = 7465 - GCJoinableCustomGameModesRequest = 7466 - GCJoinableCustomGameModesResponse = 7467 - GCJoinableCustomLobbiesRequest = 7468 - GCJoinableCustomLobbiesResponse = 7469 - GCQuickJoinCustomLobby = 7470 - GCQuickJoinCustomLobbyResponse = 7471 - GCToGCGrantEventPointAction = 7472 - GCToGCSetCompendiumSelection = 7478 - GCHasItemQuery = 7484 - GCHasItemResponse = 7485 - GCToGCGrantEventPointActionMsg = 7488 - GCToGCGetCompendiumSelections = 7492 - GCToGCGetCompendiumSelectionsResponse = 7493 - ServerToGCMatchConnectionStats = 7494 - GCToClientTournamentItemDrop = 7495 - SQLDelayedGrantLeagueDrop = 7496 - ServerGCUpdateSpectatorCount = 7497 - GCToGCEmoticonUnlock = 7501 - SignOutDraftInfo = 7502 - ClientToGCEmoticonDataRequest = 7503 - GCToClientEmoticonData = 7504 - GCPracticeLobbyToggleBroadcastChannelCameramanStatus = 7505 - DOTARedeemItem = 7518 - DOTARedeemItemResponse = 7519 - ClientToGCGetAllHeroProgress = 7521 - ClientToGCGetAllHeroProgressResponse = 7522 - GCToGCGetServerForClient = 7523 - GCToGCGetServerForClientResponse = 7524 - SQLProcessTournamentGameOutcome = 7525 - SQLGrantTrophyToAccount = 7526 - ClientToGCGetTrophyList = 7527 - ClientToGCGetTrophyListResponse = 7528 - GCToClientTrophyAwarded = 7529 - GCGameBotMatchSignOut = 7530 - GCGameBotMatchSignOutPermissionRequest = 7531 - SignOutBotInfo = 7532 - GCToGCUpdateProfileCards = 7533 - ClientToGCGetProfileCard = 7534 - ClientToGCGetProfileCardResponse = 7535 - ClientToGCGetBattleReport = 7536 - ClientToGCGetBattleReportResponse = 7537 - ClientToGCSetProfileCardSlots = 7538 - GCToClientProfileCardUpdated = 7539 - ServerToGCVictoryPredictions = 7540 - ClientToGCGetBattleReportAggregateStats = 7541 - ClientToGCGetBattleReportAggregateStatsResponse = 7542 - ClientToGCGetBattleReportInfo = 7543 - ClientToGCGetBattleReportInfoResponse = 7544 - SignOutCommunicationSummary = 7545 - ServerToGCRequestStatus_Response = 7546 - ClientToGCCreateHeroStatue = 7547 - GCToClientHeroStatueCreateResult = 7548 - GCGCToLANServerRelayConnect = 7549 - ClientToGCAcknowledgeBattleReport = 7550 - ClientToGCAcknowledgeBattleReportResponse = 7551 - ClientToGCGetBattleReportMatchHistory = 7552 - ClientToGCGetBattleReportMatchHistoryResponse = 7553 - ServerToGCReportKillSummaries = 7554 - GCToGCUpdatePlayerPredictions = 7561 - GCToServerPredictionResult = 7562 - GCToGCReplayMonitorValidateReplay = 7569 - LobbyEventPoints = 7572 - GCToGCGetCustomGameTickets = 7573 - GCToGCGetCustomGameTicketsResponse = 7574 - GCToGCCustomGamePlayed = 7576 - GCToGCGrantEventPointsToUser = 7577 - GameserverCrashReport = 7579 - GameserverCrashReportResponse = 7580 - GCToClientSteamDatagramTicket = 7581 - GCToGCSendAccountsEventPoints = 7583 - ClientToGCRerollPlayerChallenge = 7584 - ServerToGCRerollPlayerChallenge = 7585 - GCRerollPlayerChallengeResponse = 7586 - SignOutUpdatePlayerChallenge = 7587 - ClientToGCSetPartyLeader = 7588 - ClientToGCCancelPartyInvites = 7589 - SQLGrantLeagueMatchToTicketHolders = 7592 - GCToGCEmoticonUnlockNoRollback = 7594 - ClientToGCApplyGemCombiner = 7603 - ClientToGCGetAllHeroOrder = 7606 - ClientToGCGetAllHeroOrderResponse = 7607 - SQLGCToGCGrantBadgePoints = 7608 - GCToGCCheckOwnsEntireEmoticonRange = 7611 - GCToGCCheckOwnsEntireEmoticonRangeResponse = 7612 - GCToClientRequestLaneSelection = 7623 - GCToClientRequestLaneSelectionResponse = 7624 - ServerToGCCavernCrawlIsHeroActive = 7625 - ServerToGCCavernCrawlIsHeroActiveResponse = 7626 - ClientToGCPlayerCardSpecificPurchaseRequest = 7627 - ClientToGCPlayerCardSpecificPurchaseResponse = 7628 - GCtoServerTensorflowInstance = 7629 - SQLSetIsLeagueAdmin = 7630 - GCToGCGetLiveLeagueMatches = 7631 - GCToGCGetLiveLeagueMatchesResponse = 7632 - DOTALeagueInfoListAdminsRequest = 7633 - DOTALeagueInfoListAdminsReponse = 7634 - GCToGCLeagueMatchStarted = 7645 - GCToGCLeagueMatchCompleted = 7646 - GCToGCLeagueMatchStartedResponse = 7647 - DOTALeagueAvailableLobbyNodesRequest = 7650 - DOTALeagueAvailableLobbyNodes = 7651 - GCToGCLeagueRequest = 7652 - GCToGCLeagueResponse = 7653 - GCToGCLeagueNodeGroupRequest = 7654 - GCToGCLeagueNodeGroupResponse = 7655 - GCToGCLeagueNodeRequest = 7656 - GCToGCLeagueNodeResponse = 7657 - GCToGCRealtimeStatsTerseRequest = 7658 - GCToGCRealtimeStatsTerseResponse = 7659 - GCToGCGetTopMatchesRequest = 7660 - GCToGCGetTopMatchesResponse = 7661 - ClientToGCGetFilteredPlayers = 7662 - GCToClientGetFilteredPlayersResponse = 7663 - ClientToGCRemoveFilteredPlayer = 7664 - GCToClientRemoveFilteredPlayerResponse = 7665 - GCToClientPlayerBeaconState = 7666 - GCToClientPartyBeaconUpdate = 7667 - GCToClientPartySearchInvite = 7668 - ClientToGCUpdatePartyBeacon = 7669 - ClientToGCRequestActiveBeaconParties = 7670 - GCToClientRequestActiveBeaconPartiesResponse = 7671 - ClientToGCManageFavorites = 7672 - GCToClientManageFavoritesResponse = 7673 - ClientToGCJoinPartyFromBeacon = 7674 - GCToClientJoinPartyFromBeaconResponse = 7675 - ClientToGCGetFavoritePlayers = 7676 - GCToClientGetFavoritePlayersResponse = 7677 - ClientToGCVerifyFavoritePlayers = 7678 - GCToClientVerifyFavoritePlayersResponse = 7679 - GCToClientPartySearchInvites = 7680 - GCToClientRequestMMInfo = 7681 - ClientToGCMMInfo = 7682 - SignOutTextMuteInfo = 7683 - ClientToGCPurchaseLabyrinthBlessings = 7684 - ClientToGCPurchaseLabyrinthBlessingsResponse = 7685 - ClientToGCPurchaseFilteredPlayerSlot = 7686 - GCToClientPurchaseFilteredPlayerSlotResponse = 7687 - ClientToGCUpdateFilteredPlayerNote = 7688 - GCToClientUpdateFilteredPlayerNoteResponse = 7689 - ClientToGCClaimSwag = 7690 - GCToClientClaimSwagResponse = 7691 - ServerToGCLockCharmTrading = 8004 - ClientToGCPlayerStatsRequest = 8006 - GCToClientPlayerStatsResponse = 8007 - GCClearPracticeLobbyTeam = 8008 - ClientToGCFindTopSourceTVGames = 8009 - GCToClientFindTopSourceTVGamesResponse = 8010 - GCLobbyList = 8011 - GCLobbyListResponse = 8012 - GCPlayerStatsMatchSignOut = 8013 - ClientToGCSocialFeedPostCommentRequest = 8016 - GCToClientSocialFeedPostCommentResponse = 8017 - ClientToGCCustomGamesFriendsPlayedRequest = 8018 - GCToClientCustomGamesFriendsPlayedResponse = 8019 - ClientToGCFriendsPlayedCustomGameRequest = 8020 - GCToClientFriendsPlayedCustomGameResponse = 8021 - GCTopCustomGamesList = 8024 - ClientToGCSetPartyOpen = 8029 - ClientToGCMergePartyInvite = 8030 - GCToClientMergeGroupInviteReply = 8031 - ClientToGCMergePartyResponse = 8032 - GCToClientMergePartyResponseReply = 8033 - ClientToGCGetProfileCardStats = 8034 - ClientToGCGetProfileCardStatsResponse = 8035 - ClientToGCTopLeagueMatchesRequest = 8036 - ClientToGCTopFriendMatchesRequest = 8037 - GCToClientProfileCardStatsUpdated = 8040 - ServerToGCRealtimeStats = 8041 - GCToServerRealtimeStatsStartStop = 8042 - GCToGCGetServersForClients = 8045 - GCToGCGetServersForClientsResponse = 8046 - GCPracticeLobbyKickFromTeam = 8047 - DOTAChatGetMemberCount = 8048 - DOTAChatGetMemberCountResponse = 8049 - ClientToGCSocialFeedPostMessageRequest = 8050 - GCToClientSocialFeedPostMessageResponse = 8051 - CustomGameListenServerStartedLoading = 8052 - CustomGameClientFinishedLoading = 8053 - GCPracticeLobbyCloseBroadcastChannel = 8054 - GCStartFindingMatchResponse = 8055 - SQLGCToGCGrantAccountFlag = 8057 - GCToClientTopLeagueMatchesResponse = 8061 - GCToClientTopFriendMatchesResponse = 8062 - ClientToGCMatchesMinimalRequest = 8063 - ClientToGCMatchesMinimalResponse = 8064 - GCToClientChatRegionsEnabled = 8067 - ClientToGCPingData = 8068 - GCToGCEnsureAccountInParty = 8071 - GCToGCEnsureAccountInPartyResponse = 8072 - ClientToGCGetProfileTickets = 8073 - ClientToGCGetProfileTicketsResponse = 8074 - GCToClientMatchGroupsVersion = 8075 - ClientToGCH264Unsupported = 8076 - ClientToGCGetQuestProgress = 8078 - ClientToGCGetQuestProgressResponse = 8079 - SignOutXPCoins = 8080 - GCToClientMatchSignedOut = 8081 - GCGetHeroStatsHistory = 8082 - GCGetHeroStatsHistoryResponse = 8083 - ClientToGCPrivateChatInvite = 8084 - ClientToGCPrivateChatKick = 8088 - ClientToGCPrivateChatPromote = 8089 - ClientToGCPrivateChatDemote = 8090 - GCToClientPrivateChatResponse = 8091 - ClientToGCLatestConductScorecardRequest = 8095 - ClientToGCLatestConductScorecard = 8096 - ClientToGCWageringRequest = 8099 - GCToClientWageringResponse = 8100 - ClientToGCEventGoalsRequest = 8103 - ClientToGCEventGoalsResponse = 8104 - GCToGCLeaguePredictionsUpdate = 8108 - GCToGCAddUserToPostGameChat = 8110 - ClientToGCHasPlayerVotedForMVP = 8111 - ClientToGCHasPlayerVotedForMVPResponse = 8112 - ClientToGCVoteForMVP = 8113 - ClientToGCVoteForMVPResponse = 8114 - GCToGCGetEventOwnership = 8115 - GCToGCGetEventOwnershipResponse = 8116 - GCToClientAutomatedTournamentStateChange = 8117 - ClientToGCWeekendTourneyOpts = 8118 - ClientToGCWeekendTourneyOptsResponse = 8119 - ClientToGCWeekendTourneyLeave = 8120 - ClientToGCWeekendTourneyLeaveResponse = 8121 - ClientToGCTeammateStatsRequest = 8124 - ClientToGCTeammateStatsResponse = 8125 - ClientToGCGetGiftPermissions = 8126 - ClientToGCGetGiftPermissionsResponse = 8127 - ClientToGCVoteForArcana = 8128 - ClientToGCVoteForArcanaResponse = 8129 - ClientToGCRequestArcanaVotesRemaining = 8130 - ClientToGCRequestArcanaVotesRemainingResponse = 8131 - GCTransferTeamAdminResponse = 8132 - GCToClientTeamInfo = 8135 - GCToClientTeamsInfo = 8136 - ClientToGCMyTeamInfoRequest = 8137 - ClientToGCPublishUserStat = 8140 - GCToGCSignoutSpendWager = 8141 - GCSubmitLobbyMVPVote = 8144 - GCSubmitLobbyMVPVoteResponse = 8145 - SignOutCommunityGoalProgress = 8150 - GCToClientLobbyMVPAwarded = 8152 - GCToClientQuestProgressUpdated = 8153 - GCToClientWageringUpdate = 8154 - GCToClientArcanaVotesUpdate = 8155 - ClientToGCSetSpectatorLobbyDetails = 8157 - ClientToGCSetSpectatorLobbyDetailsResponse = 8158 - ClientToGCCreateSpectatorLobby = 8159 - ClientToGCCreateSpectatorLobbyResponse = 8160 - ClientToGCSpectatorLobbyList = 8161 - ClientToGCSpectatorLobbyListResponse = 8162 - SpectatorLobbyGameDetails = 8163 - ServerToGCCompendiumInGamePredictionResults = 8166 - ServerToGCCloseCompendiumInGamePredictionVoting = 8167 - ClientToGCOpenPlayerCardPack = 8168 - ClientToGCOpenPlayerCardPackResponse = 8169 - ClientToGCSelectCompendiumInGamePrediction = 8170 - ClientToGCSelectCompendiumInGamePredictionResponse = 8171 - ClientToGCWeekendTourneyGetPlayerStats = 8172 - ClientToGCWeekendTourneyGetPlayerStatsResponse = 8173 - ClientToGCRecyclePlayerCard = 8174 - ClientToGCRecyclePlayerCardResponse = 8175 - ClientToGCCreatePlayerCardPack = 8176 - ClientToGCCreatePlayerCardPackResponse = 8177 - ClientToGCGetPlayerCardRosterRequest = 8178 - ClientToGCGetPlayerCardRosterResponse = 8179 - ClientToGCSetPlayerCardRosterRequest = 8180 - ClientToGCSetPlayerCardRosterResponse = 8181 - ServerToGCCloseCompendiumInGamePredictionVotingResponse = 8183 - LobbyBattleCupVictory = 8186 - GCGetPlayerCardItemInfo = 8187 - GCGetPlayerCardItemInfoResponse = 8188 - ClientToGCRequestSteamDatagramTicket = 8189 - ClientToGCRequestSteamDatagramTicketResponse = 8190 - GCToClientBattlePassRollupRequest = 8191 - GCToClientBattlePassRollupResponse = 8192 - ClientToGCTransferSeasonalMMRRequest = 8193 - ClientToGCTransferSeasonalMMRResponse = 8194 - GCToGCPublicChatCommunicationBan = 8195 - GCToGCUpdateAccountInfo = 8196 - GCChatReportPublicSpam = 8197 - ClientToGCSetPartyBuilderOptions = 8198 - ClientToGCSetPartyBuilderOptionsResponse = 8199 - GCToClientPlaytestStatus = 8200 - ClientToGCJoinPlaytest = 8201 - ClientToGCJoinPlaytestResponse = 8202 - LobbyPlaytestDetails = 8203 - DOTASetFavoriteTeam = 8204 - GCToClientBattlePassRollupListRequest = 8205 - GCToClientBattlePassRollupListResponse = 8206 - DOTAClaimEventAction = 8209 - DOTAClaimEventActionResponse = 8210 - DOTAGetPeriodicResource = 8211 - DOTAGetPeriodicResourceResponse = 8212 - DOTAPeriodicResourceUpdated = 8213 - ServerToGCSpendWager = 8214 - GCToGCSignoutSpendWagerToken = 8215 - SubmitTriviaQuestionAnswer = 8216 - SubmitTriviaQuestionAnswerResponse = 8217 - ClientToGCGiveTip = 8218 - ClientToGCGiveTipResponse = 8219 - StartTriviaSession = 8220 - StartTriviaSessionResponse = 8221 - AnchorPhoneNumberRequest = 8222 - AnchorPhoneNumberResponse = 8223 - UnanchorPhoneNumberRequest = 8224 - UnanchorPhoneNumberResponse = 8225 - GCToGCSignoutSpendRankWager = 8229 - GCToGCGetFavoriteTeam = 8230 - GCToGCGetFavoriteTeamResponse = 8231 - SignOutEventGameData = 8232 - ClientToGCQuickStatsRequest = 8238 - ClientToGCQuickStatsResponse = 8239 - GCToGCSubtractEventPointsFromUser = 8240 - SelectionPriorityChoiceRequest = 8241 - SelectionPriorityChoiceResponse = 8242 - GCToGCCompendiumInGamePredictionResults = 8243 - GameAutographReward = 8244 - GameAutographRewardResponse = 8245 - DestroyLobbyRequest = 8246 - DestroyLobbyResponse = 8247 - PurchaseItemWithEventPoints = 8248 - PurchaseItemWithEventPointsResponse = 8249 - ServerToGCMatchPlayerItemPurchaseHistory = 8250 - GCToGCGrantPlusHeroMatchResults = 8251 - ServerToGCMatchStateHistory = 8255 - PurchaseHeroRandomRelic = 8258 - PurchaseHeroRandomRelicResponse = 8259 - ClientToGCClaimEventActionUsingItem = 8260 - ClientToGCClaimEventActionUsingItemResponse = 8261 - PartyReadyCheckRequest = 8262 - PartyReadyCheckResponse = 8263 - PartyReadyCheckAcknowledge = 8264 - GetRecentPlayTimeFriendsRequest = 8265 - GetRecentPlayTimeFriendsResponse = 8266 - GCToClientCommendNotification = 8267 - ProfileRequest = 8268 - ProfileResponse = 8269 - ProfileUpdate = 8270 - ProfileUpdateResponse = 8271 - HeroGlobalDataRequest = 8274 - HeroGlobalDataResponse = 8275 - ClientToGCRequestPlusWeeklyChallengeResult = 8276 - ClientToGCRequestPlusWeeklyChallengeResultResponse = 8277 - GCToGCGrantPlusPrepaidTime = 8278 - PrivateMetadataKeyRequest = 8279 - PrivateMetadataKeyResponse = 8280 - GCToGCReconcilePlusStatus = 8281 - GCToGCCheckPlusStatus = 8282 - GCToGCCheckPlusStatusResponse = 8283 - GCToGCReconcilePlusAutoGrantItems = 8284 - GCToGCReconcilePlusStatusUnreliable = 8285 - GCToClientCavernCrawlMapPathCompleted = 8288 - ClientToGCCavernCrawlClaimRoom = 8289 - ClientToGCCavernCrawlClaimRoomResponse = 8290 - ClientToGCCavernCrawlUseItemOnRoom = 8291 - ClientToGCCavernCrawlUseItemOnRoomResponse = 8292 - ClientToGCCavernCrawlUseItemOnPath = 8293 - ClientToGCCavernCrawlUseItemOnPathResponse = 8294 - ClientToGCCavernCrawlRequestMapState = 8295 - ClientToGCCavernCrawlRequestMapStateResponse = 8296 - SignOutTips = 8297 - ClientToGCRequestEventPointLogV2 = 8298 - ClientToGCRequestEventPointLogResponseV2 = 8299 - ClientToGCRequestEventTipsSummary = 8300 - ClientToGCRequestEventTipsSummaryResponse = 8301 - ClientToGCRequestSocialFeed = 8303 - ClientToGCRequestSocialFeedResponse = 8304 - ClientToGCRequestSocialFeedComments = 8305 - ClientToGCRequestSocialFeedCommentsResponse = 8306 - ClientToGCCavernCrawlGetClaimedRoomCount = 8308 - ClientToGCCavernCrawlGetClaimedRoomCountResponse = 8309 - GCToGCReconcilePlusAutoGrantItemsUnreliable = 8310 - ServerToGCAddBroadcastTimelineEvent = 8311 - GCToServerUpdateSteamBroadcasting = 8312 - ClientToGCRecordContestVote = 8313 - GCToClientRecordContestVoteResponse = 8314 - GCToGCGrantAutograph = 8315 - GCToGCGrantAutographResponse = 8316 - SignOutConsumableUsage = 8317 - LobbyEventGameDetails = 8318 - DevGrantEventPoints = 8319 - DevGrantEventPointsResponse = 8320 - DevGrantEventAction = 8321 - DevGrantEventActionResponse = 8322 - DevResetEventState = 8323 - DevResetEventStateResponse = 8324 - GCToGCReconcileEventOwnership = 8325 - ConsumeEventSupportGrantItem = 8326 - ConsumeEventSupportGrantItemResponse = 8327 - GCToClientClaimEventActionUsingItemCompleted = 8328 - GCToClientCavernCrawlMapUpdated = 8329 - ServerToGCRequestPlayerRecentAccomplishments = 8330 - ServerToGCRequestPlayerRecentAccomplishmentsResponse = 8331 - ClientToGCRequestPlayerRecentAccomplishments = 8332 - ClientToGCRequestPlayerRecentAccomplishmentsResponse = 8333 - ClientToGCRequestPlayerHeroRecentAccomplishments = 8334 - ClientToGCRequestPlayerHeroRecentAccomplishmentsResponse = 8335 - SignOutEventActionGrants = 8336 - ClientToGCRequestPlayerCoachMatches = 8337 - ClientToGCRequestPlayerCoachMatchesResponse = 8338 - ClientToGCSubmitCoachTeammateRating = 8341 - ClientToGCSubmitCoachTeammateRatingResponse = 8342 - GCToClientCoachTeammateRatingsChanged = 8343 - ClientToGCRequestPlayerCoachMatch = 8345 - ClientToGCRequestPlayerCoachMatchResponse = 8346 - ClientToGCRequestContestVotes = 8347 - ClientToGCRequestContestVotesResponse = 8348 - ClientToGCMVPVoteTimeout = 8349 - ClientToGCMVPVoteTimeoutResponse = 8350 - MatchMatchmakingStats = 8360 - ClientToGCSubmitPlayerMatchSurvey = 8361 - ClientToGCSubmitPlayerMatchSurveyResponse = 8362 - SQLGCToGCGrantAllHeroProgressAccount = 8363 - SQLGCToGCGrantAllHeroProgressVictory = 8364 - DevDeleteEventActions = 8365 - DevDeleteEventActionsResponse = 8366 - GCToGCGetAllHeroCurrent = 8635 - GCToGCGetAllHeroCurrentResponse = 8636 - GCSubmitPlayerAvoidRequest = 8637 - GCSubmitPlayerAvoidRequestResponse = 8638 - GCToClientNotificationsUpdated = 8639 - GCtoGCAssociatedExploiterAccountInfo = 8640 - GCtoGCAssociatedExploiterAccountInfoResponse = 8641 - GCtoGCRequestRecalibrationCheck = 8642 - GCToClientVACReminder = 8643 - ClientToGCUnderDraftBuy = 8644 - ClientToGCUnderDraftBuyResponse = 8645 - ClientToGCUnderDraftReroll = 8646 - ClientToGCUnderDraftRerollResponse = 8647 - NeutralItemStats = 8648 - ClientToGCCreateGuild = 8649 - ClientToGCCreateGuildResponse = 8650 - ClientToGCSetGuildInfo = 8651 - ClientToGCSetGuildInfoResponse = 8652 - ClientToGCAddGuildRole = 8653 - ClientToGCAddGuildRoleResponse = 8654 - ClientToGCModifyGuildRole = 8655 - ClientToGCModifyGuildRoleResponse = 8656 - ClientToGCRemoveGuildRole = 8657 - ClientToGCRemoveGuildRoleResponse = 8658 - ClientToGCJoinGuild = 8659 - ClientToGCJoinGuildResponse = 8660 - ClientToGCLeaveGuild = 8661 - ClientToGCLeaveGuildResponse = 8662 - ClientToGCInviteToGuild = 8663 - ClientToGCInviteToGuildResponse = 8664 - ClientToGCDeclineInviteToGuild = 8665 - ClientToGCDeclineInviteToGuildResponse = 8666 - ClientToGCCancelInviteToGuild = 8667 - ClientToGCCancelInviteToGuildResponse = 8668 - ClientToGCKickGuildMember = 8669 - ClientToGCKickGuildMemberResponse = 8670 - ClientToGCSetGuildMemberRole = 8671 - ClientToGCSetGuildMemberRoleResponse = 8672 - ClientToGCRequestGuildData = 8673 - ClientToGCRequestGuildDataResponse = 8674 - GCToClientGuildDataUpdated = 8675 - ClientToGCRequestGuildMembership = 8676 - ClientToGCRequestGuildMembershipResponse = 8677 - GCToClientGuildMembershipUpdated = 8678 - ClientToGCAcceptInviteToGuild = 8681 - ClientToGCAcceptInviteToGuildResponse = 8682 - ClientToGCSetGuildRoleOrder = 8683 - ClientToGCSetGuildRoleOrderResponse = 8684 - ClientToGCRequestGuildFeed = 8685 - ClientToGCRequestGuildFeedResponse = 8686 - ClientToGCRequestAccountGuildEventData = 8687 - ClientToGCRequestAccountGuildEventDataResponse = 8688 - GCToClientAccountGuildEventDataUpdated = 8689 - ClientToGCRequestActiveGuildContracts = 8690 - ClientToGCRequestActiveGuildContractsResponse = 8691 - GCToClientActiveGuildContractsUpdated = 8692 - GCToClientGuildFeedUpdated = 8693 - ClientToGCSelectGuildContract = 8694 - ClientToGCSelectGuildContractResponse = 8695 - GCToGCCompleteGuildContracts = 8696 - ClientToGCAddPlayerToGuildChat = 8698 - ClientToGCAddPlayerToGuildChatResponse = 8699 - ClientToGCUnderDraftSell = 8700 - ClientToGCUnderDraftSellResponse = 8701 - ClientToGCUnderDraftRequest = 8702 - ClientToGCUnderDraftResponse = 8703 - ClientToGCUnderDraftRedeemReward = 8704 - ClientToGCUnderDraftRedeemRewardResponse = 8705 - GCToServerLobbyHeroBanRates = 8708 - SignOutGuildContractProgress = 8711 - SignOutMVPStats = 8712 - ClientToGCRequestActiveGuildChallenge = 8713 - ClientToGCRequestActiveGuildChallengeResponse = 8714 - GCToClientActiveGuildChallengeUpdated = 8715 - ClientToGCRequestReporterUpdates = 8716 - ClientToGCRequestReporterUpdatesResponse = 8717 - ClientToGCAcknowledgeReporterUpdates = 8718 - SignOutGuildChallengeProgress = 8720 - ClientToGCRequestGuildEventMembers = 8721 - ClientToGCRequestGuildEventMembersResponse = 8722 - ClientToGCReportGuildContent = 8725 - ClientToGCReportGuildContentResponse = 8726 - ClientToGCRequestAccountGuildPersonaInfo = 8727 - ClientToGCRequestAccountGuildPersonaInfoResponse = 8728 - ClientToGCRequestAccountGuildPersonaInfoBatch = 8729 - ClientToGCRequestAccountGuildPersonaInfoBatchResponse = 8730 - GCToClientUnderDraftGoldUpdated = 8731 - GCToServerRecordTrainingData = 8732 - SignOutBounties = 8733 - LobbyFeaturedGamemodeProgress = 8734 - LobbyGauntletProgress = 8735 - ClientToGCSubmitDraftTriviaMatchAnswer = 8736 - ClientToGCSubmitDraftTriviaMatchAnswerResponse = 8737 - GCToGCSignoutSpendBounty = 8738 - ClientToGCApplyGauntletTicket = 8739 - ClientToGCUnderDraftRollBackBench = 8740 - ClientToGCUnderDraftRollBackBenchResponse = 8741 - GCToGCGetEventActionScore = 8742 - GCToGCGetEventActionScoreResponse = 8743 - ServerToGCGetGuildContracts = 8744 - ServerToGCGetGuildContractsResponse = 8745 - LobbyEventGameData = 8746 - GCToClientGuildMembersDataUpdated = 8747 - SignOutReportActivityMarkers = 8748 - SignOutDiretideCandy = 8749 - GCToClientPostGameItemAwardNotification = 8750 - ClientToGCGetOWMatchDetails = 8751 - ClientToGCGetOWMatchDetailsResponse = 8752 - ClientToGCSubmitOWConviction = 8753 - ClientToGCSubmitOWConvictionResponse = 8754 - GCToGCGetAccountSteamChina = 8755 - GCToGCGetAccountSteamChinaResponse = 8756 - ClientToGCClaimLeaderboardRewards = 8757 - ClientToGCClaimLeaderboardRewardsResponse = 8758 - ClientToGCRecalibrateMMR = 8759 - ClientToGCRecalibrateMMRResponse = 8760 - GCToGCGrantEventPointActionList = 8761 - ClientToGCChinaSSAURLRequest = 8764 - ClientToGCChinaSSAURLResponse = 8765 - ClientToGCChinaSSAAcceptedRequest = 8766 - ClientToGCChinaSSAAcceptedResponse = 8767 - SignOutOverwatchSuspicion = 8768 - ServerToGCGetSuspicionConfig = 8769 - ServerToGCGetSuspicionConfigResponse = 8770 - GCToGCGrantPlusHeroChallengeMatchResults = 8771 - GCToClientOverwatchCasesAvailable = 8772 - ServerToGCAccountCheck = 8773 - ClientToGCStartWatchingOverwatch = 8774 - ClientToGCStopWatchingOverwatch = 8775 - SignOutPerfData = 8776 - ClientToGCGetDPCFavorites = 8777 - ClientToGCGetDPCFavoritesResponse = 8778 - ClientToGCSetDPCFavoriteState = 8779 - ClientToGCSetDPCFavoriteStateResponse = 8780 - ClientToGCOverwatchReplayError = 8781 - ServerToGCPlayerChallengeHistory = 8782 - SignOutBanData = 8783 - WebapiDPCSeasonResults = 8784 - ClientToGCCoachFriend = 8785 - ClientToGCCoachFriendResponse = 8786 - ClientToGCRequestPrivateCoachingSession = 8787 - ClientToGCRequestPrivateCoachingSessionResponse = 8788 - ClientToGCAcceptPrivateCoachingSession = 8789 - ClientToGCAcceptPrivateCoachingSessionResponse = 8790 - ClientToGCLeavePrivateCoachingSession = 8791 - ClientToGCLeavePrivateCoachingSessionResponse = 8792 - ClientToGCGetCurrentPrivateCoachingSession = 8793 - ClientToGCGetCurrentPrivateCoachingSessionResponse = 8794 - GCToClientPrivateCoachingSessionUpdated = 8795 - ClientToGCSubmitPrivateCoachingSessionRating = 8796 - ClientToGCSubmitPrivateCoachingSessionRatingResponse = 8797 - ClientToGCGetAvailablePrivateCoachingSessions = 8798 - ClientToGCGetAvailablePrivateCoachingSessionsResponse = 8799 - ClientToGCGetAvailablePrivateCoachingSessionsSummary = 8800 - ClientToGCGetAvailablePrivateCoachingSessionsSummaryResponse = 8801 - ClientToGCJoinPrivateCoachingSessionLobby = 8802 - ClientToGCJoinPrivateCoachingSessionLobbyResponse = 8803 - ClientToGCRespondToCoachFriendRequest = 8804 - ClientToGCRespondToCoachFriendRequestResponse = 8805 - ClientToGCSetEventActiveSeasonID = 8806 - ClientToGCSetEventActiveSeasonIDResponse = 8807 - ServerToGCMatchPlayerNeutralItemEquipHistory = 8808 - ServerToGCCompendiumChosenInGamePredictions = 8809 - ClientToGCCreateTeamPlayerCardPack = 8810 - ClientToGCCreateTeamPlayerCardPackResponse = 8811 - GCToServerSubmitCheerData = 8812 - GCToServerCheerConfig = 8813 - ServerToGCGetCheerConfig = 8814 - ServerToGCGetCheerConfigResponse = 8815 - GCToGCGrantAutographByID = 8816 - GCToServerCheerScalesOverride = 8817 - GCToServerGetCheerState = 8818 - ServerToGCReportCheerState = 8819 - GCToServerScenarioSave = 8820 - GCToServerAbilityDraftLobbyData = 8821 - SignOutReportCommunications = 8822 - ClientToGCBatchGetPlayerCardRosterRequest = 8823 - ClientToGCBatchGetPlayerCardRosterResponse = 8824 - ClientToGCGetStickerbookRequest = 8825 - ClientToGCGetStickerbookResponse = 8826 - ClientToGCCreateStickerbookPageRequest = 8827 - ClientToGCCreateStickerbookPageResponse = 8828 - ClientToGCDeleteStickerbookPageRequest = 8829 - ClientToGCDeleteStickerbookPageResponse = 8830 - ClientToGCPlaceStickersRequest = 8831 - ClientToGCPlaceStickersResponse = 8832 - ClientToGCPlaceCollectionStickersRequest = 8833 - ClientToGCPlaceCollectionStickersResponse = 8834 - ClientToGCOrderStickerbookTeamPageRequest = 8835 - ClientToGCOrderStickerbookTeamPageResponse = 8836 - ServerToGCGetStickerHeroes = 8837 - ServerToGCGetStickerHeroesResponse = 8838 - ClientToGCCandyShopGetUserData = 8840 - ClientToGCCandyShopGetUserDataResponse = 8841 - GCToClientCandyShopUserDataUpdated = 8842 - ClientToGCCandyShopPurchaseReward = 8843 - ClientToGCCandyShopPurchaseRewardResponse = 8844 - ClientToGCCandyShopDoExchange = 8845 - ClientToGCCandyShopDoExchangeResponse = 8846 - ClientToGCCandyShopDoVariableExchange = 8847 - ClientToGCCandyShopDoVariableExchangeResponse = 8848 - ClientToGCCandyShopRerollRewards = 8849 - ClientToGCCandyShopRerollRewardsResponse = 8850 - ClientToGCSetHeroSticker = 8851 - ClientToGCSetHeroStickerResponse = 8852 - ClientToGCGetHeroStickers = 8853 - ClientToGCGetHeroStickersResponse = 8854 - ClientToGCSetFavoritePage = 8855 - ClientToGCSetFavoritePageResponse = 8856 - ClientToGCCandyShopDevGrantCandy = 8857 - ClientToGCCandyShopDevGrantCandyResponse = 8858 - ClientToGCCandyShopDevClearInventory = 8859 - ClientToGCCandyShopDevClearInventoryResponse = 8860 - ClientToGCCandyShopOpenBags = 8861 - ClientToGCCandyShopOpenBagsResponse = 8862 - ClientToGCCandyShopDevGrantCandyBags = 8863 - ClientToGCCandyShopDevGrantCandyBagsResponse = 8864 - ClientToGCCandyShopDevShuffleExchange = 8865 - ClientToGCCandyShopDevShuffleExchangeResponse = 8866 - ClientToGCCandyShopDevGrantRerollCharges = 8867 - ClientToGCCandyShopDevGrantRerollChargesResponse = 8868 - LobbyAdditionalAccountData = 8869 - ServerToGCLobbyInitialized = 8870 - ClientToGCCollectorsCacheAvailableDataRequest = 8871 - GCToClientCollectorsCacheAvailableDataResponse = 8872 - ClientToGCUploadMatchClip = 8873 - GCToClientUploadMatchClipResponse = 8874 - GCToServerSetSteamLearnKeysChanged = 8876 - SignOutMuertaMinigame = 8877 - GCToServerLobbyHeroRoleStats = 8878 - ClientToGCRankRequest = 8879 - GCToClientRankResponse = 8880 - GCToClientRankUpdate = 8881 - SignOutMapStats = 8882 - ClientToGCMapStatsRequest = 8883 - GCToClientMapStatsResponse = 8884 - GCToServerSetSteamLearnInferencing = 8885 - ClientToGCShowcaseGetUserData = 8886 - ClientToGCShowcaseGetUserDataResponse = 8887 - ClientToGCShowcaseSetUserData = 8888 - ClientToGCShowcaseSetUserDataResponse = 8889 - ClientToGCFantasyCraftingGetData = 8890 - ClientToGCFantasyCraftingGetDataResponse = 8891 - ClientToGCFantasyCraftingPerformOperation = 8892 - ClientToGCFantasyCraftingPerformOperationResponse = 8893 - GCToClientFantasyCraftingGetDataUpdated = 8894 - ClientToGCFantasyCraftingDevModifyTablet = 8895 - ClientToGCFantasyCraftingDevModifyTabletResponse = 8896 - ClientToGCRoadToTIGetQuests = 8897 - ClientToGCRoadToTIGetQuestsResponse = 8898 - ClientToGCRoadToTIGetActiveQuest = 8899 - ClientToGCRoadToTIGetActiveQuestResponse = 8900 - ClientToGCBingoGetUserData = 8901 - ClientToGCBingoGetUserDataResponse = 8902 - ClientToGCBingoClaimRow = 8903 - ClientToGCBingoClaimRowResponse = 8904 - ClientToGCBingoDevRerollCard = 8905 - ClientToGCBingoDevRerollCardResponse = 8906 - ClientToGCBingoGetStatsData = 8907 - ClientToGCBingoGetStatsDataResponse = 8908 - GCToClientBingoUserDataUpdated = 8909 - GCToClientRoadToTIQuestDataUpdated = 8910 - ClientToGCRoadToTIUseItem = 8911 - ClientToGCRoadToTIUseItemResponse = 8912 - ClientToGCShowcaseSubmitReport = 8913 - ClientToGCShowcaseSubmitReportResponse = 8914 - ClientToGCShowcaseAdminGetReportsRollupList = 8915 - ClientToGCShowcaseAdminGetReportsRollupListResponse = 8916 - ClientToGCShowcaseAdminGetReportsRollup = 8917 - ClientToGCShowcaseAdminGetReportsRollupResponse = 8918 - ClientToGCShowcaseAdminGetUserDetails = 8919 - ClientToGCShowcaseAdminGetUserDetailsResponse = 8920 - ClientToGCShowcaseAdminConvict = 8921 - ClientToGCShowcaseAdminConvictResponse = 8922 - ClientToGCShowcaseAdminExonerate = 8923 - ClientToGCShowcaseAdminExonerateResponse = 8924 - ClientToGCShowcaseAdminReset = 8925 - ClientToGCShowcaseAdminResetResponse = 8926 - ClientToGCShowcaseAdminLockAccount = 8927 - ClientToGCShowcaseAdminLockAccountResponse = 8928 - ClientToGCFantasyCraftingSelectPlayer = 8929 - ClientToGCFantasyCraftingSelectPlayerResponse = 8930 - ClientToGCFantasyCraftingGenerateTablets = 8931 - ClientToGCFantasyCraftingGenerateTabletsResponse = 8932 - ClientToGcFantasyCraftingUpgradeTablets = 8933 - ClientToGcFantasyCraftingUpgradeTabletsResponse = 8934 - ClientToGCFantasyCraftingRerollOptions = 8936 - ClientToGCFantasyCraftingRerollOptionsResponse = 8937 - ClientToGCRoadToTIDevForceQuest = 8935 - LobbyRoadToTIMatchQuestData = 8939 - ClientToGCShowcaseModerationGetQueue = 8940 - ClientToGCShowcaseModerationGetQueueResponse = 8941 - ClientToGCShowcaseModerationApplyModeration = 8942 - ClientToGCShowcaseModerationApplyModerationResponse = 8943 diff --git a/steam/ext/dota2/protobufs/dota_shared_enums.py b/steam/ext/dota2/protobufs/dota_shared_enums.py deleted file mode 100644 index 71fd9b07..00000000 --- a/steam/ext/dota2/protobufs/dota_shared_enums.py +++ /dev/null @@ -1,836 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: dota_shared_enums.proto -# plugin: python-betterproto -from __future__ import annotations - -from dataclasses import dataclass - -import betterproto - - -class DOTAGameMode(betterproto.Enum): - NONE = 0 - AP = 1 - CM = 2 - RD = 3 - SD = 4 - AR = 5 - INTRO = 6 - HW = 7 - REVERSE_CM = 8 - XMAS = 9 - TUTORIAL = 10 - MO = 11 - LP = 12 - POOL1 = 13 - FH = 14 - CUSTOM = 15 - CD = 16 - BD = 17 - ABILITY_DRAFT = 18 - EVENT = 19 - ARDM = 20 - MID1V1 = 21 - ALL_DRAFT = 22 - TURBO = 23 - MUTATION = 24 - COACHES_CHALLENGE = 25 - - -class DOTAGameState(betterproto.Enum): - INIT = 0 - WAIT_FOR_PLAYERS_TO_LOAD = 1 - HERO_SELECTION = 2 - STRATEGY_TIME = 3 - PRE_GAME = 4 - GAME_IN_PROGRESS = 5 - POST_GAME = 6 - DISCONNECT = 7 - TEAM_SHOWCASE = 8 - CUSTOM_GAME_SETUP = 9 - WAIT_FOR_MAP_TO_LOAD = 10 - SCENARIO_SETUP = 11 - PLAYER_DRAFT = 12 - LAST = 13 - - -class DOTAGCTeam(betterproto.Enum): - GOOD_GUYS = 0 - BAD_GUYS = 1 - BROADCASTER = 2 - SPECTATOR = 3 - PLAYER_POOL = 4 - NOTEAM = 5 - CUSTOM_1 = 6 - CUSTOM_2 = 7 - CUSTOM_3 = 8 - CUSTOM_4 = 9 - CUSTOM_5 = 10 - CUSTOM_6 = 11 - CUSTOM_7 = 12 - CUSTOM_8 = 13 - NEUTRALS = 14 - - -class EEvent(betterproto.Enum): - NONE = 0 - DIRETIDE = 1 - SPRING_FESTIVAL = 2 - FROSTIVUS_2013 = 3 - COMPENDIUM_2014 = 4 - NEXON_PC_BANG = 5 - PWRD_DAC_2015 = 6 - NEW_BLOOM_2015 = 7 - INTERNATIONAL_2015 = 8 - FALL_MAJOR_2015 = 9 - ORACLE_PA = 10 - NEW_BLOOM_2015_PREBEAST = 11 - FROSTIVUS = 12 - WINTER_MAJOR_2016 = 13 - INTERNATIONAL_2016 = 14 - FALL_MAJOR_2016 = 15 - WINTER_MAJOR_2017 = 16 - NEW_BLOOM_2017 = 17 - INTERNATIONAL_2017 = 18 - PLUS_SUBSCRIPTION = 19 - SINGLES_DAY_2017 = 20 - FROSTIVUS_2017 = 21 - INTERNATIONAL_2018 = 22 - FROSTIVUS_2018 = 23 - NEW_BLOOM_2019 = 24 - INTERNATIONAL_2019 = 25 - NEW_PLAYER_EXPERIENCE = 26 - FROSTIVUS_2019 = 27 - NEW_BLOOM_2020 = 28 - INTERNATIONAL_2020 = 29 - TEAM_FANDOM = 30 - DIRETIDE_2020 = 31 - SPRING_2021 = 32 - FALL_2021 = 33 - TEAM_FANDOM_FALL_2021 = 34 - TEAM_2021_2022_TOUR2 = 35 - INTERNATIONAL_2022 = 36 - TEAM_2021_2022_TOUR3 = 37 - TEAM_INTERNATIONAL_2022 = 38 - PERMANENT_GRANTS = 39 - MUERTA_RELEASE_SPRING2023 = 40 - TEAM_2023_TOUR1 = 41 - TEAM_2023_TOUR2 = 42 - TEAM_2023_TOUR3 = 43 - INTERNATIONAL_2023 = 45 - TENTH_ANNIVERSARY = 46 - FROSTIVUS_2023 = 48 - - -class ERankType(betterproto.Enum): - Invalid = 0 - Casual = 1 - Ranked = 2 - CasualLegacy = 3 - RankedLegacy = 4 - CasualGlicko = 5 - RankedGlicko = 6 - RankMax = 7 - BehaviorPrivate = 100 - BehaviorPublic = 101 - Max = 102 - - -class DOTALeaverStatusT(betterproto.Enum): - NONE = 0 - DISCONNECTED = 1 - DISCONNECTED_TOO_LONG = 2 - ABANDONED = 3 - AFK = 4 - NEVER_CONNECTED = 5 - NEVER_CONNECTED_TOO_LONG = 6 - FAILED_TO_READY_UP = 7 - DECLINED = 8 - - -class DOTAConnectionStateT(betterproto.Enum): - UNKNOWN = 0 - NOT_YET_CONNECTED = 1 - CONNECTED = 2 - DISCONNECTED = 3 - ABANDONED = 4 - LOADING = 5 - FAILED = 6 - - -class FantasyRoles(betterproto.Enum): - UNDEFINED = 0 - CORE = 1 - SUPPORT = 2 - OFFLANE = 3 - MID = 4 - - -class FantasyScoring(betterproto.Enum): - KILLS = 0 - DEATHS = 1 - CS = 2 - GPM = 3 - TOWER_KILLS = 4 - ROSHAN_KILLS = 5 - TEAMFIGHT_PARTICIPATION = 6 - WARDS_PLANTED = 7 - CAMPS_STACKED = 8 - RUNES_GRABBED = 9 - FIRST_BLOOD = 10 - STUNS = 11 - SMOKES_USED = 12 - NEUTRAL_TOKENS_FOUND = 13 - WATCHERS_TAKEN = 14 - LOTUSES_GAINED = 15 - TORMENTOR_KILLS = 16 - COURIER_KILLS = 17 - TYPES = 18 - INVALID = 19 - - -class FantasyTeamSlots(betterproto.Enum): - NONE = 0 - CORE = 1 - SUPPORT = 2 - ANY = 3 - BENCH = 4 - - -class FantasySelectionMode(betterproto.Enum): - INVALID = 0 - LOCKED = 1 - SHUFFLE = 2 - FREE_PICK = 3 - ENDED = 4 - PRE_SEASON = 5 - PRE_DRAFT = 6 - DRAFTING = 7 - REGULAR_SEASON = 8 - CARD_BASED = 9 - - -class FantasyGemType(betterproto.Enum): - RUBY = 0 - SAPPHIRE = 1 - EMERALD = 2 - - -class DOTAChatChannelTypeT(betterproto.Enum): - Regional = 0 - Custom = 1 - Party = 2 - Lobby = 3 - Team = 4 - Guild = 5 - Fantasy = 6 - Whisper = 7 - Console = 8 - Tab = 9 - Invalid = 10 - GameAll = 11 - GameAllies = 12 - GameSpectator = 13 - GameCoaching = 14 - Cafe = 15 - CustomGame = 16 - Private = 17 - PostGame = 18 - BattleCup = 19 - HLTVSpectator = 20 - GameEvents = 21 - Trivia = 22 - NewPlayer = 23 - PrivateCoaching = 24 - - -class EChatSpecialPrivileges(betterproto.Enum): - NONE = 0 - Moderator = 1 - SuperModerator = 2 - - -class DOTACommTypeT(betterproto.Enum): - NONE = 0 - PING = 1 - CHATWHEEL = 2 - TIP = 3 - TEXT = 4 - SHOWCASE = 5 - VOICE = 6 - ALLY_ABILITY = 7 - PAUSE = 8 - COACHING = 9 - NOCOOLDOWN = 10 - RANKEDMATCHMAKE = 11 - DROPS = 12 - NEWPLAYER_EXPERT = 13 - COACHED = 14 - MAPDRAWING = 15 - - -class DOTACommLevelT(betterproto.Enum): - NONE = 0 - COOLDOWN = 1 - PINGS = 2 - MAPDRAWING = 3 - CHAT = 4 - TIPPING = 5 - VOICE = 6 - ALLIED_ABILITY = 7 - - -class DOTABehaviorLevelT(betterproto.Enum): - NONE = 0 - RANKED_ALLOWED = 1 - PAUSING = 2 - DROPS = 3 - COACHING = 4 - - -class EProfileCardSlotType(betterproto.Enum): - Empty = 0 - Stat = 1 - Trophy = 2 - Item = 3 - Hero = 4 - Emoticon = 5 - Team = 6 - - -class EMatchGroupServerStatus(betterproto.Enum): - OK = 0 - LimitedAvailability = 1 - Offline = 2 - - -class DOTACMPICK(betterproto.Enum): - RANDOM = 0 - GOOD_GUYS = 1 - BAD_GUYS = 2 - - -class DOTALowPriorityBanType(betterproto.Enum): - ABANDON = 0 - REPORTS = 1 - SECONDARY_ABANDON = 2 - PRE_GAME_ROLE = 3 - - -class DOTALobbyReadyState(betterproto.Enum): - UNDECLARED = 0 - ACCEPTED = 1 - DECLINED = 2 - - -class DOTAJoinLobbyResult(betterproto.Enum): - SUCCESS = 0 - ALREADY_IN_GAME = 1 - INVALID_LOBBY = 2 - INCORRECT_PASSWORD = 3 - ACCESS_DENIED = 4 - GENERIC_ERROR = 5 - INCORRECT_VERSION = 6 - IN_TEAM_PARTY = 7 - NO_LOBBY_FOUND = 8 - LOBBY_FULL = 9 - CUSTOM_GAME_INCORRECT_VERSION = 10 - TIMEOUT = 11 - CUSTOM_GAME_COOLDOWN = 12 - BUSY = 13 - NO_PLAYTIME = 14 - - -class DOTASelectionPriorityRules(betterproto.Enum): - Manual = 0 - Automatic = 1 - - -class DOTASelectionPriorityChoice(betterproto.Enum): - Invalid = 0 - FirstPick = 1 - SecondPick = 2 - Radiant = 3 - Dire = 4 - - -class DOTAMatchVote(betterproto.Enum): - INVALID = 0 - POSITIVE = 1 - NEGATIVE = 2 - - -class DOTALobbyVisibility(betterproto.Enum): - Public = 0 - Friends = 1 - Unlisted = 2 - - -class EDOTAPlayerMMRType(betterproto.Enum): - Invalid = 0 - GeneralHidden = 1 - GeneralCompetitive = 3 - - -class EDOTAMMRBoostType(betterproto.Enum): - NONE = 0 - Leader = 1 - Follower = 2 - - -class MatchType(betterproto.Enum): - CASUAL = 0 - COOP_BOTS = 1 - COMPETITIVE = 4 - WEEKEND_TOURNEY = 5 - EVENT = 7 - COACHES_CHALLENGE = 12 - NEW_PLAYER_POOL = 14 - - -class DOTABotDifficulty(betterproto.Enum): - PASSIVE = 0 - EASY = 1 - MEDIUM = 2 - HARD = 3 - UNFAIR = 4 - INVALID = 5 - EXTRA1 = 6 - EXTRA2 = 7 - EXTRA3 = 8 - NPX = 9 - - -class DOTABotMode(betterproto.Enum): - NONE = 0 - LANING = 1 - ATTACK = 2 - ROAM = 3 - RETREAT = 4 - SECRET_SHOP = 5 - SIDE_SHOP = 6 - RUNE = 7 - PUSH_TOWER_TOP = 8 - PUSH_TOWER_MID = 9 - PUSH_TOWER_BOT = 10 - DEFEND_TOWER_TOP = 11 - DEFEND_TOWER_MID = 12 - DEFEND_TOWER_BOT = 13 - ASSEMBLE = 14 - ASSEMBLE_WITH_HUMANS = 15 - TEAM_ROAM = 16 - FARM = 17 - DEFEND_ALLY = 18 - EVASIVE_MANEUVERS = 19 - ROSHAN = 20 - ITEM = 21 - WARD = 22 - COMPANION = 23 - TUTORIAL_BOSS = 24 - MINION = 25 - OUTPOST = 26 - - -class MatchLanguages(betterproto.Enum): - INVALID = 0 - ENGLISH = 1 - RUSSIAN = 2 - CHINESE = 3 - KOREAN = 4 - SPANISH = 5 - PORTUGUESE = 6 - ENGLISH2 = 7 - - -class ETourneyQueueDeadlineState(betterproto.Enum): - Normal = 0 - Missed = 1 - ExpiredOK = 2 - SeekingBye = 3 - EligibleForRefund = 4 - NA = -1 - ExpiringSoon = 101 - - -class EMatchOutcome(betterproto.Enum): - Unknown = 0 - RadVictory = 2 - DireVictory = 3 - NeutralVictory = 4 - NoTeamWinner = 5 - Custom1Victory = 6 - Custom2Victory = 7 - Custom3Victory = 8 - Custom4Victory = 9 - Custom5Victory = 10 - Custom6Victory = 11 - Custom7Victory = 12 - Custom8Victory = 13 - NotScored_PoorNetworkConditions = 64 - NotScored_Leaver = 65 - NotScored_ServerCrash = 66 - NotScored_NeverStarted = 67 - NotScored_Canceled = 68 - NotScored_Suspicious = 69 - - -class ELaneType(betterproto.Enum): - UNKNOWN = 0 - SAFE = 1 - OFF = 2 - MID = 3 - JUNGLE = 4 - ROAM = 5 - - -class EBadgeType(betterproto.Enum): - Invalid = 0 - TI7_Midweek = 1 - TI7_Finals = 2 - TI7_AllEvent = 3 - TI8_Midweek = 4 - TI8_Finals = 5 - TI8_AllEvent = 6 - TI10 = 7 - TI11_PlayoffsDay1 = 8 - TI11_PlayoffsDay2 = 9 - TI11_PlayoffsDay3 = 10 - TI11_PlayoffsDay4 = 11 - TI11_FinalsWeekend = 12 - TI12_PlayoffsDay1 = 13 - TI12_PlayoffsDay2 = 14 - TI12_PlayoffsDay3 = 15 - TI12_FinalsWeekend = 16 - TI12_Special = 17 - - -class ELeagueStatus(betterproto.Enum): - UNSET = 0 - UNSUBMITTED = 1 - SUBMITTED = 2 - ACCEPTED = 3 - REJECTED = 4 - CONCLUDED = 5 - DELETED = 6 - - -class ELeagueRegion(betterproto.Enum): - UNSET = 0 - NA = 1 - SA = 2 - WEU = 3 - EEU = 4 - CHINA = 5 - SEA = 6 - - -class ELeagueTier(betterproto.Enum): - UNSET = 0 - AMATEUR = 1 - PROFESSIONAL = 2 - MINOR = 3 - MAJOR = 4 - INTERNATIONAL = 5 - DPC_QUALIFIER = 6 - DPC_LEAGUE_QUALIFIER = 7 - DPC_LEAGUE = 8 - DPC_LEAGUE_FINALS = 9 - - -class ELeagueTierCategory(betterproto.Enum): - AMATEUR = 1 - PROFESSIONAL = 2 - DPC = 3 - - -class ELeagueDivision(betterproto.Enum): - UNSET = 0 - I = 1 - II = 2 - - -class ELeagueBroadcastProvider(betterproto.Enum): - UNKNOWN = 0 - STEAM = 1 - TWITCH = 2 - YOUTUBE = 3 - OTHER = 100 - - -class ELeaguePhase(betterproto.Enum): - UNSET = 0 - REGIONAL_QUALIFIER = 1 - GROUP_STAGE = 2 - MAIN_EVENT = 3 - - -class ELeagueAuditAction(betterproto.Enum): - INVALID = 0 - LEAGUE_CREATE = 1 - LEAGUE_EDIT = 2 - LEAGUE_DELETE = 3 - LEAGUE_ADMIN_ADD = 4 - LEAGUE_ADMIN_REVOKE = 5 - LEAGUE_ADMIN_PROMOTE = 6 - LEAGUE_STREAM_ADD = 7 - LEAGUE_STREAM_REMOVE = 8 - LEAGUE_IMAGE_UPDATED = 9 - LEAGUE_MESSAGE_ADDED = 10 - LEAGUE_SUBMITTED = 11 - LEAGUE_SET_PRIZE_POOL = 12 - LEAGUE_ADD_PRIZE_POOL_ITEM = 13 - LEAGUE_REMOVE_PRIZE_POOL_ITEM = 14 - LEAGUE_MATCH_START = 15 - LEAGUE_MATCH_END = 16 - LEAGUE_ADD_INVITED_TEAM = 17 - LEAGUE_REMOVE_INVITED_TEAM = 18 - LEAGUE_STATUS_CHANGED = 19 - LEAGUE_STREAM_EDIT = 20 - LEAGUE_TEAM_SWAP = 21 - NODEGROUP_CREATE = 100 - NODEGROUP_DESTROY = 101 - NODEGROUP_ADD_TEAM = 102 - NODEGROUP_REMOVE_TEAM = 103 - NODEGROUP_SET_ADVANCING = 104 - NODEGROUP_EDIT = 105 - NODEGROUP_POPULATE = 106 - NODEGROUP_COMPLETED = 107 - NODEGROUP_SET_SECONDARY_ADVANCING = 108 - NODEGROUP_SET_TERTIARY_ADVANCING = 109 - NODE_CREATE = 200 - NODE_DESTROY = 201 - NODE_AUTOCREATE = 202 - NODE_SET_TEAM = 203 - NODE_SET_SERIES_ID = 204 - NODE_SET_ADVANCING = 205 - NODE_SET_TIME = 206 - NODE_MATCH_COMPLETED = 207 - NODE_COMPLETED = 208 - NODE_EDIT = 209 - - -class DOTACombatLogTypes(betterproto.Enum): - INVALID = -1 - DAMAGE = 0 - HEAL = 1 - MODIFIER_ADD = 2 - MODIFIER_REMOVE = 3 - DEATH = 4 - ABILITY = 5 - ITEM = 6 - LOCATION = 7 - GOLD = 8 - GAME_STATE = 9 - XP = 10 - PURCHASE = 11 - BUYBACK = 12 - ABILITY_TRIGGER = 13 - PLAYERSTATS = 14 - MULTIKILL = 15 - KILLSTREAK = 16 - TEAM_BUILDING_KILL = 17 - FIRST_BLOOD = 18 - MODIFIER_STACK_EVENT = 19 - NEUTRAL_CAMP_STACK = 20 - PICKUP_RUNE = 21 - REVEALED_INVISIBLE = 22 - HERO_SAVED = 23 - MANA_RESTORED = 24 - HERO_LEVELUP = 25 - BOTTLE_HEAL_ALLY = 26 - ENDGAME_STATS = 27 - INTERRUPT_CHANNEL = 28 - ALLIED_GOLD = 29 - AEGIS_TAKEN = 30 - MANA_DAMAGE = 31 - PHYSICAL_DAMAGE_PREVENTED = 32 - UNIT_SUMMONED = 33 - ATTACK_EVADE = 34 - TREE_CUT = 35 - SUCCESSFUL_SCAN = 36 - END_KILLSTREAK = 37 - BLOODSTONE_CHARGE = 38 - CRITICAL_DAMAGE = 39 - SPELL_ABSORB = 40 - UNIT_TELEPORTED = 41 - KILL_EATER_EVENT = 42 - NEUTRAL_ITEM_EARNED = 43 - - -class EDPCFavoriteType(betterproto.Enum): - ALL = 0 - PLAYER = 1 - TEAM = 2 - LEAGUE = 3 - - -class EDPCPushNotification(betterproto.Enum): - MATCH_STARTING = 1 - PLAYER_LEFT_TEAM = 10 - PLAYER_JOINED_TEAM = 11 - PLAYER_JOINED_TEAM_AS_COACH = 12 - PLAYER_LEFT_TEAM_AS_COACH = 13 - LEAGUE_RESULT = 20 - PREDICTION_MATCHES_AVAILABLE = 30 - PREDICTION_RESULT = 31 - FANTASY_PLAYER_CLEARED = 40 - FANTASY_DAILY_SUMMARY = 41 - FANTASY_FINAL_RESULTS = 42 - - -class EEventActionScoreMode(betterproto.Enum): - Add = 0 - Min = 1 - - -class EPlayerChallengeHistoryType(betterproto.Enum): - Invalid = 0 - KillEater = 1 - DotaPlusRelic = 2 - DotaPlusHeroPlayerChallenge = 3 - InGameEventChallenge = 4 - GuildContract = 5 - - -class EOverwatchReportReason(betterproto.Enum): - Unknown = 0 - Cheating = 1 - Feeding = 2 - Griefing = 3 - Suspicious = 4 - AbilityAbuse = 5 - - -@dataclass -class CDOTAClientHardwareSpecs(betterproto.Message): - logical_processors: int = betterproto.uint32_field(1) - cpu_cycles_per_second: float = betterproto.fixed64_field(2) - total_physical_memory: float = betterproto.fixed64_field(3) - is_64_bit_os: bool = betterproto.bool_field(4) - upload_measurement: int = betterproto.uint64_field(5) - prefer_not_host: bool = betterproto.bool_field(6) - crc: list[int] = betterproto.uint32_field(7) - - -@dataclass -class CDOTASaveGame(betterproto.Message): - match_id: int = betterproto.uint64_field(5) - save_time: int = betterproto.uint32_field(2) - players: list[CDOTASaveGamePlayer] = betterproto.message_field(3) - save_instances: list[CDOTASaveGameSaveInstance] = betterproto.message_field(4) - - -@dataclass -class CDOTASaveGamePlayer(betterproto.Message): - team: DOTAGCTeam = betterproto.enum_field(1) - name: str = betterproto.string_field(2) - hero: str = betterproto.string_field(3) - - -@dataclass -class CDOTASaveGameSaveInstance(betterproto.Message): - game_time: int = betterproto.uint32_field(2) - team1_score: int = betterproto.uint32_field(3) - team2_score: int = betterproto.uint32_field(4) - player_positions: list[CDOTASaveGameSaveInstancePlayerPositions] = betterproto.message_field(5) - save_id: int = betterproto.uint32_field(6) - save_time: int = betterproto.uint32_field(7) - - -@dataclass -class CDOTASaveGameSaveInstancePlayerPositions(betterproto.Message): - x: float = betterproto.float_field(1) - y: float = betterproto.float_field(2) - - -@dataclass -class CMsgDOTACombatLogEntry(betterproto.Message): - type: DOTACombatLogTypes = betterproto.enum_field(1) - target_name: int = betterproto.uint32_field(2) - target_source_name: int = betterproto.uint32_field(3) - attacker_name: int = betterproto.uint32_field(4) - damage_source_name: int = betterproto.uint32_field(5) - inflictor_name: int = betterproto.uint32_field(6) - is_attacker_illusion: bool = betterproto.bool_field(7) - is_attacker_hero: bool = betterproto.bool_field(8) - is_target_illusion: bool = betterproto.bool_field(9) - is_target_hero: bool = betterproto.bool_field(10) - is_visible_radiant: bool = betterproto.bool_field(11) - is_visible_dire: bool = betterproto.bool_field(12) - value: int = betterproto.uint32_field(13) - health: int = betterproto.int32_field(14) - timestamp: float = betterproto.float_field(15) - stun_duration: float = betterproto.float_field(16) - slow_duration: float = betterproto.float_field(17) - is_ability_toggle_on: bool = betterproto.bool_field(18) - is_ability_toggle_off: bool = betterproto.bool_field(19) - ability_level: int = betterproto.uint32_field(20) - location_x: float = betterproto.float_field(21) - location_y: float = betterproto.float_field(22) - gold_reason: int = betterproto.uint32_field(23) - timestamp_raw: float = betterproto.float_field(24) - modifier_duration: float = betterproto.float_field(25) - xp_reason: int = betterproto.uint32_field(26) - last_hits: int = betterproto.uint32_field(27) - attacker_team: int = betterproto.uint32_field(28) - target_team: int = betterproto.uint32_field(29) - obs_wards_placed: int = betterproto.uint32_field(30) - assist_player0: int = betterproto.uint32_field(31) - assist_player1: int = betterproto.uint32_field(32) - assist_player2: int = betterproto.uint32_field(33) - assist_player3: int = betterproto.uint32_field(34) - stack_count: int = betterproto.uint32_field(35) - hidden_modifier: bool = betterproto.bool_field(36) - is_target_building: bool = betterproto.bool_field(37) - neutral_camp_type: int = betterproto.uint32_field(38) - rune_type: int = betterproto.uint32_field(39) - assist_players: list[int] = betterproto.int32_field(40) - is_heal_save: bool = betterproto.bool_field(41) - is_ultimate_ability: bool = betterproto.bool_field(42) - attacker_hero_level: int = betterproto.uint32_field(43) - target_hero_level: int = betterproto.uint32_field(44) - xpm: int = betterproto.uint32_field(45) - gpm: int = betterproto.uint32_field(46) - event_location: int = betterproto.uint32_field(47) - target_is_self: bool = betterproto.bool_field(48) - damage_type: int = betterproto.uint32_field(49) - invisibility_modifier: bool = betterproto.bool_field(50) - damage_category: int = betterproto.uint32_field(51) - networth: int = betterproto.uint32_field(52) - building_type: int = betterproto.uint32_field(53) - modifier_elapsed_duration: float = betterproto.float_field(54) - silence_modifier: bool = betterproto.bool_field(55) - heal_from_lifesteal: bool = betterproto.bool_field(56) - modifier_purged: bool = betterproto.bool_field(57) - spell_evaded: bool = betterproto.bool_field(58) - motion_controller_modifier: bool = betterproto.bool_field(59) - long_range_kill: bool = betterproto.bool_field(60) - modifier_purge_ability: int = betterproto.uint32_field(61) - modifier_purge_npc: int = betterproto.uint32_field(62) - root_modifier: bool = betterproto.bool_field(63) - total_unit_death_count: int = betterproto.uint32_field(64) - aura_modifier: bool = betterproto.bool_field(65) - armor_debuff_modifier: bool = betterproto.bool_field(66) - no_physical_damage_modifier: bool = betterproto.bool_field(67) - modifier_ability: int = betterproto.uint32_field(68) - modifier_hidden: bool = betterproto.bool_field(69) - inflictor_is_stolen_ability: bool = betterproto.bool_field(70) - kill_eater_event: int = betterproto.uint32_field(71) - unit_status_label: int = betterproto.uint32_field(72) - spell_generated_attack: bool = betterproto.bool_field(73) - at_night_time: bool = betterproto.bool_field(74) - attacker_has_scepter: bool = betterproto.bool_field(75) - neutral_camp_team: int = betterproto.uint32_field(76) - regenerated_health: float = betterproto.float_field(77) - will_reincarnate: bool = betterproto.bool_field(78) - uses_charges: bool = betterproto.bool_field(79) - - -@dataclass -class CMsgPendingEventAward(betterproto.Message): - event_id: EEvent = betterproto.enum_field(1) - action_id: int = betterproto.uint32_field(2) - num_to_grant: int = betterproto.uint32_field(3) - score_mode: EEventActionScoreMode = betterproto.enum_field(4) - audit_action: int = betterproto.uint32_field(5) - audit_data: int = betterproto.uint64_field(6) diff --git a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py b/steam/ext/dota2/protobufs/gcsdk_gcmessages.py deleted file mode 100644 index 508f1eb2..00000000 --- a/steam/ext/dota2/protobufs/gcsdk_gcmessages.py +++ /dev/null @@ -1,573 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: gcsdk_gcmessages.proto -# plugin: python-betterproto -from __future__ import annotations - -from dataclasses import dataclass -from typing import TYPE_CHECKING - -import betterproto - -from ....protobufs.msg import GCProtobufMessage -from .gcsystemmsgs import EGCBaseClientMsg - -if TYPE_CHECKING: - from .steammessages import CGCSystemMsg_GetAccountDetails_Response - - -class ESourceEngine(betterproto.Enum): - Source1 = 0 - Source2 = 1 - - -class PartnerAccountType(betterproto.Enum): - NONE = 0 - PERFECT_WORLD = 1 - INVALID = 3 - - -class GCConnectionStatus(betterproto.Enum): - HAVE_SESSION = 0 - GC_GOING_DOWN = 1 - NO_SESSION = 2 - NO_SESSION_IN_LOGON_QUEUE = 3 - NO_STEAM = 4 - SUSPENDED = 5 - STEAM_GOING_DOWN = 6 - - -@dataclass -class CExtraMsgBlock(betterproto.Message): - msg_type: int = betterproto.uint32_field(1) - contents: bytes = betterproto.bytes_field(2) - msg_key: int = betterproto.uint64_field(3) - is_compressed: bool = betterproto.bool_field(4) - - -@dataclass -class CMsgGCAssertJobData(betterproto.Message): - message_type: str = betterproto.string_field(1) - message_data: bytes = betterproto.bytes_field(2) - - -@dataclass -class CMsgGCConCommand(betterproto.Message): - command: str = betterproto.string_field(1) - - -@dataclass -class CMsgSDOAssert(betterproto.Message): - sdo_type: int = betterproto.int32_field(1) - requests: list[CMsgSDOAssertRequest] = betterproto.message_field(2) - - -@dataclass -class CMsgSDOAssertRequest(betterproto.Message): - key: list[int] = betterproto.uint64_field(1) - requesting_job: str = betterproto.string_field(2) - - -@dataclass -class CMsgSOIDOwner(betterproto.Message): - type: int = betterproto.uint32_field(1) - id: int = betterproto.uint64_field(2) - - -@dataclass -class CMsgSOSingleObject(betterproto.Message): - type_id: int = betterproto.int32_field(2) - object_data: bytes = betterproto.bytes_field(3) - version: float = betterproto.fixed64_field(4) - owner_soid: CMsgSOIDOwner = betterproto.message_field(5) - service_id: int = betterproto.uint32_field(6) - - -@dataclass -class CMsgSOMultipleObjects(betterproto.Message): - objects_modified: list[CMsgSOMultipleObjectsSingleObject] = betterproto.message_field(2) - version: float = betterproto.fixed64_field(3) - objects_added: list[CMsgSOMultipleObjectsSingleObject] = betterproto.message_field(4) - objects_removed: list[CMsgSOMultipleObjectsSingleObject] = betterproto.message_field(5) - owner_soid: CMsgSOIDOwner = betterproto.message_field(6) - service_id: int = betterproto.uint32_field(7) - - -@dataclass -class CMsgSOMultipleObjectsSingleObject(betterproto.Message): - type_id: int = betterproto.int32_field(1) - object_data: bytes = betterproto.bytes_field(2) - - -@dataclass -class CMsgSOCacheSubscribed(betterproto.Message): - objects: list[CMsgSOCacheSubscribedSubscribedType] = betterproto.message_field(2) - version: float = betterproto.fixed64_field(3) - owner_soid: CMsgSOIDOwner = betterproto.message_field(4) - service_id: int = betterproto.uint32_field(5) - service_list: list[int] = betterproto.uint32_field(6) - sync_version: float = betterproto.fixed64_field(7) - - -@dataclass -class CMsgSOCacheSubscribedSubscribedType(betterproto.Message): - type_id: int = betterproto.int32_field(1) - object_data: list[bytes] = betterproto.bytes_field(2) - - -@dataclass -class CMsgSOCacheSubscribedUpToDate(betterproto.Message): - version: float = betterproto.fixed64_field(1) - owner_soid: CMsgSOIDOwner = betterproto.message_field(2) - service_id: int = betterproto.uint32_field(3) - service_list: list[int] = betterproto.uint32_field(4) - sync_version: float = betterproto.fixed64_field(5) - - -@dataclass -class CMsgSOCacheUnsubscribed(betterproto.Message): - owner_soid: CMsgSOIDOwner = betterproto.message_field(2) - - -@dataclass -class CMsgSOCacheSubscriptionCheck(betterproto.Message): - version: float = betterproto.fixed64_field(2) - owner_soid: CMsgSOIDOwner = betterproto.message_field(3) - service_id: int = betterproto.uint32_field(4) - service_list: list[int] = betterproto.uint32_field(5) - sync_version: float = betterproto.fixed64_field(6) - - -@dataclass -class CMsgSOCacheSubscriptionRefresh(betterproto.Message): - owner_soid: CMsgSOIDOwner = betterproto.message_field(2) - - -@dataclass -class CMsgSOCacheVersion(betterproto.Message): - version: float = betterproto.fixed64_field(1) - - -@dataclass -class CMsgGCMultiplexMessage(betterproto.Message): - msgtype: int = betterproto.uint32_field(1) - payload: bytes = betterproto.bytes_field(2) - steamids: list[float] = betterproto.fixed64_field(3) - - -@dataclass -class CMsgGCToGCSubGCStarting(betterproto.Message): - dir_index: int = betterproto.int32_field(1) - - -@dataclass -class CGCToGCMsgMasterAck(betterproto.Message): - dir_index: int = betterproto.int32_field(1) - machine_name: str = betterproto.string_field(3) - process_name: str = betterproto.string_field(4) - directory: list[CGCToGCMsgMasterAckProcess] = betterproto.message_field(6) - - -@dataclass -class CGCToGCMsgMasterAckProcess(betterproto.Message): - dir_index: int = betterproto.int32_field(1) - type_instances: list[int] = betterproto.uint32_field(2) - - -@dataclass -class CGCToGCMsgMasterAck_Response(betterproto.Message): - eresult: int = betterproto.int32_field(1) - - -@dataclass -class CMsgGCToGCUniverseStartup(betterproto.Message): - is_initial_startup: bool = betterproto.bool_field(1) - - -@dataclass -class CMsgGCToGCUniverseStartupResponse(betterproto.Message): - eresult: int = betterproto.int32_field(1) - - -@dataclass -class CGCToGCMsgMasterStartupComplete(betterproto.Message): - gc_info: list[CGCToGCMsgMasterStartupCompleteGCInfo] = betterproto.message_field(1) - - -@dataclass -class CGCToGCMsgMasterStartupCompleteGCInfo(betterproto.Message): - dir_index: int = betterproto.int32_field(1) - machine_name: str = betterproto.string_field(2) - - -@dataclass -class CGCToGCMsgRouted(betterproto.Message): - msg_type: int = betterproto.uint32_field(1) - sender_id: float = betterproto.fixed64_field(2) - net_message: bytes = betterproto.bytes_field(3) - - -@dataclass -class CGCToGCMsgRoutedReply(betterproto.Message): - msg_type: int = betterproto.uint32_field(1) - net_message: bytes = betterproto.bytes_field(2) - - -@dataclass -class CMsgGCUpdateSubGCSessionInfo(betterproto.Message): - updates: list[CMsgGCUpdateSubGCSessionInfoCMsgUpdate] = betterproto.message_field(1) - - -@dataclass -class CMsgGCUpdateSubGCSessionInfoCMsgUpdate(betterproto.Message): - steamid: float = betterproto.fixed64_field(1) - ip: float = betterproto.fixed32_field(2) - trusted: bool = betterproto.bool_field(3) - - -@dataclass -class CMsgGCRequestSubGCSessionInfo(betterproto.Message): - steamid: float = betterproto.fixed64_field(1) - - -@dataclass -class CMsgGCRequestSubGCSessionInfoResponse(betterproto.Message): - ip: float = betterproto.fixed32_field(1) - trusted: bool = betterproto.bool_field(2) - port: int = betterproto.uint32_field(3) - success: bool = betterproto.bool_field(4) - - -@dataclass -class CMsgSOCacheHaveVersion(betterproto.Message): - soid: CMsgSOIDOwner = betterproto.message_field(1) - version: float = betterproto.fixed64_field(2) - service_id: int = betterproto.uint32_field(3) - cached_file_version: int = betterproto.uint32_field(4) - - -class CMsgClientHello(GCProtobufMessage, msg=EGCBaseClientMsg.GCClientHello): - version: int = betterproto.uint32_field(1) - socache_have_versions: list[CMsgSOCacheHaveVersion] = betterproto.message_field(2) - client_session_need: int = betterproto.uint32_field(3) - client_launcher: PartnerAccountType = betterproto.enum_field(4) - secret_key: str = betterproto.string_field(5) - client_language: int = betterproto.uint32_field(6) - engine: ESourceEngine = betterproto.enum_field(7) - steamdatagram_login: bytes = betterproto.bytes_field(8) - platform_id: int = betterproto.uint32_field(9) - game_msg: bytes = betterproto.bytes_field(10) - os_type: int = betterproto.int32_field(11) - render_system: int = betterproto.uint32_field(12) - render_system_req: int = betterproto.uint32_field(13) - screen_width: int = betterproto.uint32_field(14) - screen_height: int = betterproto.uint32_field(15) - screen_refresh: int = betterproto.uint32_field(16) - render_width: int = betterproto.uint32_field(17) - render_height: int = betterproto.uint32_field(18) - swap_width: int = betterproto.uint32_field(19) - swap_height: int = betterproto.uint32_field(20) - is_steam_china: bool = betterproto.bool_field(22) - is_steam_china_client: bool = betterproto.bool_field(24) - platform_name: str = betterproto.string_field(23) - - -@dataclass -class CMsgClientWelcome(betterproto.Message): - version: int = betterproto.uint32_field(1) - game_data: bytes = betterproto.bytes_field(2) - outofdate_subscribed_caches: list[CMsgSOCacheSubscribed] = betterproto.message_field(3) - uptodate_subscribed_caches: list[CMsgSOCacheSubscriptionCheck] = betterproto.message_field(4) - location: CMsgClientWelcomeLocation = betterproto.message_field(5) - save_game_key: bytes = betterproto.bytes_field(6) - gc_socache_file_version: int = betterproto.uint32_field(9) - txn_country_code: str = betterproto.string_field(10) - game_data2: bytes = betterproto.bytes_field(11) - rtime32_gc_welcome_timestamp: int = betterproto.uint32_field(12) - currency: int = betterproto.uint32_field(13) - balance: int = betterproto.uint32_field(14) - balance_url: str = betterproto.string_field(15) - has_accepted_china_ssa: bool = betterproto.bool_field(16) - is_banned_steam_china: bool = betterproto.bool_field(17) - additional_welcome_msgs: CExtraMsgBlock = betterproto.message_field(18) - # steam_learn_server_info: CMsgSteamLearnServerInfo = betterproto.message_field(20) - - -@dataclass -class CMsgClientWelcomeLocation(betterproto.Message): - latitude: float = betterproto.float_field(1) - longitude: float = betterproto.float_field(2) - country: str = betterproto.string_field(3) - - -@dataclass -class CMsgConnectionStatus(betterproto.Message): - status: GCConnectionStatus = betterproto.enum_field(1) - client_session_need: int = betterproto.uint32_field(2) - queue_position: int = betterproto.int32_field(3) - queue_size: int = betterproto.int32_field(4) - wait_seconds: int = betterproto.int32_field(5) - estimated_wait_seconds_remaining: int = betterproto.int32_field(6) - - -@dataclass -class CMsgGCToGCSOCacheSubscribe(betterproto.Message): - subscriber: float = betterproto.fixed64_field(1) - subscribe_to_id: float = betterproto.fixed64_field(2) - sync_version: float = betterproto.fixed64_field(3) - have_versions: list[CMsgGCToGCSOCacheSubscribeCMsgHaveVersions] = betterproto.message_field(4) - subscribe_to_type: int = betterproto.uint32_field(5) - - -@dataclass -class CMsgGCToGCSOCacheSubscribeCMsgHaveVersions(betterproto.Message): - service_id: int = betterproto.uint32_field(1) - version: int = betterproto.uint64_field(2) - - -@dataclass -class CMsgGCToGCSOCacheUnsubscribe(betterproto.Message): - subscriber: float = betterproto.fixed64_field(1) - unsubscribe_from_id: float = betterproto.fixed64_field(2) - unsubscribe_from_type: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgGCClientPing(betterproto.Message): - pass - - -@dataclass -class CMsgGCToGCForwardAccountDetails(betterproto.Message): - steamid: float = betterproto.fixed64_field(1) - account_details: CGCSystemMsg_GetAccountDetails_Response = betterproto.message_field(2) - age_seconds: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgGCToGCLoadSessionSOCache(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - forward_account_details: CMsgGCToGCForwardAccountDetails = betterproto.message_field(2) - - -@dataclass -class CMsgGCToGCLoadSessionSOCacheResponse(betterproto.Message): - pass - - -@dataclass -class CMsgGCToGCUpdateSessionStats(betterproto.Message): - user_sessions: int = betterproto.uint32_field(1) - server_sessions: int = betterproto.uint32_field(2) - in_logon_surge: bool = betterproto.bool_field(3) - - -@dataclass -class CMsgGCToClientRequestDropped(betterproto.Message): - pass - - -@dataclass -class CWorkshop_PopulateItemDescriptions_Request(betterproto.Message): - appid: int = betterproto.uint32_field(1) - languages: list[ - CWorkshop_PopulateItemDescriptions_RequestItemDescriptionsLanguageBlock - ] = betterproto.message_field(2) - - -@dataclass -class CWorkshop_PopulateItemDescriptions_RequestSingleItemDescription(betterproto.Message): - gameitemid: int = betterproto.uint32_field(1) - item_description: str = betterproto.string_field(2) - - -@dataclass -class CWorkshop_PopulateItemDescriptions_RequestItemDescriptionsLanguageBlock(betterproto.Message): - language: str = betterproto.string_field(1) - descriptions: list[CWorkshop_PopulateItemDescriptions_RequestSingleItemDescription] = betterproto.message_field(2) - - -@dataclass -class CWorkshop_GetContributors_Request(betterproto.Message): - appid: int = betterproto.uint32_field(1) - gameitemid: int = betterproto.uint32_field(2) - - -@dataclass -class CWorkshop_GetContributors_Response(betterproto.Message): - contributors: list[float] = betterproto.fixed64_field(1) - - -@dataclass -class CWorkshop_SetItemPaymentRules_Request(betterproto.Message): - appid: int = betterproto.uint32_field(1) - gameitemid: int = betterproto.uint32_field(2) - associated_workshop_files: list[ - CWorkshop_SetItemPaymentRules_RequestWorkshopItemPaymentRule - ] = betterproto.message_field(3) - partner_accounts: list[CWorkshop_SetItemPaymentRules_RequestPartnerItemPaymentRule] = betterproto.message_field(4) - validate_only: bool = betterproto.bool_field(5) - make_workshop_files_subscribable: bool = betterproto.bool_field(6) - associated_workshop_file_for_direct_payments: CWorkshop_SetItemPaymentRules_RequestWorkshopDirectPaymentRule = ( - betterproto.message_field(7) - ) - - -@dataclass -class CWorkshop_SetItemPaymentRules_RequestWorkshopItemPaymentRule(betterproto.Message): - workshop_file_id: int = betterproto.uint64_field(1) - revenue_percentage: float = betterproto.float_field(2) - rule_description: str = betterproto.string_field(3) - rule_type: int = betterproto.uint32_field(4) - - -@dataclass -class CWorkshop_SetItemPaymentRules_RequestWorkshopDirectPaymentRule(betterproto.Message): - workshop_file_id: int = betterproto.uint64_field(1) - rule_description: str = betterproto.string_field(2) - - -@dataclass -class CWorkshop_SetItemPaymentRules_RequestPartnerItemPaymentRule(betterproto.Message): - account_id: int = betterproto.uint32_field(1) - revenue_percentage: float = betterproto.float_field(2) - rule_description: str = betterproto.string_field(3) - - -@dataclass -class CWorkshop_SetItemPaymentRules_Response(betterproto.Message): - validation_errors: list[str] = betterproto.string_field(1) - - -@dataclass -class CCommunity_ClanAnnouncementInfo(betterproto.Message): - gid: int = betterproto.uint64_field(1) - clanid: int = betterproto.uint64_field(2) - posterid: int = betterproto.uint64_field(3) - headline: str = betterproto.string_field(4) - posttime: int = betterproto.uint32_field(5) - updatetime: int = betterproto.uint32_field(6) - body: str = betterproto.string_field(7) - commentcount: int = betterproto.int32_field(8) - tags: list[str] = betterproto.string_field(9) - language: int = betterproto.int32_field(10) - hidden: bool = betterproto.bool_field(11) - forum_topic_id: float = betterproto.fixed64_field(12) - - -@dataclass -class CCommunity_GetClanAnnouncements_Request(betterproto.Message): - steamid: int = betterproto.uint64_field(1) - offset: int = betterproto.uint32_field(2) - count: int = betterproto.uint32_field(3) - maxchars: int = betterproto.uint32_field(4) - strip_html: bool = betterproto.bool_field(5) - required_tags: list[str] = betterproto.string_field(6) - require_no_tags: bool = betterproto.bool_field(7) - language_preference: list[int] = betterproto.uint32_field(8) - hidden_only: bool = betterproto.bool_field(9) - only_gid: bool = betterproto.bool_field(10) - rtime_oldest_date: int = betterproto.uint32_field(11) - include_hidden: bool = betterproto.bool_field(12) - include_partner_events: bool = betterproto.bool_field(13) - - -@dataclass -class CCommunity_GetClanAnnouncements_Response(betterproto.Message): - maxchars: int = betterproto.uint32_field(1) - strip_html: bool = betterproto.bool_field(2) - announcements: list[CCommunity_ClanAnnouncementInfo] = betterproto.message_field(3) - - -@dataclass -class CBroadcast_PostGameDataFrame_Request(betterproto.Message): - appid: int = betterproto.uint32_field(1) - steamid: float = betterproto.fixed64_field(2) - broadcast_id: float = betterproto.fixed64_field(3) - frame_data: bytes = betterproto.bytes_field(4) - - -@dataclass -class CMsgSerializedSOCache(betterproto.Message): - file_version: int = betterproto.uint32_field(1) - caches: list[CMsgSerializedSOCacheCache] = betterproto.message_field(2) - gc_socache_file_version: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgSerializedSOCacheTypeCache(betterproto.Message): - type: int = betterproto.uint32_field(1) - objects: list[bytes] = betterproto.bytes_field(2) - service_id: int = betterproto.uint32_field(3) - - -@dataclass -class CMsgSerializedSOCacheCache(betterproto.Message): - type: int = betterproto.uint32_field(1) - id: int = betterproto.uint64_field(2) - versions: list[CMsgSerializedSOCacheCacheVersion] = betterproto.message_field(3) - type_caches: list[CMsgSerializedSOCacheTypeCache] = betterproto.message_field(4) - - -@dataclass -class CMsgSerializedSOCacheCacheVersion(betterproto.Message): - service: int = betterproto.uint32_field(1) - version: int = betterproto.uint64_field(2) - - -@dataclass -class CMsgGCToClientPollConvarRequest(betterproto.Message): - convar_name: str = betterproto.string_field(1) - poll_id: int = betterproto.uint32_field(2) - - -@dataclass -class CMsgGCToClientPollConvarResponse(betterproto.Message): - poll_id: int = betterproto.uint32_field(1) - convar_value: str = betterproto.string_field(2) - - -@dataclass -class CGCMsgCompressedMsgToClient(betterproto.Message): - msg_id: int = betterproto.uint32_field(1) - compressed_msg: bytes = betterproto.bytes_field(2) - - -@dataclass -class CMsgGCToGCMasterBroadcastMessage(betterproto.Message): - users_per_second: int = betterproto.uint32_field(1) - send_to_users: bool = betterproto.bool_field(2) - send_to_servers: bool = betterproto.bool_field(3) - msg_id: int = betterproto.uint32_field(4) - msg_data: bytes = betterproto.bytes_field(5) - - -@dataclass -class CMsgGCToGCMasterSubscribeToCache(betterproto.Message): - soid_type: int = betterproto.uint32_field(1) - soid_id: float = betterproto.fixed64_field(2) - account_ids: list[int] = betterproto.uint32_field(3) - steam_ids: list[float] = betterproto.fixed64_field(4) - - -@dataclass -class CMsgGCToGCMasterSubscribeToCacheResponse(betterproto.Message): - pass - - -@dataclass -class CMsgGCToGCMasterSubscribeToCacheAsync(betterproto.Message): - subscribe_msg: CMsgGCToGCMasterSubscribeToCache = betterproto.message_field(1) - - -@dataclass -class CMsgGCToGCMasterUnsubscribeFromCache(betterproto.Message): - soid_type: int = betterproto.uint32_field(1) - soid_id: float = betterproto.fixed64_field(2) - account_ids: list[int] = betterproto.uint32_field(3) - steam_ids: list[float] = betterproto.fixed64_field(4) - - -@dataclass -class CMsgGCToGCMasterDestroyCache(betterproto.Message): - soid_type: int = betterproto.uint32_field(1) - soid_id: float = betterproto.fixed64_field(2) diff --git a/steam/ext/dota2/protobufs/gcsystemmsgs.py b/steam/ext/dota2/protobufs/gcsystemmsgs.py deleted file mode 100644 index 871f5cd1..00000000 --- a/steam/ext/dota2/protobufs/gcsystemmsgs.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: gcsystemmsgs.proto -# plugin: python-betterproto - -import betterproto - - -class ESOMsg(betterproto.Enum): - Create = 21 - Update = 22 - Destroy = 23 - CacheSubscribed = 24 - CacheUnsubscribed = 25 - UpdateMultiple = 26 - CacheSubscriptionRefresh = 28 - CacheSubscribedUpToDate = 29 - - -class EGCBaseClientMsg(betterproto.Enum): - GCPingRequest = 3001 - GCPingResponse = 3002 - GCToClientPollConvarRequest = 3003 - GCToClientPollConvarResponse = 3004 - GCCompressedMsgToClient = 3005 - GCCompressedMsgToClient_Legacy = 523 - GCToClientRequestDropped = 3006 - GCClientWelcome = 4004 - GCServerWelcome = 4005 - GCClientHello = 4006 - GCServerHello = 4007 - GCClientConnectionStatus = 4009 - GCServerConnectionStatus = 4010 diff --git a/steam/ext/dota2/protobufs/lobby.py b/steam/ext/dota2/protobufs/lobby.py new file mode 100644 index 00000000..f0e1b528 --- /dev/null +++ b/steam/ext/dota2/protobufs/lobby.py @@ -0,0 +1,50 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_gcmessages_common_lobby.proto +# plugin: python-betterproto + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from ....enums import classproperty, IntEnum + +if TYPE_CHECKING: + from collections.abc import Mapping + + from typing_extensions import Self + + +# fmt: off +class CSODOTALobbyLobbyType(IntEnum): + INVALID = -1 + CASUAL_MATCH = 0 + PRACTICE = 1 + COOP_BOT_MATCH = 4 + COMPETITIVE_MATCH = 7 + WEEKEND_TOURNEY = 9 + LOCAL_BOT_MATCH = 10 + SPECTATOR = 11 + EVENT_MATCH = 12 + NEW_PLAYER_POOL = 14 + FEATURED_GAMEMODE = 15 + + @classproperty + def DISPLAY_NAMES(cls: type[Self]) -> Mapping[CSODOTALobbyLobbyType, str]: # type: ignore + return { + cls.INVALID : 'Invalid', + cls.CASUAL_MATCH : 'Unranked', + cls.PRACTICE : 'Practice', + cls.COOP_BOT_MATCH : 'Coop Bots', + cls.COMPETITIVE_MATCH : 'Ranked', + cls.WEEKEND_TOURNEY : 'Battle Cup', + cls.LOCAL_BOT_MATCH : 'Local Bot Match', + cls.SPECTATOR : 'Spectator', + cls.EVENT_MATCH : 'Event', + cls.NEW_PLAYER_POOL : 'New Player Mode', + cls.FEATURED_GAMEMODE : 'Featured Gamemode', + } + + @property + def display_name(self) -> str: + return self.DISPLAY_NAMES[self] +# fmt: on diff --git a/steam/ext/dota2/protobufs/sdk.py b/steam/ext/dota2/protobufs/sdk.py new file mode 100644 index 00000000..d747a72c --- /dev/null +++ b/steam/ext/dota2/protobufs/sdk.py @@ -0,0 +1,66 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: gcsdk_gcmessages.proto +# plugin: python-betterproto + +from __future__ import annotations + +from dataclasses import dataclass + + +import betterproto + +from ....protobufs.msg import GCProtobufMessage +from ..enums import EMsg + + +# fmt: off +class ESourceEngine(betterproto.Enum): + Source1 = 0 + Source2 = 1 + + +class PartnerAccountType(betterproto.Enum): + NONE = 0 + PERFECT_WORLD = 1 + INVALID = 3 +# fmt: on + + +@dataclass +class CMsgSOIDOwner(betterproto.Message): + type: int = betterproto.uint32_field(1) + id: int = betterproto.uint64_field(2) + + +@dataclass +class CMsgSOCacheHaveVersion(betterproto.Message): + soid: CMsgSOIDOwner = betterproto.message_field(1) + version: float = betterproto.fixed64_field(2) + service_id: int = betterproto.uint32_field(3) + cached_file_version: int = betterproto.uint32_field(4) + + +class CMsgClientHello(GCProtobufMessage, msg=EMsg.GCClientHello): + version: int = betterproto.uint32_field(1) + socache_have_versions: list[CMsgSOCacheHaveVersion] = betterproto.message_field(2) + client_session_need: int = betterproto.uint32_field(3) + client_launcher: PartnerAccountType = betterproto.enum_field(4) + secret_key: str = betterproto.string_field(5) + client_language: int = betterproto.uint32_field(6) + engine: ESourceEngine = betterproto.enum_field(7) + steamdatagram_login: bytes = betterproto.bytes_field(8) + platform_id: int = betterproto.uint32_field(9) + game_msg: bytes = betterproto.bytes_field(10) + os_type: int = betterproto.int32_field(11) + render_system: int = betterproto.uint32_field(12) + render_system_req: int = betterproto.uint32_field(13) + screen_width: int = betterproto.uint32_field(14) + screen_height: int = betterproto.uint32_field(15) + screen_refresh: int = betterproto.uint32_field(16) + render_width: int = betterproto.uint32_field(17) + render_height: int = betterproto.uint32_field(18) + swap_width: int = betterproto.uint32_field(19) + swap_height: int = betterproto.uint32_field(20) + is_steam_china: bool = betterproto.bool_field(22) + is_steam_china_client: bool = betterproto.bool_field(24) + platform_name: str = betterproto.string_field(23) diff --git a/steam/ext/dota2/protobufs/shared_enums.py b/steam/ext/dota2/protobufs/shared_enums.py new file mode 100644 index 00000000..83e18591 --- /dev/null +++ b/steam/ext/dota2/protobufs/shared_enums.py @@ -0,0 +1,81 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_shared_enums.proto +# plugin: python-betterproto + +from __future__ import annotations + + +from typing import TYPE_CHECKING + + +from ....enums import classproperty, IntEnum + +if TYPE_CHECKING: + from collections.abc import Mapping + + from typing_extensions import Self + + +# fmt: off +class DOTAGameMode(IntEnum): + NONE = 0 + AP = 1 + CM = 2 + RD = 3 + SD = 4 + AR = 5 + INTRO = 6 + HW = 7 + REVERSE_CM = 8 + XMAS = 9 + TUTORIAL = 10 + MO = 11 + LP = 12 + POOL1 = 13 + FH = 14 + CUSTOM = 15 + CD = 16 + BD = 17 + ABILITY_DRAFT = 18 + EVENT = 19 + ARDM = 20 + MID1V1 = 21 + ALL_DRAFT = 22 + TURBO = 23 + MUTATION = 24 + COACHES_CHALLENGE = 25 + + @classproperty + def DISPLAY_NAMES(cls: type[Self]) -> Mapping[DOTAGameMode, str]: # type: ignore + return { + cls.NONE : "None", + cls.AP : "All Pick", + cls.CM : "Captains Mode", + cls.RD : "Random Draft", + cls.SD : "Single Draft", + cls.AR : "All Random", + cls.INTRO : "Intro", + cls.HW : "Diretide", + cls.REVERSE_CM : "Reverse Captains Mode", + cls.XMAS : "Frostivus", + cls.TUTORIAL : "Tutorial", + cls.MO : "Mid Only", + cls.LP : "Least Played", + cls.POOL1 : "New Player Mode", + cls.FH : "Compendium Match", + cls.CUSTOM : "Custom Game", + cls.CD : "Captains Draft", + cls.BD : "Balanced Draft", + cls.ABILITY_DRAFT : "Ability Draft", + cls.EVENT : "Event Game", + cls.ARDM : "All Random DeathMatch", + cls.MID1V1 : "1v1 Mid Only", + cls.ALL_DRAFT : "All Pick", + cls.TURBO : "Turbo", + cls.MUTATION : "Mutation", + cls.COACHES_CHALLENGE: "Coaches Challenge", + } + + @property + def display_name(self) -> str: + return self.DISPLAY_NAMES[self] diff --git a/steam/ext/dota2/protobufs/steammessages.py b/steam/ext/dota2/protobufs/steammessages.py deleted file mode 100644 index da0bb776..00000000 --- a/steam/ext/dota2/protobufs/steammessages.py +++ /dev/null @@ -1,102 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: steammessages.proto -# plugin: python-betterproto -from __future__ import annotations - -from dataclasses import dataclass - -import betterproto - - -class EGCPlatform(betterproto.Enum): - NONE = 0 - PC = 1 - Mac = 2 - Linux = 3 - Android = 4 - iOS = 5 - - -class GCProtoBufMsgSrc(betterproto.Enum): - Unspecified = 0 - FromSystem = 1 - FromSteamID = 2 - FromGC = 3 - ReplySystem = 4 - SpoofedSteamID = 5 - - -@dataclass -class CMsgProtoBufHeader(betterproto.Message): - client_steam_id: float = betterproto.fixed64_field(1) - client_session_id: int = betterproto.int32_field(2) - source_app_id: int = betterproto.uint32_field(3) - job_id_source: float = betterproto.fixed64_field(10) - job_id_target: float = betterproto.fixed64_field(11) - target_job_name: str = betterproto.string_field(12) - eresult: int = betterproto.int32_field(13) - error_message: str = betterproto.string_field(14) - gc_msg_src: GCProtoBufMsgSrc = betterproto.enum_field(200) - gc_dir_index_source: int = betterproto.int32_field(201) - - -@dataclass -class CGCSystemMsg_GetAccountDetails(betterproto.Message): - steamid: float = betterproto.fixed64_field(1) - appid: int = betterproto.uint32_field(2) - - -@dataclass -class CGCSystemMsg_GetAccountDetails_Response(betterproto.Message): - eresult_deprecated: int = betterproto.uint32_field(1) - account_name: str = betterproto.string_field(2) - persona_name: str = betterproto.string_field(3) - is_profile_created: bool = betterproto.bool_field(26) - is_profile_public: bool = betterproto.bool_field(4) - is_inventory_public: bool = betterproto.bool_field(5) - is_vac_banned: bool = betterproto.bool_field(7) - is_cyber_cafe: bool = betterproto.bool_field(8) - is_school_account: bool = betterproto.bool_field(9) - is_limited: bool = betterproto.bool_field(10) - is_subscribed: bool = betterproto.bool_field(11) - package: int = betterproto.uint32_field(12) - is_free_trial_account: bool = betterproto.bool_field(13) - free_trial_expiration: int = betterproto.uint32_field(14) - is_low_violence: bool = betterproto.bool_field(15) - is_account_locked_down: bool = betterproto.bool_field(16) - is_community_banned: bool = betterproto.bool_field(17) - is_trade_banned: bool = betterproto.bool_field(18) - trade_ban_expiration: int = betterproto.uint32_field(19) - accountid: int = betterproto.uint32_field(20) - suspension_end_time: int = betterproto.uint32_field(21) - currency: str = betterproto.string_field(22) - steam_level: int = betterproto.uint32_field(23) - friend_count: int = betterproto.uint32_field(24) - account_creation_time: int = betterproto.uint32_field(25) - is_steamguard_enabled: bool = betterproto.bool_field(27) - is_phone_verified: bool = betterproto.bool_field(28) - is_two_factor_auth_enabled: bool = betterproto.bool_field(29) - two_factor_enabled_time: int = betterproto.uint32_field(30) - phone_verification_time: int = betterproto.uint32_field(31) - phone_id: int = betterproto.uint64_field(33) - is_phone_identifying: bool = betterproto.bool_field(34) - rt_identity_linked: int = betterproto.uint32_field(35) - rt_birth_date: int = betterproto.uint32_field(36) - txn_country_code: str = betterproto.string_field(37) - has_accepted_china_ssa: bool = betterproto.bool_field(38) - is_banned_steam_china: bool = betterproto.bool_field(39) - - -@dataclass -class CIPLocationInfo(betterproto.Message): - ip: int = betterproto.uint32_field(1) - latitude: float = betterproto.float_field(2) - longitude: float = betterproto.float_field(3) - country: str = betterproto.string_field(4) - state: str = betterproto.string_field(5) - city: str = betterproto.string_field(6) - - -@dataclass -class CGCMsgGetIPLocationResponse(betterproto.Message): - infos: list[CIPLocationInfo] = betterproto.message_field(1) diff --git a/steam/ext/dota2/protobufs/watch.py b/steam/ext/dota2/protobufs/watch.py new file mode 100644 index 00000000..c31e4a04 --- /dev/null +++ b/steam/ext/dota2/protobufs/watch.py @@ -0,0 +1,76 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_gcmessages_client_watch.proto +# plugin: python-betterproto + +from __future__ import annotations + +from dataclasses import dataclass + +import betterproto + +from ....protobufs.msg import GCProtobufMessage +from ..enums import EMsg + + +@dataclass +class CSourceTVGameSmall(betterproto.Message): + activate_time: int = betterproto.uint32_field(1) + deactivate_time: int = betterproto.uint32_field(2) + server_steam_id: int = betterproto.uint64_field(3) + lobby_id: int = betterproto.uint64_field(4) + league_id: int = betterproto.uint32_field(5) + lobby_type: int = betterproto.uint32_field(6) + game_time: int = betterproto.int32_field(7) + delay: int = betterproto.uint32_field(8) + spectators: int = betterproto.uint32_field(9) + game_mode: int = betterproto.uint32_field(10) + average_mmr: int = betterproto.uint32_field(11) + match_id: int = betterproto.uint64_field(12) + series_id: int = betterproto.uint32_field(13) + team_name_radiant: str = betterproto.string_field(15) + team_name_dire: str = betterproto.string_field(16) + team_logo_radiant: float = betterproto.fixed64_field(24) + team_logo_dire: float = betterproto.fixed64_field(25) + team_id_radiant: int = betterproto.uint32_field(30) + team_id_dire: int = betterproto.uint32_field(31) + sort_score: int = betterproto.uint32_field(17) + last_update_time: float = betterproto.float_field(18) + radiant_lead: int = betterproto.int32_field(19) + radiant_score: int = betterproto.uint32_field(20) + dire_score: int = betterproto.uint32_field(21) + players: list[CSourceTVGameSmallPlayer] = betterproto.message_field(22) + building_state: float = betterproto.fixed32_field(23) + weekend_tourney_tournament_id: int = betterproto.uint32_field(26) + weekend_tourney_division: int = betterproto.uint32_field(27) + weekend_tourney_skill_level: int = betterproto.uint32_field(28) + weekend_tourney_bracket_round: int = betterproto.uint32_field(29) + custom_game_difficulty: int = betterproto.uint32_field(32) + + +@dataclass +class CSourceTVGameSmallPlayer(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + hero_id: int = betterproto.uint32_field(2) + team_slot: int = betterproto.uint32_field(3) + team: int = betterproto.uint32_field(4) + + +class CMsgClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EMsg.ClientToGCFindTopSourceTVGames): + search_key: str = betterproto.string_field(1) + league_id: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + start_game: int = betterproto.uint32_field(4) + game_list_index: int = betterproto.uint32_field(5) + lobby_ids: list[int] = betterproto.uint64_field(6) + + +class CMsgGCToClientFindTopSourceTVGamesResponse(GCProtobufMessage, msg=EMsg.GCToClientFindTopSourceTVGamesResponse): + search_key: str = betterproto.string_field(1) + league_id: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + start_game: int = betterproto.uint32_field(4) + num_games: int = betterproto.uint32_field(5) + game_list_index: int = betterproto.uint32_field(6) + game_list: list[CSourceTVGameSmall] = betterproto.message_field(7) + specific_games: bool = betterproto.bool_field(8) + bot_game: CSourceTVGameSmall = betterproto.message_field(9) diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index 644f728d..cf65ac03 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -6,7 +6,9 @@ from ..._gc import GCState as GCState_ from ...app import DOTA2 -from .protobufs.gcsdk_gcmessages import CMsgClientHello +from .protobufs.sdk import CMsgClientHello +from .protobufs.common import CMsgDOTAProfileCard +from .protobufs.client_messages import CMsgClientToGCGetProfileCard if TYPE_CHECKING: from .client import Client @@ -18,3 +20,10 @@ class GCState(GCState_[Any]): # todo: implement basket-analogy for dota2 def _get_gc_message(self) -> CMsgClientHello: return CMsgClientHello() + + async def fetch_user_dota2_profile_card(self, user_id: int): + await self.ws.send_gc_message(CMsgClientToGCGetProfileCard(account_id=user_id)) + return await self.ws.gc_wait_for( + CMsgDOTAProfileCard, + check=lambda msg: msg.account_id == user_id, + ) diff --git a/tests/unit/test_ext_dota2.py b/tests/unit/test_ext_dota2.py new file mode 100644 index 00000000..872cb403 --- /dev/null +++ b/tests/unit/test_ext_dota2.py @@ -0,0 +1,5 @@ +from steam.ext import dota2 + + +client = dota2.Client() +bot = dota2.Bot(command_prefix="!") From f8bd9b6ad0368044f5fa595d65faea3091b0444e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 22:26:55 +0000 Subject: [PATCH 13/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/client.py | 4 ++-- steam/ext/dota2/enums.py | 8 ++++---- steam/ext/dota2/models.py | 8 ++++---- steam/ext/dota2/protobufs/client_messages.py | 2 +- steam/ext/dota2/protobufs/common.py | 1 - steam/ext/dota2/protobufs/lobby.py | 2 +- steam/ext/dota2/protobufs/sdk.py | 1 - steam/ext/dota2/protobufs/shared_enums.py | 10 ++++------ steam/ext/dota2/state.py | 4 ++-- tests/unit/test_ext_dota2.py | 1 - 10 files changed, 18 insertions(+), 23 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index ffa3b933..fdec7663 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -11,13 +11,13 @@ from ...app import DOTA2 from ...ext import commands from ...utils import MISSING +from .enums import Hero from .models import LiveMatch from .protobufs.watch import ( CMsgClientToGCFindTopSourceTVGames, CMsgGCToClientFindTopSourceTVGamesResponse, ) from .state import GCState # noqa: TCH001 -from .enums import Hero __all__ = ( "Client", @@ -71,7 +71,7 @@ async def top_live_matches( Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ - if max_matches < 1 or 100 < max_matches: + if max_matches < 1 or max_matches > 100: raise ValueError("max_games value should be between 1 and 100.") # mini-math: max_matches 100 -> start_game 90, 91 -> 90, 90 -> 80 diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 42624239..6c26c286 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -15,8 +15,8 @@ # fmt: off class Hero(IntEnum): """Enum representing Dota 2 hero. - - Primarily, mapping hero_id to hero name. + + Primarily, mapping hero_id to hero name. """ NONE = 0 AntiMage = 1 @@ -273,14 +273,14 @@ def DISPLAY_NAMES(cls: type[Self]) -> Mapping[Hero, str]: # type: ignore cls.PrimalBeast : "Primal Beast", cls.Muerta : "Muerta", } - + @property def display_name(self) -> str: return self.DISPLAY_NAMES[self] @property def hero_id(self) -> int: - return self.value + return self.value class EMsg(IntEnum): diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index afdb2c10..6ba8a1fc 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -4,17 +4,17 @@ import datetime from dataclasses import dataclass -from typing import TYPE_CHECKING, TypeVar, Generic, Self +from typing import TYPE_CHECKING, Generic, Self, TypeVar -from .enums import Hero from ... import abc -from .protobufs.shared_enums import DOTAGameMode +from .enums import Hero from .protobufs.lobby import CSODOTALobbyLobbyType +from .protobufs.shared_enums import DOTAGameMode if TYPE_CHECKING: + from .protobufs.common import CMsgDOTAProfileCard from .protobufs.watch import CSourceTVGameSmall from .state import GCState - from .protobufs.common import CMsgDOTAProfileCard __all__ = ("LiveMatch",) diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py index 6ada0f2e..8bcaa461 100644 --- a/steam/ext/dota2/protobufs/client_messages.py +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -4,8 +4,8 @@ from __future__ import annotations - import betterproto + from ....protobufs.msg import GCProtobufMessage from ..enums import EMsg diff --git a/steam/ext/dota2/protobufs/common.py b/steam/ext/dota2/protobufs/common.py index 51c3d3b5..c2ddb492 100644 --- a/steam/ext/dota2/protobufs/common.py +++ b/steam/ext/dota2/protobufs/common.py @@ -6,7 +6,6 @@ from dataclasses import dataclass - import betterproto from ....protobufs.msg import GCProtobufMessage diff --git a/steam/ext/dota2/protobufs/lobby.py b/steam/ext/dota2/protobufs/lobby.py index f0e1b528..28f85dc7 100644 --- a/steam/ext/dota2/protobufs/lobby.py +++ b/steam/ext/dota2/protobufs/lobby.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING -from ....enums import classproperty, IntEnum +from ....enums import IntEnum, classproperty if TYPE_CHECKING: from collections.abc import Mapping diff --git a/steam/ext/dota2/protobufs/sdk.py b/steam/ext/dota2/protobufs/sdk.py index d747a72c..c7870228 100644 --- a/steam/ext/dota2/protobufs/sdk.py +++ b/steam/ext/dota2/protobufs/sdk.py @@ -6,7 +6,6 @@ from dataclasses import dataclass - import betterproto from ....protobufs.msg import GCProtobufMessage diff --git a/steam/ext/dota2/protobufs/shared_enums.py b/steam/ext/dota2/protobufs/shared_enums.py index 83e18591..cafd5eb8 100644 --- a/steam/ext/dota2/protobufs/shared_enums.py +++ b/steam/ext/dota2/protobufs/shared_enums.py @@ -4,11 +4,9 @@ from __future__ import annotations - from typing import TYPE_CHECKING - -from ....enums import classproperty, IntEnum +from ....enums import IntEnum, classproperty if TYPE_CHECKING: from collections.abc import Mapping @@ -44,7 +42,7 @@ class DOTAGameMode(IntEnum): TURBO = 23 MUTATION = 24 COACHES_CHALLENGE = 25 - + @classproperty def DISPLAY_NAMES(cls: type[Self]) -> Mapping[DOTAGameMode, str]: # type: ignore return { @@ -56,8 +54,8 @@ def DISPLAY_NAMES(cls: type[Self]) -> Mapping[DOTAGameMode, str]: # type: ignor cls.AR : "All Random", cls.INTRO : "Intro", cls.HW : "Diretide", - cls.REVERSE_CM : "Reverse Captains Mode", - cls.XMAS : "Frostivus", + cls.REVERSE_CM : "Reverse Captains Mode", + cls.XMAS : "Frostivus", cls.TUTORIAL : "Tutorial", cls.MO : "Mid Only", cls.LP : "Least Played", diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index cf65ac03..a614502b 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -6,9 +6,9 @@ from ..._gc import GCState as GCState_ from ...app import DOTA2 -from .protobufs.sdk import CMsgClientHello -from .protobufs.common import CMsgDOTAProfileCard from .protobufs.client_messages import CMsgClientToGCGetProfileCard +from .protobufs.common import CMsgDOTAProfileCard +from .protobufs.sdk import CMsgClientHello if TYPE_CHECKING: from .client import Client diff --git a/tests/unit/test_ext_dota2.py b/tests/unit/test_ext_dota2.py index 872cb403..33f54f41 100644 --- a/tests/unit/test_ext_dota2.py +++ b/tests/unit/test_ext_dota2.py @@ -1,5 +1,4 @@ from steam.ext import dota2 - client = dota2.Client() bot = dota2.Bot(command_prefix="!") From 2e9383fcc7cfc823986ed63a7f69d20590b0c52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 02:31:15 +0300 Subject: [PATCH 14/50] =?UTF-8?q?=F0=9F=96=8B=EF=B8=8FSmall=20doc=20edit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 2 +- steam/ext/dota2/models.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index fdec7663..49ba0c00 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -55,7 +55,7 @@ async def top_live_matches( Filter matches by Hero. Note, in this case Game Coordinator will still use only current top100 live matches, i.e. requesting "filter by Muerta" will return only subset of those matches in which Muerta is currently being played. - It will not look into lower MMR games than top100. + It will not look into lower MMR games than top100. This behavior is consistent with how Watch Tab works. max_matches Maximum amount of matches to be fetched. diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 6ba8a1fc..cffe4f88 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -122,6 +122,7 @@ def __init__(self, state: GCState, proto: CSourceTVGameSmall) -> None: self.tournament: TournamentMatch | None = None if proto.league_id: # if it is 0 then all tournament related fields are going to be 0 as well battle_cup = None + # todo: check if battle cup has league_id, otherwise we need to separate tournament from battle_cup if proto.weekend_tourney_tournament_id: # if it is 0 then all battle cup related fields are going to be 0 battle_cup = BattleCup( proto.weekend_tourney_tournament_id, From da096d4f2923cd7cee0ba5ab88cbd4265def315d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= <33165440+Aluerie@users.noreply.github.com> Date: Thu, 25 Jan 2024 00:24:37 +0000 Subject: [PATCH 15/50] =?UTF-8?q?=F0=9F=86=98Apply=20suggestions=20from=20?= =?UTF-8?q?code=20review=20by=20Gobot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: James Hilton-Balfe --- steam/ext/dota2/client.py | 4 ++-- steam/ext/dota2/models.py | 17 ++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 49ba0c00..f2641c33 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -51,12 +51,12 @@ async def top_live_matches( Parameters ---------- - hero_id + hero Filter matches by Hero. Note, in this case Game Coordinator will still use only current top100 live matches, i.e. requesting "filter by Muerta" will return only subset of those matches in which Muerta is currently being played. It will not look into lower MMR games than top100. This behavior is consistent with how Watch Tab works. - max_matches + limit Maximum amount of matches to be fetched. Returns diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index cffe4f88..4a057ed2 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -101,9 +101,9 @@ class LiveMatch: """ def __init__(self, state: GCState, proto: CSourceTVGameSmall) -> None: - self._state: GCState = state + self._state = state - self.match_id: int = proto.match_id + self.id = proto.match_id self.server_steam_id: int = proto.match_id self.lobby_id: int = proto.lobby_id @@ -140,17 +140,17 @@ def __init__(self, state: GCState, proto: CSourceTVGameSmall) -> None: battle_cup, ) - self.radiant_lead: int = proto.radiant_lead - self.radiant_score: int = proto.radiant_score - self.dire_score: int = proto.dire_score - self.building_state: float = proto.building_state # todo: helper function to decode this into human-readable + self.radiant_lead = proto.radiant_lead + self.radiant_score = proto.radiant_score + self.dire_score = proto.dire_score + self.building_state = proto.building_state # todo: helper function to decode this into human-readable - self.custom_game_difficulty: int = proto.custom_game_difficulty + self.custom_game_difficulty = proto.custom_game_difficulty # Since Immortal Draft update, players come from the proto message in a wrong order # which can be fixed back with extra fields that they introduced later: `team`, `team_slot` # why valve chose to introduce extra bytes fields instead of resorting it once after player selection - no clue - sorted_players = [p for p in sorted(proto.players, key=lambda player: (player.team, player.team_slot))] + sorted_players = sorted(proto.players, key=attrgetter("team", "team_slot")) self.players = [ LivePlayer( @@ -176,7 +176,6 @@ async def dota2_profile_card(self) -> ProfileCard[Self]: class ProfileCard(Generic[UserT]): def __init__(self, user: UserT, proto: CMsgDOTAProfileCard): - print(proto) self.user = user self.slots = proto.slots self.badge_points = proto.badge_points From ab908727ff4780d6ca3b0640afc78a573856f862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 05:11:02 +0300 Subject: [PATCH 16/50] =?UTF-8?q?=F0=9F=A9=BA=20More=20feedback=20correcti?= =?UTF-8?q?ons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 36 +- steam/ext/dota2/enums.py | 466 +++++++++++-------- steam/ext/dota2/models.py | 47 +- steam/ext/dota2/protobufs/__init__.py | 2 - steam/ext/dota2/protobufs/client_messages.py | 2 +- steam/ext/dota2/protobufs/common.py | 54 +-- steam/ext/dota2/protobufs/lobby.py | 50 -- steam/ext/dota2/protobufs/sdk.py | 97 +++- steam/ext/dota2/protobufs/shared_enums.py | 79 ---- steam/ext/dota2/protobufs/watch.py | 8 +- steam/ext/dota2/state.py | 66 ++- 11 files changed, 503 insertions(+), 404 deletions(-) delete mode 100644 steam/ext/dota2/protobufs/lobby.py delete mode 100644 steam/ext/dota2/protobufs/shared_enums.py diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index f2641c33..2ac64468 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -13,10 +13,7 @@ from ...utils import MISSING from .enums import Hero from .models import LiveMatch -from .protobufs.watch import ( - CMsgClientToGCFindTopSourceTVGames, - CMsgGCToClientFindTopSourceTVGamesResponse, -) +from .protobufs import watch from .state import GCState # noqa: TCH001 __all__ = ( @@ -38,8 +35,9 @@ class Client(Client_): async def top_live_matches( self, + *, hero: Hero = MISSING, - max_matches: int = 100, + limit: int = 100, ) -> list[LiveMatch]: """Fetch top live matches @@ -66,33 +64,33 @@ async def top_live_matches( Raises ------ ValueError - `max_games` value should be between 1 and 100 inclusively. + `limit` value should be between 1 and 100 inclusively. asyncio.TimeoutError Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ - if max_matches < 1 or max_matches > 100: - raise ValueError("max_games value should be between 1 and 100.") + if limit < 1 or limit > 100: + raise ValueError("limit value should be between 1 and 100 inclusively.") - # mini-math: max_matches 100 -> start_game 90, 91 -> 90, 90 -> 80 - start_game = (max_matches - 1) // 10 * 10 + # mini-math: limit 100 -> start_game 90, 91 -> 90, 90 -> 80 + start_game = (limit - 1) // 10 * 10 - def callback(start_game: int, msg: CMsgGCToClientFindTopSourceTVGamesResponse) -> bool: + def callback(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) -> bool: return msg.start_game == start_game futures = [ self._state.ws.gc_wait_for( - CMsgGCToClientFindTopSourceTVGamesResponse, + watch.GCToClientFindTopSourceTVGamesResponse, check=partial(callback, start_game), ) for start_game in range(0, start_game + 1, 10) ] if hero is MISSING: - await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(start_game=start_game)) + await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(start_game=start_game)) else: await self._state.ws.send_gc_message( - CMsgClientToGCFindTopSourceTVGames(start_game=start_game, hero_id=hero.value) + watch.ClientToGCFindTopSourceTVGames(start_game=start_game, hero_id=hero.value) ) async with timeout(30.0): @@ -101,7 +99,7 @@ def callback(start_game: int, msg: CMsgGCToClientFindTopSourceTVGamesResponse) - LiveMatch(self._state, match_info) for response in responses for match_info in response.game_list ] # still need to slice the list, i.e. in case user asks for 85 games, but live_matches above will have 90 matches - return live_matches[:max_matches] + return live_matches[:limit] async def tournament_live_games( self, @@ -126,10 +124,10 @@ async def tournament_live_games( """ future = self._state.ws.gc_wait_for( - CMsgGCToClientFindTopSourceTVGamesResponse, + watch.GCToClientFindTopSourceTVGamesResponse, check=lambda msg: msg.league_id == league_id, ) - await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(league_id=league_id)) + await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(league_id=league_id)) async with timeout(30.0): response = await future @@ -157,10 +155,10 @@ async def live_matches( Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ future = self._state.ws.gc_wait_for( - CMsgGCToClientFindTopSourceTVGamesResponse, + watch.GCToClientFindTopSourceTVGamesResponse, check=lambda msg: msg.specific_games == True, ) - await self._state.ws.send_gc_message(CMsgClientToGCFindTopSourceTVGames(lobby_ids=lobby_ids)) + await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(lobby_ids=lobby_ids)) async with timeout(30.0): response = await future diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 6c26c286..c2bf6add 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -283,115 +283,213 @@ def hero_id(self) -> int: return self.value +class GameMode(IntEnum): # source: dota_shared_enums.proto + NONE = 0 + AllPick = 1 + CaptainsMode = 2 + RandomDraft = 3 + SingleDraft = 4 + AllRandom = 5 + Intro = 6 + Diretide = 7 + ReverseCaptainsMode = 8 + Xmas = 9 + Tutorial = 10 + MidOnly = 11 + LeastPlayed = 12 + NewPlayerMode = 13 + FH = 14 + Custom = 15 + CaptainsDraft = 16 + BD = 17 + AbilityDraft = 18 + Event = 19 + AllRandomDeathMatch = 20 + Mid1v1 = 21 + AllDraft = 22 + Turbo = 23 + Mutation = 24 + CoachesChallenge = 25 + + @classproperty + def DISPLAY_NAMES(cls: type[Self]) -> Mapping[GameMode, str]: # type: ignore + return { + cls.NONE : "None", + cls.AllPick : "All Pick", + cls.CaptainsMode : "Captains Mode", + cls.RandomDraft : "Random Draft", + cls.SingleDraft : "Single Draft", + cls.AllRandom : "All Random", + cls.Intro : "Intro", + cls.Diretide : "Diretide", + cls.ReverseCaptainsMode: "Reverse Captains Mode", + cls.Xmas : "Frostivus", + cls.Tutorial : "Tutorial", + cls.MidOnly : "Mid Only", + cls.LeastPlayed : "Least Played", + cls.NewPlayerMode : "New Player Mode", + cls.FH : "Compendium Match", + cls.Custom : "Custom Game", + cls.CaptainsDraft : "Captains Draft", + cls.BD : "Balanced Draft", + cls.AbilityDraft : "Ability Draft", + cls.Event : "Event Game", + cls.AllRandomDeathMatch: "All Random DeathMatch", + cls.Mid1v1 : "1v1 Mid Only", + cls.AllDraft : "All Pick", + cls.Turbo : "Turbo", + cls.Mutation : "Mutation", + cls.CoachesChallenge : "Coaches Challenge", + } + + @property + def display_name(self) -> str: + return self.DISPLAY_NAMES[self] + + +class LobbyType(IntEnum): # source: dota_gcmessages_common_lobby.proto + Invalid = -1 + CasualMatch = 0 + Practice = 1 + CoopBotMatch = 4 + CompetitiveMatch = 7 + WeekendTourney = 9 + LocalBotMatch = 10 + Spectator = 11 + EventMatch = 12 + NewPlayerPool = 14 + FeaturedGamemode = 15 + + @classproperty + def DISPLAY_NAMES(cls: type[Self]) -> Mapping[LobbyType, str]: # type: ignore + return { + cls.Invalid : 'Invalid', + cls.CasualMatch : 'Unranked', + cls.Practice : 'Practice', + cls.CoopBotMatch : 'Coop Bots', + cls.CompetitiveMatch: 'Ranked', + cls.WeekendTourney : 'Battle Cup', + cls.LocalBotMatch : 'Local Bot Match', + cls.Spectator : 'Spectator', + cls.EventMatch : 'Event', + cls.NewPlayerPool : 'New Player Mode', + cls.FeaturedGamemode: 'Featured Gamemode', + } + + @property + def display_name(self) -> str: + return self.DISPLAY_NAMES[self] + + class EMsg(IntEnum): - # EGCBaseClientMsg - gcsystemmsgs.proto - GCPingRequest = 3001 - GCPingResponse = 3002 - GCToClientPollConvarRequest = 3003 - GCToClientPollConvarResponse = 3004 - GCCompressedMsgToClient = 3005 - GCCompressedMsgToClient_Legacy = 523 - GCToClientRequestDropped = 3006 - GCClientWelcome = 4004 - GCServerWelcome = 4005 - GCClientHello = 4006 - GCServerHello = 4007 - GCClientConnectionStatus = 4009 - GCServerConnectionStatus = 4010 + # EGCBaseClientMsg - source: gcsystemmsgs.proto + PingRequest = 3001 + PingResponse = 3002 + GCToClientPollConvarRequest = 3003 + GCToClientPollConvarResponse = 3004 + CompressedMsgToClient = 3005 + CompressedMsgToClient_Legacy = 523 + GCToClientRequestDropped = 3006 + ClientWelcome = 4004 + ServerWelcome = 4005 + ClientHello = 4006 + ServerHello = 4007 + ClientConnectionStatus = 4009 + ServerConnectionStatus = 4010 - # EDOTAGCMsg - dota_gcmessages_msgid.proto - GCDOTABase = 7000 - GCGameMatchSignOut = 7004 - GCGameMatchSignOutResponse = 7005 - GCJoinChatChannel = 7009 - GCJoinChatChannelResponse = 7010 - GCOtherJoinedChannel = 7013 - GCOtherLeftChannel = 7014 + # EDOTAGCMsg - source: dota_gcmessages_msgid.proto + DOTABase = 7000 + GameMatchSignOut = 7004 + GameMatchSignOutResponse = 7005 + JoinChatChannel = 7009 + JoinChatChannelResponse = 7010 + OtherJoinedChannel = 7013 + OtherLeftChannel = 7014 ServerToGCRequestStatus = 7026 - GCStartFindingMatch = 7033 - GCConnectedPlayers = 7034 - GCAbandonCurrentGame = 7035 - GCStopFindingMatch = 7036 - GCPracticeLobbyCreate = 7038 - GCPracticeLobbyLeave = 7040 - GCPracticeLobbyLaunch = 7041 - GCPracticeLobbyList = 7042 - GCPracticeLobbyListResponse = 7043 - GCPracticeLobbyJoin = 7044 - GCPracticeLobbySetDetails = 7046 - GCPracticeLobbySetTeamSlot = 7047 - GCInitialQuestionnaireResponse = 7049 - GCPracticeLobbyResponse = 7055 - GCBroadcastNotification = 7056 - GCLiveScoreboardUpdate = 7057 - GCRequestChatChannelList = 7060 - GCRequestChatChannelListResponse = 7061 - GCReadyUp = 7070 - GCKickedFromMatchmakingQueue = 7071 - GCLeaverDetected = 7072 - GCSpectateFriendGame = 7073 - GCSpectateFriendGameResponse = 7074 - GCReportsRemainingRequest = 7076 - GCReportsRemainingResponse = 7077 - GCSubmitPlayerReport = 7078 - GCSubmitPlayerReportResponse = 7079 - GCPracticeLobbyKick = 7081 - GCSubmitPlayerReportV2 = 7082 - GCSubmitPlayerReportResponseV2 = 7083 - GCRequestSaveGames = 7084 - GCRequestSaveGamesServer = 7085 - GCRequestSaveGamesResponse = 7086 - GCLeaverDetectedResponse = 7087 - GCPlayerFailedToConnect = 7088 - GCGCToRelayConnect = 7089 - GCGCToRelayConnectresponse = 7090 - GCWatchGame = 7091 - GCWatchGameResponse = 7092 - GCBanStatusRequest = 7093 - GCBanStatusResponse = 7094 - GCMatchDetailsRequest = 7095 - GCMatchDetailsResponse = 7096 - GCCancelWatchGame = 7097 - GCPopup = 7102 - GCFriendPracticeLobbyListRequest = 7111 - GCFriendPracticeLobbyListResponse = 7112 - GCPracticeLobbyJoinResponse = 7113 - GCCreateTeam = 7115 - GCCreateTeamResponse = 7116 - GCTeamInvite_InviterToGC = 7122 - GCTeamInvite_GCImmediateResponseToInviter = 7123 - GCTeamInvite_GCRequestToInvitee = 7124 - GCTeamInvite_InviteeResponseToGC = 7125 - GCTeamInvite_GCResponseToInviter = 7126 - GCTeamInvite_GCResponseToInvitee = 7127 - GCKickTeamMember = 7128 - GCKickTeamMemberResponse = 7129 - GCLeaveTeam = 7130 - GCLeaveTeamResponse = 7131 - GCApplyTeamToPracticeLobby = 7142 - GCTransferTeamAdmin = 7144 - GCPracticeLobbyJoinBroadcastChannel = 7149 - GC_TournamentItemEvent = 7150 - GC_TournamentItemEventResponse = 7151 + StartFindingMatch = 7033 + ConnectedPlayers = 7034 + AbandonCurrentGame = 7035 + StopFindingMatch = 7036 + PracticeLobbyCreate = 7038 + PracticeLobbyLeave = 7040 + PracticeLobbyLaunch = 7041 + PracticeLobbyList = 7042 + PracticeLobbyListResponse = 7043 + PracticeLobbyJoin = 7044 + PracticeLobbySetDetails = 7046 + PracticeLobbySetTeamSlot = 7047 + InitialQuestionnaireResponse = 7049 + PracticeLobbyResponse = 7055 + BroadcastNotification = 7056 + LiveScoreboardUpdate = 7057 + RequestChatChannelList = 7060 + RequestChatChannelListResponse = 7061 + ReadyUp = 7070 + KickedFromMatchmakingQueue = 7071 + LeaverDetected = 7072 + SpectateFriendGame = 7073 + SpectateFriendGameResponse = 7074 + ReportsRemainingRequest = 7076 + ReportsRemainingResponse = 7077 + SubmitPlayerReport = 7078 + SubmitPlayerReportResponse = 7079 + PracticeLobbyKick = 7081 + SubmitPlayerReportV2 = 7082 + SubmitPlayerReportResponseV2 = 7083 + RequestSaveGames = 7084 + RequestSaveGamesServer = 7085 + RequestSaveGamesResponse = 7086 + LeaverDetectedResponse = 7087 + PlayerFailedToConnect = 7088 + GCToRelayConnect = 7089 + GCToRelayConnectresponse = 7090 + WatchGame = 7091 + WatchGameResponse = 7092 + BanStatusRequest = 7093 + BanStatusResponse = 7094 + MatchDetailsRequest = 7095 + MatchDetailsResponse = 7096 + CancelWatchGame = 7097 + Popup = 7102 + FriendPracticeLobbyListRequest = 7111 + FriendPracticeLobbyListResponse = 7112 + PracticeLobbyJoinResponse = 7113 + CreateTeam = 7115 + CreateTeamResponse = 7116 + TeamInviteInviterToGC = 7122 + TeamInviteImmediateResponseToInviter = 7123 + TeamInviteRequestToInvitee = 7124 + TeamInviteInviteeResponseToGC = 7125 + TeamInviteResponseToInviter = 7126 + TeamInviteResponseToInvitee = 7127 + KickTeamMember = 7128 + KickTeamMemberResponse = 7129 + LeaveTeam = 7130 + LeaveTeamResponse = 7131 + ApplyTeamToPracticeLobby = 7142 + TransferTeamAdmin = 7144 + PracticeLobbyJoinBroadcastChannel = 7149 + TournamentItemEvent = 7150 + TournamentItemEventResponse = 7151 TeamFanfare = 7156 ResponseTeamFanfare = 7157 - GC_GameServerUploadSaveGame = 7158 - GC_GameServerSaveGameResult = 7159 - GC_GameServerGetLoadGame = 7160 - GC_GameServerGetLoadGameResult = 7161 - GCEditTeamDetails = 7166 - GCEditTeamDetailsResponse = 7167 - GCReadyUpStatus = 7170 + GameServerUploadSaveGame = 7158 + GameServerSaveGameResult = 7159 + GameServerGetLoadGame = 7160 + GameServerGetLoadGameResult = 7161 + EditTeamDetails = 7166 + EditTeamDetailsResponse = 7167 + ReadyUpStatus = 7170 GCToGCMatchCompleted = 7186 - GCBalancedShuffleLobby = 7188 - GCMatchmakingStatsRequest = 7197 - GCMatchmakingStatsResponse = 7198 - GCBotGameCreate = 7199 - GCSetMatchHistoryAccess = 7200 - GCSetMatchHistoryAccessResponse = 7201 + BalancedShuffleLobby = 7188 + MatchmakingStatsRequest = 7197 + MatchmakingStatsResponse = 7198 + BotGameCreate = 7199 + SetMatchHistoryAccess = 7200 + SetMatchHistoryAccessResponse = 7201 UpgradeLeagueItem = 7203 UpgradeLeagueItemResponse = 7204 - GCWatchDownloadedReplay = 7206 + WatchDownloadedReplay = 7206 ClientsRejoinChatChannels = 7217 GCToGCGetUserChatInfo = 7218 GCToGCGetUserChatInfoResponse = 7219 @@ -408,32 +506,32 @@ class EMsg(IntEnum): GCToGCValidateTeamResponse = 7242 GCToGCGetLeagueAdmin = 7255 GCToGCGetLeagueAdminResponse = 7256 - GCLeaveChatChannel = 7272 - GCChatMessage = 7273 - GCGetHeroStandings = 7274 - GCGetHeroStandingsResponse = 7275 - GCItemEditorReservationsRequest = 7283 - GCItemEditorReservationsResponse = 7284 - GCItemEditorReserveItemDef = 7285 - GCItemEditorReserveItemDefResponse = 7286 - GCItemEditorReleaseReservation = 7287 - GCItemEditorReleaseReservationResponse = 7288 - GCRewardTutorialPrizes = 7289 - GCFantasyLivePlayerStats = 7308 - GCFantasyFinalPlayerStats = 7309 - GCFlipLobbyTeams = 7320 + LeaveChatChannel = 7272 + ChatMessage = 7273 + GetHeroStandings = 7274 + GetHeroStandingsResponse = 7275 + ItemEditorReservationsRequest = 7283 + ItemEditorReservationsResponse = 7284 + ItemEditorReserveItemDef = 7285 + ItemEditorReserveItemDefResponse = 7286 + ItemEditorReleaseReservation = 7287 + ItemEditorReleaseReservationResponse = 7288 + RewardTutorialPrizes = 7289 + FantasyLivePlayerStats = 7308 + FantasyFinalPlayerStats = 7309 + FlipLobbyTeams = 7320 GCToGCEvaluateReportedPlayer = 7322 GCToGCEvaluateReportedPlayerResponse = 7323 GCToGCProcessPlayerReportForTarget = 7324 GCToGCProcessReportSuccess = 7325 - GCNotifyAccountFlagsChange = 7326 - GCSetProfilePrivacy = 7327 - GCSetProfilePrivacyResponse = 7328 - GCClientSuspended = 7342 - GCPartyMemberSetCoach = 7343 - GCPracticeLobbySetCoach = 7346 - GCChatModeratorBan = 7359 - GCLobbyUpdateBroadcastChannelInfo = 7367 + NotifyAccountFlagsChange = 7326 + SetProfilePrivacy = 7327 + SetProfilePrivacyResponse = 7328 + ClientSuspended = 7342 + PartyMemberSetCoach = 7343 + PracticeLobbySetCoach = 7346 + ChatModeratorBan = 7359 + LobbyUpdateBroadcastChannelInfo = 7367 GCToGCGrantTournamentItem = 7372 GCToGCUpgradeTwitchViewerItems = 7375 GCToGCGetLiveMatchAffiliates = 7376 @@ -441,17 +539,17 @@ class EMsg(IntEnum): GCToGCUpdatePlayerPennantCounts = 7378 GCToGCGetPlayerPennantCounts = 7379 GCToGCGetPlayerPennantCountsResponse = 7380 - GCGameMatchSignOutPermissionRequest = 7381 - GCGameMatchSignOutPermissionResponse = 7382 - DOTAAwardEventPoints = 7384 - DOTAGetEventPoints = 7387 - DOTAGetEventPointsResponse = 7388 - GCPartyLeaderWatchGamePrompt = 7397 - GCCompendiumSetSelection = 7405 - GCCompendiumDataRequest = 7406 - GCCompendiumDataResponse = 7407 - DOTAGetPlayerMatchHistory = 7408 - DOTAGetPlayerMatchHistoryResponse = 7409 + GameMatchSignOutPermissionRequest = 7381 + GameMatchSignOutPermissionResponse = 7382 + AwardEventPoints = 7384 + GetEventPoints = 7387 + GetEventPointsResponse = 7388 + PartyLeaderWatchGamePrompt = 7397 + CompendiumSetSelection = 7405 + CompendiumDataRequest = 7406 + CompendiumDataResponse = 7407 + GetPlayerMatchHistory = 7408 + GetPlayerMatchHistoryResponse = 7409 GCToGCMatchmakingAddParty = 7410 GCToGCMatchmakingRemoveParty = 7411 GCToGCMatchmakingRemoveAllParties = 7412 @@ -464,30 +562,30 @@ class EMsg(IntEnum): ServerToGCEvaluateToxicChat = 7419 ServerToGCEvaluateToxicChatResponse = 7420 GCToGCProcessMatchLeaver = 7426 - GCNotificationsRequest = 7427 - GCNotificationsResponse = 7428 + NotificationsRequest = 7427 + NotificationsResponse = 7428 GCToGCModifyNotification = 7429 - GCLeagueAdminList = 7434 - GCNotificationsMarkReadRequest = 7435 + LeagueAdminList = 7434 + NotificationsMarkReadRequest = 7435 ServerToGCRequestBatchPlayerResources = 7450 ServerToGCRequestBatchPlayerResourcesResponse = 7451 - GCCompendiumSetSelectionResponse = 7453 - GCPlayerInfoSubmit = 7456 - GCPlayerInfoSubmitResponse = 7457 + CompendiumSetSelectionResponse = 7453 + PlayerInfoSubmit = 7456 + PlayerInfoSubmitResponse = 7457 GCToGCGetAccountLevel = 7458 GCToGCGetAccountLevelResponse = 7459 DOTAGetWeekendTourneySchedule = 7464 DOTAWeekendTourneySchedule = 7465 - GCJoinableCustomGameModesRequest = 7466 - GCJoinableCustomGameModesResponse = 7467 - GCJoinableCustomLobbiesRequest = 7468 - GCJoinableCustomLobbiesResponse = 7469 - GCQuickJoinCustomLobby = 7470 - GCQuickJoinCustomLobbyResponse = 7471 + JoinableCustomGameModesRequest = 7466 + JoinableCustomGameModesResponse = 7467 + JoinableCustomLobbiesRequest = 7468 + JoinableCustomLobbiesResponse = 7469 + QuickJoinCustomLobby = 7470 + QuickJoinCustomLobbyResponse = 7471 GCToGCGrantEventPointAction = 7472 GCToGCSetCompendiumSelection = 7478 - GCHasItemQuery = 7484 - GCHasItemResponse = 7485 + HasItemQuery = 7484 + HasItemResponse = 7485 GCToGCGrantEventPointActionMsg = 7488 GCToGCGetCompendiumSelections = 7492 GCToGCGetCompendiumSelectionsResponse = 7493 @@ -499,9 +597,9 @@ class EMsg(IntEnum): SignOutDraftInfo = 7502 ClientToGCEmoticonDataRequest = 7503 GCToClientEmoticonData = 7504 - GCPracticeLobbyToggleBroadcastChannelCameramanStatus = 7505 - DOTARedeemItem = 7518 - DOTARedeemItemResponse = 7519 + PracticeLobbyToggleBroadcastChannelCameramanStatus = 7505 + RedeemItem = 7518 + RedeemItemResponse = 7519 ClientToGCGetAllHeroProgress = 7521 ClientToGCGetAllHeroProgressResponse = 7522 GCToGCGetServerForClient = 7523 @@ -530,7 +628,7 @@ class EMsg(IntEnum): ServerToGCRequestStatus_Response = 7546 ClientToGCCreateHeroStatue = 7547 GCToClientHeroStatueCreateResult = 7548 - GCGCToLANServerRelayConnect = 7549 + GCToLANServerRelayConnect = 7549 ClientToGCAcknowledgeBattleReport = 7550 ClientToGCAcknowledgeBattleReportResponse = 7551 ClientToGCGetBattleReportMatchHistory = 7552 @@ -550,7 +648,7 @@ class EMsg(IntEnum): GCToGCSendAccountsEventPoints = 7583 ClientToGCRerollPlayerChallenge = 7584 ServerToGCRerollPlayerChallenge = 7585 - GCRerollPlayerChallengeResponse = 7586 + RerollPlayerChallengeResponse = 7586 SignOutUpdatePlayerChallenge = 7587 ClientToGCSetPartyLeader = 7588 ClientToGCCancelPartyInvites = 7589 @@ -572,13 +670,13 @@ class EMsg(IntEnum): SQLSetIsLeagueAdmin = 7630 GCToGCGetLiveLeagueMatches = 7631 GCToGCGetLiveLeagueMatchesResponse = 7632 - DOTALeagueInfoListAdminsRequest = 7633 - DOTALeagueInfoListAdminsReponse = 7634 + LeagueInfoListAdminsRequest = 7633 + LeagueInfoListAdminsReponse = 7634 GCToGCLeagueMatchStarted = 7645 GCToGCLeagueMatchCompleted = 7646 GCToGCLeagueMatchStartedResponse = 7647 - DOTALeagueAvailableLobbyNodesRequest = 7650 - DOTALeagueAvailableLobbyNodes = 7651 + LeagueAvailableLobbyNodesRequest = 7650 + LeagueAvailableLobbyNodes = 7651 GCToGCLeagueRequest = 7652 GCToGCLeagueResponse = 7653 GCToGCLeagueNodeGroupRequest = 7654 @@ -622,19 +720,19 @@ class EMsg(IntEnum): ServerToGCLockCharmTrading = 8004 ClientToGCPlayerStatsRequest = 8006 GCToClientPlayerStatsResponse = 8007 - GCClearPracticeLobbyTeam = 8008 + ClearPracticeLobbyTeam = 8008 ClientToGCFindTopSourceTVGames = 8009 GCToClientFindTopSourceTVGamesResponse = 8010 - GCLobbyList = 8011 - GCLobbyListResponse = 8012 - GCPlayerStatsMatchSignOut = 8013 + LobbyList = 8011 + LobbyListResponse = 8012 + PlayerStatsMatchSignOut = 8013 ClientToGCSocialFeedPostCommentRequest = 8016 GCToClientSocialFeedPostCommentResponse = 8017 ClientToGCCustomGamesFriendsPlayedRequest = 8018 GCToClientCustomGamesFriendsPlayedResponse = 8019 ClientToGCFriendsPlayedCustomGameRequest = 8020 GCToClientFriendsPlayedCustomGameResponse = 8021 - GCTopCustomGamesList = 8024 + TopCustomGamesList = 8024 ClientToGCSetPartyOpen = 8029 ClientToGCMergePartyInvite = 8030 GCToClientMergeGroupInviteReply = 8031 @@ -649,15 +747,15 @@ class EMsg(IntEnum): GCToServerRealtimeStatsStartStop = 8042 GCToGCGetServersForClients = 8045 GCToGCGetServersForClientsResponse = 8046 - GCPracticeLobbyKickFromTeam = 8047 - DOTAChatGetMemberCount = 8048 - DOTAChatGetMemberCountResponse = 8049 + PracticeLobbyKickFromTeam = 8047 + ChatGetMemberCount = 8048 + ChatGetMemberCountResponse = 8049 ClientToGCSocialFeedPostMessageRequest = 8050 GCToClientSocialFeedPostMessageResponse = 8051 CustomGameListenServerStartedLoading = 8052 CustomGameClientFinishedLoading = 8053 - GCPracticeLobbyCloseBroadcastChannel = 8054 - GCStartFindingMatchResponse = 8055 + PracticeLobbyCloseBroadcastChannel = 8054 + StartFindingMatchResponse = 8055 SQLGCToGCGrantAccountFlag = 8057 GCToClientTopLeagueMatchesResponse = 8061 GCToClientTopFriendMatchesResponse = 8062 @@ -675,8 +773,8 @@ class EMsg(IntEnum): ClientToGCGetQuestProgressResponse = 8079 SignOutXPCoins = 8080 GCToClientMatchSignedOut = 8081 - GCGetHeroStatsHistory = 8082 - GCGetHeroStatsHistoryResponse = 8083 + GetHeroStatsHistory = 8082 + GetHeroStatsHistoryResponse = 8083 ClientToGCPrivateChatInvite = 8084 ClientToGCPrivateChatKick = 8088 ClientToGCPrivateChatPromote = 8089 @@ -709,14 +807,14 @@ class EMsg(IntEnum): ClientToGCVoteForArcanaResponse = 8129 ClientToGCRequestArcanaVotesRemaining = 8130 ClientToGCRequestArcanaVotesRemainingResponse = 8131 - GCTransferTeamAdminResponse = 8132 + TransferTeamAdminResponse = 8132 GCToClientTeamInfo = 8135 GCToClientTeamsInfo = 8136 ClientToGCMyTeamInfoRequest = 8137 ClientToGCPublishUserStat = 8140 GCToGCSignoutSpendWager = 8141 - GCSubmitLobbyMVPVote = 8144 - GCSubmitLobbyMVPVoteResponse = 8145 + SubmitLobbyMVPVote = 8144 + SubmitLobbyMVPVoteResponse = 8145 SignOutCommunityGoalProgress = 8150 GCToClientLobbyMVPAwarded = 8152 GCToClientQuestProgressUpdated = 8153 @@ -747,8 +845,8 @@ class EMsg(IntEnum): ClientToGCSetPlayerCardRosterResponse = 8181 ServerToGCCloseCompendiumInGamePredictionVotingResponse = 8183 LobbyBattleCupVictory = 8186 - GCGetPlayerCardItemInfo = 8187 - GCGetPlayerCardItemInfoResponse = 8188 + GetPlayerCardItemInfo = 8187 + GetPlayerCardItemInfoResponse = 8188 ClientToGCRequestSteamDatagramTicket = 8189 ClientToGCRequestSteamDatagramTicketResponse = 8190 GCToClientBattlePassRollupRequest = 8191 @@ -757,21 +855,21 @@ class EMsg(IntEnum): ClientToGCTransferSeasonalMMRResponse = 8194 GCToGCPublicChatCommunicationBan = 8195 GCToGCUpdateAccountInfo = 8196 - GCChatReportPublicSpam = 8197 + ChatReportPublicSpam = 8197 ClientToGCSetPartyBuilderOptions = 8198 ClientToGCSetPartyBuilderOptionsResponse = 8199 GCToClientPlaytestStatus = 8200 ClientToGCJoinPlaytest = 8201 ClientToGCJoinPlaytestResponse = 8202 LobbyPlaytestDetails = 8203 - DOTASetFavoriteTeam = 8204 + SetFavoriteTeam = 8204 GCToClientBattlePassRollupListRequest = 8205 GCToClientBattlePassRollupListResponse = 8206 - DOTAClaimEventAction = 8209 - DOTAClaimEventActionResponse = 8210 - DOTAGetPeriodicResource = 8211 - DOTAGetPeriodicResourceResponse = 8212 - DOTAPeriodicResourceUpdated = 8213 + ClaimEventAction = 8209 + ClaimEventActionResponse = 8210 + GetPeriodicResource = 8211 + GetPeriodicResourceResponse = 8212 + PeriodicResourceUpdated = 8213 ServerToGCSpendWager = 8214 GCToGCSignoutSpendWagerToken = 8215 SubmitTriviaQuestionAnswer = 8216 @@ -896,8 +994,8 @@ class EMsg(IntEnum): DevDeleteEventActionsResponse = 8366 GCToGCGetAllHeroCurrent = 8635 GCToGCGetAllHeroCurrentResponse = 8636 - GCSubmitPlayerAvoidRequest = 8637 - GCSubmitPlayerAvoidRequestResponse = 8638 + SubmitPlayerAvoidRequest = 8637 + SubmitPlayerAvoidRequestResponse = 8638 GCToClientNotificationsUpdated = 8639 GCtoGCAssociatedExploiterAccountInfo = 8640 GCtoGCAssociatedExploiterAccountInfoResponse = 8641 diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 4a057ed2..324c46ec 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -4,16 +4,15 @@ import datetime from dataclasses import dataclass +from operator import attrgetter from typing import TYPE_CHECKING, Generic, Self, TypeVar -from ... import abc -from .enums import Hero -from .protobufs.lobby import CSODOTALobbyLobbyType -from .protobufs.shared_enums import DOTAGameMode +from ... import abc, user +from ...utils import DateTime +from .enums import GameMode, Hero, LobbyType if TYPE_CHECKING: - from .protobufs.common import CMsgDOTAProfileCard - from .protobufs.watch import CSourceTVGameSmall + from .protobufs import common, watch from .state import GCState __all__ = ("LiveMatch",) @@ -44,9 +43,9 @@ class TournamentTeam: @dataclass(slots=True) class TournamentMatch: - league_id: int + league_id: int # todo: can I get more info like name of the tournament series_id: int - teams: list[TournamentTeam] + teams: tuple[TournamentTeam, TournamentTeam] battle_cup_info: BattleCup | None @@ -100,24 +99,24 @@ class LiveMatch: Custom Game Difficulty """ - def __init__(self, state: GCState, proto: CSourceTVGameSmall) -> None: + def __init__(self, state: GCState, proto: watch.CSourceTVGameSmall) -> None: self._state = state self.id = proto.match_id - self.server_steam_id: int = proto.match_id - self.lobby_id: int = proto.lobby_id + self.server_steam_id = proto.server_steam_id + self.lobby_id = proto.lobby_id - self.lobby_type = CSODOTALobbyLobbyType.try_value(proto.lobby_type) - self.game_mode = DOTAGameMode.try_value(proto.game_mode) - self.average_mmr: int = proto.average_mmr - self.sort_score: int = proto.sort_score - self.spectators: int = proto.spectators + self.lobby_type = LobbyType.try_value(proto.lobby_type) + self.game_mode = GameMode.try_value(proto.game_mode) + self.average_mmr = proto.average_mmr + self.sort_score = proto.sort_score + self.spectators = proto.spectators - self.start_time = datetime.datetime.fromtimestamp(proto.activate_time, datetime.timezone.utc) + self.start_time = DateTime.from_timestamp(proto.activate_time) self.game_time = datetime.timedelta(seconds=proto.game_time) self.end_time = datetime.timedelta(seconds=proto.deactivate_time) self.delay = datetime.timedelta(seconds=proto.delay) - self.last_update_time = datetime.datetime.fromtimestamp(proto.last_update_time, datetime.timezone.utc) + self.last_update_time = DateTime.from_timestamp(proto.last_update_time) self.tournament: TournamentMatch | None = None if proto.league_id: # if it is 0 then all tournament related fields are going to be 0 as well @@ -133,10 +132,10 @@ def __init__(self, state: GCState, proto: CSourceTVGameSmall) -> None: self.tournament = TournamentMatch( proto.league_id, proto.series_id, - [ + ( TournamentTeam(proto.team_id_radiant, proto.team_name_radiant, proto.team_logo_radiant), TournamentTeam(proto.team_id_dire, proto.team_name_dire, proto.team_logo_dire), - ], + ), battle_cup, ) @@ -161,7 +160,7 @@ def __init__(self, state: GCState, proto: CSourceTVGameSmall) -> None: ] def __repr__(self) -> str: - return f"<{self.__class__.__name__} match_id={self.match_id} server_steam_id={self.server_steam_id}>" + return f"<{self.__class__.__name__} id={self.id} server_steam_id={self.server_steam_id}>" class PartialUser(abc.PartialUser): @@ -174,8 +173,12 @@ async def dota2_profile_card(self) -> ProfileCard[Self]: return ProfileCard(self, msg) +class User(PartialUser, user.User): # type: ignore + __slots__ = () + + class ProfileCard(Generic[UserT]): - def __init__(self, user: UserT, proto: CMsgDOTAProfileCard): + def __init__(self, user: UserT, proto: common.ProfileCard): self.user = user self.slots = proto.slots self.badge_points = proto.badge_points diff --git a/steam/ext/dota2/protobufs/__init__.py b/steam/ext/dota2/protobufs/__init__.py index 9bc38b26..13e2ab08 100644 --- a/steam/ext/dota2/protobufs/__init__.py +++ b/steam/ext/dota2/protobufs/__init__.py @@ -8,9 +8,7 @@ from . import ( client_messages as client_messages, common as common, - lobby as lobby, sdk as sdk, - shared_enums as shared_enums, watch as watch, ) diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py index 8bcaa461..cdb26fa2 100644 --- a/steam/ext/dota2/protobufs/client_messages.py +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -10,5 +10,5 @@ from ..enums import EMsg -class CMsgClientToGCGetProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCard): +class ClientToGCGetProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCard): account_id: int = betterproto.uint32_field(1) diff --git a/steam/ext/dota2/protobufs/common.py b/steam/ext/dota2/protobufs/common.py index c2ddb492..7cdc1cef 100644 --- a/steam/ext/dota2/protobufs/common.py +++ b/steam/ext/dota2/protobufs/common.py @@ -13,7 +13,7 @@ # fmt: off -class CMsgDOTAProfileCardEStatID(betterproto.Enum): +class ProfileCardEStatID(betterproto.Enum): Wins = 3 Commends = 4 GamesPlayed = 5 @@ -23,8 +23,8 @@ class CMsgDOTAProfileCardEStatID(betterproto.Enum): # fmt: on -@dataclass -class CMsgBattleCupVictory(betterproto.Message): +@dataclass(eq=False, repr=False) +class BattleCupVictory(betterproto.Message): account_id: int = betterproto.uint32_field(1) win_date: int = betterproto.uint32_field(2) valid_until: int = betterproto.uint32_field(3) @@ -36,59 +36,59 @@ class CMsgBattleCupVictory(betterproto.Message): trophy_id: int = betterproto.uint32_field(9) -@dataclass -class CMsgDOTAProfileCardSlot(betterproto.Message): +@dataclass(eq=False, repr=False) +class ProfileCardSlot(betterproto.Message): slot_id: int = betterproto.uint32_field(1) - trophy: CMsgDOTAProfileCardSlotTrophy = betterproto.message_field(2) - stat: CMsgDOTAProfileCardSlotStat = betterproto.message_field(3) - item: CMsgDOTAProfileCardSlotItem = betterproto.message_field(4) - hero: CMsgDOTAProfileCardSlotHero = betterproto.message_field(5) - emoticon: CMsgDOTAProfileCardSlotEmoticon = betterproto.message_field(6) - team: CMsgDOTAProfileCardSlotTeam = betterproto.message_field(7) + trophy: ProfileCardSlotTrophy = betterproto.message_field(2) + stat: ProfileCardSlotStat = betterproto.message_field(3) + item: ProfileCardSlotItem = betterproto.message_field(4) + hero: ProfileCardSlotHero = betterproto.message_field(5) + emoticon: ProfileCardSlotEmoticon = betterproto.message_field(6) + team: ProfileCardSlotTeam = betterproto.message_field(7) -@dataclass -class CMsgDOTAProfileCardSlotTrophy(betterproto.Message): +@dataclass(eq=False, repr=False) +class ProfileCardSlotTrophy(betterproto.Message): trophy_id: int = betterproto.uint32_field(1) trophy_score: int = betterproto.uint32_field(2) -@dataclass -class CMsgDOTAProfileCardSlotStat(betterproto.Message): - stat_id: CMsgDOTAProfileCardEStatID = betterproto.enum_field(1) +@dataclass(eq=False, repr=False) +class ProfileCardSlotStat(betterproto.Message): + stat_id: ProfileCardEStatID = betterproto.enum_field(1) stat_score: int = betterproto.uint32_field(2) -@dataclass -class CMsgDOTAProfileCardSlotItem(betterproto.Message): +@dataclass(eq=False, repr=False) +class ProfileCardSlotItem(betterproto.Message): serialized_item: bytes = betterproto.bytes_field(1) item_id: int = betterproto.uint64_field(2) -@dataclass -class CMsgDOTAProfileCardSlotHero(betterproto.Message): +@dataclass(eq=False, repr=False) +class ProfileCardSlotHero(betterproto.Message): hero_id: int = betterproto.uint32_field(1) hero_wins: int = betterproto.uint32_field(2) hero_losses: int = betterproto.uint32_field(3) -@dataclass -class CMsgDOTAProfileCardSlotEmoticon(betterproto.Message): +@dataclass(eq=False, repr=False) +class ProfileCardSlotEmoticon(betterproto.Message): emoticon_id: int = betterproto.uint32_field(1) -@dataclass -class CMsgDOTAProfileCardSlotTeam(betterproto.Message): +@dataclass(eq=False, repr=False) +class ProfileCardSlotTeam(betterproto.Message): team_id: int = betterproto.uint32_field(1) -class CMsgDOTAProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCardResponse): +class ProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCardResponse): account_id: int = betterproto.uint32_field(1) - slots: list[CMsgDOTAProfileCardSlot] = betterproto.message_field(3) + slots: list[ProfileCardSlot] = betterproto.message_field(3) badge_points: int = betterproto.uint32_field(4) event_points: int = betterproto.uint32_field(5) event_id: int = betterproto.uint32_field(6) - recent_battle_cup_victory: CMsgBattleCupVictory = betterproto.message_field(7) + recent_battle_cup_victory: BattleCupVictory = betterproto.message_field(7) rank_tier: int = betterproto.uint32_field(8) leaderboard_rank: int = betterproto.uint32_field(9) is_plus_subscriber: bool = betterproto.bool_field(10) diff --git a/steam/ext/dota2/protobufs/lobby.py b/steam/ext/dota2/protobufs/lobby.py deleted file mode 100644 index 28f85dc7..00000000 --- a/steam/ext/dota2/protobufs/lobby.py +++ /dev/null @@ -1,50 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: dota_gcmessages_common_lobby.proto -# plugin: python-betterproto - -from __future__ import annotations - -from typing import TYPE_CHECKING - -from ....enums import IntEnum, classproperty - -if TYPE_CHECKING: - from collections.abc import Mapping - - from typing_extensions import Self - - -# fmt: off -class CSODOTALobbyLobbyType(IntEnum): - INVALID = -1 - CASUAL_MATCH = 0 - PRACTICE = 1 - COOP_BOT_MATCH = 4 - COMPETITIVE_MATCH = 7 - WEEKEND_TOURNEY = 9 - LOCAL_BOT_MATCH = 10 - SPECTATOR = 11 - EVENT_MATCH = 12 - NEW_PLAYER_POOL = 14 - FEATURED_GAMEMODE = 15 - - @classproperty - def DISPLAY_NAMES(cls: type[Self]) -> Mapping[CSODOTALobbyLobbyType, str]: # type: ignore - return { - cls.INVALID : 'Invalid', - cls.CASUAL_MATCH : 'Unranked', - cls.PRACTICE : 'Practice', - cls.COOP_BOT_MATCH : 'Coop Bots', - cls.COMPETITIVE_MATCH : 'Ranked', - cls.WEEKEND_TOURNEY : 'Battle Cup', - cls.LOCAL_BOT_MATCH : 'Local Bot Match', - cls.SPECTATOR : 'Spectator', - cls.EVENT_MATCH : 'Event', - cls.NEW_PLAYER_POOL : 'New Player Mode', - cls.FEATURED_GAMEMODE : 'Featured Gamemode', - } - - @property - def display_name(self) -> str: - return self.DISPLAY_NAMES[self] -# fmt: on diff --git a/steam/ext/dota2/protobufs/sdk.py b/steam/ext/dota2/protobufs/sdk.py index c7870228..552d022c 100644 --- a/steam/ext/dota2/protobufs/sdk.py +++ b/steam/ext/dota2/protobufs/sdk.py @@ -20,28 +20,38 @@ class ESourceEngine(betterproto.Enum): class PartnerAccountType(betterproto.Enum): NONE = 0 - PERFECT_WORLD = 1 - INVALID = 3 + PerfectWorld = 1 + Invalid = 3 + + +class GCConnectionStatus(betterproto.Enum): + HaveSession = 0 + GcGoingDown = 1 + NoSession = 2 + NoSessionInLogonQueue = 3 + NoSteam = 4 + Suspended = 5 + SteamGoingDown = 6 # fmt: on -@dataclass -class CMsgSOIDOwner(betterproto.Message): +@dataclass(eq=False, repr=False) +class SOIDOwner(betterproto.Message): type: int = betterproto.uint32_field(1) id: int = betterproto.uint64_field(2) -@dataclass -class CMsgSOCacheHaveVersion(betterproto.Message): - soid: CMsgSOIDOwner = betterproto.message_field(1) +@dataclass(eq=False, repr=False) +class SOCacheHaveVersion(betterproto.Message): + soid: SOIDOwner = betterproto.message_field(1) version: float = betterproto.fixed64_field(2) service_id: int = betterproto.uint32_field(3) cached_file_version: int = betterproto.uint32_field(4) -class CMsgClientHello(GCProtobufMessage, msg=EMsg.GCClientHello): +class ClientHello(GCProtobufMessage, msg=EMsg.ClientHello): version: int = betterproto.uint32_field(1) - socache_have_versions: list[CMsgSOCacheHaveVersion] = betterproto.message_field(2) + socache_have_versions: list[SOCacheHaveVersion] = betterproto.message_field(2) client_session_need: int = betterproto.uint32_field(3) client_launcher: PartnerAccountType = betterproto.enum_field(4) secret_key: str = betterproto.string_field(5) @@ -63,3 +73,72 @@ class CMsgClientHello(GCProtobufMessage, msg=EMsg.GCClientHello): is_steam_china: bool = betterproto.bool_field(22) is_steam_china_client: bool = betterproto.bool_field(24) platform_name: str = betterproto.string_field(23) + + +@dataclass(eq=False, repr=False) +class CExtraMsgBlock(betterproto.Message): + msg_type: int = betterproto.uint32_field(1) + contents: bytes = betterproto.bytes_field(2) + msg_key: int = betterproto.uint64_field(3) + is_compressed: bool = betterproto.bool_field(4) + + +@dataclass(eq=False, repr=False) +class ClientWelcomeLocation(betterproto.Message): + latitude: float = betterproto.float_field(1) + longitude: float = betterproto.float_field(2) + country: str = betterproto.string_field(3) + + +class ConnectionStatus(GCProtobufMessage, msg=EMsg.ClientConnectionStatus): + status: GCConnectionStatus = betterproto.enum_field(1) + client_session_need: int = betterproto.uint32_field(2) + queue_position: int = betterproto.int32_field(3) + queue_size: int = betterproto.int32_field(4) + wait_seconds: int = betterproto.int32_field(5) + estimated_wait_seconds_remaining: int = betterproto.int32_field(6) + + +@dataclass(eq=False, repr=False) +class SOCacheSubscriptionCheck(betterproto.Message): + version: float = betterproto.fixed64_field(2) + owner_soid: SOIDOwner = betterproto.message_field(3) + service_id: int = betterproto.uint32_field(4) + service_list: list[int] = betterproto.uint32_field(5) + sync_version: float = betterproto.fixed64_field(6) + + +@dataclass(eq=False, repr=False) +class SOCacheSubscribedSubscribedType(betterproto.Message): + type_id: int = betterproto.int32_field(1) + object_data: list[bytes] = betterproto.bytes_field(2) + + +@dataclass(eq=False, repr=False) +class SOCacheSubscribed(betterproto.Message): + objects: list[SOCacheSubscribedSubscribedType] = betterproto.message_field(2) + version: float = betterproto.fixed64_field(3) + owner_soid: SOIDOwner = betterproto.message_field(4) + service_id: int = betterproto.uint32_field(5) + service_list: list[int] = betterproto.uint32_field(6) + sync_version: float = betterproto.fixed64_field(7) + + +class ClientWelcome(GCProtobufMessage, msg=EMsg.ClientWelcome): + version: int = betterproto.uint32_field(1) + game_data: bytes = betterproto.bytes_field(2) + outofdate_subscribed_caches: list[SOCacheSubscribed] = betterproto.message_field(3) + uptodate_subscribed_caches: list[SOCacheSubscriptionCheck] = betterproto.message_field(4) + location: ClientWelcomeLocation = betterproto.message_field(5) + save_game_key: bytes = betterproto.bytes_field(6) + gc_socache_file_version: int = betterproto.uint32_field(9) + txn_country_code: str = betterproto.string_field(10) + game_data2: bytes = betterproto.bytes_field(11) + rtime32_gc_welcome_timestamp: int = betterproto.uint32_field(12) + currency: int = betterproto.uint32_field(13) + balance: int = betterproto.uint32_field(14) + balance_url: str = betterproto.string_field(15) + has_accepted_china_ssa: bool = betterproto.bool_field(16) + is_banned_steam_china: bool = betterproto.bool_field(17) + additional_welcome_msgs: CExtraMsgBlock = betterproto.message_field(18) + # steam_learn_server_info: SteamLearnServerInfo = betterproto.message_field(20) # steam nonsense diff --git a/steam/ext/dota2/protobufs/shared_enums.py b/steam/ext/dota2/protobufs/shared_enums.py deleted file mode 100644 index cafd5eb8..00000000 --- a/steam/ext/dota2/protobufs/shared_enums.py +++ /dev/null @@ -1,79 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# sources: dota_shared_enums.proto -# plugin: python-betterproto - -from __future__ import annotations - -from typing import TYPE_CHECKING - -from ....enums import IntEnum, classproperty - -if TYPE_CHECKING: - from collections.abc import Mapping - - from typing_extensions import Self - - -# fmt: off -class DOTAGameMode(IntEnum): - NONE = 0 - AP = 1 - CM = 2 - RD = 3 - SD = 4 - AR = 5 - INTRO = 6 - HW = 7 - REVERSE_CM = 8 - XMAS = 9 - TUTORIAL = 10 - MO = 11 - LP = 12 - POOL1 = 13 - FH = 14 - CUSTOM = 15 - CD = 16 - BD = 17 - ABILITY_DRAFT = 18 - EVENT = 19 - ARDM = 20 - MID1V1 = 21 - ALL_DRAFT = 22 - TURBO = 23 - MUTATION = 24 - COACHES_CHALLENGE = 25 - - @classproperty - def DISPLAY_NAMES(cls: type[Self]) -> Mapping[DOTAGameMode, str]: # type: ignore - return { - cls.NONE : "None", - cls.AP : "All Pick", - cls.CM : "Captains Mode", - cls.RD : "Random Draft", - cls.SD : "Single Draft", - cls.AR : "All Random", - cls.INTRO : "Intro", - cls.HW : "Diretide", - cls.REVERSE_CM : "Reverse Captains Mode", - cls.XMAS : "Frostivus", - cls.TUTORIAL : "Tutorial", - cls.MO : "Mid Only", - cls.LP : "Least Played", - cls.POOL1 : "New Player Mode", - cls.FH : "Compendium Match", - cls.CUSTOM : "Custom Game", - cls.CD : "Captains Draft", - cls.BD : "Balanced Draft", - cls.ABILITY_DRAFT : "Ability Draft", - cls.EVENT : "Event Game", - cls.ARDM : "All Random DeathMatch", - cls.MID1V1 : "1v1 Mid Only", - cls.ALL_DRAFT : "All Pick", - cls.TURBO : "Turbo", - cls.MUTATION : "Mutation", - cls.COACHES_CHALLENGE: "Coaches Challenge", - } - - @property - def display_name(self) -> str: - return self.DISPLAY_NAMES[self] diff --git a/steam/ext/dota2/protobufs/watch.py b/steam/ext/dota2/protobufs/watch.py index c31e4a04..0ce7f7a1 100644 --- a/steam/ext/dota2/protobufs/watch.py +++ b/steam/ext/dota2/protobufs/watch.py @@ -12,7 +12,7 @@ from ..enums import EMsg -@dataclass +@dataclass(eq=False, repr=False) class CSourceTVGameSmall(betterproto.Message): activate_time: int = betterproto.uint32_field(1) deactivate_time: int = betterproto.uint32_field(2) @@ -47,7 +47,7 @@ class CSourceTVGameSmall(betterproto.Message): custom_game_difficulty: int = betterproto.uint32_field(32) -@dataclass +@dataclass(eq=False, repr=False) class CSourceTVGameSmallPlayer(betterproto.Message): account_id: int = betterproto.uint32_field(1) hero_id: int = betterproto.uint32_field(2) @@ -55,7 +55,7 @@ class CSourceTVGameSmallPlayer(betterproto.Message): team: int = betterproto.uint32_field(4) -class CMsgClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EMsg.ClientToGCFindTopSourceTVGames): +class ClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EMsg.ClientToGCFindTopSourceTVGames): search_key: str = betterproto.string_field(1) league_id: int = betterproto.uint32_field(2) hero_id: int = betterproto.uint32_field(3) @@ -64,7 +64,7 @@ class CMsgClientToGCFindTopSourceTVGames(GCProtobufMessage, msg=EMsg.ClientToGCF lobby_ids: list[int] = betterproto.uint64_field(6) -class CMsgGCToClientFindTopSourceTVGamesResponse(GCProtobufMessage, msg=EMsg.GCToClientFindTopSourceTVGamesResponse): +class GCToClientFindTopSourceTVGamesResponse(GCProtobufMessage, msg=EMsg.GCToClientFindTopSourceTVGamesResponse): search_key: str = betterproto.string_field(1) league_id: int = betterproto.uint32_field(2) hero_id: int = betterproto.uint32_field(3) diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index a614502b..fc489ccd 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -6,24 +6,76 @@ from ..._gc import GCState as GCState_ from ...app import DOTA2 -from .protobufs.client_messages import CMsgClientToGCGetProfileCard -from .protobufs.common import CMsgDOTAProfileCard -from .protobufs.sdk import CMsgClientHello +from ...id import _ID64_TO_ID32 +from ...state import parser +from .models import PartialUser, User +from .protobufs import client_messages, common, sdk if TYPE_CHECKING: + from collections.abc import Iterable, Sequence + from weakref import WeakValueDictionary + + from ...protobufs import friends + from ...types.id import ID32, ID64, Intable from .client import Client class GCState(GCState_[Any]): # todo: implement basket-analogy for dota2 client: Client # type: ignore # PEP 705 + _users: WeakValueDictionary[ID32, User] _APP = DOTA2 # type: ignore - def _get_gc_message(self) -> CMsgClientHello: - return CMsgClientHello() + def _store_user(self, proto: friends.CMsgClientPersonaStateFriend) -> User: + try: + user = self._users[_ID64_TO_ID32(proto.friendid)] + except KeyError: + user = User(state=self, proto=proto) + self._users[user.id] = user + else: + user._update(proto) + return user + + def get_partial_user(self, id: Intable) -> PartialUser: + return PartialUser(self, id) + + if TYPE_CHECKING: + + def get_user(self, id: ID32) -> User | None: + ... + + async def fetch_user(self, user_id64: ID64) -> User: + ... + + async def fetch_users(self, user_id64s: Iterable[ID64]) -> Sequence[User]: + ... + + async def _maybe_user(self, id: Intable) -> User: + ... + + async def _maybe_users(self, id64s: Iterable[ID64]) -> Sequence[User]: + ... + + def _get_gc_message(self) -> sdk.ClientHello: + return sdk.ClientHello() async def fetch_user_dota2_profile_card(self, user_id: int): - await self.ws.send_gc_message(CMsgClientToGCGetProfileCard(account_id=user_id)) + await self.ws.send_gc_message(client_messages.ClientToGCGetProfileCard(account_id=user_id)) return await self.ws.gc_wait_for( - CMsgDOTAProfileCard, + common.ProfileCard, check=lambda msg: msg.account_id == user_id, ) + + @parser + def parse_client_goodbye(self, msg: sdk.ConnectionStatus | None = None) -> None: + if msg is None or msg.status == sdk.GCConnectionStatus.NoSession: + self.dispatch("gc_disconnect") + self._gc_connected.clear() + self._gc_ready.clear() + if msg is not None: + self.dispatch("gc_status_change", msg.status) + + @parser + async def parse_gc_client_connect(self, msg: sdk.ClientWelcome) -> None: + if not self._gc_ready.is_set(): + self._gc_ready.set() + self.dispatch("gc_ready") From c07dff9f70d4536190e90c1666f6dd6c3141d86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 05:16:12 +0300 Subject: [PATCH 17/50] =?UTF-8?q?=F0=9F=AA=BFRemove=20`fmt:=20off`=20from?= =?UTF-8?q?=20betterproto=20Enums?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/protobufs/common.py | 12 +++++------- steam/ext/dota2/protobufs/sdk.py | 20 +++++++++----------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/steam/ext/dota2/protobufs/common.py b/steam/ext/dota2/protobufs/common.py index 7cdc1cef..65cf8cc1 100644 --- a/steam/ext/dota2/protobufs/common.py +++ b/steam/ext/dota2/protobufs/common.py @@ -12,15 +12,13 @@ from ..enums import EMsg -# fmt: off class ProfileCardEStatID(betterproto.Enum): - Wins = 3 - Commends = 4 - GamesPlayed = 5 - FirstMatchDate = 6 + Wins = 3 + Commends = 4 + GamesPlayed = 5 + FirstMatchDate = 6 PreviousSeasonRank = 7 - GamesMVP = 8 -# fmt: on + GamesMVP = 8 @dataclass(eq=False, repr=False) diff --git a/steam/ext/dota2/protobufs/sdk.py b/steam/ext/dota2/protobufs/sdk.py index 552d022c..a74d5493 100644 --- a/steam/ext/dota2/protobufs/sdk.py +++ b/steam/ext/dota2/protobufs/sdk.py @@ -12,27 +12,25 @@ from ..enums import EMsg -# fmt: off class ESourceEngine(betterproto.Enum): Source1 = 0 Source2 = 1 class PartnerAccountType(betterproto.Enum): - NONE = 0 - PerfectWorld = 1 - Invalid = 3 + NONE = 0 + PerfectWorld = 1 + Invalid = 3 class GCConnectionStatus(betterproto.Enum): - HaveSession = 0 - GcGoingDown = 1 - NoSession = 2 + HaveSession = 0 + GcGoingDown = 1 + NoSession = 2 NoSessionInLogonQueue = 3 - NoSteam = 4 - Suspended = 5 - SteamGoingDown = 6 -# fmt: on + NoSteam = 4 + Suspended = 5 + SteamGoingDown = 6 @dataclass(eq=False, repr=False) From dd1b73184299b6f5852ec4f431d79baf6f671960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 05:27:15 +0300 Subject: [PATCH 18/50] =?UTF-8?q?=F0=9F=A4=BAQuotes=20'=20->=20"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Black didn't automate it cause fmt: off 😒custom rule-set when --- steam/ext/dota2/enums.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index c2bf6add..1f358637 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -363,17 +363,17 @@ class LobbyType(IntEnum): # source: dota_gcmessages_common_lobby.proto @classproperty def DISPLAY_NAMES(cls: type[Self]) -> Mapping[LobbyType, str]: # type: ignore return { - cls.Invalid : 'Invalid', - cls.CasualMatch : 'Unranked', - cls.Practice : 'Practice', - cls.CoopBotMatch : 'Coop Bots', - cls.CompetitiveMatch: 'Ranked', - cls.WeekendTourney : 'Battle Cup', - cls.LocalBotMatch : 'Local Bot Match', - cls.Spectator : 'Spectator', - cls.EventMatch : 'Event', - cls.NewPlayerPool : 'New Player Mode', - cls.FeaturedGamemode: 'Featured Gamemode', + cls.Invalid : "Invalid", + cls.CasualMatch : "Unranked", + cls.Practice : "Practice", + cls.CoopBotMatch : "Coop Bots", + cls.CompetitiveMatch: "Ranked", + cls.WeekendTourney : "Battle Cup", + cls.LocalBotMatch : "Local Bot Match", + cls.Spectator : "Spectator", + cls.EventMatch : "Event", + cls.NewPlayerPool : "New Player Mode", + cls.FeaturedGamemode: "Featured Gamemode", } @property From db78cd085532b5ea93b51751a20282a8cffbb1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 13:41:11 +0300 Subject: [PATCH 19/50] =?UTF-8?q?=F0=9F=AA=A5=20Few=20more=20brush=20ups?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 8 ++++---- steam/ext/dota2/enums.py | 36 ++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 2ac64468..a24685b4 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -50,10 +50,10 @@ async def top_live_matches( Parameters ---------- hero - Filter matches by Hero. - Note, in this case Game Coordinator will still use only current top100 live matches, i.e. requesting - "filter by Muerta" will return only subset of those matches in which Muerta is currently being played. - It will not look into lower MMR games than top100. This behavior is consistent with how Watch Tab works. + Filter matches by Hero. Note, in this case Game Coordinator will still use only current top100 live matches, + i.e. requesting "filter by Muerta" will return only subset of those matches in which + Muerta is currently being played. It will not look into lower MMR match than top100 to extend the return + list to number of games from `limit` argument. This behavior is consistent with how Watch Tab works. limit Maximum amount of matches to be fetched. diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 1f358637..1d38c101 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -293,15 +293,15 @@ class GameMode(IntEnum): # source: dota_shared_enums.proto Intro = 6 Diretide = 7 ReverseCaptainsMode = 8 - Xmas = 9 + Frostivus = 9 Tutorial = 10 MidOnly = 11 LeastPlayed = 12 NewPlayerMode = 13 - FH = 14 + CompendiumMatch = 14 Custom = 15 CaptainsDraft = 16 - BD = 17 + BalancedDraft = 17 AbilityDraft = 18 Event = 19 AllRandomDeathMatch = 20 @@ -323,15 +323,15 @@ def DISPLAY_NAMES(cls: type[Self]) -> Mapping[GameMode, str]: # type: ignore cls.Intro : "Intro", cls.Diretide : "Diretide", cls.ReverseCaptainsMode: "Reverse Captains Mode", - cls.Xmas : "Frostivus", + cls.Frostivus : "Frostivus", cls.Tutorial : "Tutorial", cls.MidOnly : "Mid Only", cls.LeastPlayed : "Least Played", cls.NewPlayerMode : "New Player Mode", - cls.FH : "Compendium Match", + cls.CompendiumMatch : "Compendium Match", cls.Custom : "Custom Game", cls.CaptainsDraft : "Captains Draft", - cls.BD : "Balanced Draft", + cls.BalancedDraft : "Balanced Draft", cls.AbilityDraft : "Ability Draft", cls.Event : "Event Game", cls.AllRandomDeathMatch: "All Random DeathMatch", @@ -349,31 +349,31 @@ def display_name(self) -> str: class LobbyType(IntEnum): # source: dota_gcmessages_common_lobby.proto Invalid = -1 - CasualMatch = 0 + Unranked = 0 Practice = 1 CoopBotMatch = 4 - CompetitiveMatch = 7 - WeekendTourney = 9 + Ranked = 7 + BattleCup = 9 LocalBotMatch = 10 Spectator = 11 - EventMatch = 12 - NewPlayerPool = 14 - FeaturedGamemode = 15 + EventGameMode = 12 + NewPlayerMode = 14 + FeaturedGameMode = 15 @classproperty def DISPLAY_NAMES(cls: type[Self]) -> Mapping[LobbyType, str]: # type: ignore return { cls.Invalid : "Invalid", - cls.CasualMatch : "Unranked", + cls.Unranked : "Unranked", cls.Practice : "Practice", cls.CoopBotMatch : "Coop Bots", - cls.CompetitiveMatch: "Ranked", - cls.WeekendTourney : "Battle Cup", + cls.Ranked : "Ranked", + cls.BattleCup : "Battle Cup", cls.LocalBotMatch : "Local Bot Match", cls.Spectator : "Spectator", - cls.EventMatch : "Event", - cls.NewPlayerPool : "New Player Mode", - cls.FeaturedGamemode: "Featured Gamemode", + cls.EventGameMode : "Event", + cls.NewPlayerMode : "New Player Mode", + cls.FeaturedGameMode: "Featured Gamemode", } @property From 8ec073f395e65ebe4f1430026379fff20cbb0322 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 10:41:28 +0000 Subject: [PATCH 20/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/client.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index a24685b4..d9dd4231 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -50,9 +50,9 @@ async def top_live_matches( Parameters ---------- hero - Filter matches by Hero. Note, in this case Game Coordinator will still use only current top100 live matches, - i.e. requesting "filter by Muerta" will return only subset of those matches in which - Muerta is currently being played. It will not look into lower MMR match than top100 to extend the return + Filter matches by Hero. Note, in this case Game Coordinator will still use only current top100 live matches, + i.e. requesting "filter by Muerta" will return only subset of those matches in which + Muerta is currently being played. It will not look into lower MMR match than top100 to extend the return list to number of games from `limit` argument. This behavior is consistent with how Watch Tab works. limit Maximum amount of matches to be fetched. From 3c89f4af4d2bad6c01ae1e5d76f493da9817c499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 14:32:35 +0300 Subject: [PATCH 21/50] =?UTF-8?q?=F0=9F=AA=A5and=20more?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 2 +- steam/ext/dota2/enums.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index d9dd4231..cd6d52f2 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -101,7 +101,7 @@ def callback(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) # still need to slice the list, i.e. in case user asks for 85 games, but live_matches above will have 90 matches return live_matches[:limit] - async def tournament_live_games( + async def tournament_live_matches( self, # todo: league_id as integer is not human-readable/gettable thing, introduce methods to easily find those league_id: int, diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 1d38c101..692a12d8 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -279,7 +279,7 @@ def display_name(self) -> str: return self.DISPLAY_NAMES[self] @property - def hero_id(self) -> int: + def id(self) -> int: return self.value From e353b49a5282eac418179d02c1d0f3b83bf42205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 15:25:37 +0300 Subject: [PATCH 22/50] =?UTF-8?q?=F0=9F=93=BALiveMatchPlayer=20should=20su?= =?UTF-8?q?bclass=20Partial=20user?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 11 ++++++----- steam/ext/dota2/models.py | 27 ++++++++++++++------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index cd6d52f2..1da03244 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -6,6 +6,7 @@ from functools import partial from typing import Final + from ..._const import timeout from ..._gc import Client as Client_ from ...app import DOTA2 @@ -16,6 +17,7 @@ from .protobufs import watch from .state import GCState # noqa: TCH001 + __all__ = ( "Client", "Bot", @@ -95,9 +97,7 @@ def callback(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) async with timeout(30.0): responses = await asyncio.gather(*futures) - live_matches = [ - LiveMatch(self._state, match_info) for response in responses for match_info in response.game_list - ] + live_matches = [LiveMatch(self._state, match) for response in responses for match in response.game_list] # still need to slice the list, i.e. in case user asks for 85 games, but live_matches above will have 90 matches return live_matches[:limit] @@ -131,7 +131,7 @@ async def tournament_live_matches( async with timeout(30.0): response = await future - return [LiveMatch(self._state, match_info) for match_info in response.game_list] + return [LiveMatch(self._state, match) for match in response.game_list] async def live_matches( self, @@ -163,7 +163,8 @@ async def live_matches( async with timeout(30.0): response = await future # todo: test with more than 10 lobby_ids, Game Coordinator will probably chunk it wrongly or fail at all - return [LiveMatch(self._state, match_info) for match_info in response.game_list] + + return [LiveMatch(self._state, match) for match in response.game_list] class Bot(commands.Bot, Client): diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 324c46ec..0204ff93 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -7,6 +7,7 @@ from operator import attrgetter from typing import TYPE_CHECKING, Generic, Self, TypeVar + from ... import abc, user from ...utils import DateTime from .enums import GameMode, Hero, LobbyType @@ -20,12 +21,6 @@ UserT = TypeVar("UserT", bound=abc.PartialUser) -@dataclass(slots=True) -class LivePlayer: - user: PartialUser - hero: Hero - - @dataclass(slots=True) class BattleCup: tournament_id: int @@ -151,13 +146,12 @@ def __init__(self, state: GCState, proto: watch.CSourceTVGameSmall) -> None: # why valve chose to introduce extra bytes fields instead of resorting it once after player selection - no clue sorted_players = sorted(proto.players, key=attrgetter("team", "team_slot")) - self.players = [ - LivePlayer( - user=PartialUser(self._state, p.account_id), - hero=Hero.try_value(p.hero_id), - ) - for p in sorted_players - ] + self.players: list[LiveMatchPlayer] = [] + for player in sorted_players: + live_match_player = LiveMatchPlayer(self._state, player.account_id) + live_match_player.hero = Hero.try_value(player.hero_id) + self.players.append(live_match_player) + def __repr__(self) -> str: return f"<{self.__class__.__name__} id={self.id} server_steam_id={self.server_steam_id}>" @@ -177,6 +171,13 @@ class User(PartialUser, user.User): # type: ignore __slots__ = () +class LiveMatchPlayer(PartialUser): + hero: Hero + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} id={self.id} hero={self.hero!r}>" + + class ProfileCard(Generic[UserT]): def __init__(self, user: UserT, proto: common.ProfileCard): self.user = user From 49ac5378a8492bdbdd6adeacd568ab80435ec17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 15:25:55 +0300 Subject: [PATCH 23/50] =?UTF-8?q?=F0=9F=A6=B8=E2=80=8D=E2=99=80=EF=B8=8Fhe?= =?UTF-8?q?roes=20property=20for=20LiveMatch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/models.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 0204ff93..8fcb3dfe 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -152,6 +152,10 @@ def __init__(self, state: GCState, proto: watch.CSourceTVGameSmall) -> None: live_match_player.hero = Hero.try_value(player.hero_id) self.players.append(live_match_player) + @property + def heroes(self) -> list[Hero]: + """List of heroes in the match. The list is sorted by their player's colour.""" + return [p.hero for p in self.players] def __repr__(self) -> str: return f"<{self.__class__.__name__} id={self.id} server_steam_id={self.server_steam_id}>" From 9fd115f1c1664b88995816eecc1ab09a6e345df6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:26:12 +0000 Subject: [PATCH 24/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/client.py | 2 -- steam/ext/dota2/models.py | 1 - 2 files changed, 3 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 1da03244..c70b542c 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -6,7 +6,6 @@ from functools import partial from typing import Final - from ..._const import timeout from ..._gc import Client as Client_ from ...app import DOTA2 @@ -17,7 +16,6 @@ from .protobufs import watch from .state import GCState # noqa: TCH001 - __all__ = ( "Client", "Bot", diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 8fcb3dfe..a289c37a 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -7,7 +7,6 @@ from operator import attrgetter from typing import TYPE_CHECKING, Generic, Self, TypeVar - from ... import abc, user from ...utils import DateTime from .enums import GameMode, Hero, LobbyType From aa7433bf42f5e7cfcb22c02efb1e5dc080ad3587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 15:39:56 +0300 Subject: [PATCH 25/50] =?UTF-8?q?=F0=9F=A4=A7fix=20import=20*=20abd=20`=5F?= =?UTF-8?q?=5Fall=5F=5F`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/__init__.py | 2 ++ steam/ext/dota2/enums.py | 5 +++++ steam/ext/dota2/models.py | 13 +++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/steam/ext/dota2/__init__.py b/steam/ext/dota2/__init__.py index ce837571..bbca0a53 100644 --- a/steam/ext/dota2/__init__.py +++ b/steam/ext/dota2/__init__.py @@ -8,3 +8,5 @@ """ from .client import * +from .enums import * +from .models import * diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 692a12d8..10766acb 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -11,6 +11,11 @@ from typing_extensions import Self +__all__ = ( + "Hero", + "GameMode", + "LobbyType", +) # fmt: off class Hero(IntEnum): diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 8fcb3dfe..f59e41e3 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -16,7 +16,16 @@ from .protobufs import common, watch from .state import GCState -__all__ = ("LiveMatch",) +__all__ = ( + "BattleCup", + "TournamentTeam", + "TournamentMatch", + "LiveMatch", + "LiveMatchPlayer", + "PartialUser", + "User", + "ProfileCard", +) UserT = TypeVar("UserT", bound=abc.PartialUser) @@ -37,7 +46,7 @@ class TournamentTeam: @dataclass(slots=True) -class TournamentMatch: +class TournamentMatch: # should this be named LiveTournamentMatch ? Idk how fast I gonna break all these namings, league_id: int # todo: can I get more info like name of the tournament series_id: int teams: tuple[TournamentTeam, TournamentTeam] From 59bf6fda0b63e1c4529ec27077a348cc80088098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 25 Jan 2024 19:58:41 +0300 Subject: [PATCH 26/50] =?UTF-8?q?=20=F0=9F=94=A3Doc=20String=20+=20Remove?= =?UTF-8?q?=20C=20prefix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 7 +++++-- steam/ext/dota2/models.py | 2 +- steam/ext/dota2/protobufs/watch.py | 10 +++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index c70b542c..964850ec 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -55,7 +55,9 @@ async def top_live_matches( Muerta is currently being played. It will not look into lower MMR match than top100 to extend the return list to number of games from `limit` argument. This behavior is consistent with how Watch Tab works. limit - Maximum amount of matches to be fetched. + Maximum amount of matches to fetch. This works rather as a boundary limit than "number of matches" to + fetch, i.e. Dota 2 will sometimes give 90 matches when `limit` is 100. + Or even "successfully" return 0 matches. Returns ------- @@ -95,8 +97,9 @@ def callback(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) async with timeout(30.0): responses = await asyncio.gather(*futures) + # each response.game_list is 10 games (except possibly last one if filtered by hero) live_matches = [LiveMatch(self._state, match) for response in responses for match in response.game_list] - # still need to slice the list, i.e. in case user asks for 85 games, but live_matches above will have 90 matches + # still need to slice the list, i.e. limit = 85, but live_matches above will have 90 matches return live_matches[:limit] async def tournament_live_matches( diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 20a7b7cf..5966fae7 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -102,7 +102,7 @@ class LiveMatch: Custom Game Difficulty """ - def __init__(self, state: GCState, proto: watch.CSourceTVGameSmall) -> None: + def __init__(self, state: GCState, proto: watch.SourceTVGameSmall) -> None: self._state = state self.id = proto.match_id diff --git a/steam/ext/dota2/protobufs/watch.py b/steam/ext/dota2/protobufs/watch.py index 0ce7f7a1..24f57b7e 100644 --- a/steam/ext/dota2/protobufs/watch.py +++ b/steam/ext/dota2/protobufs/watch.py @@ -13,7 +13,7 @@ @dataclass(eq=False, repr=False) -class CSourceTVGameSmall(betterproto.Message): +class SourceTVGameSmall(betterproto.Message): activate_time: int = betterproto.uint32_field(1) deactivate_time: int = betterproto.uint32_field(2) server_steam_id: int = betterproto.uint64_field(3) @@ -38,7 +38,7 @@ class CSourceTVGameSmall(betterproto.Message): radiant_lead: int = betterproto.int32_field(19) radiant_score: int = betterproto.uint32_field(20) dire_score: int = betterproto.uint32_field(21) - players: list[CSourceTVGameSmallPlayer] = betterproto.message_field(22) + players: list[SourceTVGameSmallPlayer] = betterproto.message_field(22) building_state: float = betterproto.fixed32_field(23) weekend_tourney_tournament_id: int = betterproto.uint32_field(26) weekend_tourney_division: int = betterproto.uint32_field(27) @@ -48,7 +48,7 @@ class CSourceTVGameSmall(betterproto.Message): @dataclass(eq=False, repr=False) -class CSourceTVGameSmallPlayer(betterproto.Message): +class SourceTVGameSmallPlayer(betterproto.Message): account_id: int = betterproto.uint32_field(1) hero_id: int = betterproto.uint32_field(2) team_slot: int = betterproto.uint32_field(3) @@ -71,6 +71,6 @@ class GCToClientFindTopSourceTVGamesResponse(GCProtobufMessage, msg=EMsg.GCToCli start_game: int = betterproto.uint32_field(4) num_games: int = betterproto.uint32_field(5) game_list_index: int = betterproto.uint32_field(6) - game_list: list[CSourceTVGameSmall] = betterproto.message_field(7) + game_list: list[SourceTVGameSmall] = betterproto.message_field(7) specific_games: bool = betterproto.bool_field(8) - bot_game: CSourceTVGameSmall = betterproto.message_field(9) + bot_game: SourceTVGameSmall = betterproto.message_field(9) From 037355fa7f11ce03c267dac42595edfd2316c1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Sat, 27 Jan 2024 04:20:20 +0300 Subject: [PATCH 27/50] =?UTF-8?q?=F0=9F=93=88=20Glicko=20Rating=20and=20Be?= =?UTF-8?q?havior=20Summary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 33 +++++++++---- steam/ext/dota2/models.py | 52 ++++++++++++++++++-- steam/ext/dota2/protobufs/client_messages.py | 32 ++++++++++++ 3 files changed, 104 insertions(+), 13 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 964850ec..adadaab0 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -4,18 +4,23 @@ import asyncio from functools import partial -from typing import Final +from typing import TYPE_CHECKING, Final -from ..._const import timeout +from ..._const import DOCS_BUILDING, timeout from ..._gc import Client as Client_ from ...app import DOTA2 from ...ext import commands +from ...utils import cached_property # noqa: TCH001 from ...utils import MISSING from .enums import Hero -from .models import LiveMatch +from .models import ClientUser, LiveMatch from .protobufs import watch from .state import GCState # noqa: TCH001 +if TYPE_CHECKING: + from ...types.id import Intable + from .models import User + __all__ = ( "Client", "Bot", @@ -31,14 +36,16 @@ class Client(Client_): """ _APP: Final = DOTA2 + _ClientUserCls = ClientUser _state: GCState # type: ignore # PEP 705 - async def top_live_matches( - self, - *, - hero: Hero = MISSING, - limit: int = 100, - ) -> list[LiveMatch]: + if TYPE_CHECKING: + + @cached_property + def user(self) -> ClientUser: + ... + + async def top_live_matches(self, *, hero: Hero = MISSING, limit: int = 100) -> list[LiveMatch]: """Fetch top live matches This is similar to game list in the Watch Tab of Dota 2 game app. @@ -167,6 +174,14 @@ async def live_matches( return [LiveMatch(self._state, match) for match in response.game_list] + if TYPE_CHECKING or DOCS_BUILDING: + + def get_user(self, id: Intable) -> User | None: + ... + + async def fetch_user(self, id: Intable) -> User: + ... + class Bot(commands.Bot, Client): """Represents a Steam bot. diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 5966fae7..2b5f047c 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -8,8 +8,10 @@ from typing import TYPE_CHECKING, Generic, Self, TypeVar from ... import abc, user +from ..._gc.client import ClientUser as ClientUser_ from ...utils import DateTime from .enums import GameMode, Hero, LobbyType +from .protobufs import client_messages if TYPE_CHECKING: from .protobufs import common, watch @@ -179,10 +181,6 @@ async def dota2_profile_card(self) -> ProfileCard[Self]: return ProfileCard(self, msg) -class User(PartialUser, user.User): # type: ignore - __slots__ = () - - class LiveMatchPlayer(PartialUser): hero: Hero @@ -190,6 +188,52 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__} id={self.id} hero={self.hero!r}>" +class User(PartialUser, user.User): # type: ignore + __slots__ = () + + +class ClientUser(PartialUser, ClientUser_): # type: ignore + # todo: if TYPE_CHECKING: for inventory + + async def glicko_rating(self): + """Request Glicko Rank Information.""" + future = self._state.ws.gc_wait_for(client_messages.CMsgGCToClientRankResponse) + await self._state.ws.send_gc_message( + client_messages.CMsgClientToGCRankRequest(rank_type=client_messages.ERankType.RankedGlicko) + ) + resp = await future + return GlickoRating( + mmr=resp.rank_value, deviation=resp.rank_data1, volatility=resp.rank_data2, const=resp.rank_data3 + ) + + async def behavior_summary(self) -> BehaviorSummary: + future = self._state.ws.gc_wait_for(client_messages.CMsgGCToClientRankResponse) + await self._state.ws.send_gc_message( + client_messages.CMsgClientToGCRankRequest(rank_type=client_messages.ERankType.BehaviorPublic) + ) + resp = await future + return BehaviorSummary(behavior_score=resp.rank_value, communication_score=resp.rank_data1) + + +@dataclass(slots=True) +class GlickoRating: + mmr: int + deviation: int + volatility: int # the numbers, mason, what do they mean + const: int # todo: confirm all those names somehow or leave a note in doc that I'm clueless + + @property + def confidence(self): + # todo: rofl, confirm this please :D + return self.deviation / self.volatility + + +@dataclass(slots=True) +class BehaviorSummary: + behavior_score: int + communication_score: int + + class ProfileCard(Generic[UserT]): def __init__(self, user: UserT, proto: common.ProfileCard): self.user = user diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py index cdb26fa2..73a804eb 100644 --- a/steam/ext/dota2/protobufs/client_messages.py +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -12,3 +12,35 @@ class ClientToGCGetProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCard): account_id: int = betterproto.uint32_field(1) + + +class ERankType(betterproto.Enum): + Invalid = 0 + Casual = 1 + Ranked = 2 + CasualLegacy = 3 + RankedLegacy = 4 + CasualGlicko = 5 + RankedGlicko = 6 + RankMax = 7 + BehaviorPrivate = 100 + BehaviorPublic = 101 + Max = 102 + + +class CMsgClientToGCRankRequest(GCProtobufMessage, msg=EMsg.ClientToGCRankRequest): + rank_type: ERankType = betterproto.enum_field(1) + + +class CMsgGCToClientRankResponseEResultCode(betterproto.Enum): + k_Succeeded = 0 + k_Failed = 1 + k_InvalidRankType = 2 + + +class CMsgGCToClientRankResponse(GCProtobufMessage, msg=EMsg.GCToClientRankResponse): + result_enum: CMsgGCToClientRankResponseEResultCode = betterproto.enum_field(1) + rank_value: int = betterproto.uint32_field(2) + rank_data1: int = betterproto.uint32_field(3) + rank_data2: int = betterproto.uint32_field(4) + rank_data3: int = betterproto.uint32_field(5) From 5a19a1dfd0da04ae9f1d787293b17a07de02807e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 27 Jan 2024 01:20:37 +0000 Subject: [PATCH 28/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/client.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index adadaab0..0759f57b 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -10,8 +10,10 @@ from ..._gc import Client as Client_ from ...app import DOTA2 from ...ext import commands -from ...utils import cached_property # noqa: TCH001 -from ...utils import MISSING +from ...utils import ( + MISSING, + cached_property, +) from .enums import Hero from .models import ClientUser, LiveMatch from .protobufs import watch From 7e3ddb1e40968e58bd7f2430246f9db8c4b37678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Sun, 4 Feb 2024 02:32:48 +0300 Subject: [PATCH 29/50] =?UTF-8?q?=F0=9F=92=A5MatchDetails,=20MM=20stats,?= =?UTF-8?q?=20rating=20-=20very=20raw?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Idk, is it too bad if I dont title stuff properly --- steam/ext/dota2/client.py | 27 +- steam/ext/dota2/enums.py | 10 +- steam/ext/dota2/models.py | 166 ++++++++--- steam/ext/dota2/protobufs/client_messages.py | 51 +++- steam/ext/dota2/protobufs/common.py | 276 ++++++++++++++++--- steam/ext/dota2/protobufs/shared_enums.py | 87 ++++++ steam/ext/dota2/state.py | 11 +- 7 files changed, 540 insertions(+), 88 deletions(-) create mode 100644 steam/ext/dota2/protobufs/shared_enums.py diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 0759f57b..a7869d91 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -14,13 +14,13 @@ MISSING, cached_property, ) -from .enums import Hero -from .models import ClientUser, LiveMatch -from .protobufs import watch +from .models import ClientUser, LiveMatch, MatchDetails +from .protobufs import client_messages, watch from .state import GCState # noqa: TCH001 if TYPE_CHECKING: from ...types.id import Intable + from .enums import Hero from .models import User __all__ = ( @@ -104,7 +104,7 @@ def callback(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) watch.ClientToGCFindTopSourceTVGames(start_game=start_game, hero_id=hero.value) ) - async with timeout(30.0): + async with timeout(15.0): responses = await asyncio.gather(*futures) # each response.game_list is 10 games (except possibly last one if filtered by hero) live_matches = [LiveMatch(self._state, match) for response in responses for match in response.game_list] @@ -139,7 +139,7 @@ async def tournament_live_matches( ) await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(league_id=league_id)) - async with timeout(30.0): + async with timeout(15.0): response = await future return [LiveMatch(self._state, match) for match in response.game_list] @@ -170,12 +170,27 @@ async def live_matches( ) await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(lobby_ids=lobby_ids)) - async with timeout(30.0): + async with timeout(15.0): response = await future # todo: test with more than 10 lobby_ids, Game Coordinator will probably chunk it wrongly or fail at all return [LiveMatch(self._state, match) for match in response.game_list] + async def match_details(self, match_id: int) -> MatchDetails: + proto = await self._state.fetch_match_details(match_id) + if proto.eresult == 1: + return MatchDetails(self._state, proto.match) + else: + msg = f"Failed to get match_details for {match_id}" + raise ValueError(msg) + + async def matchmaking_stats(self): + future = self._state.ws.gc_wait_for(client_messages.MatchmakingStatsResponse) + await self._state.ws.send_gc_message(client_messages.MatchmakingStatsRequest()) + async with timeout(15.0): + return await future + # return BehaviorSummary(behavior_score=resp.rank_value, communication_score=resp.rank_data1) + if TYPE_CHECKING or DOCS_BUILDING: def get_user(self, id: Intable) -> User | None: diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 10766acb..6a4b01b2 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -321,27 +321,27 @@ def DISPLAY_NAMES(cls: type[Self]) -> Mapping[GameMode, str]: # type: ignore return { cls.NONE : "None", cls.AllPick : "All Pick", - cls.CaptainsMode : "Captains Mode", + cls.CaptainsMode : "Captain's Mode", cls.RandomDraft : "Random Draft", cls.SingleDraft : "Single Draft", cls.AllRandom : "All Random", cls.Intro : "Intro", cls.Diretide : "Diretide", - cls.ReverseCaptainsMode: "Reverse Captains Mode", - cls.Frostivus : "Frostivus", + cls.ReverseCaptainsMode: "Reverse Captain's Mode", + cls.Frostivus : "Frostivus", # XMAS, The Greeviling cls.Tutorial : "Tutorial", cls.MidOnly : "Mid Only", cls.LeastPlayed : "Least Played", cls.NewPlayerMode : "New Player Mode", cls.CompendiumMatch : "Compendium Match", cls.Custom : "Custom Game", - cls.CaptainsDraft : "Captains Draft", + cls.CaptainsDraft : "Captain's Draft", cls.BalancedDraft : "Balanced Draft", cls.AbilityDraft : "Ability Draft", cls.Event : "Event Game", cls.AllRandomDeathMatch: "All Random DeathMatch", cls.Mid1v1 : "1v1 Mid Only", - cls.AllDraft : "All Pick", + cls.AllDraft : "All Draft", # Ranked Matchmaking cls.Turbo : "Turbo", cls.Mutation : "Mutation", cls.CoachesChallenge : "Coaches Challenge", diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 2b5f047c..4be67e9b 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -18,10 +18,10 @@ from .state import GCState __all__ = ( - "BattleCup", - "TournamentTeam", - "TournamentMatch", "LiveMatch", + "TournamentMatch", + "TournamentTeam", + "BattleCup", "LiveMatchPlayer", "PartialUser", "User", @@ -31,27 +31,78 @@ UserT = TypeVar("UserT", bound=abc.PartialUser) -@dataclass(slots=True) -class BattleCup: - tournament_id: int - division: int - skill_level: int - bracket_round: int +class PartialMatch: + def __init__(self, state: GCState, id: int): + self._state = state + self.id = id + async def details(self): + """Fetch Match Details. -@dataclass(slots=True) -class TournamentTeam: - id: int - name: str - logo: float # todo: can I get more info on logo than float nonsense ? + Raises + ------ + asyncio.TimeoutError + Request time-outed. Potential reasons: + * Match ID is incorrect. + * This match is still live. + * Dota 2 Game Coordinator lagging or being down. + """ + proto = await self._state.fetch_match_details(self.id) + proto.match -@dataclass(slots=True) -class TournamentMatch: # should this be named LiveTournamentMatch ? Idk how fast I gonna break all these namings, - league_id: int # todo: can I get more info like name of the tournament - series_id: int - teams: tuple[TournamentTeam, TournamentTeam] - battle_cup_info: BattleCup | None +class MatchDetails: + def __init__(self, state: GCState, proto: common.Match) -> None: + self._state = state + + self.id = proto.match_id + self.duration = datetime.timedelta(seconds=proto.duration) + self.start_time = DateTime.from_timestamp(proto.starttime) + self.human_players_amount = proto.human_players + self.players = proto.players # todo: modelize + self.tower_status = proto.tower_status # todo: decipher + self.barracks_status = proto.barracks_status # todo: decipher + self.cluster = proto.cluster + self.first_blood_time = proto.first_blood_time + self.replay_salt = proto.replay_salt + self.server_port = proto.server_port + self.lobby_type = proto.lobby_type # todo: use enum + self.server_ip = proto.server_ip + self.average_skill = proto.average_skill + self.game_balance = proto.game_balance + self.radiant_team_id = proto.radiant_team_id + self.dire_team_id = proto.dire_team_id + self.league_id = proto.leagueid + self.radiant_team_name = proto.radiant_team_name + self.dire_team_name = proto.dire_team_name + self.radiant_team_logo = proto.radiant_team_logo + self.dire_team_logo = proto.dire_team_logo + self.radiant_team_logo_url = proto.radiant_team_logo_url + self.dire_team_logo_url = proto.dire_team_logo_url + self.radiant_team_complete = proto.radiant_team_complete + self.dire_team_complete = proto.dire_team_complete + self.game_mode = proto.game_mode # todo: use enum + self.picks_bans = proto.picks_bans # todo: modelize + self.match_seq_num = proto.match_seq_num + self.replay_state = proto.replay_state + self.radiant_guild_id = proto.radiant_guild_id + self.dire_guild_id = proto.dire_guild_id + self.radiant_team_tag = proto.radiant_team_tag + self.dire_team_tag: str = proto.dire_team_tag + self.series_id = proto.series_id + self.series_type = proto.series_type + self.broadcaster_channels = proto.broadcaster_channels # todo: modelize + self.engine = proto.engine + self.custom_game_data = proto.custom_game_data # todo: ??? + self.match_flags = proto.match_flags # todo: ??? + self.private_metadata_key = proto.private_metadata_key # todo: ??? + self.radiant_team_score = proto.radiant_team_score + self.dire_team_score = proto.dire_team_score + self.match_outcome = proto.match_outcome # todo: enumize + self.tournament_id = proto.tournament_id + self.tournament_round = proto.tournament_round + self.pre_game_duration = proto.pre_game_duration + self.coaches = proto.coaches # todo: modelize class LiveMatch: @@ -59,7 +110,7 @@ class LiveMatch: Attributes ----------- - match_id + id Match ID. server_steam_id Server Steam ID. @@ -92,6 +143,10 @@ class LiveMatch: Time the data was updated last by the Game Coordinator. tournament Tournament information, if the match is a tournament game. + Includes information about tournament teams. + battle_cup + Battle Cup information, if the match is a battle cup game. + Includes information about tournament teams. radiant_lead Amount of gold lead Radiant team has. Negative value in case Dire is leading. radiant_score @@ -123,26 +178,32 @@ def __init__(self, state: GCState, proto: watch.SourceTVGameSmall) -> None: self.delay = datetime.timedelta(seconds=proto.delay) self.last_update_time = DateTime.from_timestamp(proto.last_update_time) - self.tournament: TournamentMatch | None = None - if proto.league_id: # if it is 0 then all tournament related fields are going to be 0 as well - battle_cup = None - # todo: check if battle cup has league_id, otherwise we need to separate tournament from battle_cup - if proto.weekend_tourney_tournament_id: # if it is 0 then all battle cup related fields are going to be 0 - battle_cup = BattleCup( - proto.weekend_tourney_tournament_id, - proto.weekend_tourney_division, - proto.weekend_tourney_skill_level, - proto.weekend_tourney_bracket_round, - ) - self.tournament = TournamentMatch( + self.tournament = ( + TournamentMatch( proto.league_id, proto.series_id, ( TournamentTeam(proto.team_id_radiant, proto.team_name_radiant, proto.team_logo_radiant), TournamentTeam(proto.team_id_dire, proto.team_name_dire, proto.team_logo_dire), ), - battle_cup, ) + if proto.league_id # if it is 0 then all tournament related fields are going to be 0 as well + else None + ) + self.battle_cup = ( + BattleCup( + proto.weekend_tourney_tournament_id, + proto.weekend_tourney_division, + proto.weekend_tourney_skill_level, + proto.weekend_tourney_bracket_round, + ( + TournamentTeam(proto.team_id_radiant, proto.team_name_radiant, proto.team_logo_radiant), + TournamentTeam(proto.team_id_dire, proto.team_name_dire, proto.team_logo_dire), + ), + ) + if proto.weekend_tourney_tournament_id # if it is 0 then all battle cup related fields are going to be 0 + else None + ) self.radiant_lead = proto.radiant_lead self.radiant_score = proto.radiant_score @@ -171,6 +232,29 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__} id={self.id} server_steam_id={self.server_steam_id}>" +@dataclass(slots=True) +class TournamentMatch: # should this be named LiveTournamentMatch ? Idk how fast I gonna break all these namings, + league_id: int # todo: can I get more info like name of the tournament + series_id: int + teams: tuple[TournamentTeam, TournamentTeam] + + +@dataclass(slots=True) +class TournamentTeam: + id: int + name: str + logo: float # todo: can I get more info on logo than float nonsense ? + + +@dataclass(slots=True) +class BattleCup: + tournament_id: int + division: int + skill_level: int + bracket_round: int + teams: tuple[TournamentTeam, TournamentTeam] + + class PartialUser(abc.PartialUser): __slots__ = () _state: GCState @@ -197,19 +281,23 @@ class ClientUser(PartialUser, ClientUser_): # type: ignore async def glicko_rating(self): """Request Glicko Rank Information.""" - future = self._state.ws.gc_wait_for(client_messages.CMsgGCToClientRankResponse) + future = self._state.ws.gc_wait_for(client_messages.GCToClientRankResponse) await self._state.ws.send_gc_message( - client_messages.CMsgClientToGCRankRequest(rank_type=client_messages.ERankType.RankedGlicko) + client_messages.ClientToGCRankRequest(rank_type=client_messages.ERankType.RankedGlicko) ) resp = await future return GlickoRating( - mmr=resp.rank_value, deviation=resp.rank_data1, volatility=resp.rank_data2, const=resp.rank_data3 + mmr=resp.rank_value, + deviation=resp.rank_data1, + volatility=resp.rank_data2, + const=resp.rank_data3, ) async def behavior_summary(self) -> BehaviorSummary: - future = self._state.ws.gc_wait_for(client_messages.CMsgGCToClientRankResponse) + """Request Behavior Summary.""" + future = self._state.ws.gc_wait_for(client_messages.GCToClientRankResponse) await self._state.ws.send_gc_message( - client_messages.CMsgClientToGCRankRequest(rank_type=client_messages.ERankType.BehaviorPublic) + client_messages.ClientToGCRankRequest(rank_type=client_messages.ERankType.BehaviorPublic) ) resp = await future return BehaviorSummary(behavior_score=resp.rank_value, communication_score=resp.rank_data1) diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py index 73a804eb..433ce64b 100644 --- a/steam/ext/dota2/protobufs/client_messages.py +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -4,16 +4,25 @@ from __future__ import annotations +from dataclasses import dataclass + import betterproto from ....protobufs.msg import GCProtobufMessage from ..enums import EMsg +from .common import Match # noqa: TCH001 +from .shared_enums import EMatchGroupServerStatus, MatchVote # noqa: TCH001 + +# PROFILE CARD class ClientToGCGetProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCard): account_id: int = betterproto.uint32_field(1) +# RANK/BEHAVIOR + + class ERankType(betterproto.Enum): Invalid = 0 Casual = 1 @@ -28,19 +37,53 @@ class ERankType(betterproto.Enum): Max = 102 -class CMsgClientToGCRankRequest(GCProtobufMessage, msg=EMsg.ClientToGCRankRequest): +class ClientToGCRankRequest(GCProtobufMessage, msg=EMsg.ClientToGCRankRequest): rank_type: ERankType = betterproto.enum_field(1) -class CMsgGCToClientRankResponseEResultCode(betterproto.Enum): +class GCToClientRankResponseEResultCode(betterproto.Enum): k_Succeeded = 0 k_Failed = 1 k_InvalidRankType = 2 -class CMsgGCToClientRankResponse(GCProtobufMessage, msg=EMsg.GCToClientRankResponse): - result_enum: CMsgGCToClientRankResponseEResultCode = betterproto.enum_field(1) +class GCToClientRankResponse(GCProtobufMessage, msg=EMsg.GCToClientRankResponse): + result_enum: GCToClientRankResponseEResultCode = betterproto.enum_field(1) rank_value: int = betterproto.uint32_field(2) rank_data1: int = betterproto.uint32_field(3) rank_data2: int = betterproto.uint32_field(4) rank_data3: int = betterproto.uint32_field(5) + + +# MATCHMAKING STATS + + +class MatchmakingStatsRequest(GCProtobufMessage, msg=EMsg.MatchmakingStatsRequest): + pass + + +class MatchmakingStatsResponse(GCProtobufMessage, msg=EMsg.MatchmakingStatsResponse): + matchgroups_version: int = betterproto.uint32_field(1) + legacy_searching_players_by_group_source2: list[int] = betterproto.uint32_field(7) + match_groups: list[MatchmakingMatchGroupInfo] = betterproto.message_field(8) + + +@dataclass(eq=False, repr=False) +class MatchmakingMatchGroupInfo(betterproto.Message): + players_searching: int = betterproto.uint32_field(1) + auto_region_select_ping_penalty: int = betterproto.sint32_field(2) + auto_region_select_ping_penalty_custom: int = betterproto.sint32_field(4) + status: EMatchGroupServerStatus = betterproto.enum_field(3) + + +# MATCH DETAILS + + +class MatchDetailsRequest(GCProtobufMessage, msg=EMsg.MatchDetailsRequest): + match_id: int = betterproto.uint64_field(1) + + +class MatchDetailsResponse(GCProtobufMessage, msg=EMsg.MatchDetailsResponse): + eresult: int = betterproto.uint32_field(1) # originally called result + match: Match = betterproto.message_field(2) + vote: MatchVote = betterproto.enum_field(3) diff --git a/steam/ext/dota2/protobufs/common.py b/steam/ext/dota2/protobufs/common.py index 65cf8cc1..e2c14d23 100644 --- a/steam/ext/dota2/protobufs/common.py +++ b/steam/ext/dota2/protobufs/common.py @@ -10,28 +10,27 @@ from ....protobufs.msg import GCProtobufMessage from ..enums import EMsg +from .shared_enums import EMatchOutcome, GameMode, Team # noqa: TCH001 +# PROFILE CARD -class ProfileCardEStatID(betterproto.Enum): - Wins = 3 - Commends = 4 - GamesPlayed = 5 - FirstMatchDate = 6 - PreviousSeasonRank = 7 - GamesMVP = 8 - -@dataclass(eq=False, repr=False) -class BattleCupVictory(betterproto.Message): +class ProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCardResponse): account_id: int = betterproto.uint32_field(1) - win_date: int = betterproto.uint32_field(2) - valid_until: int = betterproto.uint32_field(3) - skill_level: int = betterproto.uint32_field(4) - tournament_id: int = betterproto.uint32_field(5) - division_id: int = betterproto.uint32_field(6) - team_id: int = betterproto.uint32_field(7) - streak: int = betterproto.uint32_field(8) - trophy_id: int = betterproto.uint32_field(9) + slots: list[ProfileCardSlot] = betterproto.message_field(3) + badge_points: int = betterproto.uint32_field(4) + event_points: int = betterproto.uint32_field(5) + event_id: int = betterproto.uint32_field(6) + recent_battle_cup_victory: BattleCupVictory = betterproto.message_field(7) + rank_tier: int = betterproto.uint32_field(8) + leaderboard_rank: int = betterproto.uint32_field(9) + is_plus_subscriber: bool = betterproto.bool_field(10) + plus_original_start_date: int = betterproto.uint32_field(11) + rank_tier_score: int = betterproto.uint32_field(12) + leaderboard_rank_core: int = betterproto.uint32_field(17) + title: int = betterproto.uint32_field(23) + favorite_team_packed: int = betterproto.uint64_field(24) + lifetime_games: int = betterproto.uint32_field(25) @dataclass(eq=False, repr=False) @@ -57,6 +56,15 @@ class ProfileCardSlotStat(betterproto.Message): stat_score: int = betterproto.uint32_field(2) +class ProfileCardEStatID(betterproto.Enum): + Wins = 3 + Commends = 4 + GamesPlayed = 5 + FirstMatchDate = 6 + PreviousSeasonRank = 7 + GamesMVP = 8 + + @dataclass(eq=False, repr=False) class ProfileCardSlotItem(betterproto.Message): serialized_item: bytes = betterproto.bytes_field(1) @@ -80,19 +88,221 @@ class ProfileCardSlotTeam(betterproto.Message): team_id: int = betterproto.uint32_field(1) -class ProfileCard(GCProtobufMessage, msg=EMsg.ClientToGCGetProfileCardResponse): +@dataclass(eq=False, repr=False) +class BattleCupVictory(betterproto.Message): account_id: int = betterproto.uint32_field(1) - slots: list[ProfileCardSlot] = betterproto.message_field(3) - badge_points: int = betterproto.uint32_field(4) - event_points: int = betterproto.uint32_field(5) - event_id: int = betterproto.uint32_field(6) - recent_battle_cup_victory: BattleCupVictory = betterproto.message_field(7) - rank_tier: int = betterproto.uint32_field(8) - leaderboard_rank: int = betterproto.uint32_field(9) - is_plus_subscriber: bool = betterproto.bool_field(10) - plus_original_start_date: int = betterproto.uint32_field(11) - rank_tier_score: int = betterproto.uint32_field(12) - leaderboard_rank_core: int = betterproto.uint32_field(17) - title: int = betterproto.uint32_field(23) - favorite_team_packed: int = betterproto.uint64_field(24) - lifetime_games: int = betterproto.uint32_field(25) + win_date: int = betterproto.uint32_field(2) + valid_until: int = betterproto.uint32_field(3) + skill_level: int = betterproto.uint32_field(4) + tournament_id: int = betterproto.uint32_field(5) + division_id: int = betterproto.uint32_field(6) + team_id: int = betterproto.uint32_field(7) + streak: int = betterproto.uint32_field(8) + trophy_id: int = betterproto.uint32_field(9) + + +# MATCH DETAILS + + +@dataclass(eq=False, repr=False) +class Match(betterproto.Message): + duration: int = betterproto.uint32_field(3) + starttime: float = betterproto.fixed32_field(4) + players: list[Player] = betterproto.message_field(5) + match_id: int = betterproto.uint64_field(6) + tower_status: list[int] = betterproto.uint32_field(8) + barracks_status: list[int] = betterproto.uint32_field(9) + cluster: int = betterproto.uint32_field(10) + first_blood_time: int = betterproto.uint32_field(12) + replay_salt: float = betterproto.fixed32_field(13) + server_ip: float = betterproto.fixed32_field(14) + server_port: int = betterproto.uint32_field(15) + lobby_type: int = betterproto.uint32_field(16) + human_players: int = betterproto.uint32_field(17) + average_skill: int = betterproto.uint32_field(18) + game_balance: float = betterproto.float_field(19) + radiant_team_id: int = betterproto.uint32_field(20) + dire_team_id: int = betterproto.uint32_field(21) + leagueid: int = betterproto.uint32_field(22) + radiant_team_name: str = betterproto.string_field(23) + dire_team_name: str = betterproto.string_field(24) + radiant_team_logo: int = betterproto.uint64_field(25) + dire_team_logo: int = betterproto.uint64_field(26) + radiant_team_logo_url: str = betterproto.string_field(54) + dire_team_logo_url: str = betterproto.string_field(55) + radiant_team_complete: int = betterproto.uint32_field(27) + dire_team_complete: int = betterproto.uint32_field(28) + game_mode: GameMode = betterproto.enum_field(31) + picks_bans: list[HeroSelectEvent] = betterproto.message_field(32) + match_seq_num: int = betterproto.uint64_field(33) + replay_state: ReplayState = betterproto.enum_field(34) + radiant_guild_id: int = betterproto.uint32_field(35) + dire_guild_id: int = betterproto.uint32_field(36) + radiant_team_tag: str = betterproto.string_field(37) + dire_team_tag: str = betterproto.string_field(38) + series_id: int = betterproto.uint32_field(39) + series_type: int = betterproto.uint32_field(40) + broadcaster_channels: list[BroadcasterChannel] = betterproto.message_field(43) + engine: int = betterproto.uint32_field(44) + custom_game_data: CustomGameData = betterproto.message_field(45) + match_flags: int = betterproto.uint32_field(46) + private_metadata_key: float = betterproto.fixed32_field(47) + radiant_team_score: int = betterproto.uint32_field(48) + dire_team_score: int = betterproto.uint32_field(49) + match_outcome: EMatchOutcome = betterproto.enum_field(50) + tournament_id: int = betterproto.uint32_field(51) + tournament_round: int = betterproto.uint32_field(52) + pre_game_duration: int = betterproto.uint32_field(53) + coaches: list[Coach] = betterproto.message_field(57) + + +@dataclass(eq=False, repr=False) +class Player(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + player_slot: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + item_0: int = betterproto.int32_field(4) + item_1: int = betterproto.int32_field(5) + item_2: int = betterproto.int32_field(6) + item_3: int = betterproto.int32_field(7) + item_4: int = betterproto.int32_field(8) + item_5: int = betterproto.int32_field(9) + item_6: int = betterproto.int32_field(59) + item_7: int = betterproto.int32_field(60) + item_8: int = betterproto.int32_field(61) + item_9: int = betterproto.int32_field(76) + expected_team_contribution: float = betterproto.float_field(10) + scaled_metric: float = betterproto.float_field(11) + previous_rank: int = betterproto.uint32_field(12) + rank_change: int = betterproto.sint32_field(13) + mmr_type: int = betterproto.uint32_field(74) + kills: int = betterproto.uint32_field(14) + deaths: int = betterproto.uint32_field(15) + assists: int = betterproto.uint32_field(16) + leaver_status: int = betterproto.uint32_field(17) + gold: int = betterproto.uint32_field(18) + last_hits: int = betterproto.uint32_field(19) + denies: int = betterproto.uint32_field(20) + gold_per_min: int = betterproto.uint32_field(21) + xp_per_min: int = betterproto.uint32_field(22) + gold_spent: int = betterproto.uint32_field(23) + hero_damage: int = betterproto.uint32_field(24) + tower_damage: int = betterproto.uint32_field(25) + hero_healing: int = betterproto.uint32_field(26) + level: int = betterproto.uint32_field(27) + time_last_seen: int = betterproto.uint32_field(28) + player_name: str = betterproto.string_field(29) + support_ability_value: int = betterproto.uint32_field(30) + feeding_detected: bool = betterproto.bool_field(32) + search_rank: int = betterproto.uint32_field(34) + search_rank_uncertainty: int = betterproto.uint32_field(35) + rank_uncertainty_change: int = betterproto.int32_field(36) + hero_play_count: int = betterproto.uint32_field(37) + party_id: float = betterproto.fixed64_field(38) + scaled_hero_damage: int = betterproto.uint32_field(54) + scaled_tower_damage: int = betterproto.uint32_field(55) + scaled_hero_healing: int = betterproto.uint32_field(56) + scaled_kills: float = betterproto.float_field(39) + scaled_deaths: float = betterproto.float_field(40) + scaled_assists: float = betterproto.float_field(41) + claimed_farm_gold: int = betterproto.uint32_field(42) + support_gold: int = betterproto.uint32_field(43) + claimed_denies: int = betterproto.uint32_field(44) + claimed_misses: int = betterproto.uint32_field(45) + misses: int = betterproto.uint32_field(46) + ability_upgrades: list[AbilityUpgrade] = betterproto.message_field(47) + additional_units_inventory: list[AdditionalUnitInventory] = betterproto.message_field(48) + permanent_buffs: list[PermanentBuff] = betterproto.message_field(57) + pro_name: str = betterproto.string_field(72) + real_name: str = betterproto.string_field(73) + custom_game_data: CustomGameData = betterproto.message_field(50) + active_plus_subscription: bool = betterproto.bool_field(51) + net_worth: int = betterproto.uint32_field(52) + bot_difficulty: int = betterproto.uint32_field(58) + hero_pick_order: int = betterproto.uint32_field(63) + hero_was_randomed: bool = betterproto.bool_field(64) + hero_was_dota_plus_suggestion: bool = betterproto.bool_field(69) + hero_damage_received: list[HeroDamageReceived] = betterproto.message_field(67) + hero_damage_dealt: list[HeroDamageReceived] = betterproto.message_field(79) + seconds_dead: int = betterproto.uint32_field(70) + gold_lost_to_death: int = betterproto.uint32_field(71) + lane_selection_flags: int = betterproto.uint32_field(75) + bounty_runes: int = betterproto.uint32_field(77) + outposts_captured: int = betterproto.uint32_field(78) + team_number: Team = betterproto.enum_field(80) + team_slot: int = betterproto.uint32_field(81) + + +@dataclass(eq=False, repr=False) +class AbilityUpgrade(betterproto.Message): + ability: int = betterproto.int32_field(1) + time: int = betterproto.uint32_field(2) + + +@dataclass(eq=False, repr=False) +class AdditionalUnitInventory(betterproto.Message): + unit_name: str = betterproto.string_field(1) + items: list[int] = betterproto.int32_field(2) + + +@dataclass(eq=False, repr=False) +class PermanentBuff(betterproto.Message): + permanent_buff: int = betterproto.uint32_field(1) + stack_count: int = betterproto.uint32_field(2) + grant_time: int = betterproto.uint32_field(3) + + +@dataclass(eq=False, repr=False) +class CustomGameData(betterproto.Message): + dota_team: int = betterproto.uint32_field(1) + winner: bool = betterproto.bool_field(2) + + +@dataclass(eq=False, repr=False) +class HeroDamageReceived(betterproto.Message): + pre_reduction: int = betterproto.uint32_field(1) + post_reduction: int = betterproto.uint32_field(2) + damage_type: HeroDamageType = betterproto.enum_field(3) + + +class HeroDamageType(betterproto.Enum): + Physical = 0 + Magical = 1 + Pure = 2 + + +@dataclass(eq=False, repr=False) +class HeroSelectEvent(betterproto.Message): + is_pick: bool = betterproto.bool_field(1) + team: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + + +class ReplayState(betterproto.Enum): + Available = 0 + NotRecorded = 1 + Expired = 2 + + +@dataclass(eq=False, repr=False) +class BroadcasterChannel(betterproto.Message): + country_code: str = betterproto.string_field(1) + description: str = betterproto.string_field(2) + broadcaster_infos: list[BroadcasterInfo] = betterproto.message_field(3) + language_code: str = betterproto.string_field(4) + + +@dataclass(eq=False, repr=False) +class BroadcasterInfo(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + name: str = betterproto.string_field(2) + + +@dataclass +class Coach(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + coach_name: str = betterproto.string_field(2) + coach_rating: int = betterproto.uint32_field(3) + coach_team: int = betterproto.uint32_field(4) + coach_party_id: int = betterproto.uint64_field(5) + is_private_coach: bool = betterproto.bool_field(6) diff --git a/steam/ext/dota2/protobufs/shared_enums.py b/steam/ext/dota2/protobufs/shared_enums.py new file mode 100644 index 00000000..68d03ec6 --- /dev/null +++ b/steam/ext/dota2/protobufs/shared_enums.py @@ -0,0 +1,87 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: dota_shared_enums.proto +# plugin: python-betterproto + + +import betterproto + + +class EMatchGroupServerStatus(betterproto.Enum): + OK = 0 + LimitedAvailability = 1 + Offline = 2 + + +class GameMode(betterproto.Enum): + NONE = 0 + AllPick = 1 + CaptainsMode = 2 + RandomDraft = 3 + SingleDraft = 4 + AllRandom = 5 + Intro = 6 + Diretide = 7 + ReverseCaptainsMode = 8 + Frostivus = 9 + Tutorial = 10 + MidOnly = 11 + LeastPlayed = 12 + NewPlayerMode = 13 + CompendiumMatch = 14 + Custom = 15 + CaptainsDraft = 16 + BalancedDraft = 17 + AbilityDraft = 18 + Event = 19 + AllRandomDeathMatch = 20 + Mid1v1 = 21 + AllDraft = 22 + Turbo = 23 + Mutation = 24 + CoachesChallenge = 25 + + +class Team(betterproto.Enum): + GoodGuys = 0 + BadGuys = 1 + Broadcaster = 2 + Spectator = 3 + PlayerPool = 4 + NoTeam = 5 + Custom1 = 6 + Custom2 = 7 + Custom3 = 8 + Custom4 = 9 + Custom5 = 10 + Custom6 = 11 + Custom7 = 12 + Custom8 = 13 + Neutrals = 14 + + +class EMatchOutcome(betterproto.Enum): + Unknown = 0 + RadVictory = 2 + DireVictory = 3 + NeutralVictory = 4 + NoTeamWinner = 5 + Custom1Victory = 6 + Custom2Victory = 7 + Custom3Victory = 8 + Custom4Victory = 9 + Custom5Victory = 10 + Custom6Victory = 11 + Custom7Victory = 12 + Custom8Victory = 13 + NotScoredPoorNetworkConditions = 64 + NotScoredLeaver = 65 + NotScoredServerCrash = 66 + NotScoredNeverStarted = 67 + NotScoredCanceled = 68 + NotScoredSuspicious = 69 + + +class MatchVote(betterproto.Enum): + Invalid = 0 + Positive = 1 + Negative = 2 diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index fc489ccd..8ba854d8 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Any +from ..._const import timeout from ..._gc import GCState as GCState_ from ...app import DOTA2 from ...id import _ID64_TO_ID32 @@ -58,13 +59,21 @@ async def _maybe_users(self, id64s: Iterable[ID64]) -> Sequence[User]: def _get_gc_message(self) -> sdk.ClientHello: return sdk.ClientHello() - async def fetch_user_dota2_profile_card(self, user_id: int): + async def fetch_user_dota2_profile_card(self, user_id: int) -> common.ProfileCard: await self.ws.send_gc_message(client_messages.ClientToGCGetProfileCard(account_id=user_id)) return await self.ws.gc_wait_for( common.ProfileCard, check=lambda msg: msg.account_id == user_id, ) + async def fetch_match_details(self, match_id: int) -> client_messages.MatchDetailsResponse: + await self.ws.send_gc_message(client_messages.MatchDetailsRequest(match_id=match_id)) + async with timeout(15.0): + return await self.ws.gc_wait_for( + client_messages.MatchDetailsResponse, + check=lambda msg: msg.match.match_id == match_id, + ) + @parser def parse_client_goodbye(self, msg: sdk.ConnectionStatus | None = None) -> None: if msg is None or msg.status == sdk.GCConnectionStatus.NoSession: From 3b839285323b5de7609ac96d5844903e61028c5c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:33:04 +0000 Subject: [PATCH 30/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/ext/commands/api.rst | 12 ++++-------- steam/ext/commands/cog.py | 3 +-- steam/ext/commands/commands.py | 8 ++++---- steam/ext/commands/converters.py | 17 +++++++---------- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/docs/ext/commands/api.rst b/docs/ext/commands/api.rst index ebf5d45b..01eb4d22 100644 --- a/docs/ext/commands/api.rst +++ b/docs/ext/commands/api.rst @@ -91,8 +91,7 @@ Example: @bot.command() - async def command(ctx, argument_1, argument_2): - ... + async def command(ctx, argument_1, argument_2): ... An invocation of ``!command some string`` would pass ``"some"`` to ``argument_1`` and ``"string"`` to ``argument_2``. @@ -107,8 +106,7 @@ Example: .. code-block:: python @bot.command() - async def command(ctx, argument_1, *arguments): - ... + async def command(ctx, argument_1, *arguments): ... An invocation of ``!command some longer string`` would pass ``"some"`` to ``argument_1`` and ``("longer", "string")`` to ``arguments``. @@ -128,8 +126,7 @@ Example: .. code-block:: python @bot.command() - async def command(ctx, argument_1, *, argument_2): - ... + async def command(ctx, argument_1, *, argument_2): ... An invocation of ``!command some longer string`` would pass ``"some"`` to ``argument_1`` and ``"longer string"`` to ``argument_2``. @@ -150,8 +147,7 @@ Example: .. code-block:: python @bot.command() - async def command(ctx, argument_1, **arguments): - ... + async def command(ctx, argument_1, **arguments): ... An invocation of ``!command some string=long`` would pass ``"some"`` to ``argument_1`` and ``{"string": "long"}`` to ``**arguments``. diff --git a/steam/ext/commands/cog.py b/steam/ext/commands/cog.py index ff96978e..79f5d0fc 100644 --- a/steam/ext/commands/cog.py +++ b/steam/ext/commands/cog.py @@ -78,8 +78,7 @@ class Cog(Generic[BotT]): .. code:: python - class MyCog(commands.Cog, name="SpecialCogName"): - ... + class MyCog(commands.Cog, name="SpecialCogName"): ... Defaults to ``Cog.__name__``. diff --git a/steam/ext/commands/commands.py b/steam/ext/commands/commands.py index 30edeea9..4c6dd4df 100644 --- a/steam/ext/commands/commands.py +++ b/steam/ext/commands/commands.py @@ -906,8 +906,7 @@ def is_mod(ctx: commands.Context) -> bool: @is_mod @bot.command - async def kick(ctx: commands.Context, user: steam.User) -> None: - ... + async def kick(ctx: commands.Context, user: steam.User) -> None: ... This will raise an :exc:`steam.ext.commands.CheckFailure` if the user is not an a mod in the clan. @@ -1009,8 +1008,9 @@ def cooldown(rate: int, per: float, type: BucketType = BucketType.Default) -> Co @bot.command @commands.cooldown(rate=1, per=10, type=commands.BucketType.User) - async def once_every_ten_seconds(ctx: commands.Context) -> None: - ... # this can only be invoked a user every ten seconds. + async def once_every_ten_seconds( + ctx: commands.Context, + ) -> None: ... # this can only be invoked a user every ten seconds. """ def decorator(command: MaybeCommandT) -> MaybeCommandT: diff --git a/steam/ext/commands/converters.py b/steam/ext/commands/converters.py index 42cd902a..2019075d 100644 --- a/steam/ext/commands/converters.py +++ b/steam/ext/commands/converters.py @@ -160,8 +160,9 @@ class Converter(ConverterBase[T_co], ABC): .. code:: python @bot.command - async def command(ctx, user: steam.User): - ... # this will tell the parser to convert user from a str to a steam.User object. + async def command( + ctx, user: steam.User + ): ... # this will tell the parser to convert user from a str to a steam.User object. # invoked as @@ -205,14 +206,12 @@ def register(cls, command: MaybeCommandT) -> MaybeCommandT: .. code:: python class CustomUserConverter(commands.Converter[steam.User]): - async def convert(self, ctx: commands.Context, argument: str) -> steam.User: - ... + async def convert(self, ctx: commands.Context, argument: str) -> steam.User: ... @bot.command @CustomUserConverter.register - async def is_cool(ctx, user: steam.User): - ... + async def is_cool(ctx, user: steam.User): ... In this example ``is_cool``'s user parameter would be registered to the ``CustomUserConverter`` rather than the global :class:`UserConverter`. @@ -411,8 +410,7 @@ class Default(Protocol, Any if TYPE_CHECKING else object): .. code:: python @bot.command() - async def info(ctx, user=DefaultAuthor): - ... # if no user is passed it will be ctx.author + async def info(ctx, user=DefaultAuthor): ... # if no user is passed it will be ctx.author A custom default: @@ -425,8 +423,7 @@ async def default(self, ctx: commands.Context) -> commands.Command: # then later @bot.command - async def source(ctx: commands.Context, command: commands.Command = CurrentCommand): - ... # command would now be source + async def source(ctx: commands.Context, command: commands.Command = CurrentCommand): ... # command would now be source # this could also be mixed in with a converter to convert a string to a command. From 69d0c925cbebeba4af4f2726b16f9b1e623103b1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 21 Sep 2024 14:28:10 +0000 Subject: [PATCH 31/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/client.py | 9 +++------ steam/ext/dota2/state.py | 15 +++++---------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index a7869d91..b20706d3 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -44,8 +44,7 @@ class Client(Client_): if TYPE_CHECKING: @cached_property - def user(self) -> ClientUser: - ... + def user(self) -> ClientUser: ... async def top_live_matches(self, *, hero: Hero = MISSING, limit: int = 100) -> list[LiveMatch]: """Fetch top live matches @@ -193,11 +192,9 @@ async def matchmaking_stats(self): if TYPE_CHECKING or DOCS_BUILDING: - def get_user(self, id: Intable) -> User | None: - ... + def get_user(self, id: Intable) -> User | None: ... - async def fetch_user(self, id: Intable) -> User: - ... + async def fetch_user(self, id: Intable) -> User: ... class Bot(commands.Bot, Client): diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index 8ba854d8..8aa07f89 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -41,20 +41,15 @@ def get_partial_user(self, id: Intable) -> PartialUser: if TYPE_CHECKING: - def get_user(self, id: ID32) -> User | None: - ... + def get_user(self, id: ID32) -> User | None: ... - async def fetch_user(self, user_id64: ID64) -> User: - ... + async def fetch_user(self, user_id64: ID64) -> User: ... - async def fetch_users(self, user_id64s: Iterable[ID64]) -> Sequence[User]: - ... + async def fetch_users(self, user_id64s: Iterable[ID64]) -> Sequence[User]: ... - async def _maybe_user(self, id: Intable) -> User: - ... + async def _maybe_user(self, id: Intable) -> User: ... - async def _maybe_users(self, id64s: Iterable[ID64]) -> Sequence[User]: - ... + async def _maybe_users(self, id64s: Iterable[ID64]) -> Sequence[User]: ... def _get_gc_message(self) -> sdk.ClientHello: return sdk.ClientHello() From 517e33fbab93a2aaa90b5e1ae4eca48d1ef7c55b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Tue, 24 Sep 2024 23:55:52 +0300 Subject: [PATCH 32/50] =?UTF-8?q?=F0=9F=8F=85Implement=20RankTier=20Medals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and a few brush ups --- steam/ext/dota2/client.py | 12 ++------ steam/ext/dota2/enums.py | 64 +++++++++++++++++++++++++++++++++++++++ steam/ext/dota2/models.py | 19 ++++++++---- steam/ext/dota2/state.py | 52 ++++++++++++++++++++++--------- 4 files changed, 116 insertions(+), 31 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index b20706d3..8d840e67 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -52,7 +52,7 @@ async def top_live_matches(self, *, hero: Hero = MISSING, limit: int = 100) -> l This is similar to game list in the Watch Tab of Dota 2 game app. "Top matches" in this context means - * tournament matches + * featured tournament matches * highest average MMR matches Parameters @@ -163,16 +163,8 @@ async def live_matches( asyncio.TimeoutError Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ - future = self._state.ws.gc_wait_for( - watch.GCToClientFindTopSourceTVGamesResponse, - check=lambda msg: msg.specific_games == True, - ) - await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(lobby_ids=lobby_ids)) - - async with timeout(15.0): - response = await future - # todo: test with more than 10 lobby_ids, Game Coordinator will probably chunk it wrongly or fail at all + response = await self._state.fetch_live_matches(lobby_ids) return [LiveMatch(self._state, match) for match in response.game_list] async def match_details(self, match_id: int) -> MatchDetails: diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 6a4b01b2..2a9b8282 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -15,8 +15,10 @@ "Hero", "GameMode", "LobbyType", + "RankTier", ) + # fmt: off class Hero(IntEnum): """Enum representing Dota 2 hero. @@ -144,6 +146,7 @@ class Hero(IntEnum): VoidSpirit = 126 Snapfire = 128 Mars = 129 + Ringmaster = 131 Dawnbreaker = 135 Marci = 136 PrimalBeast = 137 @@ -273,6 +276,7 @@ def DISPLAY_NAMES(cls: type[Self]) -> Mapping[Hero, str]: # type: ignore cls.VoidSpirit : "Void Spirit", cls.Snapfire : "Snapfire", cls.Mars : "Mars", + cls.Ringmaster : "Ringmaster", cls.Dawnbreaker : "Dawnbreaker", cls.Marci : "Marci", cls.PrimalBeast : "Primal Beast", @@ -386,6 +390,66 @@ def display_name(self) -> str: return self.DISPLAY_NAMES[self] +class RankTier(IntEnum): + """Enum representing Dota 2 Rank Tier. + + Commonly called "ranked medals". + """ + Uncalibrated = 0 + + Herald1 = 11 + Herald2 = 12 + Herald3 = 13 + Herald4 = 14 + Herald5 = 15 + + Guardian1 = 21 + Guardian2 = 22 + Guardian3 = 23 + Guardian4 = 24 + Guardian5 = 25 + + Crusader1 = 31 + Crusader2 = 32 + Crusader3 = 33 + Crusader4 = 34 + Crusader5 = 35 + + Archon1 = 41 + Archon2 = 42 + Archon3 = 43 + Archon4 = 44 + Archon5 = 45 + + Legend1 = 51 + Legend2 = 52 + Legend3 = 53 + Legend4 = 54 + Legend5 = 55 + + Ancient1 = 61 + Ancient2 = 62 + Ancient3 = 63 + Ancient4 = 64 + Ancient5 = 65 + + Divine1 = 71 + Divine2 = 72 + Divine3 = 73 + Divine4 = 74 + Divine5 = 75 + + Immortal = 80 + + @property + def display_name(self) -> str: + if self.value % 10 == 0: + return self.name + else: + return self.name[:-1] + ' ' + self.name[-1] + + + class EMsg(IntEnum): # EGCBaseClientMsg - source: gcsystemmsgs.proto PingRequest = 3001 diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 4be67e9b..e599ad33 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -10,7 +10,7 @@ from ... import abc, user from ..._gc.client import ClientUser as ClientUser_ from ...utils import DateTime -from .enums import GameMode, Hero, LobbyType +from .enums import GameMode, Hero, LobbyType, RankTier from .protobufs import client_messages if TYPE_CHECKING: @@ -325,20 +325,27 @@ class BehaviorSummary: class ProfileCard(Generic[UserT]): def __init__(self, user: UserT, proto: common.ProfileCard): self.user = user - self.slots = proto.slots self.badge_points = proto.badge_points self.event_points = proto.event_points self.event_id = proto.event_id self.recent_battle_cup_victory = proto.recent_battle_cup_victory - self.rank_tier = proto.rank_tier + self.rank_tier = RankTier.try_value(proto.rank_tier) + """Ranked medal like Herald-Immortal with a number of stars, i.e. Legend 5.""" self.leaderboard_rank = proto.leaderboard_rank + """Leaderboard rank, i.e. found here https://www.dota2.com/leaderboards/#europe.""" self.is_plus_subscriber = proto.is_plus_subscriber + """Is Dota Plus Subscriber.""" self.plus_original_start_date = proto.plus_original_start_date - self.rank_tier_score = proto.rank_tier_score - self.leaderboard_rank_core = proto.leaderboard_rank_core - self.title = proto.title + """When user subscribed to Dota Plus for their very first time.""" self.favorite_team_packed = proto.favorite_team_packed self.lifetime_games = proto.lifetime_games + """Amount of lifetime games, includes Turbo games as well.""" + + # (?) Unused/Deprecated by Valve + # self.slots = proto.slots # profile page was reworked + # self.title = proto.title + # self.rank_tier_score = proto.rank_tier_score # relic from time when support/core MMR were separated + # self.leaderboard_rank_core = proto.leaderboard_rank_core # relic from time when support/core MMR were separated def __repr__(self) -> str: return f"<{self.__class__.__name__} user={self.user!r}>" diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index 8aa07f89..89a2c114 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -10,7 +10,7 @@ from ...id import _ID64_TO_ID32 from ...state import parser from .models import PartialUser, User -from .protobufs import client_messages, common, sdk +from .protobufs import client_messages, common, sdk, watch if TYPE_CHECKING: from collections.abc import Iterable, Sequence @@ -54,7 +54,30 @@ async def _maybe_users(self, id64s: Iterable[ID64]) -> Sequence[User]: ... def _get_gc_message(self) -> sdk.ClientHello: return sdk.ClientHello() + @parser + def parse_client_goodbye(self, msg: sdk.ConnectionStatus | None = None) -> None: + if msg is None or msg.status == sdk.GCConnectionStatus.NoSession: + self.dispatch("gc_disconnect") + self._gc_connected.clear() + self._gc_ready.clear() + if msg is not None: + self.dispatch("gc_status_change", msg.status) + + @parser + async def parse_gc_client_connect(self, msg: sdk.ClientWelcome) -> None: + if not self._gc_ready.is_set(): + self._gc_ready.set() + self.dispatch("gc_ready") + + # dota fetch proto calls + # the difference between these and the functions in `client`/`models` is that + # these give raw proto responses while the latter modelize/structure/refine them. + async def fetch_user_dota2_profile_card(self, user_id: int) -> common.ProfileCard: + """Fetch User's Dota 2 Profile Card. + + Contains basic info about the account. Kinda mirrors old profile page. + """ await self.ws.send_gc_message(client_messages.ClientToGCGetProfileCard(account_id=user_id)) return await self.ws.gc_wait_for( common.ProfileCard, @@ -62,6 +85,10 @@ async def fetch_user_dota2_profile_card(self, user_id: int) -> common.ProfileCar ) async def fetch_match_details(self, match_id: int) -> client_messages.MatchDetailsResponse: + """Fetch Match Details. + + This call is for already finished games. Contains most of the info that can be found in post-match stats. + """ await self.ws.send_gc_message(client_messages.MatchDetailsRequest(match_id=match_id)) async with timeout(15.0): return await self.ws.gc_wait_for( @@ -69,17 +96,12 @@ async def fetch_match_details(self, match_id: int) -> client_messages.MatchDetai check=lambda msg: msg.match.match_id == match_id, ) - @parser - def parse_client_goodbye(self, msg: sdk.ConnectionStatus | None = None) -> None: - if msg is None or msg.status == sdk.GCConnectionStatus.NoSession: - self.dispatch("gc_disconnect") - self._gc_connected.clear() - self._gc_ready.clear() - if msg is not None: - self.dispatch("gc_status_change", msg.status) - - @parser - async def parse_gc_client_connect(self, msg: sdk.ClientWelcome) -> None: - if not self._gc_ready.is_set(): - self._gc_ready.set() - self.dispatch("gc_ready") + async def fetch_live_matches(self, lobby_ids: list[int]) -> watch.GCToClientFindTopSourceTVGamesResponse: + """Fetch Live Match by lobby ids.""" + await self.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(lobby_ids=lobby_ids)) + async with timeout(15.0): + # todo: test with more than 10 lobby_ids, Game Coordinator will probably chunk it wrongly or fail at all + return await self.ws.gc_wait_for( + watch.GCToClientFindTopSourceTVGamesResponse, + check=lambda msg: msg.specific_games == True, + ) From 04fcdef18964eb8c387f74e5670b5ef97c41d0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Sun, 29 Sep 2024 18:14:12 +0300 Subject: [PATCH 33/50] =?UTF-8?q?=F0=9F=94=ACIntroduce=20Match=20Minimal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 6 +++- steam/ext/dota2/enums.py | 50 ++++++++++++++++++++------- steam/ext/dota2/models.py | 32 ++++++++++++++++++ steam/ext/dota2/protobufs/common.py | 52 ++++++++++++++++++++++++++++- steam/ext/dota2/protobufs/watch.py | 15 +++++++++ steam/ext/dota2/state.py | 11 ++++++ 6 files changed, 152 insertions(+), 14 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 8d840e67..751a486f 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -14,7 +14,7 @@ MISSING, cached_property, ) -from .models import ClientUser, LiveMatch, MatchDetails +from .models import ClientUser, LiveMatch, MatchDetails, MatchMinimal, PartialUser from .protobufs import client_messages, watch from .state import GCState # noqa: TCH001 @@ -175,6 +175,10 @@ async def match_details(self, match_id: int) -> MatchDetails: msg = f"Failed to get match_details for {match_id}" raise ValueError(msg) + async def match_minimal(self, match_id: int) -> MatchMinimal: + proto = await self._state.fetch_match_minimal(match_ids=[match_id]) + return MatchMinimal(self._state, proto.matches[0]) + async def matchmaking_stats(self): future = self._state.ws.gc_wait_for(client_messages.MatchmakingStatsResponse) await self._state.ws.send_gc_message(client_messages.MatchmakingStatsRequest()) diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 2a9b8282..424a0151 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -396,58 +396,84 @@ class RankTier(IntEnum): Commonly called "ranked medals". """ Uncalibrated = 0 - Herald1 = 11 Herald2 = 12 Herald3 = 13 Herald4 = 14 Herald5 = 15 - Guardian1 = 21 Guardian2 = 22 Guardian3 = 23 Guardian4 = 24 Guardian5 = 25 - Crusader1 = 31 Crusader2 = 32 Crusader3 = 33 Crusader4 = 34 Crusader5 = 35 - Archon1 = 41 Archon2 = 42 Archon3 = 43 Archon4 = 44 Archon5 = 45 - Legend1 = 51 Legend2 = 52 Legend3 = 53 Legend4 = 54 Legend5 = 55 - Ancient1 = 61 Ancient2 = 62 Ancient3 = 63 Ancient4 = 64 Ancient5 = 65 - Divine1 = 71 Divine2 = 72 Divine3 = 73 Divine4 = 74 Divine5 = 75 - Immortal = 80 @property - def display_name(self) -> str: - if self.value % 10 == 0: - return self.name + def division(self) -> str: + if self.name[-1].isdigit(): + return self.name[:-1] else: - return self.name[:-1] + ' ' + self.name[-1] + return self.name + + @property + def stars(self) -> str: + return self.value % 10 + + + # @property + # def display_name(self) -> str: + # if self.value % 10 == 0: + # return self.name + # else: + # return self.name[:-1] + ' ' + self.name[-1] + +class Outcome(IntEnum): # source: dota_shared_enums.proto + """Represents Match Outcome.""" + Unknown = 0 + RadiantVictory = 2 + DireVictory = 3 + NeutralVictory = 4 + NoTeamWinner = 5 + Custom1Victory = 6 + Custom2Victory = 7 + Custom3Victory = 8 + Custom4Victory = 9 + Custom5Victory = 10 + Custom6Victory = 11 + Custom7Victory = 12 + Custom8Victory = 13 + NotScoredPoorNetworkConditions = 64 + NotScoredLeaver = 65 + NotScoredServerCrash = 66 + NotScoredNeverStarted = 67 + NotScoredCanceled = 68 + NotScoredSuspicious = 69 class EMsg(IntEnum): diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index e599ad33..d3394325 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -51,6 +51,38 @@ async def details(self): proto.match +class MatchMinimalPlayer: + def __init__(self, state: GCState, proto: common.MatchMinimalPlayer): + self._state = state + + self.id = proto.account_id + self.hero = Hero.try_value(proto.hero_id) + self.kills = proto.kills + self.deaths = proto.deaths + self.assists = proto.assists + self.items = proto.items + self.player_slot = proto.player_slot + self.pro_name = proto.pro_name + self.level = proto.level + self.team_number = proto.team_number + + +class MatchMinimal: + def __init__(self, state: GCState, proto: common.MatchMinimal) -> None: + self._state = state + + self.id = proto.match_id + self.start_time = DateTime.from_timestamp(proto.start_time) + self.duration = datetime.timedelta(seconds=proto.duration) + self.game_mode = GameMode.try_value(proto.game_mode) + self.players = [MatchMinimalPlayer(state, player) for player in proto.players] + self.tourney = proto.tourney # TODO: modelize further `common.MatchMinimalTourney` + self.outcome = proto.match_outcome + self.radiant_score = proto.radiant_score + self.dire_score = proto.dire_score + self.lobby_type = LobbyType.try_value(proto.lobby_type) + + class MatchDetails: def __init__(self, state: GCState, proto: common.Match) -> None: self._state = state diff --git a/steam/ext/dota2/protobufs/common.py b/steam/ext/dota2/protobufs/common.py index e2c14d23..78cb24a5 100644 --- a/steam/ext/dota2/protobufs/common.py +++ b/steam/ext/dota2/protobufs/common.py @@ -298,7 +298,7 @@ class BroadcasterInfo(betterproto.Message): name: str = betterproto.string_field(2) -@dataclass +@dataclass(eq=False, repr=False) class Coach(betterproto.Message): account_id: int = betterproto.uint32_field(1) coach_name: str = betterproto.string_field(2) @@ -306,3 +306,53 @@ class Coach(betterproto.Message): coach_team: int = betterproto.uint32_field(4) coach_party_id: int = betterproto.uint64_field(5) is_private_coach: bool = betterproto.bool_field(6) + + +# MATCH MINIMAL + + +@dataclass(eq=False, repr=False) +class MatchMinimal(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + start_time: float = betterproto.fixed32_field(2) + duration: int = betterproto.uint32_field(3) + game_mode: GameMode = betterproto.enum_field(4) + players: list[MatchMinimalPlayer] = betterproto.message_field(6) + tourney: MatchMinimalTourney = betterproto.message_field(7) + match_outcome: EMatchOutcome = betterproto.enum_field(8) + radiant_score: int = betterproto.uint32_field(9) + dire_score: int = betterproto.uint32_field(10) + lobby_type: int = betterproto.uint32_field(11) + + +@dataclass(eq=False, repr=False) +class MatchMinimalPlayer(betterproto.Message): + account_id: int = betterproto.uint32_field(1) + hero_id: int = betterproto.uint32_field(2) + kills: int = betterproto.uint32_field(3) + deaths: int = betterproto.uint32_field(4) + assists: int = betterproto.uint32_field(5) + items: list[int] = betterproto.int32_field(6) + player_slot: int = betterproto.uint32_field(7) + pro_name: str = betterproto.string_field(8) + level: int = betterproto.uint32_field(9) + team_number: Team = betterproto.enum_field(10) + + +@dataclass(eq=False, repr=False) +class MatchMinimalTourney(betterproto.Message): + league_id: int = betterproto.uint32_field(1) + series_type: int = betterproto.uint32_field(8) + series_game: int = betterproto.uint32_field(9) + weekend_tourney_tournament_id: int = betterproto.uint32_field(10) + weekend_tourney_season_trophy_id: int = betterproto.uint32_field(11) + weekend_tourney_division: int = betterproto.uint32_field(12) + weekend_tourney_skill_level: int = betterproto.uint32_field(13) + radiant_team_id: int = betterproto.uint32_field(2) + radiant_team_name: str = betterproto.string_field(3) + radiant_team_logo: float = betterproto.fixed64_field(4) + radiant_team_logo_url: str = betterproto.string_field(14) + dire_team_id: int = betterproto.uint32_field(5) + dire_team_name: str = betterproto.string_field(6) + dire_team_logo: float = betterproto.fixed64_field(7) + dire_team_logo_url: str = betterproto.string_field(15) diff --git a/steam/ext/dota2/protobufs/watch.py b/steam/ext/dota2/protobufs/watch.py index 24f57b7e..bc5ece96 100644 --- a/steam/ext/dota2/protobufs/watch.py +++ b/steam/ext/dota2/protobufs/watch.py @@ -10,6 +10,9 @@ from ....protobufs.msg import GCProtobufMessage from ..enums import EMsg +from .common import MatchMinimal # noqa: TCH001 + +# FIND TOP SOURCE TV GAMES @dataclass(eq=False, repr=False) @@ -74,3 +77,15 @@ class GCToClientFindTopSourceTVGamesResponse(GCProtobufMessage, msg=EMsg.GCToCli game_list: list[SourceTVGameSmall] = betterproto.message_field(7) specific_games: bool = betterproto.bool_field(8) bot_game: SourceTVGameSmall = betterproto.message_field(9) + + +# MATCHES MINIMAL + + +class ClientToGCMatchesMinimalRequest(GCProtobufMessage, msg=EMsg.ClientToGCMatchesMinimalRequest): + match_ids: list[int] = betterproto.uint64_field(1) + + +class ClientToGCMatchesMinimalResponse(GCProtobufMessage, msg=EMsg.ClientToGCMatchesMinimalResponse): + matches: list[MatchMinimal] = betterproto.message_field(1) + last_match: bool = betterproto.bool_field(2) diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index 89a2c114..c8a3047a 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -96,6 +96,17 @@ async def fetch_match_details(self, match_id: int) -> client_messages.MatchDetai check=lambda msg: msg.match.match_id == match_id, ) + async def fetch_match_minimal(self, match_ids: list[int]) -> watch.ClientToGCMatchesMinimalResponse: + """Fetch Match Minimal. + + This call is for already finished games. Contains basic data about the match. + """ + await self.ws.send_gc_message(watch.ClientToGCMatchesMinimalRequest(match_ids=match_ids)) + async with timeout(15.0): + return await self.ws.gc_wait_for( + watch.ClientToGCMatchesMinimalResponse, + ) + async def fetch_live_matches(self, lobby_ids: list[int]) -> watch.GCToClientFindTopSourceTVGamesResponse: """Fetch Live Match by lobby ids.""" await self.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(lobby_ids=lobby_ids)) From 5d5088874a24fc2664648104e7e11971edf4ba09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Mon, 30 Sep 2024 04:30:41 +0300 Subject: [PATCH 34/50] =?UTF-8?q?=F0=9F=93=82Divide=20`models.py`=20into?= =?UTF-8?q?=20a=20folder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/models/client_user.py | 52 +++++ .../dota2/{models.py => models/matches.py} | 191 ++++++------------ steam/ext/dota2/models/users.py | 76 +++++++ 3 files changed, 185 insertions(+), 134 deletions(-) create mode 100644 steam/ext/dota2/models/client_user.py rename steam/ext/dota2/{models.py => models/matches.py} (64%) create mode 100644 steam/ext/dota2/models/users.py diff --git a/steam/ext/dota2/models/client_user.py b/steam/ext/dota2/models/client_user.py new file mode 100644 index 00000000..f90655ac --- /dev/null +++ b/steam/ext/dota2/models/client_user.py @@ -0,0 +1,52 @@ +"""Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE""" + +from __future__ import annotations + +from dataclasses import dataclass + +from ...._gc.client import ClientUser as ClientUser_ +from ..protobufs import client_messages +from . import users + + +class ClientUser(users.PartialUser, ClientUser_): # type: ignore + # TODO: if TYPE_CHECKING: for inventory + + async def glicko_rating(self) -> GlickoRating: + """Request Glicko Rank Information.""" + future = self._state.ws.gc_wait_for(client_messages.GCToClientRankResponse) + await self._state.ws.send_gc_message( + client_messages.ClientToGCRankRequest(rank_type=client_messages.ERankType.RankedGlicko) + ) + response = await future + return GlickoRating( + mmr=response.rank_value, + deviation=response.rank_data1, + volatility=response.rank_data2, + const=response.rank_data3, + ) + + async def behavior_summary(self) -> BehaviorSummary: + """Request Behavior Summary.""" + future = self._state.ws.gc_wait_for(client_messages.GCToClientRankResponse) + await self._state.ws.send_gc_message( + client_messages.ClientToGCRankRequest(rank_type=client_messages.ERankType.BehaviorPublic) + ) + response = await future + return BehaviorSummary(behavior_score=response.rank_value, communication_score=response.rank_data1) +@dataclass(slots=True) +class GlickoRating: + mmr: int + deviation: int + volatility: int + const: int # TODO: confirm all those names somehow or leave a note in doc that I'm clueless + + @property + def confidence(self): + return self.deviation / self.volatility # TODO: confirm this + + +@dataclass(slots=True) +class BehaviorSummary: + behavior_score: int + communication_score: int diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models/matches.py similarity index 64% rename from steam/ext/dota2/models.py rename to steam/ext/dota2/models/matches.py index d3394325..f4f76ca9 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models/matches.py @@ -3,42 +3,42 @@ from __future__ import annotations import datetime +from asyncio import timeout from dataclasses import dataclass from operator import attrgetter -from typing import TYPE_CHECKING, Generic, Self, TypeVar +from typing import TYPE_CHECKING -from ... import abc, user -from ..._gc.client import ClientUser as ClientUser_ -from ...utils import DateTime -from .enums import GameMode, Hero, LobbyType, RankTier -from .protobufs import client_messages +from ....utils import DateTime +from ..enums import GameMode, Hero, LobbyType, Outcome +from ..protobufs import client_messages, common, watch +from . import users if TYPE_CHECKING: - from .protobufs import common, watch - from .state import GCState + from ..protobufs import common, watch + from ..state import GCState __all__ = ( "LiveMatch", - "TournamentMatch", - "TournamentTeam", - "BattleCup", - "LiveMatchPlayer", - "PartialUser", - "User", - "ProfileCard", + "MatchMinimal", + "PartialMatch", ) -UserT = TypeVar("UserT", bound=abc.PartialUser) - class PartialMatch: + """Represents an already finished Dota 2 Match. + + This class allows using Dota 2 Coordinator requests related to matches. + """ + def __init__(self, state: GCState, id: int): self._state = state self.id = id - async def details(self): + async def details(self) -> MatchDetails | None: """Fetch Match Details. + Contains most of the information that can be found in post-match stats in-game. + Raises ------ asyncio.TimeoutError @@ -47,8 +47,27 @@ async def details(self): * This match is still live. * Dota 2 Game Coordinator lagging or being down. """ - proto = await self._state.fetch_match_details(self.id) - proto.match + await self._state.ws.send_gc_message(client_messages.MatchDetailsRequest(match_id=self.id)) + async with timeout(15.0): + response = await self._state.ws.gc_wait_for( + client_messages.MatchDetailsResponse, + check=lambda msg: msg.match.match_id == self.id, + ) + if response.eresult == 1: + return MatchDetails(self._state, response.match) + else: + msg = f"Failed to get match_details for {self.id}" + raise ValueError(msg) + + async def minimal(self) -> MatchMinimal: + """Fetches basic "minimal" information about the match.""" + proto = await self._state.fetch_matches_minimal(match_ids=[self.id]) + match = next(iter(proto.matches), None) + if match is not None: + return MatchMinimal(self._state, match) + else: + msg = f"Failed to get match_minimal for {self.id}" + raise ValueError(msg) class MatchMinimalPlayer: @@ -77,7 +96,7 @@ def __init__(self, state: GCState, proto: common.MatchMinimal) -> None: self.game_mode = GameMode.try_value(proto.game_mode) self.players = [MatchMinimalPlayer(state, player) for player in proto.players] self.tourney = proto.tourney # TODO: modelize further `common.MatchMinimalTourney` - self.outcome = proto.match_outcome + self.outcome = Outcome.try_value(proto.match_outcome) self.radiant_score = proto.radiant_score self.dire_score = proto.dire_score self.lobby_type = LobbyType.try_value(proto.lobby_type) @@ -91,14 +110,14 @@ def __init__(self, state: GCState, proto: common.Match) -> None: self.duration = datetime.timedelta(seconds=proto.duration) self.start_time = DateTime.from_timestamp(proto.starttime) self.human_players_amount = proto.human_players - self.players = proto.players # todo: modelize - self.tower_status = proto.tower_status # todo: decipher - self.barracks_status = proto.barracks_status # todo: decipher + self.players = proto.players # TODO: modelize + self.tower_status = proto.tower_status # TODO: decipher + self.barracks_status = proto.barracks_status # TODO: decipher self.cluster = proto.cluster self.first_blood_time = proto.first_blood_time self.replay_salt = proto.replay_salt self.server_port = proto.server_port - self.lobby_type = proto.lobby_type # todo: use enum + self.lobby_type = LobbyType.try_value(proto.lobby_type) self.server_ip = proto.server_ip self.average_skill = proto.average_skill self.game_balance = proto.game_balance @@ -113,8 +132,8 @@ def __init__(self, state: GCState, proto: common.Match) -> None: self.dire_team_logo_url = proto.dire_team_logo_url self.radiant_team_complete = proto.radiant_team_complete self.dire_team_complete = proto.dire_team_complete - self.game_mode = proto.game_mode # todo: use enum - self.picks_bans = proto.picks_bans # todo: modelize + self.game_mode = GameMode.try_value(proto.game_mode) + self.picks_bans = proto.picks_bans # TODO: modelize self.match_seq_num = proto.match_seq_num self.replay_state = proto.replay_state self.radiant_guild_id = proto.radiant_guild_id @@ -123,18 +142,18 @@ def __init__(self, state: GCState, proto: common.Match) -> None: self.dire_team_tag: str = proto.dire_team_tag self.series_id = proto.series_id self.series_type = proto.series_type - self.broadcaster_channels = proto.broadcaster_channels # todo: modelize + self.broadcaster_channels = proto.broadcaster_channels # TODO: modelize self.engine = proto.engine - self.custom_game_data = proto.custom_game_data # todo: ??? - self.match_flags = proto.match_flags # todo: ??? - self.private_metadata_key = proto.private_metadata_key # todo: ??? + self.custom_game_data = proto.custom_game_data # TODO: ??? + self.match_flags = proto.match_flags # TODO: ??? + self.private_metadata_key = proto.private_metadata_key # TODO: ??? self.radiant_team_score = proto.radiant_team_score self.dire_team_score = proto.dire_team_score - self.match_outcome = proto.match_outcome # todo: enumize + self.match_outcome = Outcome.try_value(proto.match_outcome) self.tournament_id = proto.tournament_id self.tournament_round = proto.tournament_round self.pre_game_duration = proto.pre_game_duration - self.coaches = proto.coaches # todo: modelize + self.coaches = proto.coaches # TODO: modelize class LiveMatch: @@ -240,7 +259,7 @@ def __init__(self, state: GCState, proto: watch.SourceTVGameSmall) -> None: self.radiant_lead = proto.radiant_lead self.radiant_score = proto.radiant_score self.dire_score = proto.dire_score - self.building_state = proto.building_state # todo: helper function to decode this into human-readable + self.building_state = proto.building_state # TODO: helper function to decode this into human-readable self.custom_game_difficulty = proto.custom_game_difficulty @@ -249,9 +268,9 @@ def __init__(self, state: GCState, proto: watch.SourceTVGameSmall) -> None: # why valve chose to introduce extra bytes fields instead of resorting it once after player selection - no clue sorted_players = sorted(proto.players, key=attrgetter("team", "team_slot")) - self.players: list[LiveMatchPlayer] = [] + self.players: list[users.LiveMatchPlayer] = [] for player in sorted_players: - live_match_player = LiveMatchPlayer(self._state, player.account_id) + live_match_player = users.LiveMatchPlayer(self._state, player.account_id) live_match_player.hero = Hero.try_value(player.hero_id) self.players.append(live_match_player) @@ -266,7 +285,7 @@ def __repr__(self) -> str: @dataclass(slots=True) class TournamentMatch: # should this be named LiveTournamentMatch ? Idk how fast I gonna break all these namings, - league_id: int # todo: can I get more info like name of the tournament + league_id: int # TODO: can I get more info like name of the tournament series_id: int teams: tuple[TournamentTeam, TournamentTeam] @@ -275,7 +294,7 @@ class TournamentMatch: # should this be named LiveTournamentMatch ? Idk how fas class TournamentTeam: id: int name: str - logo: float # todo: can I get more info on logo than float nonsense ? + logo: float # TODO: can I get more info on logo than float nonsense ? @dataclass(slots=True) @@ -285,99 +304,3 @@ class BattleCup: skill_level: int bracket_round: int teams: tuple[TournamentTeam, TournamentTeam] - - -class PartialUser(abc.PartialUser): - __slots__ = () - _state: GCState - - async def dota2_profile_card(self) -> ProfileCard[Self]: - """Fetches this users Dota 2 profile card.""" - msg = await self._state.fetch_user_dota2_profile_card(self.id) - return ProfileCard(self, msg) - - -class LiveMatchPlayer(PartialUser): - hero: Hero - - def __repr__(self) -> str: - return f"<{self.__class__.__name__} id={self.id} hero={self.hero!r}>" - - -class User(PartialUser, user.User): # type: ignore - __slots__ = () - - -class ClientUser(PartialUser, ClientUser_): # type: ignore - # todo: if TYPE_CHECKING: for inventory - - async def glicko_rating(self): - """Request Glicko Rank Information.""" - future = self._state.ws.gc_wait_for(client_messages.GCToClientRankResponse) - await self._state.ws.send_gc_message( - client_messages.ClientToGCRankRequest(rank_type=client_messages.ERankType.RankedGlicko) - ) - resp = await future - return GlickoRating( - mmr=resp.rank_value, - deviation=resp.rank_data1, - volatility=resp.rank_data2, - const=resp.rank_data3, - ) - - async def behavior_summary(self) -> BehaviorSummary: - """Request Behavior Summary.""" - future = self._state.ws.gc_wait_for(client_messages.GCToClientRankResponse) - await self._state.ws.send_gc_message( - client_messages.ClientToGCRankRequest(rank_type=client_messages.ERankType.BehaviorPublic) - ) - resp = await future - return BehaviorSummary(behavior_score=resp.rank_value, communication_score=resp.rank_data1) - - -@dataclass(slots=True) -class GlickoRating: - mmr: int - deviation: int - volatility: int # the numbers, mason, what do they mean - const: int # todo: confirm all those names somehow or leave a note in doc that I'm clueless - - @property - def confidence(self): - # todo: rofl, confirm this please :D - return self.deviation / self.volatility - - -@dataclass(slots=True) -class BehaviorSummary: - behavior_score: int - communication_score: int - - -class ProfileCard(Generic[UserT]): - def __init__(self, user: UserT, proto: common.ProfileCard): - self.user = user - self.badge_points = proto.badge_points - self.event_points = proto.event_points - self.event_id = proto.event_id - self.recent_battle_cup_victory = proto.recent_battle_cup_victory - self.rank_tier = RankTier.try_value(proto.rank_tier) - """Ranked medal like Herald-Immortal with a number of stars, i.e. Legend 5.""" - self.leaderboard_rank = proto.leaderboard_rank - """Leaderboard rank, i.e. found here https://www.dota2.com/leaderboards/#europe.""" - self.is_plus_subscriber = proto.is_plus_subscriber - """Is Dota Plus Subscriber.""" - self.plus_original_start_date = proto.plus_original_start_date - """When user subscribed to Dota Plus for their very first time.""" - self.favorite_team_packed = proto.favorite_team_packed - self.lifetime_games = proto.lifetime_games - """Amount of lifetime games, includes Turbo games as well.""" - - # (?) Unused/Deprecated by Valve - # self.slots = proto.slots # profile page was reworked - # self.title = proto.title - # self.rank_tier_score = proto.rank_tier_score # relic from time when support/core MMR were separated - # self.leaderboard_rank_core = proto.leaderboard_rank_core # relic from time when support/core MMR were separated - - def __repr__(self) -> str: - return f"<{self.__class__.__name__} user={self.user!r}>" diff --git a/steam/ext/dota2/models/users.py b/steam/ext/dota2/models/users.py new file mode 100644 index 00000000..573d7273 --- /dev/null +++ b/steam/ext/dota2/models/users.py @@ -0,0 +1,76 @@ +"""Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, TypeVar + +from .... import abc, user +from ..enums import Hero, RankTier +from ..protobufs import client_messages, common +from . import matches + +if TYPE_CHECKING: + from ..state import GCState + +UserT = TypeVar("UserT", bound=abc.PartialUser) + +__all__ = ( + "ProfileCard", + "PartialUser", + "User", +) + + +class PartialUser(abc.PartialUser): + __slots__ = () + _state: GCState + + async def profile_card(self) -> ProfileCard: + """Fetch user's Dota 2 profile card. + + Contains basic information about the account. Somewhat mirrors old profile page. + """ + await self._state.ws.send_gc_message(client_messages.ClientToGCGetProfileCard(account_id=self.id)) + response = await self._state.ws.gc_wait_for( + common.ProfileCard, + check=lambda msg: msg.account_id == self.id, + ) + return ProfileCard(response) +class User(PartialUser, user.User): # type: ignore + __slots__ = () + + +class ProfileCard: + def __init__(self, proto: common.ProfileCard): + self.account_id = proto.account_id + self.badge_points = proto.badge_points + self.event_points = proto.event_points + self.event_id = proto.event_id + self.recent_battle_cup_victory = proto.recent_battle_cup_victory + self.rank_tier = RankTier.try_value(proto.rank_tier) + """Ranked medal like Herald-Immortal with a number of stars, i.e. Legend 5.""" + self.leaderboard_rank = proto.leaderboard_rank + """Leaderboard rank, i.e. found here https://www.dota2.com/leaderboards/#europe.""" + self.is_plus_subscriber = proto.is_plus_subscriber + """Is Dota Plus Subscriber.""" + self.plus_original_start_date = proto.plus_original_start_date + """When user subscribed to Dota Plus for their very first time.""" + self.favorite_team_packed = proto.favorite_team_packed + self.lifetime_games = proto.lifetime_games + """Amount of lifetime games, includes Turbo games as well.""" + + # (?) Unused/Deprecated by Valve + # self.slots = proto.slots # profile page was reworked + # self.title = proto.title + # self.rank_tier_score = proto.rank_tier_score # relic from time when support/core MMR were separated + # self.leaderboard_rank_core = proto.leaderboard_rank_core # relic from time when support/core MMR were separated + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} account_id={self.account_id}>" + + +class LiveMatchPlayer(PartialUser): + hero: Hero + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} id={self.id} hero={self.hero!r}>" From 38a8f390f6c418abc8b29687c14ef23dd823501e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Mon, 30 Sep 2024 04:32:18 +0300 Subject: [PATCH 35/50] Create models.py --- steam/ext/dota2/models/__init__.py | 3 ++ steam/ext/dota2/protobufs/client_messages.py | 44 ++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 steam/ext/dota2/models/__init__.py diff --git a/steam/ext/dota2/models/__init__.py b/steam/ext/dota2/models/__init__.py new file mode 100644 index 00000000..05448c41 --- /dev/null +++ b/steam/ext/dota2/models/__init__.py @@ -0,0 +1,3 @@ +from .client_user import * +from .matches import * +from .users import * diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py index 433ce64b..8cebf59a 100644 --- a/steam/ext/dota2/protobufs/client_messages.py +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -87,3 +87,47 @@ class MatchDetailsResponse(GCProtobufMessage, msg=EMsg.MatchDetailsResponse): eresult: int = betterproto.uint32_field(1) # originally called result match: Match = betterproto.message_field(2) vote: MatchVote = betterproto.enum_field(3) + + +# MATCH HISTORY + + +class GetPlayerMatchHistory(GCProtobufMessage, msg=EMsg.GetPlayerMatchHistory): + account_id: int = betterproto.uint32_field(1) + start_at_match_id: int = betterproto.uint64_field(2) + matches_requested: int = betterproto.uint32_field(3) + hero_id: int = betterproto.uint32_field(4) + request_id: int = betterproto.uint32_field(5) + include_practice_matches: bool = betterproto.bool_field(7) + include_custom_games: bool = betterproto.bool_field(8) + include_event_games: bool = betterproto.bool_field(9) + + +class GetPlayerMatchHistoryResponse(GCProtobufMessage, msg=EMsg.GetPlayerMatchHistoryResponse): + matches: list[GetPlayerMatchHistoryResponseMatch] = betterproto.message_field(1) + request_id: int = betterproto.uint32_field(2) + + +@dataclass(eq=False, repr=False) +class GetPlayerMatchHistoryResponseMatch(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + start_time: int = betterproto.uint32_field(2) + hero_id: int = betterproto.uint32_field(3) + winner: bool = betterproto.bool_field(4) + game_mode: int = betterproto.uint32_field(5) + rank_change: int = betterproto.int32_field(6) + previous_rank: int = betterproto.uint32_field(7) + lobby_type: int = betterproto.uint32_field(8) + solo_rank: bool = betterproto.bool_field(9) + abandon: bool = betterproto.bool_field(10) + duration: int = betterproto.uint32_field(11) + engine: int = betterproto.uint32_field(12) + active_plus_subscription: bool = betterproto.bool_field(13) + seasonal_rank: bool = betterproto.bool_field(14) + tourney_id: int = betterproto.uint32_field(15) + tourney_round: int = betterproto.uint32_field(16) + tourney_tier: int = betterproto.uint32_field(17) + tourney_division: int = betterproto.uint32_field(18) + team_id: int = betterproto.uint32_field(19) + team_name: str = betterproto.string_field(20) + ugc_team_ui_logo: int = betterproto.uint64_field(21) From 702f88358ecba462090ee7a64b2b39c24aee9afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Mon, 30 Sep 2024 04:34:22 +0300 Subject: [PATCH 36/50] =?UTF-8?q?=F0=9F=A7=93Match=20History?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/models/matches.py | 33 +++++++++++++++++++++++++++++++ steam/ext/dota2/models/users.py | 31 +++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/steam/ext/dota2/models/matches.py b/steam/ext/dota2/models/matches.py index f4f76ca9..e21b9c82 100644 --- a/steam/ext/dota2/models/matches.py +++ b/steam/ext/dota2/models/matches.py @@ -304,3 +304,36 @@ class BattleCup: skill_level: int bracket_round: int teams: tuple[TournamentTeam, TournamentTeam] + + +# maybe name it Match History Record +class MatchHistoryMatch(PartialMatch): + def __init__(self, state: GCState, proto: client_messages.GetPlayerMatchHistoryResponseMatch) -> None: + super().__init__(state, proto.match_id) + + self.start_time = DateTime.from_timestamp(proto.start_time) + self.hero = Hero.try_value(proto.hero_id) + self.win = proto.winner + self.game_mode = GameMode.try_value(proto.game_mode) + self.lobby_type = LobbyType.try_value(proto.lobby_type) + self.abandon = proto.abandon + self.duration = datetime.timedelta(seconds=proto.duration) + self.active_plus_subscription = proto.active_plus_subscription + + self.tourney_id = proto.tourney_id + self.tourney_round = proto.tourney_round + self.tourney_tier = proto.tourney_tier + self.tourney_division = proto.tourney_division + self.team_id = proto.team_id + self.team_name = proto.team_name + self.ugc_team_ui_logo = proto.ugc_team_ui_logo + + # Deprecated / Pointless (?) + # self.previous_rank = proto.previous_rank + # self.solo_rank = proto.solo_rank # always False + # self.rank_change = proto.rank_change + # self.seasonal_rank = proto.seasonal_rank # always False + # self.engine = proto.engine # always 1 + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} id={self.id} hero={self.hero} win={self.win}>" diff --git a/steam/ext/dota2/models/users.py b/steam/ext/dota2/models/users.py index 573d7273..e19cdd59 100644 --- a/steam/ext/dota2/models/users.py +++ b/steam/ext/dota2/models/users.py @@ -36,6 +36,37 @@ async def profile_card(self) -> ProfileCard: check=lambda msg: msg.account_id == self.id, ) return ProfileCard(response) + + async def match_history( + self, + *, + start_at_match_id: int = 0, + matches_requested: int = 20, + hero: Hero = Hero.NONE, + include_practice_matches: bool = False, + include_custom_games: bool = False, + include_event_games: bool = False, + ) -> list[matches.MatchHistoryMatch]: + """Fetch user's Dota 2 match history. + + Only works for steam friends. + """ + await self._state.ws.send_gc_message( + client_messages.GetPlayerMatchHistory( + account_id=self.id, + start_at_match_id=start_at_match_id, + matches_requested=matches_requested, + hero_id=hero.value, + include_practice_matches=include_practice_matches, + include_custom_games=include_custom_games, + include_event_games=include_event_games, + # request_id=69, # but where to get it without asking for MatchHistory first + ) + ) + response = await self._state.ws.gc_wait_for(client_messages.GetPlayerMatchHistoryResponse) + return [matches.MatchHistoryMatch(self._state, match) for match in response.matches] + + class User(PartialUser, user.User): # type: ignore __slots__ = () From f553a8d27ca46852daad993a883be191bcdf2505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Mon, 30 Sep 2024 04:35:01 +0300 Subject: [PATCH 37/50] =?UTF-8?q?=F0=9F=93=B2Social=20Feed=20Post=20Messag?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/models/client_user.py | 15 +++++++++++++++ steam/ext/dota2/protobufs/client_messages.py | 13 +++++++++++++ 2 files changed, 28 insertions(+) diff --git a/steam/ext/dota2/models/client_user.py b/steam/ext/dota2/models/client_user.py index f90655ac..1a765c6d 100644 --- a/steam/ext/dota2/models/client_user.py +++ b/steam/ext/dota2/models/client_user.py @@ -34,6 +34,21 @@ async def behavior_summary(self) -> BehaviorSummary: ) response = await future return BehaviorSummary(behavior_score=response.rank_value, communication_score=response.rank_data1) + + async def post_social_message(self, message: str) -> None: + """Post message in social feed. + + Currently, messages sent with this are visible in "User Feed - Widget" of Profile Showcase. + This functionality was possible long ago naturally in the in-game client. + """ + future = self._state.ws.gc_wait_for(client_messages.GCToClientSocialFeedPostMessageResponse) + await self._state.ws.send_gc_message(client_messages.ClientToGCSocialFeedPostMessageRequest(message=message)) + response = await future + if not response.success: + msg = "Failed to post a social message." + raise RuntimeError(msg) + + @dataclass(slots=True) class GlickoRating: mmr: int diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py index 8cebf59a..10fe8814 100644 --- a/steam/ext/dota2/protobufs/client_messages.py +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -131,3 +131,16 @@ class GetPlayerMatchHistoryResponseMatch(betterproto.Message): team_id: int = betterproto.uint32_field(19) team_name: str = betterproto.string_field(20) ugc_team_ui_logo: int = betterproto.uint64_field(21) + + +# SOCIAL FEED POST MESSAGE + + +class ClientToGCSocialFeedPostMessageRequest(GCProtobufMessage, msg=EMsg.ClientToGCSocialFeedPostMessageRequest): + message: str = betterproto.string_field(1) + match_id: int = betterproto.uint64_field(2) # doesn't seem like we can use it + match_timestamp: int = betterproto.uint32_field(3) # doesn't seem like we can use it + + +class GCToClientSocialFeedPostMessageResponse(GCProtobufMessage, msg=EMsg.GCToClientSocialFeedPostMessageResponse): + success: bool = betterproto.bool_field(1) From bfef6bd5bb8f183e6fb66e1974154618ab107cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Mon, 30 Sep 2024 04:35:18 +0300 Subject: [PATCH 38/50] =?UTF-8?q?=F0=9F=AA=A5Some=20Brush-ups?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Erm --- steam/ext/dota2/client.py | 125 +++++++++++++++++++------------------- steam/ext/dota2/enums.py | 22 ++++--- steam/ext/dota2/state.py | 52 +++------------- 3 files changed, 82 insertions(+), 117 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 751a486f..2246df85 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -4,7 +4,7 @@ import asyncio from functools import partial -from typing import TYPE_CHECKING, Final +from typing import TYPE_CHECKING, Any, Final, overload from ..._const import DOCS_BUILDING, timeout from ..._gc import Client as Client_ @@ -14,7 +14,7 @@ MISSING, cached_property, ) -from .models import ClientUser, LiveMatch, MatchDetails, MatchMinimal, PartialUser +from .models import ClientUser, LiveMatch, MatchMinimal, PartialUser from .protobufs import client_messages, watch from .state import GCState # noqa: TCH001 @@ -46,21 +46,55 @@ class Client(Client_): @cached_property def user(self) -> ClientUser: ... + # TODO: maybe this should exist as a part of the whole lib (?) + def instantiate_partial_user(self, id: Intable) -> PartialUser: + return PartialUser(self._state, id) + + async def _fetch_find_top_source_tv_games(self, *, limit: int = 100, **kwargs: Any) -> list[LiveMatch]: + """Private helper method to use `watch.ClientToGCFindTopSourceTVGames` requests. + + Valid kwargs are fields from `watch.ClientToGCFindTopSourceTVGames` definition. + Some combinations are not working together. + This is why `Client` offers three methods below with offered prepared kwargs options that make sense. + """ + if limit < 1 or limit > 100: + raise ValueError("limit value should be between 1 and 100 inclusively.") + + # mini-math: limit 100 -> start_game 90, 91 -> 90, 90 -> 80 + start_game = (limit - 1) // 10 * 10 + + def check(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) -> bool: + return msg.start_game == start_game + + futures = [ + self._state.ws.gc_wait_for( + watch.GCToClientFindTopSourceTVGamesResponse, + check=partial(check, start_game), + ) + for start_game in range(0, start_game + 1, 10) + ] + await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(start_game=start_game, **kwargs)) + async with timeout(15.0): + responses = await asyncio.gather(*futures) + # each response.game_list is 10 games (except possibly last one if filtered by hero) + live_matches = [LiveMatch(self._state, match) for response in responses for match in response.game_list] + # still need to slice the list, i.e. limit = 85, but live_matches above will have 90 matches + return live_matches[:limit] + async def top_live_matches(self, *, hero: Hero = MISSING, limit: int = 100) -> list[LiveMatch]: - """Fetch top live matches + """Fetch top live matches. This is similar to game list in the Watch Tab of Dota 2 game app. "Top matches" in this context means - - * featured tournament matches - * highest average MMR matches + * featured tournament matches + * highest average MMR matches Parameters ---------- hero - Filter matches by Hero. Note, in this case Game Coordinator will still use only current top100 live matches, - i.e. requesting "filter by Muerta" will return only subset of those matches in which - Muerta is currently being played. It will not look into lower MMR match than top100 to extend the return + Filter matches by Hero. Note, in this case Game Coordinator still only uses current top100 live matches, + i.e. requesting "filter by Muerta" results only in subset of those matches in which + Muerta is currently being played. It does not look into lower MMR match than top100 to extend the return list to number of games from `limit` argument. This behavior is consistent with how Watch Tab works. limit Maximum amount of matches to fetch. This works rather as a boundary limit than "number of matches" to @@ -79,42 +113,10 @@ async def top_live_matches(self, *, hero: Hero = MISSING, limit: int = 100) -> l Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ - if limit < 1 or limit > 100: - raise ValueError("limit value should be between 1 and 100 inclusively.") - - # mini-math: limit 100 -> start_game 90, 91 -> 90, 90 -> 80 - start_game = (limit - 1) // 10 * 10 - - def callback(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) -> bool: - return msg.start_game == start_game - - futures = [ - self._state.ws.gc_wait_for( - watch.GCToClientFindTopSourceTVGamesResponse, - check=partial(callback, start_game), - ) - for start_game in range(0, start_game + 1, 10) - ] - - if hero is MISSING: - await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(start_game=start_game)) - else: - await self._state.ws.send_gc_message( - watch.ClientToGCFindTopSourceTVGames(start_game=start_game, hero_id=hero.value) - ) + hero_id = hero.value if hero else 0 + return await self._fetch_find_top_source_tv_games(limit=limit, hero_id=hero_id) - async with timeout(15.0): - responses = await asyncio.gather(*futures) - # each response.game_list is 10 games (except possibly last one if filtered by hero) - live_matches = [LiveMatch(self._state, match) for response in responses for match in response.game_list] - # still need to slice the list, i.e. limit = 85, but live_matches above will have 90 matches - return live_matches[:limit] - - async def tournament_live_matches( - self, - # todo: league_id as integer is not human-readable/gettable thing, introduce methods to easily find those - league_id: int, - ) -> list[LiveMatch]: + async def tournament_live_matches(self, league_id: int) -> list[LiveMatch]: """Fetch currently live tournament matches Parameters @@ -142,11 +144,13 @@ async def tournament_live_matches( response = await future return [LiveMatch(self._state, match) for match in response.game_list] - async def live_matches( - self, - # todo: lobby_ids is not easy to get by the user. Introduce methods to get it, i.e. from Rich Presence - lobby_ids: list[int], - ) -> list[LiveMatch]: + @overload + async def live_matches(self, *, lobby_id: int = ...) -> LiveMatch: ... + + @overload + async def live_matches(self, *, lobby_ids: list[int] = ...) -> list[LiveMatch]: ... + + async def live_matches(self, *, lobby_id: int = MISSING, lobby_ids: list[int] = MISSING): """Fetch currently live matches by lobby_ids Parameters @@ -163,28 +167,23 @@ async def live_matches( asyncio.TimeoutError Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ + if lobby_id is not MISSING and lobby_ids is not MISSING: + raise TypeError("Cannot mix lobby_id and lobby_ids keyword arguments.") - response = await self._state.fetch_live_matches(lobby_ids) - return [LiveMatch(self._state, match) for match in response.game_list] - - async def match_details(self, match_id: int) -> MatchDetails: - proto = await self._state.fetch_match_details(match_id) - if proto.eresult == 1: - return MatchDetails(self._state, proto.match) - else: - msg = f"Failed to get match_details for {match_id}" - raise ValueError(msg) + lobby_ids = [lobby_id] if lobby_id else lobby_ids + live_matches = await self._fetch_find_top_source_tv_games(limit=len(lobby_ids), lobby_ids=[lobby_ids]) + # ig live_matches[0] is IndexError safe because if lobby_id is not valid then TimeoutError occurs above; + return live_matches[0] if lobby_id else live_matches - async def match_minimal(self, match_id: int) -> MatchMinimal: - proto = await self._state.fetch_match_minimal(match_ids=[match_id]) - return MatchMinimal(self._state, proto.matches[0]) + async def matches_minimal(self, match_id: int) -> list[MatchMinimal]: + proto = await self._state.fetch_matches_minimal(match_ids=[match_id]) + return [MatchMinimal(self._state, match) for match in proto.matches] async def matchmaking_stats(self): future = self._state.ws.gc_wait_for(client_messages.MatchmakingStatsResponse) await self._state.ws.send_gc_message(client_messages.MatchmakingStatsRequest()) async with timeout(15.0): return await future - # return BehaviorSummary(behavior_score=resp.rank_value, communication_score=resp.rank_data1) if TYPE_CHECKING or DOCS_BUILDING: diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index 424a0151..f5918d5a 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -15,6 +15,7 @@ "Hero", "GameMode", "LobbyType", + "Outcome", "RankTier", ) @@ -291,6 +292,9 @@ def display_name(self) -> str: def id(self) -> int: return self.value + def __bool__(self) -> bool: # type: ignore # idk I need Hero.NONE to be False + return bool(self.value) + class GameMode(IntEnum): # source: dota_shared_enums.proto NONE = 0 @@ -435,22 +439,20 @@ class RankTier(IntEnum): @property def division(self) -> str: - if self.name[-1].isdigit(): - return self.name[:-1] - else: + if self.value % 10 == 0: return self.name + else: + return self.name[:-1] @property def stars(self) -> str: return self.value % 10 - - # @property - # def display_name(self) -> str: - # if self.value % 10 == 0: - # return self.name - # else: - # return self.name[:-1] + ' ' + self.name[-1] + # do we need it as a factory helper method? + @property + def display_name(self) -> str: + suffix = f' {self.stars}' if self.stars else '' + return self.division + suffix class Outcome(IntEnum): # source: dota_shared_enums.proto diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index c8a3047a..65125bcf 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -2,15 +2,15 @@ from __future__ import annotations +from asyncio import timeout from typing import TYPE_CHECKING, Any -from ..._const import timeout from ..._gc import GCState as GCState_ from ...app import DOTA2 from ...id import _ID64_TO_ID32 from ...state import parser from .models import PartialUser, User -from .protobufs import client_messages, common, sdk, watch +from .protobufs import sdk, watch if TYPE_CHECKING: from collections.abc import Iterable, Sequence @@ -21,7 +21,7 @@ from .client import Client -class GCState(GCState_[Any]): # todo: implement basket-analogy for dota2 +class GCState(GCState_[Any]): # TODO: implement basket-analogy for dota2 client: Client # type: ignore # PEP 705 _users: WeakValueDictionary[ID32, User] _APP = DOTA2 # type: ignore @@ -70,49 +70,13 @@ async def parse_gc_client_connect(self, msg: sdk.ClientWelcome) -> None: self.dispatch("gc_ready") # dota fetch proto calls - # the difference between these and the functions in `client`/`models` is that - # these give raw proto responses while the latter modelize/structure/refine them. + # shortcuts to proto calls that are used more than once in `client`/`models` - async def fetch_user_dota2_profile_card(self, user_id: int) -> common.ProfileCard: - """Fetch User's Dota 2 Profile Card. + async def fetch_matches_minimal(self, match_ids: list[int]) -> watch.ClientToGCMatchesMinimalResponse: + """Fetch Matches Minimal. - Contains basic info about the account. Kinda mirrors old profile page. - """ - await self.ws.send_gc_message(client_messages.ClientToGCGetProfileCard(account_id=user_id)) - return await self.ws.gc_wait_for( - common.ProfileCard, - check=lambda msg: msg.account_id == user_id, - ) - - async def fetch_match_details(self, match_id: int) -> client_messages.MatchDetailsResponse: - """Fetch Match Details. - - This call is for already finished games. Contains most of the info that can be found in post-match stats. - """ - await self.ws.send_gc_message(client_messages.MatchDetailsRequest(match_id=match_id)) - async with timeout(15.0): - return await self.ws.gc_wait_for( - client_messages.MatchDetailsResponse, - check=lambda msg: msg.match.match_id == match_id, - ) - - async def fetch_match_minimal(self, match_ids: list[int]) -> watch.ClientToGCMatchesMinimalResponse: - """Fetch Match Minimal. - - This call is for already finished games. Contains basic data about the match. + This call is for already finished games. Contains basic data about the matches. """ await self.ws.send_gc_message(watch.ClientToGCMatchesMinimalRequest(match_ids=match_ids)) async with timeout(15.0): - return await self.ws.gc_wait_for( - watch.ClientToGCMatchesMinimalResponse, - ) - - async def fetch_live_matches(self, lobby_ids: list[int]) -> watch.GCToClientFindTopSourceTVGamesResponse: - """Fetch Live Match by lobby ids.""" - await self.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(lobby_ids=lobby_ids)) - async with timeout(15.0): - # todo: test with more than 10 lobby_ids, Game Coordinator will probably chunk it wrongly or fail at all - return await self.ws.gc_wait_for( - watch.GCToClientFindTopSourceTVGamesResponse, - check=lambda msg: msg.specific_games == True, - ) + return await self.ws.gc_wait_for(watch.ClientToGCMatchesMinimalResponse) From da9d4591a05ec012e5fbfc6b01abd159bc2a1f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Mon, 30 Sep 2024 10:22:51 +0300 Subject: [PATCH 39/50] =?UTF-8?q?=E3=80=BD=EF=B8=8FInstantiate=20Partial?= =?UTF-8?q?=20Match?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 2246df85..762d8e6a 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -14,7 +14,7 @@ MISSING, cached_property, ) -from .models import ClientUser, LiveMatch, MatchMinimal, PartialUser +from .models import ClientUser, LiveMatch, MatchMinimal, PartialMatch, PartialUser from .protobufs import client_messages, watch from .state import GCState # noqa: TCH001 @@ -48,7 +48,15 @@ def user(self) -> ClientUser: ... # TODO: maybe this should exist as a part of the whole lib (?) def instantiate_partial_user(self, id: Intable) -> PartialUser: - return PartialUser(self._state, id) + return self._state.get_partial_user(id) + + def instantiate_partial_match(self, id: int) -> PartialMatch: + """Instantiate partial match. + + Convenience method, allows using match related requests to gc like `match.details` + for any match. + """ + return PartialMatch(self._state, id) async def _fetch_find_top_source_tv_games(self, *, limit: int = 100, **kwargs: Any) -> list[LiveMatch]: """Private helper method to use `watch.ClientToGCFindTopSourceTVGames` requests. From 8d166c3ef290709c9a8a13797fa2895ea0d6440b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Mon, 30 Sep 2024 11:19:56 +0300 Subject: [PATCH 40/50] =?UTF-8?q?=F0=9F=96=BC=EF=B8=8FProfile=20Request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/models/users.py | 11 +++- steam/ext/dota2/protobufs/base.py | 42 +++++++++++++++ steam/ext/dota2/protobufs/client_messages.py | 45 +++++++++++++++- steam/ext/dota2/protobufs/common.py | 56 +++++++++++++++++++- steam/ext/dota2/protobufs/shared_enums.py | 50 +++++++++++++++++ 5 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 steam/ext/dota2/protobufs/base.py diff --git a/steam/ext/dota2/models/users.py b/steam/ext/dota2/models/users.py index e19cdd59..66100c8a 100644 --- a/steam/ext/dota2/models/users.py +++ b/steam/ext/dota2/models/users.py @@ -25,7 +25,16 @@ class PartialUser(abc.PartialUser): __slots__ = () _state: GCState - async def profile_card(self) -> ProfileCard: + async def dota2_profile(self): + """Fetch user's Dota 2 profile card. + + Contains basic information about the account. Somewhat mirrors old profile page. + """ + await self._state.ws.send_gc_message(client_messages.ProfileRequest(account_id=self.id)) + response = await self._state.ws.gc_wait_for(client_messages.ProfileResponse) + return response # TODO: Modelize (?) + + async def dota2_profile_card(self) -> ProfileCard: """Fetch user's Dota 2 profile card. Contains basic information about the account. Somewhat mirrors old profile page. diff --git a/steam/ext/dota2/protobufs/base.py b/steam/ext/dota2/protobufs/base.py new file mode 100644 index 00000000..01448423 --- /dev/null +++ b/steam/ext/dota2/protobufs/base.py @@ -0,0 +1,42 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# sources: base_gcmessages.proto +# plugin: python-betterproto + +from __future__ import annotations + +from dataclasses import dataclass + +import betterproto + +# PROFILE + + +@dataclass(eq=False, repr=False) +class SOEconItem(betterproto.Message): + id: int = betterproto.uint64_field(1) + account_id: int = betterproto.uint32_field(2) + inventory: int = betterproto.uint32_field(3) + def_index: int = betterproto.uint32_field(4) + quantity: int = betterproto.uint32_field(5) + level: int = betterproto.uint32_field(6) + quality: int = betterproto.uint32_field(7) + flags: int = betterproto.uint32_field(8) + origin: int = betterproto.uint32_field(9) + attribute: list[SOEconItemAttribute] = betterproto.message_field(12) + interior_item: SOEconItem = betterproto.message_field(13) + style: int = betterproto.uint32_field(15) + original_id: int = betterproto.uint64_field(16) + equipped_state: list[SOEconItemEquipped] = betterproto.message_field(18) + + +@dataclass(eq=False, repr=False) +class SOEconItemAttribute(betterproto.Message): + def_index: int = betterproto.uint32_field(1) + value: int = betterproto.uint32_field(2) + value_bytes: bytes = betterproto.bytes_field(3) + + +@dataclass(eq=False, repr=False) +class SOEconItemEquipped(betterproto.Message): + new_class: int = betterproto.uint32_field(1) + new_slot: int = betterproto.uint32_field(2) diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py index 10fe8814..33e7f8e5 100644 --- a/steam/ext/dota2/protobufs/client_messages.py +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -10,7 +10,8 @@ from ....protobufs.msg import GCProtobufMessage from ..enums import EMsg -from .common import Match # noqa: TCH001 +from .base import SOEconItem # noqa: TCH001 +from .common import Match, RecentMatchInfo, StickerbookPage, SuccessfulHero # noqa: TCH001 from .shared_enums import EMatchGroupServerStatus, MatchVote # noqa: TCH001 # PROFILE CARD @@ -144,3 +145,45 @@ class ClientToGCSocialFeedPostMessageRequest(GCProtobufMessage, msg=EMsg.ClientT class GCToClientSocialFeedPostMessageResponse(GCProtobufMessage, msg=EMsg.GCToClientSocialFeedPostMessageResponse): success: bool = betterproto.bool_field(1) + + +# PROFILE REQUEST + + +class ProfileRequest(GCProtobufMessage, msg=EMsg.ProfileRequest): + account_id: int = betterproto.uint32_field(1) + + +class ProfileResponseEResponse(betterproto.Enum): + InternalError = 0 + Success = 1 + TooBusy = 2 + Disabled = 3 + + +class ProfileResponse(GCProtobufMessage, msg=EMsg.ProfileResponse): + background_item: SOEconItem = betterproto.message_field(1) + featured_heroes: list[ProfileResponseFeaturedHero] = betterproto.message_field(2) + recent_matches: list[ProfileResponseMatchInfo] = betterproto.message_field(3) + successful_heroes: list[SuccessfulHero] = betterproto.message_field(4) + recent_match_details: RecentMatchInfo = betterproto.message_field(5) + eresult: ProfileResponseEResponse = betterproto.enum_field(6) + stickerbook_page: StickerbookPage = betterproto.message_field(7) + + +@dataclass +class ProfileResponseFeaturedHero(betterproto.Message): + hero_id: int = betterproto.uint32_field(1) + equipped_econ_items: list[SOEconItem] = betterproto.message_field(2) + manually_set: bool = betterproto.bool_field(3) + plus_hero_xp: int = betterproto.uint32_field(4) + plus_hero_relics_item: SOEconItem = betterproto.message_field(5) + + +@dataclass +class ProfileResponseMatchInfo(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + match_timestamp: int = betterproto.uint32_field(2) + performance_rating: int = betterproto.sint32_field(3) + hero_id: int = betterproto.uint32_field(4) + won_match: bool = betterproto.bool_field(5) diff --git a/steam/ext/dota2/protobufs/common.py b/steam/ext/dota2/protobufs/common.py index 78cb24a5..c8241fb7 100644 --- a/steam/ext/dota2/protobufs/common.py +++ b/steam/ext/dota2/protobufs/common.py @@ -10,7 +10,7 @@ from ....protobufs.msg import GCProtobufMessage from ..enums import EMsg -from .shared_enums import EMatchOutcome, GameMode, Team # noqa: TCH001 +from .shared_enums import EEvent, EMatchOutcome, GameMode, Team # noqa: TCH001 # PROFILE CARD @@ -356,3 +356,57 @@ class MatchMinimalTourney(betterproto.Message): dire_team_name: str = betterproto.string_field(6) dire_team_logo: float = betterproto.fixed64_field(7) dire_team_logo_url: str = betterproto.string_field(15) + + +# PROFILE REQUEST + + +@dataclass(eq=False, repr=False) +class SuccessfulHero(betterproto.Message): + hero_id: int = betterproto.uint32_field(1) + win_percent: float = betterproto.float_field(2) + longest_streak: int = betterproto.uint32_field(3) + + +@dataclass(eq=False, repr=False) +class RecentMatchInfo(betterproto.Message): + match_id: int = betterproto.uint64_field(1) + game_mode: GameMode = betterproto.enum_field(2) + kills: int = betterproto.uint32_field(3) + deaths: int = betterproto.uint32_field(4) + assists: int = betterproto.uint32_field(5) + duration: int = betterproto.uint32_field(6) + player_slot: int = betterproto.uint32_field(7) + match_outcome: EMatchOutcome = betterproto.enum_field(8) + timestamp: int = betterproto.uint32_field(9) + lobby_type: int = betterproto.uint32_field(10) + team_number: int = betterproto.uint32_field(11) + + +@dataclass(eq=False, repr=False) +class StickerbookPage(betterproto.Message): + page_num: int = betterproto.uint32_field(1) + event_id: EEvent = betterproto.enum_field(2) + team_id: int = betterproto.uint32_field(3) + stickers: list[StickerbookSticker] = betterproto.message_field(4) + page_type: EStickerbookPageType = betterproto.enum_field(5) + + +@dataclass(eq=False, repr=False) +class StickerbookSticker(betterproto.Message): + item_def_id: int = betterproto.uint32_field(1) + sticker_num: int = betterproto.uint32_field(2) + quality: int = betterproto.uint32_field(3) + position_x: float = betterproto.float_field(4) + position_y: float = betterproto.float_field(5) + position_z: float = betterproto.float_field(8) + rotation: float = betterproto.float_field(6) + scale: float = betterproto.float_field(7) + source_item_id: int = betterproto.uint64_field(9) + depth_bias: int = betterproto.uint32_field(10) + + +class EStickerbookPageType(betterproto.Enum): + Generic = 0 + Team = 1 + Talent = 2 diff --git a/steam/ext/dota2/protobufs/shared_enums.py b/steam/ext/dota2/protobufs/shared_enums.py index 68d03ec6..3929985a 100644 --- a/steam/ext/dota2/protobufs/shared_enums.py +++ b/steam/ext/dota2/protobufs/shared_enums.py @@ -85,3 +85,53 @@ class MatchVote(betterproto.Enum): Invalid = 0 Positive = 1 Negative = 2 + + +class EEvent(betterproto.Enum): + NONE = 0 + Diretide = 1 + SpringFestival = 2 + Frostivus2013 = 3 + Compendium2014 = 4 + NexonPcBang = 5 + PwrdDac2015 = 6 + NewBloom2015 = 7 + International2015 = 8 + FallMajor2015 = 9 + OraclePa = 10 + NewBloom2015Prebeast = 11 + Frostivus = 12 + WinterMajor2016 = 13 + International2016 = 14 + FallMajor2016 = 15 + WinterMajor2017 = 16 + NewBloom2017 = 17 + International2017 = 18 + PlusSubscription = 19 + SinglesDay2017 = 20 + Frostivus2017 = 21 + International2018 = 22 + Frostivus2018 = 23 + NewBloom2019 = 24 + International2019 = 25 + NewPlayerExperience = 26 + Frostivus2019 = 27 + NewBloom2020 = 28 + International2020 = 29 + TeamFandom = 30 + Diretide2020 = 31 + Spring2021 = 32 + Fall2021 = 33 + TeamFandomFall2021 = 34 + Team20212022Tour2 = 35 + International2022 = 36 + Team20212022Tour3 = 37 + TeamInternational2022 = 38 + PermanentGrants = 39 + MuertaReleaseSpring2023 = 40 + Team2023Tour1 = 41 + Team2023Tour2 = 42 + Team023Tour3 = 43 + International2023 = 45 + TenthAnniversary = 46 + Frostivus2023 = 48 From 37a8fa72dbe6cedfa55e5a2242b44d8055ce6d1f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 08:20:17 +0000 Subject: [PATCH 41/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/models/users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/steam/ext/dota2/models/users.py b/steam/ext/dota2/models/users.py index 66100c8a..9fd61402 100644 --- a/steam/ext/dota2/models/users.py +++ b/steam/ext/dota2/models/users.py @@ -32,7 +32,7 @@ async def dota2_profile(self): """ await self._state.ws.send_gc_message(client_messages.ProfileRequest(account_id=self.id)) response = await self._state.ws.gc_wait_for(client_messages.ProfileResponse) - return response # TODO: Modelize (?) + return response # TODO: Modelize (?) async def dota2_profile_card(self) -> ProfileCard: """Fetch user's Dota 2 profile card. From 55f048656c1ff69a09bb6c1a1520c33af5b5cd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Mon, 30 Sep 2024 11:21:39 +0300 Subject: [PATCH 42/50] Doc Edits --- steam/ext/dota2/models/users.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/steam/ext/dota2/models/users.py b/steam/ext/dota2/models/users.py index 66100c8a..8592aec2 100644 --- a/steam/ext/dota2/models/users.py +++ b/steam/ext/dota2/models/users.py @@ -26,9 +26,9 @@ class PartialUser(abc.PartialUser): _state: GCState async def dota2_profile(self): - """Fetch user's Dota 2 profile card. + """Fetch user's Dota 2 profile. - Contains basic information about the account. Somewhat mirrors old profile page. + Almost fully mirrors old profile page. """ await self._state.ws.send_gc_message(client_messages.ProfileRequest(account_id=self.id)) response = await self._state.ws.gc_wait_for(client_messages.ProfileResponse) @@ -37,7 +37,7 @@ async def dota2_profile(self): async def dota2_profile_card(self) -> ProfileCard: """Fetch user's Dota 2 profile card. - Contains basic information about the account. Somewhat mirrors old profile page. + Contains basic information about the account. Mirrors some from old profile page. """ await self._state.ws.send_gc_message(client_messages.ClientToGCGetProfileCard(account_id=self.id)) response = await self._state.ws.gc_wait_for( From 39f907ff4643a12c07f7b7fedb7fe12cbf51ed15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 2 Oct 2024 22:03:17 +0300 Subject: [PATCH 43/50] =?UTF-8?q?=F0=9F=94=AERefactor=20things=20back=20to?= =?UTF-8?q?=20proper=20state=20->=20models?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also got rid of the folder `models`; it was a bad idea. --- steam/ext/dota2/client.py | 3 +- steam/ext/dota2/enums.py | 6 +- .../dota2/{models/matches.py => models.py} | 186 +++++++++++++++--- steam/ext/dota2/models/__init__.py | 3 - steam/ext/dota2/models/client_user.py | 67 ------- steam/ext/dota2/models/users.py | 116 ----------- steam/ext/dota2/state.py | 88 +++++++-- 7 files changed, 243 insertions(+), 226 deletions(-) rename steam/ext/dota2/{models/matches.py => models.py} (67%) delete mode 100644 steam/ext/dota2/models/__init__.py delete mode 100644 steam/ext/dota2/models/client_user.py delete mode 100644 steam/ext/dota2/models/users.py diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 762d8e6a..44850d09 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -179,8 +179,9 @@ async def live_matches(self, *, lobby_id: int = MISSING, lobby_ids: list[int] = raise TypeError("Cannot mix lobby_id and lobby_ids keyword arguments.") lobby_ids = [lobby_id] if lobby_id else lobby_ids - live_matches = await self._fetch_find_top_source_tv_games(limit=len(lobby_ids), lobby_ids=[lobby_ids]) + live_matches = await self._fetch_find_top_source_tv_games(limit=len(lobby_ids), lobby_ids=lobby_ids) # ig live_matches[0] is IndexError safe because if lobby_id is not valid then TimeoutError occurs above; + # TODO: apparently not true^ private games have valid ids but dont get fetched. [] return live_matches[0] if lobby_id else live_matches async def matches_minimal(self, match_id: int) -> list[MatchMinimal]: diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index f5918d5a..eb5ef2f9 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -15,7 +15,7 @@ "Hero", "GameMode", "LobbyType", - "Outcome", + "MatchOutcome", "RankTier", ) @@ -292,7 +292,7 @@ def display_name(self) -> str: def id(self) -> int: return self.value - def __bool__(self) -> bool: # type: ignore # idk I need Hero.NONE to be False + def __bool__(self) -> bool: # type: ignore # idk I need `Hero.NONE` to be `False` return bool(self.value) @@ -455,7 +455,7 @@ def display_name(self) -> str: return self.division + suffix -class Outcome(IntEnum): # source: dota_shared_enums.proto +class MatchOutcome(IntEnum): # source: dota_shared_enums.proto """Represents Match Outcome.""" Unknown = 0 RadiantVictory = 2 diff --git a/steam/ext/dota2/models/matches.py b/steam/ext/dota2/models.py similarity index 67% rename from steam/ext/dota2/models/matches.py rename to steam/ext/dota2/models.py index e21b9c82..c28fdfd6 100644 --- a/steam/ext/dota2/models/matches.py +++ b/steam/ext/dota2/models.py @@ -3,27 +3,83 @@ from __future__ import annotations import datetime -from asyncio import timeout from dataclasses import dataclass from operator import attrgetter -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, TypeVar -from ....utils import DateTime -from ..enums import GameMode, Hero, LobbyType, Outcome -from ..protobufs import client_messages, common, watch -from . import users +from ... import abc, user +from ..._gc.client import ClientUser as ClientUser_ +from ...utils import DateTime +from .enums import GameMode, Hero, LobbyType, MatchOutcome, RankTier +from .protobufs.client_messages import ERankType if TYPE_CHECKING: - from ..protobufs import common, watch - from ..state import GCState + from ...types.id import Intable + from .protobufs import client_messages, common, watch + from .state import GCState + +UserT = TypeVar("UserT", bound=abc.PartialUser) __all__ = ( + "ClientUser", "LiveMatch", "MatchMinimal", "PartialMatch", + "PartialUser", + "ProfileCard", + "User", ) +class PartialUser(abc.PartialUser): + __slots__ = () + _state: GCState + + async def dota2_profile(self): # TODO: Don't forget to include return type + """Fetch user's Dota 2 profile. + + Almost fully mirrors old profile page. + """ + proto = await self._state.fetch_dota2_profile(account_id=self.id) + return proto # TODO: Modelize (?) + + async def dota2_profile_card(self) -> ProfileCard: + """Fetch user's Dota 2 profile card. + + Contains basic information about the account. Mirrors some from old profile page. + """ + proto = await self._state.fetch_dota2_profile_card(self.id) + return ProfileCard(proto) + + async def match_history( + self, + *, + start_at_match_id: int = 0, + matches_requested: int = 20, + hero: Hero = Hero.NONE, + include_practice_matches: bool = False, + include_custom_games: bool = False, + include_event_games: bool = False, + ) -> list[MatchHistoryMatch]: + """Fetch user's Dota 2 match history. + + Only works for steam friends. + """ + proto = await self._state.fetch_match_history( + start_at_match_id=start_at_match_id, + matches_requested=matches_requested, + hero_id=hero.id, + include_practice_matches=include_practice_matches, + include_custom_games=include_custom_games, + include_event_games=include_event_games, + ) + return [MatchHistoryMatch(self._state, match) for match in proto.matches] + + +class User(PartialUser, user.User): # type: ignore + __slots__ = () + + class PartialMatch: """Represents an already finished Dota 2 Match. @@ -47,17 +103,8 @@ async def details(self) -> MatchDetails | None: * This match is still live. * Dota 2 Game Coordinator lagging or being down. """ - await self._state.ws.send_gc_message(client_messages.MatchDetailsRequest(match_id=self.id)) - async with timeout(15.0): - response = await self._state.ws.gc_wait_for( - client_messages.MatchDetailsResponse, - check=lambda msg: msg.match.match_id == self.id, - ) - if response.eresult == 1: - return MatchDetails(self._state, response.match) - else: - msg = f"Failed to get match_details for {self.id}" - raise ValueError(msg) + proto = await self._state.fetch_match_details(match_id=self.id) + return MatchDetails(self._state, proto.match) async def minimal(self) -> MatchMinimal: """Fetches basic "minimal" information about the match.""" @@ -70,6 +117,77 @@ async def minimal(self) -> MatchMinimal: raise ValueError(msg) +class ClientUser(PartialUser, ClientUser_): # type: ignore + # TODO: if TYPE_CHECKING: for inventory + + async def glicko_rating(self) -> GlickoRating: + """Request Glicko Rank Information.""" + proto = await self._state.fetch_rank(rank_type=ERankType.RankedGlicko) + return GlickoRating( + mmr=proto.rank_value, deviation=proto.rank_data1, volatility=proto.rank_data2, const=proto.rank_data3 + ) + + async def behavior_summary(self) -> BehaviorSummary: + """Request Behavior Summary.""" + proto = await self._state.fetch_rank(rank_type=ERankType.BehaviorPublic) + return BehaviorSummary(behavior_score=proto.rank_value, communication_score=proto.rank_data1) + + async def post_social_message(self, message: str) -> None: + """Post message in social feed. + + Currently, messages sent with this are visible in "User Feed - Widget" of Profile Showcase. + This functionality was possible long ago naturally in the in-game client. + """ + await self._state.post_social_message(message=message) + + +class ProfileCard: + def __init__(self, proto: common.ProfileCard): + self.account_id = proto.account_id + self.badge_points = proto.badge_points + self.event_points = proto.event_points + self.event_id = proto.event_id + self.recent_battle_cup_victory = proto.recent_battle_cup_victory + self.rank_tier = RankTier.try_value(proto.rank_tier) + """Ranked medal like Herald-Immortal with a number of stars, i.e. Legend 5.""" + self.leaderboard_rank = proto.leaderboard_rank + """Leaderboard rank, i.e. found here https://www.dota2.com/leaderboards/#europe.""" + self.is_plus_subscriber = proto.is_plus_subscriber + """Is Dota Plus Subscriber.""" + self.plus_original_start_date = proto.plus_original_start_date + """When user subscribed to Dota Plus for their very first time.""" + self.favorite_team_packed = proto.favorite_team_packed + self.lifetime_games = proto.lifetime_games + """Amount of lifetime games, includes Turbo games as well.""" + + # (?) Unused/Deprecated by Valve + # self.slots = proto.slots # profile page was reworked + # self.title = proto.title + # self.rank_tier_score = proto.rank_tier_score # relic from time when support/core MMR were separated + # self.leaderboard_rank_core = proto.leaderboard_rank_core # relic from time when support/core MMR were separated + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} account_id={self.account_id}>" + + +class LiveMatchPlayer(PartialUser): + def __init__( + self, + state: GCState, + id: Intable, + hero: Hero, + team: int, + team_slot: int, + ) -> None: + super().__init__(state, id) + self.hero = hero + self.team = team + self.team_slot = team_slot + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} id={self.id} hero={self.hero!r}>" + + class MatchMinimalPlayer: def __init__(self, state: GCState, proto: common.MatchMinimalPlayer): self._state = state @@ -96,7 +214,7 @@ def __init__(self, state: GCState, proto: common.MatchMinimal) -> None: self.game_mode = GameMode.try_value(proto.game_mode) self.players = [MatchMinimalPlayer(state, player) for player in proto.players] self.tourney = proto.tourney # TODO: modelize further `common.MatchMinimalTourney` - self.outcome = Outcome.try_value(proto.match_outcome) + self.outcome = MatchOutcome.try_value(proto.match_outcome) self.radiant_score = proto.radiant_score self.dire_score = proto.dire_score self.lobby_type = LobbyType.try_value(proto.lobby_type) @@ -149,7 +267,7 @@ def __init__(self, state: GCState, proto: common.Match) -> None: self.private_metadata_key = proto.private_metadata_key # TODO: ??? self.radiant_team_score = proto.radiant_team_score self.dire_team_score = proto.dire_team_score - self.match_outcome = Outcome.try_value(proto.match_outcome) + self.match_outcome = MatchOutcome.try_value(proto.match_outcome) self.tournament_id = proto.tournament_id self.tournament_round = proto.tournament_round self.pre_game_duration = proto.pre_game_duration @@ -265,13 +383,13 @@ def __init__(self, state: GCState, proto: watch.SourceTVGameSmall) -> None: # Since Immortal Draft update, players come from the proto message in a wrong order # which can be fixed back with extra fields that they introduced later: `team`, `team_slot` - # why valve chose to introduce extra bytes fields instead of resorting it once after player selection - no clue sorted_players = sorted(proto.players, key=attrgetter("team", "team_slot")) - self.players: list[users.LiveMatchPlayer] = [] + self.players: list[LiveMatchPlayer] = [] for player in sorted_players: - live_match_player = users.LiveMatchPlayer(self._state, player.account_id) - live_match_player.hero = Hero.try_value(player.hero_id) + live_match_player = LiveMatchPlayer( + self._state, player.account_id, Hero.try_value(player.hero_id), player.team, player.team_slot + ) self.players.append(live_match_player) @property @@ -337,3 +455,21 @@ def __init__(self, state: GCState, proto: client_messages.GetPlayerMatchHistoryR def __repr__(self) -> str: return f"<{self.__class__.__name__} id={self.id} hero={self.hero} win={self.win}>" + + +@dataclass(slots=True) +class GlickoRating: + mmr: int + deviation: int + volatility: int + const: int # TODO: confirm all those names somehow or leave a note in doc that I'm clueless + + @property + def confidence(self): + return self.deviation / self.volatility # TODO: confirm this + + +@dataclass(slots=True) +class BehaviorSummary: + behavior_score: int + communication_score: int diff --git a/steam/ext/dota2/models/__init__.py b/steam/ext/dota2/models/__init__.py deleted file mode 100644 index 05448c41..00000000 --- a/steam/ext/dota2/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .client_user import * -from .matches import * -from .users import * diff --git a/steam/ext/dota2/models/client_user.py b/steam/ext/dota2/models/client_user.py deleted file mode 100644 index 1a765c6d..00000000 --- a/steam/ext/dota2/models/client_user.py +++ /dev/null @@ -1,67 +0,0 @@ -"""Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE""" - -from __future__ import annotations - -from dataclasses import dataclass - -from ...._gc.client import ClientUser as ClientUser_ -from ..protobufs import client_messages -from . import users - - -class ClientUser(users.PartialUser, ClientUser_): # type: ignore - # TODO: if TYPE_CHECKING: for inventory - - async def glicko_rating(self) -> GlickoRating: - """Request Glicko Rank Information.""" - future = self._state.ws.gc_wait_for(client_messages.GCToClientRankResponse) - await self._state.ws.send_gc_message( - client_messages.ClientToGCRankRequest(rank_type=client_messages.ERankType.RankedGlicko) - ) - response = await future - return GlickoRating( - mmr=response.rank_value, - deviation=response.rank_data1, - volatility=response.rank_data2, - const=response.rank_data3, - ) - - async def behavior_summary(self) -> BehaviorSummary: - """Request Behavior Summary.""" - future = self._state.ws.gc_wait_for(client_messages.GCToClientRankResponse) - await self._state.ws.send_gc_message( - client_messages.ClientToGCRankRequest(rank_type=client_messages.ERankType.BehaviorPublic) - ) - response = await future - return BehaviorSummary(behavior_score=response.rank_value, communication_score=response.rank_data1) - - async def post_social_message(self, message: str) -> None: - """Post message in social feed. - - Currently, messages sent with this are visible in "User Feed - Widget" of Profile Showcase. - This functionality was possible long ago naturally in the in-game client. - """ - future = self._state.ws.gc_wait_for(client_messages.GCToClientSocialFeedPostMessageResponse) - await self._state.ws.send_gc_message(client_messages.ClientToGCSocialFeedPostMessageRequest(message=message)) - response = await future - if not response.success: - msg = "Failed to post a social message." - raise RuntimeError(msg) - - -@dataclass(slots=True) -class GlickoRating: - mmr: int - deviation: int - volatility: int - const: int # TODO: confirm all those names somehow or leave a note in doc that I'm clueless - - @property - def confidence(self): - return self.deviation / self.volatility # TODO: confirm this - - -@dataclass(slots=True) -class BehaviorSummary: - behavior_score: int - communication_score: int diff --git a/steam/ext/dota2/models/users.py b/steam/ext/dota2/models/users.py deleted file mode 100644 index 0309056d..00000000 --- a/steam/ext/dota2/models/users.py +++ /dev/null @@ -1,116 +0,0 @@ -"""Licensed under The MIT License (MIT) - Copyright (c) 2020-present James H-B. See LICENSE""" - -from __future__ import annotations - -from typing import TYPE_CHECKING, TypeVar - -from .... import abc, user -from ..enums import Hero, RankTier -from ..protobufs import client_messages, common -from . import matches - -if TYPE_CHECKING: - from ..state import GCState - -UserT = TypeVar("UserT", bound=abc.PartialUser) - -__all__ = ( - "ProfileCard", - "PartialUser", - "User", -) - - -class PartialUser(abc.PartialUser): - __slots__ = () - _state: GCState - - async def dota2_profile(self): - """Fetch user's Dota 2 profile. - - Almost fully mirrors old profile page. - """ - await self._state.ws.send_gc_message(client_messages.ProfileRequest(account_id=self.id)) - response = await self._state.ws.gc_wait_for(client_messages.ProfileResponse) - return response # TODO: Modelize (?) - - async def dota2_profile_card(self) -> ProfileCard: - """Fetch user's Dota 2 profile card. - - Contains basic information about the account. Mirrors some from old profile page. - """ - await self._state.ws.send_gc_message(client_messages.ClientToGCGetProfileCard(account_id=self.id)) - response = await self._state.ws.gc_wait_for( - common.ProfileCard, - check=lambda msg: msg.account_id == self.id, - ) - return ProfileCard(response) - - async def match_history( - self, - *, - start_at_match_id: int = 0, - matches_requested: int = 20, - hero: Hero = Hero.NONE, - include_practice_matches: bool = False, - include_custom_games: bool = False, - include_event_games: bool = False, - ) -> list[matches.MatchHistoryMatch]: - """Fetch user's Dota 2 match history. - - Only works for steam friends. - """ - await self._state.ws.send_gc_message( - client_messages.GetPlayerMatchHistory( - account_id=self.id, - start_at_match_id=start_at_match_id, - matches_requested=matches_requested, - hero_id=hero.value, - include_practice_matches=include_practice_matches, - include_custom_games=include_custom_games, - include_event_games=include_event_games, - # request_id=69, # but where to get it without asking for MatchHistory first - ) - ) - response = await self._state.ws.gc_wait_for(client_messages.GetPlayerMatchHistoryResponse) - return [matches.MatchHistoryMatch(self._state, match) for match in response.matches] - - -class User(PartialUser, user.User): # type: ignore - __slots__ = () - - -class ProfileCard: - def __init__(self, proto: common.ProfileCard): - self.account_id = proto.account_id - self.badge_points = proto.badge_points - self.event_points = proto.event_points - self.event_id = proto.event_id - self.recent_battle_cup_victory = proto.recent_battle_cup_victory - self.rank_tier = RankTier.try_value(proto.rank_tier) - """Ranked medal like Herald-Immortal with a number of stars, i.e. Legend 5.""" - self.leaderboard_rank = proto.leaderboard_rank - """Leaderboard rank, i.e. found here https://www.dota2.com/leaderboards/#europe.""" - self.is_plus_subscriber = proto.is_plus_subscriber - """Is Dota Plus Subscriber.""" - self.plus_original_start_date = proto.plus_original_start_date - """When user subscribed to Dota Plus for their very first time.""" - self.favorite_team_packed = proto.favorite_team_packed - self.lifetime_games = proto.lifetime_games - """Amount of lifetime games, includes Turbo games as well.""" - - # (?) Unused/Deprecated by Valve - # self.slots = proto.slots # profile page was reworked - # self.title = proto.title - # self.rank_tier_score = proto.rank_tier_score # relic from time when support/core MMR were separated - # self.leaderboard_rank_core = proto.leaderboard_rank_core # relic from time when support/core MMR were separated - - def __repr__(self) -> str: - return f"<{self.__class__.__name__} account_id={self.account_id}>" - - -class LiveMatchPlayer(PartialUser): - hero: Hero - - def __repr__(self) -> str: - return f"<{self.__class__.__name__} id={self.id} hero={self.hero!r}>" diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index 65125bcf..777d92af 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -2,15 +2,17 @@ from __future__ import annotations -from asyncio import timeout -from typing import TYPE_CHECKING, Any +import asyncio +from typing import TYPE_CHECKING, Any, NotRequired, TypedDict, Unpack from ..._gc import GCState as GCState_ from ...app import DOTA2 +from ...enums import IntEnum +from ...errors import WSException from ...id import _ID64_TO_ID32 from ...state import parser from .models import PartialUser, User -from .protobufs import sdk, watch +from .protobufs import client_messages, common, sdk, watch if TYPE_CHECKING: from collections.abc import Iterable, Sequence @@ -20,6 +22,30 @@ from ...types.id import ID32, ID64, Intable from .client import Client + # TODO: test this whole Kwargs thing, does it error if we don't provide some of them? + # what defaults does it assume? + + class MatchHistoryKwargs(TypedDict): + account_id: NotRequired[int] + start_at_match_id: NotRequired[int] + matches_requested: NotRequired[int] + hero_id: NotRequired[int] + include_practice_matches: NotRequired[bool] + include_custom_games: NotRequired[bool] + include_event_games: NotRequired[bool] + request_id: NotRequired[int] + + class PostSocialMessageKwargs(TypedDict): + message: NotRequired[str] + match_id: NotRequired[int] + match_timestamp: NotRequired[int] + + +class Result(IntEnum): + # TODO: is there an official list for this? + Invalid = 0 + OK = 1 + class GCState(GCState_[Any]): # TODO: implement basket-analogy for dota2 client: Client # type: ignore # PEP 705 @@ -70,13 +96,53 @@ async def parse_gc_client_connect(self, msg: sdk.ClientWelcome) -> None: self.dispatch("gc_ready") # dota fetch proto calls - # shortcuts to proto calls that are used more than once in `client`/`models` - - async def fetch_matches_minimal(self, match_ids: list[int]) -> watch.ClientToGCMatchesMinimalResponse: - """Fetch Matches Minimal. - - This call is for already finished games. Contains basic data about the matches. - """ + # the difference between these calls and the ones in `client`/`models` is that + # they directly give proto-response while the latter modelize them into more convenient formats. + + async def fetch_dota2_profile(self, account_id: int) -> client_messages.ProfileResponse: + """Fetch user's dota 2 profile.""" + await self.ws.send_gc_message(client_messages.ProfileRequest(account_id=account_id)) + return await self.ws.gc_wait_for(client_messages.ProfileResponse) + + async def fetch_dota2_profile_card(self, account_id: int) -> common.ProfileCard: + """Fetch user's dota 2 profile card.""" + await self.ws.send_gc_message(client_messages.ClientToGCGetProfileCard(account_id=account_id)) + return await self.ws.gc_wait_for(common.ProfileCard, check=lambda msg: msg.account_id == account_id) + + async def fetch_match_history(self, **kwargs: Unpack[MatchHistoryKwargs]): + """Fetch match history.""" + await self.ws.send_gc_message(client_messages.GetPlayerMatchHistory(**kwargs)) + return await self.ws.gc_wait_for(client_messages.GetPlayerMatchHistoryResponse) + + async def fetch_matches_minimal( + self, match_ids: list[int], *, timeout: float = 7.0 + ) -> watch.ClientToGCMatchesMinimalResponse: + """Fetch matches minimal.""" await self.ws.send_gc_message(watch.ClientToGCMatchesMinimalRequest(match_ids=match_ids)) - async with timeout(15.0): + async with asyncio.timeout(timeout): return await self.ws.gc_wait_for(watch.ClientToGCMatchesMinimalResponse) + + async def fetch_match_details(self, match_id: int, timeout: float = 7.0) -> client_messages.MatchDetailsResponse: + """Fetch match details.""" + await self.ws.send_gc_message(client_messages.MatchDetailsRequest(match_id=match_id)) + async with asyncio.timeout(timeout): + response = await self.ws.gc_wait_for( + client_messages.MatchDetailsResponse, check=lambda msg: msg.match.match_id == match_id + ) + if response.eresult != Result.OK: + raise WSException(response) + return response + + async def fetch_rank(self, rank_type: client_messages.ERankType) -> client_messages.GCToClientRankResponse: + """Fetch rank.""" + await self.ws.send_gc_message(client_messages.ClientToGCRankRequest(rank_type=rank_type)) + return await self.ws.gc_wait_for(client_messages.GCToClientRankResponse) + + async def post_social_message( + self, **kwargs: Unpack[PostSocialMessageKwargs] + ) -> client_messages.GCToClientSocialFeedPostMessageResponse: + await self.ws.send_gc_message(client_messages.ClientToGCSocialFeedPostMessageRequest(**kwargs)) + response = await self.ws.gc_wait_for(client_messages.GCToClientSocialFeedPostMessageResponse) + if response.success != Result.OK: + raise WSException(response) + return response From 047da1f1047fbdd3c638b4dbf586a9c64063f80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 2 Oct 2024 23:04:15 +0300 Subject: [PATCH 44/50] =?UTF-8?q?=F0=9F=94=9DSeparate=20state=20for=20TopS?= =?UTF-8?q?ource=20too?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 77 ++++++++++++++------------------------- steam/ext/dota2/state.py | 34 +++++++++++++++++ 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 44850d09..e140f68a 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -2,9 +2,7 @@ from __future__ import annotations -import asyncio -from functools import partial -from typing import TYPE_CHECKING, Any, Final, overload +from typing import TYPE_CHECKING, Final, overload from ..._const import DOCS_BUILDING, timeout from ..._gc import Client as Client_ @@ -15,7 +13,7 @@ cached_property, ) from .models import ClientUser, LiveMatch, MatchMinimal, PartialMatch, PartialUser -from .protobufs import client_messages, watch +from .protobufs import client_messages from .state import GCState # noqa: TCH001 if TYPE_CHECKING: @@ -58,37 +56,6 @@ def instantiate_partial_match(self, id: int) -> PartialMatch: """ return PartialMatch(self._state, id) - async def _fetch_find_top_source_tv_games(self, *, limit: int = 100, **kwargs: Any) -> list[LiveMatch]: - """Private helper method to use `watch.ClientToGCFindTopSourceTVGames` requests. - - Valid kwargs are fields from `watch.ClientToGCFindTopSourceTVGames` definition. - Some combinations are not working together. - This is why `Client` offers three methods below with offered prepared kwargs options that make sense. - """ - if limit < 1 or limit > 100: - raise ValueError("limit value should be between 1 and 100 inclusively.") - - # mini-math: limit 100 -> start_game 90, 91 -> 90, 90 -> 80 - start_game = (limit - 1) // 10 * 10 - - def check(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) -> bool: - return msg.start_game == start_game - - futures = [ - self._state.ws.gc_wait_for( - watch.GCToClientFindTopSourceTVGamesResponse, - check=partial(check, start_game), - ) - for start_game in range(0, start_game + 1, 10) - ] - await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(start_game=start_game, **kwargs)) - async with timeout(15.0): - responses = await asyncio.gather(*futures) - # each response.game_list is 10 games (except possibly last one if filtered by hero) - live_matches = [LiveMatch(self._state, match) for response in responses for match in response.game_list] - # still need to slice the list, i.e. limit = 85, but live_matches above will have 90 matches - return live_matches[:limit] - async def top_live_matches(self, *, hero: Hero = MISSING, limit: int = 100) -> list[LiveMatch]: """Fetch top live matches. @@ -120,9 +87,16 @@ async def top_live_matches(self, *, hero: Hero = MISSING, limit: int = 100) -> l asyncio.TimeoutError Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ + if limit < 1 or limit > 100: + raise ValueError("limit value should be between 1 and 100 inclusively.") - hero_id = hero.value if hero else 0 - return await self._fetch_find_top_source_tv_games(limit=limit, hero_id=hero_id) + protos = await self._state.fetch_top_source_tv_games( + start_game=(limit - 1) // 10 * 10, # mini-math: limit 100 -> start_game 90, 91 -> 90, 90 -> 80 + hero_id=hero.value if hero else 0, + ) + live_matches = [LiveMatch(self._state, match) for proto in protos for match in proto.game_list] + # still need to slice the list, i.e. limit = 85, but live_matches above will have 90 matches + return live_matches[:limit] async def tournament_live_matches(self, league_id: int) -> list[LiveMatch]: """Fetch currently live tournament matches @@ -142,15 +116,10 @@ async def tournament_live_matches(self, league_id: int) -> list[LiveMatch]: Request time-outed. The reason is usually Dota 2 Game Coordinator lagging or being down. """ - future = self._state.ws.gc_wait_for( - watch.GCToClientFindTopSourceTVGamesResponse, - check=lambda msg: msg.league_id == league_id, - ) - await self._state.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(league_id=league_id)) - - async with timeout(15.0): - response = await future - return [LiveMatch(self._state, match) for match in response.game_list] + protos = await self._state.fetch_top_source_tv_games(league_id=league_id) + # TODO: ^ this will only fetch 10 games because of implementation... + # but does any tournament play more than 10 games at once? :x + return [LiveMatch(self._state, match) for proto in protos for match in proto.game_list] @overload async def live_matches(self, *, lobby_id: int = ...) -> LiveMatch: ... @@ -179,10 +148,20 @@ async def live_matches(self, *, lobby_id: int = MISSING, lobby_ids: list[int] = raise TypeError("Cannot mix lobby_id and lobby_ids keyword arguments.") lobby_ids = [lobby_id] if lobby_id else lobby_ids - live_matches = await self._fetch_find_top_source_tv_games(limit=len(lobby_ids), lobby_ids=lobby_ids) + + protos = await self._state.fetch_top_source_tv_games( + start_game=(len(lobby_ids) - 1) // 10 * 10, + lobby_ids=lobby_ids, + ) + live_matches = [LiveMatch(self._state, match) for proto in protos for match in proto.game_list] # ig live_matches[0] is IndexError safe because if lobby_id is not valid then TimeoutError occurs above; - # TODO: apparently not true^ private games have valid ids but dont get fetched. [] - return live_matches[0] if lobby_id else live_matches + if lobby_id: + try: + return live_matches[0] + except IndexError: + raise RuntimeError(f"Failed to fetch match with {lobby_id=}") + else: + return live_matches async def matches_minimal(self, match_id: int) -> list[MatchMinimal]: proto = await self._state.fetch_matches_minimal(match_ids=[match_id]) diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index 777d92af..7797c6e2 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio +from functools import partial from typing import TYPE_CHECKING, Any, NotRequired, TypedDict, Unpack from ..._gc import GCState as GCState_ @@ -40,6 +41,14 @@ class PostSocialMessageKwargs(TypedDict): match_id: NotRequired[int] match_timestamp: NotRequired[int] + class TopSourceTVGamesKwargs(TypedDict): + search_key: NotRequired[str] + league_id: NotRequired[int] + hero_id: NotRequired[int] + start_game: NotRequired[int] + game_list_index: NotRequired[int] + lobby_ids: NotRequired[list[int]] + class Result(IntEnum): # TODO: is there an official list for this? @@ -99,6 +108,31 @@ async def parse_gc_client_connect(self, msg: sdk.ClientWelcome) -> None: # the difference between these calls and the ones in `client`/`models` is that # they directly give proto-response while the latter modelize them into more convenient formats. + async def fetch_top_source_tv_games( + self, *, timeout: float = 7.0, **kwargs: Unpack[TopSourceTVGamesKwargs] + ) -> list[watch.GCToClientFindTopSourceTVGamesResponse]: + """Fetch Top Source TV Games.""" + start_game = kwargs.get("start_game") or 0 + # # if start_game and (start_game < 0 or start_game > 90): # TODO: ??? + # # # in my experience it never answers in these cases + # # raise ValueError("start_game should be between 0 and 90 inclusively.") + + def check(start_game: int, msg: watch.GCToClientFindTopSourceTVGamesResponse) -> bool: + return msg.start_game == start_game + + futures = [ + self.ws.gc_wait_for( + watch.GCToClientFindTopSourceTVGamesResponse, + check=partial(check, start_game), + ) + for start_game in range(0, start_game + 1, 10) # TODO: is it correct as in same as it'd be missing + ] + await self.ws.send_gc_message(watch.ClientToGCFindTopSourceTVGames(**kwargs)) + async with asyncio.timeout(timeout): + responses = await asyncio.gather(*futures) + # each response.game_list is 10 games (except possibly last one if filtered by hero) + return responses + async def fetch_dota2_profile(self, account_id: int) -> client_messages.ProfileResponse: """Fetch user's dota 2 profile.""" await self.ws.send_gc_message(client_messages.ProfileRequest(account_id=account_id)) From 6abe79965a198f607274c020c446a884c48e5a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 2 Oct 2024 23:09:07 +0300 Subject: [PATCH 45/50] =?UTF-8?q?=F0=9F=A6=9CSeparate=20state=20for=20MM?= =?UTF-8?q?=20stats?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 8 +++----- steam/ext/dota2/state.py | 6 ++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index e140f68a..3dce7387 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -154,11 +154,11 @@ async def live_matches(self, *, lobby_id: int = MISSING, lobby_ids: list[int] = lobby_ids=lobby_ids, ) live_matches = [LiveMatch(self._state, match) for proto in protos for match in proto.game_list] - # ig live_matches[0] is IndexError safe because if lobby_id is not valid then TimeoutError occurs above; if lobby_id: try: return live_matches[0] except IndexError: + # can happen even with valid lobby_id if it's private raise RuntimeError(f"Failed to fetch match with {lobby_id=}") else: return live_matches @@ -168,10 +168,8 @@ async def matches_minimal(self, match_id: int) -> list[MatchMinimal]: return [MatchMinimal(self._state, match) for match in proto.matches] async def matchmaking_stats(self): - future = self._state.ws.gc_wait_for(client_messages.MatchmakingStatsResponse) - await self._state.ws.send_gc_message(client_messages.MatchmakingStatsRequest()) - async with timeout(15.0): - return await future + proto = await self._state.fetch_matchmaking_stats() + return proto # TODO: Modelize (I never figured out what regions are which) if TYPE_CHECKING or DOCS_BUILDING: diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index 7797c6e2..f53e1cc2 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -175,8 +175,14 @@ async def fetch_rank(self, rank_type: client_messages.ERankType) -> client_messa async def post_social_message( self, **kwargs: Unpack[PostSocialMessageKwargs] ) -> client_messages.GCToClientSocialFeedPostMessageResponse: + """Post social message.""" await self.ws.send_gc_message(client_messages.ClientToGCSocialFeedPostMessageRequest(**kwargs)) response = await self.ws.gc_wait_for(client_messages.GCToClientSocialFeedPostMessageResponse) if response.success != Result.OK: raise WSException(response) return response + + async def fetch_matchmaking_stats(self) -> client_messages.MatchmakingStatsResponse: + """Fetch matchmaking stats.""" + await self.ws.send_gc_message(client_messages.MatchmakingStatsRequest()) + return await self.ws.gc_wait_for(client_messages.MatchmakingStatsResponse) From 12c6df1759ba63a5a48d210b2d0c5bbf1f708059 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 20:09:38 +0000 Subject: [PATCH 46/50] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- steam/ext/dota2/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 3dce7387..a0e62fee 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -169,7 +169,7 @@ async def matches_minimal(self, match_id: int) -> list[MatchMinimal]: async def matchmaking_stats(self): proto = await self._state.fetch_matchmaking_stats() - return proto # TODO: Modelize (I never figured out what regions are which) + return proto # TODO: Modelize (I never figured out what regions are which) if TYPE_CHECKING or DOCS_BUILDING: From e47e6243e95a565f385a07c83c54fdc174420674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Wed, 2 Oct 2024 23:18:04 +0300 Subject: [PATCH 47/50] =?UTF-8?q?=F0=9F=8C=90=20`replay=5Furl`,=20`metadat?= =?UTF-8?q?a=5Furl`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/client.py | 3 +-- steam/ext/dota2/models.py | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index a0e62fee..194f9d5b 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Final, overload -from ..._const import DOCS_BUILDING, timeout +from ..._const import DOCS_BUILDING from ..._gc import Client as Client_ from ...app import DOTA2 from ...ext import commands @@ -13,7 +13,6 @@ cached_property, ) from .models import ClientUser, LiveMatch, MatchMinimal, PartialMatch, PartialUser -from .protobufs import client_messages from .state import GCState # noqa: TCH001 if TYPE_CHECKING: diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index c28fdfd6..4233fd2f 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -273,6 +273,14 @@ def __init__(self, state: GCState, proto: common.Match) -> None: self.pre_game_duration = proto.pre_game_duration self.coaches = proto.coaches # TODO: modelize + @property + def replay_url(self) -> str: + return f"http://replay{self.cluster}.valve.net/570/{self.id}_{self.replay_salt}.dem.bz2" + + @property + def metadata_url(self) -> str: + return f"http://replay{self.cluster}.valve.net/570/{self.id}_{self.replay_salt}.meta.bz2" + class LiveMatch: """Represents a live match of Dota 2 From 4a54ad1cd68cf210fbeb45bc548153b9cdcf9108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Thu, 3 Oct 2024 04:28:50 +0300 Subject: [PATCH 48/50] =?UTF-8?q?=F0=9F=99=82Add=20Facets=20to=20protos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Protobufs were updated :x --- steam/ext/dota2/client.py | 1 + steam/ext/dota2/models.py | 1 + steam/ext/dota2/protobufs/client_messages.py | 1 + steam/ext/dota2/protobufs/common.py | 1 + 4 files changed, 4 insertions(+) diff --git a/steam/ext/dota2/client.py b/steam/ext/dota2/client.py index 194f9d5b..335133ea 100644 --- a/steam/ext/dota2/client.py +++ b/steam/ext/dota2/client.py @@ -117,6 +117,7 @@ async def tournament_live_matches(self, league_id: int) -> list[LiveMatch]: protos = await self._state.fetch_top_source_tv_games(league_id=league_id) # TODO: ^ this will only fetch 10 games because of implementation... + # but there is no good way to know if there gonna be more than 10 games # but does any tournament play more than 10 games at once? :x return [LiveMatch(self._state, match) for proto in protos for match in proto.game_list] diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 4233fd2f..165b4f0e 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -453,6 +453,7 @@ def __init__(self, state: GCState, proto: client_messages.GetPlayerMatchHistoryR self.team_id = proto.team_id self.team_name = proto.team_name self.ugc_team_ui_logo = proto.ugc_team_ui_logo + self.selected_facet = proto.selected_facet # Deprecated / Pointless (?) # self.previous_rank = proto.previous_rank diff --git a/steam/ext/dota2/protobufs/client_messages.py b/steam/ext/dota2/protobufs/client_messages.py index 33e7f8e5..2421eecb 100644 --- a/steam/ext/dota2/protobufs/client_messages.py +++ b/steam/ext/dota2/protobufs/client_messages.py @@ -132,6 +132,7 @@ class GetPlayerMatchHistoryResponseMatch(betterproto.Message): team_id: int = betterproto.uint32_field(19) team_name: str = betterproto.string_field(20) ugc_team_ui_logo: int = betterproto.uint64_field(21) + selected_facet: int = betterproto.uint32_field(22) # SOCIAL FEED POST MESSAGE diff --git a/steam/ext/dota2/protobufs/common.py b/steam/ext/dota2/protobufs/common.py index c8241fb7..fdab2d9c 100644 --- a/steam/ext/dota2/protobufs/common.py +++ b/steam/ext/dota2/protobufs/common.py @@ -231,6 +231,7 @@ class Player(betterproto.Message): outposts_captured: int = betterproto.uint32_field(78) team_number: Team = betterproto.enum_field(80) team_slot: int = betterproto.uint32_field(81) + selected_facet: int = betterproto.uint32_field(82) @dataclass(eq=False, repr=False) From f465544f4c0354113a2b2d5c5bfe22b099264e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Tue, 8 Oct 2024 01:46:59 +0300 Subject: [PATCH 49/50] =?UTF-8?q?=F0=9F=8E=B6Fix=20Match=20History?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- steam/ext/dota2/models.py | 30 ++++++++++++++++++------------ steam/ext/dota2/state.py | 10 +++++----- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/steam/ext/dota2/models.py b/steam/ext/dota2/models.py index 165b4f0e..2e70137c 100644 --- a/steam/ext/dota2/models.py +++ b/steam/ext/dota2/models.py @@ -9,14 +9,14 @@ from ... import abc, user from ..._gc.client import ClientUser as ClientUser_ -from ...utils import DateTime +from ...utils import MISSING, DateTime from .enums import GameMode, Hero, LobbyType, MatchOutcome, RankTier from .protobufs.client_messages import ERankType if TYPE_CHECKING: from ...types.id import Intable from .protobufs import client_messages, common, watch - from .state import GCState + from .state import GCState, MatchHistoryKwargs UserT = TypeVar("UserT", bound=abc.PartialUser) @@ -24,6 +24,7 @@ "ClientUser", "LiveMatch", "MatchMinimal", + "MatchHistoryMatch", "PartialMatch", "PartialUser", "ProfileCard", @@ -54,9 +55,9 @@ async def dota2_profile_card(self) -> ProfileCard: async def match_history( self, *, - start_at_match_id: int = 0, + start_at_match_id: int = MISSING, matches_requested: int = 20, - hero: Hero = Hero.NONE, + hero: Hero = MISSING, include_practice_matches: bool = False, include_custom_games: bool = False, include_event_games: bool = False, @@ -65,14 +66,19 @@ async def match_history( Only works for steam friends. """ - proto = await self._state.fetch_match_history( - start_at_match_id=start_at_match_id, - matches_requested=matches_requested, - hero_id=hero.id, - include_practice_matches=include_practice_matches, - include_custom_games=include_custom_games, - include_event_games=include_event_games, - ) + kwargs: MatchHistoryKwargs = { + "account_id": self.id, + "matches_requested": matches_requested, + "include_practice_matches": include_practice_matches, + "include_custom_games": include_custom_games, + "include_event_games": include_event_games, + } + if start_at_match_id: + kwargs["start_at_match_id"] = start_at_match_id + if hero: + kwargs["hero_id"] = hero.id + + proto = await self._state.fetch_match_history(**kwargs) return [MatchHistoryMatch(self._state, match) for match in proto.matches] diff --git a/steam/ext/dota2/state.py b/steam/ext/dota2/state.py index f53e1cc2..c78c0dfe 100644 --- a/steam/ext/dota2/state.py +++ b/steam/ext/dota2/state.py @@ -27,13 +27,13 @@ # what defaults does it assume? class MatchHistoryKwargs(TypedDict): - account_id: NotRequired[int] + account_id: int start_at_match_id: NotRequired[int] - matches_requested: NotRequired[int] + matches_requested: int hero_id: NotRequired[int] - include_practice_matches: NotRequired[bool] - include_custom_games: NotRequired[bool] - include_event_games: NotRequired[bool] + include_practice_matches: bool + include_custom_games: bool + include_event_games: bool request_id: NotRequired[int] class PostSocialMessageKwargs(TypedDict): From 1a96c93cd6fa0c707eeeb20eaeb57c688e99eeed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aluerie=E2=9D=A4?= Date: Fri, 22 Nov 2024 15:15:34 +0300 Subject: [PATCH 50/50] =?UTF-8?q?=F0=9F=86=95Add=20Kez=20hero?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit also fix for OD type 🤦‍♀️ --- steam/ext/dota2/enums.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/steam/ext/dota2/enums.py b/steam/ext/dota2/enums.py index eb5ef2f9..1585d7dc 100644 --- a/steam/ext/dota2/enums.py +++ b/steam/ext/dota2/enums.py @@ -101,7 +101,7 @@ class Hero(IntEnum): Alchemist = 73 Invoker = 74 Silencer = 75 - OutworldDevourer = 76 + OutworldDestroyer = 76 Lycan = 77 Brewmaster = 78 ShadowDemon = 79 @@ -152,6 +152,7 @@ class Hero(IntEnum): Marci = 136 PrimalBeast = 137 Muerta = 138 + Kez = 145 @classproperty def DISPLAY_NAMES(cls: type[Self]) -> Mapping[Hero, str]: # type: ignore @@ -231,7 +232,7 @@ def DISPLAY_NAMES(cls: type[Self]) -> Mapping[Hero, str]: # type: ignore cls.Alchemist : "Alchemist", cls.Invoker : "Invoker", cls.Silencer : "Silencer", - cls.OutworldDevourer : "Outworld Devourer", + cls.OutworldDestroyer: "Outworld Destroyer", cls.Lycan : "Lycan", cls.Brewmaster : "Brewmaster", cls.ShadowDemon : "Shadow Demon", @@ -282,6 +283,7 @@ def DISPLAY_NAMES(cls: type[Self]) -> Mapping[Hero, str]: # type: ignore cls.Marci : "Marci", cls.PrimalBeast : "Primal Beast", cls.Muerta : "Muerta", + cls.Kez : "Kez", } @property