├── .npmrc ├── .gitignore ├── protobufs ├── generated │ └── _load.js ├── steamdatagram_auth_messages.proto ├── gcsdk_gcmessages.proto ├── gcsystemmsgs.proto ├── econ_gcmessages.proto ├── base_gcmessages.proto ├── steammessages.proto ├── steamdatagram_messages.proto ├── google │ └── protobuf │ │ └── descriptor.proto └── tf_proto_def_messages.proto ├── package.json ├── LICENSE ├── scripts └── generate-protos.js ├── enums.js ├── index.js ├── language.js ├── handlers.js └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | test/* 3 | .idea/ 4 | -------------------------------------------------------------------------------- /protobufs/generated/_load.js: -------------------------------------------------------------------------------- 1 | // Auto-generated by generate-protos script on Wed Jan 30 2019 01:41:54 GMT-0500 (Eastern Standard Time) 2 | 3 | const Schema = module.exports; 4 | 5 | mergeObjects(Schema, require('./base_gcmessages.js')); 6 | mergeObjects(Schema, require('./econ_gcmessages.js')); 7 | mergeObjects(Schema, require('./gcsdk_gcmessages.js')); 8 | mergeObjects(Schema, require('./gcsystemmsgs.js')); 9 | mergeObjects(Schema, require('./steamdatagram_auth_messages.js')); 10 | mergeObjects(Schema, require('./steamdatagram_messages.js')); 11 | mergeObjects(Schema, require('./steammessages.js')); 12 | mergeObjects(Schema, require('./tf_gcmessages.js')); 13 | mergeObjects(Schema, require('./tf_proto_def_messages.js')); 14 | 15 | function mergeObjects(destinationObject, sourceObject) { 16 | for (let i in sourceObject) { 17 | if (sourceObject.hasOwnProperty(i)) { 18 | destinationObject[i] = sourceObject[i]; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tf2", 3 | "version": "4.0.0", 4 | "description": "Exposes a simple API for interacting with the Team Fortress 2 game coordinator", 5 | "keywords": [ 6 | "tf2", 7 | "tf", 8 | "team fortress", 9 | "team fortress 2", 10 | "steam" 11 | ], 12 | "homepage": "https://github.com/DoctorMcKay/node-tf2", 13 | "bugs": { 14 | "url": "https://github.com/DoctorMcKay/node-tf2/issues" 15 | }, 16 | "license": "MIT", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/DoctorMcKay/node-tf2.git" 20 | }, 21 | "dependencies": { 22 | "@doctormckay/stdlib": "^2.7.1", 23 | "bytebuffer": "^5.0.1", 24 | "kvparser": "^1.0.2", 25 | "protobufjs": "^7.2.5", 26 | "steamid": "^2.0.0" 27 | }, 28 | "devDependencies": { 29 | "steam-user": "^4.2.0" 30 | }, 31 | "scripts": { 32 | "generate-protos": "node scripts/generate-protos.js" 33 | }, 34 | "engines": { 35 | "node": ">=14.0.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Alexander Corn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /protobufs/steamdatagram_auth_messages.proto: -------------------------------------------------------------------------------- 1 | option cc_generic_services = false; 2 | 3 | message CMsgSteamDatagramRelayAuthTicket { 4 | message ExtraField { 5 | optional string name = 1; 6 | optional string string_value = 2; 7 | optional sint64 int64_value = 3; 8 | optional fixed64 fixed64_value = 5; 9 | } 10 | 11 | optional fixed32 time_expiry = 1; 12 | optional fixed64 authorized_steam_id = 2; 13 | optional fixed32 authorized_public_ip = 3; 14 | optional fixed64 gameserver_steam_id = 4; 15 | optional fixed64 gameserver_net_id = 5; 16 | optional bytes legacy_signature = 6; 17 | optional uint32 app_id = 7; 18 | optional fixed32 gameserver_pop_id = 9; 19 | optional uint32 virtual_port = 10; 20 | repeated .CMsgSteamDatagramRelayAuthTicket.ExtraField extra_fields = 8; 21 | } 22 | 23 | message CMsgSteamDatagramSignedRelayAuthTicket { 24 | optional fixed64 reserved_do_not_use = 1; 25 | optional fixed64 key_id = 2; 26 | optional bytes ticket = 3; 27 | optional bytes signature = 4; 28 | } 29 | 30 | message CMsgSteamDatagramCertificate { 31 | enum EKeyType { 32 | INVALID = 0; 33 | ED25519 = 1; 34 | } 35 | 36 | optional .CMsgSteamDatagramCertificate.EKeyType key_type = 1 [default = INVALID]; 37 | optional bytes key_data = 2; 38 | optional fixed64 steam_id = 4; 39 | repeated fixed32 gameserver_datacenter_ids = 5; 40 | optional fixed32 time_created = 8; 41 | optional fixed32 time_expiry = 9; 42 | optional uint32 app_id = 10; 43 | } 44 | 45 | message CMsgSteamDatagramCertificateSigned { 46 | optional bytes cert = 4; 47 | optional fixed64 ca_key_id = 5; 48 | optional bytes ca_signature = 6; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /scripts/generate-protos.js: -------------------------------------------------------------------------------- 1 | const ChildProcess = require('child_process'); 2 | const FS = require('fs'); 3 | const Path = require('path'); 4 | 5 | const PBJS_BINARY_PATH = Path.join(__dirname, '..', 'node_modules', 'protobufjs', 'bin', 'pbjs'); 6 | const PROTO_FILE_PATH = Path.join(__dirname, '..', 'protobufs', '%s.proto'); 7 | const DESTINATION_PATH = Path.join(__dirname, '..', 'protobufs', 'generated', '%s.js'); 8 | const PBJS_COMMAND_LINE = `node "${PBJS_BINARY_PATH}" --target static-module --out "${DESTINATION_PATH}" --keep-case "${PROTO_FILE_PATH}"`; 9 | const GENERATED_DIR = __dirname + '/../protobufs/generated'; 10 | 11 | let loader = "// Auto-generated by generate-protos script on " + (new Date()).toString() + "\n\n"; 12 | loader += "const Schema = module.exports;\n\n"; 13 | 14 | if (!FS.existsSync(GENERATED_DIR)) { 15 | FS.mkdirSync(GENERATED_DIR); 16 | } 17 | 18 | FS.readdirSync(__dirname + '/../protobufs').forEach((filename) => { 19 | if (!filename.match(/\.proto$/)) { 20 | return; 21 | } 22 | 23 | let filenameWithoutExtension = filename.replace('.proto', ''); 24 | let cmdLine = PBJS_COMMAND_LINE.replace(/%s/g, filenameWithoutExtension); 25 | console.log(cmdLine); 26 | 27 | ChildProcess.execSync(cmdLine); 28 | loader += `mergeObjects(Schema, require('./${filenameWithoutExtension}.js'));\n`; 29 | }); 30 | 31 | console.log("Generating _load.js"); 32 | loader += "\n" + mergeObjects.toString() + "\n"; 33 | FS.writeFileSync(GENERATED_DIR + '/_load.js', loader); 34 | 35 | function mergeObjects(destinationObject, sourceObject) { 36 | for (let i in sourceObject) { 37 | if (sourceObject.hasOwnProperty(i)) { 38 | destinationObject[i] = sourceObject[i]; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /enums.js: -------------------------------------------------------------------------------- 1 | const TeamFortress2 = require('./index.js'); 2 | 3 | TeamFortress2.GCGoodbyeReason = { 4 | GC_GOING_DOWN: 1, 5 | NO_SESSION: 2 6 | }; 7 | 8 | TeamFortress2.TradeResponse = { 9 | Accepted: 0, 10 | Declined: 1, 11 | TradeBannedInitiator: 2, 12 | TradeBannedTarget: 3, 13 | TargetAlreadyTrading: 4, 14 | Disabled: 5, 15 | NotLoggedIn: 6, 16 | Cancel: 7, 17 | TooSoon: 8, 18 | TooSoonPenalty: 9, 19 | ConnectionFailed: 10, 20 | AlreadyTrading: 11, 21 | AlreadyHasTradeRequest: 12, 22 | NoResponse: 13, 23 | CyberCafeInitiator: 14, 24 | CyberCafeTarget: 15, 25 | SchoolLabInitiator: 16, 26 | SchoolLabTarget: 16, 27 | InitiatorBlockedTarget: 18, 28 | InitiatorNeedsVerifiedEmail: 20, 29 | InitiatorNeedsSteamGuard: 21, 30 | TargetAccountCannotTrade: 22, 31 | InitiatorSteamGuardDuration: 23, 32 | InitiatorPasswordResetProbation: 24, 33 | InitiatorNewDeviceCooldown: 25, 34 | OKToDeliver: 50 35 | }; 36 | 37 | TeamFortress2.Class = { 38 | Scout: 1, 39 | Sniper: 2, 40 | Soldier: 3, 41 | Demoman: 4, 42 | Medic: 5, 43 | Heavy: 6, 44 | Pyro: 7, 45 | Spy: 8, 46 | Engineer: 9 47 | }; 48 | 49 | TeamFortress2.ItemSlot = { 50 | Primary: 0, 51 | Secondary: 1, 52 | Melee: 2, 53 | // 3 appears to be unused 54 | Sapper: 4, // Sapper 55 | PDA: 5, 56 | PDA2: 6, 57 | Cosmetic1: 7, 58 | Cosmetic2: 8, 59 | Action: 9, 60 | Cosmetic3: 10, 61 | Taunt1: 11, 62 | Taunt2: 12, 63 | Taunt3: 13, 64 | Taunt4: 14, 65 | Taunt5: 15, 66 | Taunt6: 16, 67 | Taunt7: 17, 68 | Taunt8: 18 69 | }; 70 | 71 | TeamFortress2.ItemFlags = { 72 | CannotTrade: (1 << 0), 73 | CannotCraft: (1 << 1), 74 | NotEcon: (1 << 3), 75 | Preview: (1 << 7) 76 | }; 77 | 78 | TeamFortress2.War = { 79 | HeavyVsPyro: 0 80 | }; 81 | 82 | TeamFortress2.HeavyVsPyroWarSide = { 83 | Heavy: 0, 84 | Pyro: 1 85 | }; 86 | -------------------------------------------------------------------------------- /protobufs/gcsdk_gcmessages.proto: -------------------------------------------------------------------------------- 1 | import "steammessages.proto"; 2 | 3 | option optimize_for = SPEED; 4 | option cc_generic_services = false; 5 | 6 | enum PartnerAccountType { 7 | PARTNER_NONE = 0; 8 | PARTNER_PERFECT_WORLD = 1; 9 | PARTNER_NEXON = 2; 10 | } 11 | 12 | enum GCConnectionStatus { 13 | GCConnectionStatus_HAVE_SESSION = 0; 14 | GCConnectionStatus_GC_GOING_DOWN = 1; 15 | GCConnectionStatus_NO_SESSION = 2; 16 | GCConnectionStatus_NO_SESSION_IN_LOGON_QUEUE = 3; 17 | GCConnectionStatus_NO_STEAM = 4; 18 | GCConnectionStatus_SUSPENDED = 5; 19 | } 20 | 21 | message CMsgSOIDOwner { 22 | optional uint32 type = 1; 23 | optional uint64 id = 2; 24 | } 25 | 26 | message CMsgSOSingleObject { 27 | optional fixed64 owner = 1; 28 | optional int32 type_id = 2; 29 | optional bytes object_data = 3; 30 | optional fixed64 version = 4; 31 | optional .CMsgSOIDOwner owner_soid = 5; 32 | optional uint32 service_id = 6; 33 | } 34 | 35 | message CMsgSOMultipleObjects { 36 | message SingleObject { 37 | optional int32 type_id = 1; 38 | optional bytes object_data = 2; 39 | } 40 | 41 | optional fixed64 owner = 1; 42 | repeated .CMsgSOMultipleObjects.SingleObject objects = 2; 43 | optional fixed64 version = 3; 44 | optional .CMsgSOIDOwner owner_soid = 6; 45 | optional uint32 service_id = 7; 46 | } 47 | 48 | message CMsgSOCacheSubscribed { 49 | message SubscribedType { 50 | optional int32 type_id = 1; 51 | repeated bytes object_data = 2; 52 | } 53 | 54 | optional fixed64 owner = 1; 55 | repeated .CMsgSOCacheSubscribed.SubscribedType objects = 2; 56 | optional fixed64 version = 3; 57 | optional .CMsgSOIDOwner owner_soid = 4; 58 | optional uint32 service_id = 5; 59 | repeated uint32 service_list = 6; 60 | optional fixed64 sync_version = 7; 61 | } 62 | 63 | message CMsgSOCacheSubscribedUpToDate { 64 | optional fixed64 version = 1; 65 | optional .CMsgSOIDOwner owner_soid = 2; 66 | optional uint32 service_id = 3; 67 | repeated uint32 service_list = 4; 68 | optional fixed64 sync_version = 5; 69 | } 70 | 71 | message CMsgSOCacheUnsubscribed { 72 | optional fixed64 owner = 1; 73 | } 74 | 75 | message CMsgSOCacheSubscriptionCheck { 76 | optional fixed64 owner = 1; 77 | optional fixed64 version = 2; 78 | optional .CMsgSOIDOwner owner_soid = 3; 79 | optional uint32 service_id = 4; 80 | repeated uint32 service_list = 5; 81 | optional fixed64 sync_version = 6; 82 | } 83 | 84 | message CMsgSOCacheSubscriptionRefresh { 85 | optional fixed64 owner = 1; 86 | optional .CMsgSOIDOwner owner_soid = 2; 87 | } 88 | 89 | message CMsgSOCacheVersion { 90 | optional fixed64 version = 1; 91 | } 92 | 93 | message CMsgGCMultiplexMessage { 94 | optional uint32 msgtype = 1; 95 | optional bytes payload = 2; 96 | repeated fixed64 steamids = 3; 97 | } 98 | 99 | message CGCToGCMsgMasterAck { 100 | optional uint32 dir_index = 1; 101 | optional string machine_name = 3; 102 | optional string process_name = 4; 103 | repeated uint32 type_instances = 5; 104 | } 105 | 106 | message CGCToGCMsgMasterAck_Response { 107 | optional int32 eresult = 1 [default = 2]; 108 | } 109 | 110 | message CGCToGCMsgMasterStartupComplete { 111 | message GCInfo { 112 | optional uint32 dir_index = 1; 113 | optional string machine_name = 2; 114 | } 115 | 116 | repeated .CGCToGCMsgMasterStartupComplete.GCInfo gc_info = 1; 117 | } 118 | 119 | message CGCToGCMsgRouted { 120 | optional uint32 msg_type = 1; 121 | optional fixed64 sender_id = 2; 122 | optional bytes net_message = 3; 123 | } 124 | 125 | message CGCToGCMsgRoutedReply { 126 | optional uint32 msg_type = 1; 127 | optional bytes net_message = 2; 128 | } 129 | 130 | message CMsgGCUpdateSubGCSessionInfo { 131 | message CMsgUpdate { 132 | optional fixed64 steamid = 1; 133 | optional fixed32 ip = 2; 134 | optional bool trusted = 3; 135 | } 136 | 137 | repeated .CMsgGCUpdateSubGCSessionInfo.CMsgUpdate updates = 1; 138 | } 139 | 140 | message CMsgGCRequestSubGCSessionInfo { 141 | optional fixed64 steamid = 1; 142 | } 143 | 144 | message CMsgGCRequestSubGCSessionInfoResponse { 145 | optional fixed32 ip = 1; 146 | optional bool trusted = 2; 147 | } 148 | 149 | message CMsgGCToGCIncrementRecruitmentLevel { 150 | optional fixed64 steamid = 1; 151 | } 152 | 153 | message CMsgSOCacheHaveVersion { 154 | optional .CMsgSOIDOwner soid = 1; 155 | optional fixed64 version = 2; 156 | optional uint32 service_id = 3; 157 | } 158 | 159 | message CMsgConnectionStatus { 160 | optional .GCConnectionStatus status = 1 [default = GCConnectionStatus_HAVE_SESSION]; 161 | optional uint32 client_session_need = 2; 162 | optional int32 queue_position = 3; 163 | optional int32 queue_size = 4; 164 | optional int32 wait_seconds = 5; 165 | optional int32 estimated_wait_seconds_remaining = 6; 166 | } 167 | 168 | message CMsgGCToGCSOCacheSubscribe { 169 | message CMsgHaveVersions { 170 | optional uint32 service_id = 1; 171 | optional uint64 version = 2; 172 | } 173 | 174 | optional fixed64 subscriber = 1; 175 | optional fixed64 subscribe_to = 2; 176 | optional fixed64 sync_version = 3; 177 | repeated .CMsgGCToGCSOCacheSubscribe.CMsgHaveVersions have_versions = 4; 178 | } 179 | 180 | message CMsgGCToGCSOCacheUnsubscribe { 181 | optional fixed64 subscriber = 1; 182 | optional fixed64 unsubscribe_from = 2; 183 | } 184 | 185 | message CMsgGCClientPing { 186 | } 187 | 188 | -------------------------------------------------------------------------------- /protobufs/gcsystemmsgs.proto: -------------------------------------------------------------------------------- 1 | option optimize_for = SPEED; 2 | option cc_generic_services = false; 3 | 4 | enum EGCSystemMsg { 5 | k_EGCMsgInvalid = 0; 6 | k_EGCMsgMulti = 1; 7 | k_EGCMsgGenericReply = 10; 8 | k_EGCMsgSystemBase = 50; 9 | k_EGCMsgAchievementAwarded = 51; 10 | k_EGCMsgConCommand = 52; 11 | k_EGCMsgStartPlaying = 53; 12 | k_EGCMsgStopPlaying = 54; 13 | k_EGCMsgStartGameserver = 55; 14 | k_EGCMsgStopGameserver = 56; 15 | k_EGCMsgWGRequest = 57; 16 | k_EGCMsgWGResponse = 58; 17 | k_EGCMsgGetUserGameStatsSchema = 59; 18 | k_EGCMsgGetUserGameStatsSchemaResponse = 60; 19 | k_EGCMsgGetUserStatsDEPRECATED = 61; 20 | k_EGCMsgGetUserStatsResponse = 62; 21 | k_EGCMsgAppInfoUpdated = 63; 22 | k_EGCMsgValidateSession = 64; 23 | k_EGCMsgValidateSessionResponse = 65; 24 | k_EGCMsgLookupAccountFromInput = 66; 25 | k_EGCMsgSendHTTPRequest = 67; 26 | k_EGCMsgSendHTTPRequestResponse = 68; 27 | k_EGCMsgPreTestSetup = 69; 28 | k_EGCMsgRecordSupportAction = 70; 29 | k_EGCMsgGetAccountDetails_DEPRECATED = 71; 30 | k_EGCMsgReceiveInterAppMessage = 73; 31 | k_EGCMsgFindAccounts = 74; 32 | k_EGCMsgPostAlert = 75; 33 | k_EGCMsgGetLicenses = 76; 34 | k_EGCMsgGetUserStats = 77; 35 | k_EGCMsgGetCommands = 78; 36 | k_EGCMsgGetCommandsResponse = 79; 37 | k_EGCMsgAddFreeLicense = 80; 38 | k_EGCMsgAddFreeLicenseResponse = 81; 39 | k_EGCMsgGetIPLocation = 82; 40 | k_EGCMsgGetIPLocationResponse = 83; 41 | k_EGCMsgSystemStatsSchema = 84; 42 | k_EGCMsgGetSystemStats = 85; 43 | k_EGCMsgGetSystemStatsResponse = 86; 44 | k_EGCMsgSendEmail = 87; 45 | k_EGCMsgSendEmailResponse = 88; 46 | k_EGCMsgGetEmailTemplate = 89; 47 | k_EGCMsgGetEmailTemplateResponse = 90; 48 | k_EGCMsgGrantGuestPass = 91; 49 | k_EGCMsgGrantGuestPassResponse = 92; 50 | k_EGCMsgGetAccountDetails = 93; 51 | k_EGCMsgGetAccountDetailsResponse = 94; 52 | k_EGCMsgGetPersonaNames = 95; 53 | k_EGCMsgGetPersonaNamesResponse = 96; 54 | k_EGCMsgMultiplexMsg = 97; 55 | k_EGCMsgWebAPIRegisterInterfaces = 101; 56 | k_EGCMsgWebAPIJobRequest = 102; 57 | k_EGCMsgWebAPIJobRequestHttpResponse = 104; 58 | k_EGCMsgWebAPIJobRequestForwardResponse = 105; 59 | k_EGCMsgMemCachedGet = 200; 60 | k_EGCMsgMemCachedGetResponse = 201; 61 | k_EGCMsgMemCachedSet = 202; 62 | k_EGCMsgMemCachedDelete = 203; 63 | k_EGCMsgMemCachedStats = 204; 64 | k_EGCMsgMemCachedStatsResponse = 205; 65 | k_EGCMsgSQLStats = 210; 66 | k_EGCMsgSQLStatsResponse = 211; 67 | k_EGCMsgMasterSetDirectory = 220; 68 | k_EGCMsgMasterSetDirectoryResponse = 221; 69 | k_EGCMsgMasterSetWebAPIRouting = 222; 70 | k_EGCMsgMasterSetWebAPIRoutingResponse = 223; 71 | k_EGCMsgMasterSetClientMsgRouting = 224; 72 | k_EGCMsgMasterSetClientMsgRoutingResponse = 225; 73 | k_EGCMsgSetOptions = 226; 74 | k_EGCMsgSetOptionsResponse = 227; 75 | k_EGCMsgSystemBase2 = 500; 76 | k_EGCMsgGetPurchaseTrustStatus = 501; 77 | k_EGCMsgGetPurchaseTrustStatusResponse = 502; 78 | k_EGCMsgUpdateSession = 503; 79 | k_EGCMsgGCAccountVacStatusChange = 504; 80 | k_EGCMsgCheckFriendship = 505; 81 | k_EGCMsgCheckFriendshipResponse = 506; 82 | k_EGCMsgGetPartnerAccountLink = 507; 83 | k_EGCMsgGetPartnerAccountLinkResponse = 508; 84 | k_EGCMsgVSReportedSuspiciousActivity = 509; 85 | k_EGCMsgAccountTradeBanStatusChange = 510; 86 | k_EGCMsgAccountLockStatusChange = 511; 87 | k_EGCMsgDPPartnerMicroTxns = 512; 88 | k_EGCMsgDPPartnerMicroTxnsResponse = 513; 89 | k_EGCMsgGetIPASN = 514; 90 | k_EGCMsgGetIPASNResponse = 515; 91 | k_EGCMsgGetAppFriendsList = 516; 92 | k_EGCMsgGetAppFriendsListResponse = 517; 93 | k_EGCMsgVacVerificationChange = 518; 94 | k_EGCMsgAccountPhoneNumberChange = 519; 95 | k_EGCMsgAccountTwoFactorChange = 520; 96 | k_EGCMsgCheckClanMembership = 521; 97 | k_EGCMsgCheckClanMembershipResponse = 522; 98 | k_EGCMsgInviteUserToLobby = 523; 99 | k_EGCMsgGetGamePersonalDataCategoriesRequest = 524; 100 | k_EGCMsgGetGamePersonalDataCategoriesResponse = 525; 101 | k_EGCMsgGetGamePersonalDataEntriesRequest = 526; 102 | k_EGCMsgGetGamePersonalDataEntriesResponse = 527; 103 | k_EGCMsgTerminateGamePersonalDataEntriesRequest = 528; 104 | k_EGCMsgTerminateGamePersonalDataEntriesResponse = 529; 105 | } 106 | 107 | enum ESOMsg { 108 | k_ESOMsg_Create = 21; 109 | k_ESOMsg_Update = 22; 110 | k_ESOMsg_Destroy = 23; 111 | k_ESOMsg_CacheSubscribed = 24; 112 | k_ESOMsg_CacheUnsubscribed = 25; 113 | k_ESOMsg_UpdateMultiple = 26; 114 | k_ESOMsg_CacheSubscriptionCheck = 27; 115 | k_ESOMsg_CacheSubscriptionRefresh = 28; 116 | k_ESOMsg_CacheSubscribedUpToDate = 29; 117 | } 118 | 119 | enum EGCBaseClientMsg { 120 | k_EMsgGCPingRequest = 3001; 121 | k_EMsgGCPingResponse = 3002; 122 | k_EMsgGCClientWelcome = 4004; 123 | k_EMsgGCServerWelcome = 4005; 124 | k_EMsgGCClientHello = 4006; 125 | k_EMsgGCServerHello = 4007; 126 | k_EMsgGCClientGoodbye = 4008; 127 | k_EMsgGCServerGoodbye = 4009; 128 | } 129 | 130 | enum EGCToGCMsg { 131 | k_EGCToGCMsgMasterAck = 150; 132 | k_EGCToGCMsgMasterAckResponse = 151; 133 | k_EGCToGCMsgRouted = 152; 134 | k_EGCToGCMsgRoutedReply = 153; 135 | k_EMsgGCUpdateSubGCSessionInfo = 154; 136 | k_EMsgGCRequestSubGCSessionInfo = 155; 137 | k_EMsgGCRequestSubGCSessionInfoResponse = 156; 138 | k_EGCToGCMsgMasterStartupComplete = 157; 139 | k_EMsgGCToGCSOCacheSubscribe = 158; 140 | k_EMsgGCToGCSOCacheUnsubscribe = 159; 141 | } 142 | 143 | message CCommunity_GamePersonalDataCategoryInfo { 144 | optional string type = 1; 145 | optional string localization_token = 2; 146 | optional string template_file = 3; 147 | } 148 | 149 | message CCommunity_GetGamePersonalDataCategories_Request { 150 | optional uint32 appid = 1; 151 | } 152 | 153 | message CCommunity_GetGamePersonalDataCategories_Response { 154 | repeated .CCommunity_GamePersonalDataCategoryInfo categories = 1; 155 | optional string app_assets_basename = 2; 156 | } 157 | 158 | message CCommunity_GetGamePersonalDataEntries_Request { 159 | optional uint32 appid = 1; 160 | optional uint64 steamid = 2; 161 | optional string type = 3; 162 | optional string continue_token = 4; 163 | } 164 | 165 | message CCommunity_GetGamePersonalDataEntries_Response { 166 | optional uint32 gceresult = 1; 167 | repeated string entries = 2; 168 | optional string continue_token = 3; 169 | } 170 | 171 | message CCommunity_TerminateGamePersonalDataEntries_Request { 172 | optional uint32 appid = 1; 173 | optional uint64 steamid = 2; 174 | } 175 | 176 | message CCommunity_TerminateGamePersonalDataEntries_Response { 177 | optional uint32 gceresult = 1; 178 | } 179 | 180 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const ByteBuffer = require('bytebuffer'); 2 | const EventEmitter = require('events').EventEmitter; 3 | const SteamID = require('steamid'); 4 | const Util = require('util'); 5 | const VDF = require('kvparser'); 6 | 7 | const Language = require('./language.js'); 8 | const Schema = require('./protobufs/generated/_load.js'); 9 | 10 | const STEAM_APPID = 440; 11 | 12 | module.exports = TeamFortress2; 13 | 14 | Util.inherits(TeamFortress2, EventEmitter); 15 | 16 | function TeamFortress2(steam) { 17 | if (steam.packageName != 'steam-user' || !steam.packageVersion || !steam.constructor) { 18 | throw new Error('tf2 v3 only supports steam-user v4.2.0 or later.'); 19 | } else { 20 | let [major, minor] = steam.packageVersion.split('.'); 21 | if (major < 4 || (major == 4 && minor < 2)) { 22 | throw new Error(`tf2 v3 only supports node-steam-user v4.2.0 or later. ${steam.constructor.name} v${steam.packageVersion} given.`); 23 | } 24 | } 25 | 26 | this._steam = steam; 27 | this.haveGCSession = false; 28 | this._isInTF2 = false; 29 | 30 | this._steam.on('receivedFromGC', (appid, msgType, payload) => { 31 | if (appid != STEAM_APPID) { 32 | return; // we don't care 33 | } 34 | 35 | let isProtobuf = !Buffer.isBuffer(payload); 36 | let handler = null; 37 | 38 | if (this._handlers[msgType]) { 39 | handler = this._handlers[msgType]; 40 | } 41 | 42 | let msgName = msgType; 43 | for (let i in Language) { 44 | if (Language.hasOwnProperty(i) && Language[i] == msgType) { 45 | msgName = i; 46 | break; 47 | } 48 | } 49 | 50 | this.emit('debug', "Got " + (handler ? "handled" : "unhandled") + " GC message " + msgName + (isProtobuf ? " (protobuf)" : "")); 51 | if (handler) { 52 | handler.call(this, isProtobuf ? payload : ByteBuffer.wrap(payload, ByteBuffer.LITTLE_ENDIAN)); 53 | } 54 | }); 55 | 56 | this._steam.on('appLaunched', (appid) => { 57 | if (this._isInTF2) { 58 | return; // we don't care if it was launched again 59 | } 60 | 61 | if (appid == STEAM_APPID) { 62 | this._isInTF2 = true; 63 | if (!this.haveGCSession) { 64 | this._connect(); 65 | } 66 | } 67 | }); 68 | 69 | let handleAppQuit = (emitDisconnectEvent) => { 70 | if (this._helloInterval) { 71 | clearInterval(this._helloInterval); 72 | this._helloInterval = null; 73 | } 74 | 75 | if (this.haveGCSession && emitDisconnectEvent) { 76 | this.emit('disconnectedFromGC', TeamFortress2.GCGoodbyeReason.NO_SESSION); 77 | } 78 | 79 | this._isInTF2 = false; 80 | this.haveGCSession = false; 81 | }; 82 | 83 | this._steam.on('appQuit', (appid) => { 84 | if (!this._isInTF2) { 85 | return; 86 | } 87 | 88 | if (appid == STEAM_APPID) { 89 | handleAppQuit(false); 90 | } 91 | }); 92 | 93 | this._steam.on('disconnected', () => { 94 | handleAppQuit(true); 95 | }); 96 | 97 | this._steam.on('error', (err) => { 98 | handleAppQuit(true); 99 | }); 100 | } 101 | 102 | TeamFortress2.prototype._connect = function() { 103 | if (!this._isInTF2 || this._helloInterval) { 104 | return; // We're not in TF2 or we're already trying to connect 105 | } 106 | 107 | let sendHello = () => { 108 | if (this.haveGCSession) { 109 | clearInterval(this._helloInterval); 110 | this._helloInterval = null; 111 | return; 112 | } 113 | 114 | if (this._isServer()) { 115 | this._send(Language.ServerHello, Schema.CMsgServerHello, {}); 116 | } else { 117 | this._send(Language.ClientHello, Schema.CMsgClientHello, {}); 118 | } 119 | }; 120 | 121 | this._helloInterval = setInterval(sendHello, 5000); 122 | sendHello(); 123 | }; 124 | 125 | TeamFortress2.prototype._isServer = function() { 126 | let serverTypes = [SteamID.Type.ANON_GAMESERVER, SteamID.Type.GAMESERVER]; 127 | return this._steam.steamID && serverTypes.includes(this._steam.steamID.type); 128 | }; 129 | 130 | TeamFortress2.prototype._send = function(type, protobuf, body) { 131 | if (!this._steam.steamID) { 132 | return false; 133 | } 134 | 135 | let msgName = type; 136 | for (let i in Language) { 137 | if (Language[i] == type) { 138 | msgName = i; 139 | break; 140 | } 141 | } 142 | 143 | this.emit('debug', "Sending GC message " + msgName); 144 | 145 | if (protobuf) { 146 | this._steam.sendToGC(STEAM_APPID, type, {}, protobuf.encode(body).finish()); 147 | } else { 148 | // This is a ByteBuffer 149 | this._steam.sendToGC(STEAM_APPID, type, null, body.flip().toBuffer()); 150 | } 151 | 152 | return true; 153 | }; 154 | 155 | TeamFortress2.prototype.setLang = function(langFile) { 156 | let lang = VDF.parse(langFile); 157 | // The vdf parser appears to add some random characters and quotes to the root 'lang' key, so we'll just use a loop to find it 158 | for (let i in lang) { 159 | this.lang = lang[i].Tokens; 160 | } 161 | }; 162 | 163 | TeamFortress2.prototype.craft = function(items, recipe) { 164 | let buffer = new ByteBuffer(2 + 2 + (8 * items.length), ByteBuffer.LITTLE_ENDIAN); 165 | buffer.writeInt16(recipe || -2); // -2 is wildcard 166 | buffer.writeInt16(items.length); 167 | for (let i = 0; i < items.length; i++) { 168 | buffer.writeUint64(coerceToLong(items[i])); 169 | } 170 | 171 | this._send(Language.Craft, null, buffer); 172 | }; 173 | 174 | TeamFortress2.prototype.trade = function(steamID) { 175 | if (typeof steamID == 'string') { 176 | steamID = new SteamID(steamID); 177 | } 178 | 179 | let buffer = new ByteBuffer(12, ByteBuffer.LITTLE_ENDIAN); 180 | buffer.writeUint32(0); 181 | buffer.writeUint64(coerceToLong(steamID.getSteamID64())); 182 | this._send(Language.Trading_InitiateTradeRequest, null, buffer); 183 | }; 184 | 185 | TeamFortress2.prototype.cancelTradeRequest = function() { 186 | let buffer = new ByteBuffer(0, ByteBuffer.LITTLE_ENDIAN); 187 | this._send(Language.Trading_CancelSession, null, buffer); 188 | }; 189 | 190 | TeamFortress2.prototype.respondToTrade = function(tradeID, accept) { 191 | let buffer = new ByteBuffer(8, ByteBuffer.LITTLE_ENDIAN); 192 | buffer.writeUint32(accept ? TeamFortress2.TradeResponse.Accepted : TeamFortress2.TradeResponse.Declined); 193 | buffer.writeUint32(tradeID); 194 | this._send(Language.Trading_InitiateTradeResponse, null, buffer); 195 | }; 196 | 197 | TeamFortress2.prototype.setStyle = function(item, style) { 198 | let buffer = new ByteBuffer(12, ByteBuffer.LITTLE_ENDIAN); 199 | buffer.writeUint64(coerceToLong(item)); 200 | buffer.writeUint32(style); 201 | this._send(Language.SetItemStyle, null, buffer); 202 | }; 203 | 204 | TeamFortress2.prototype.setPosition = function(item, position) { 205 | let buffer = new ByteBuffer(16, ByteBuffer.LITTLE_ENDIAN); 206 | buffer.writeUint64(coerceToLong(item)); 207 | buffer.writeUint64(coerceToLong(position)); 208 | this._send(Language.SetSingleItemPosition, null, buffer); 209 | }; 210 | 211 | TeamFortress2.prototype.setPositions = function(items) { 212 | this._send(Language.SetItemPositions, Schema.CMsgSetItemPositions, {"item_positions": items}); 213 | }; 214 | 215 | TeamFortress2.prototype.deleteItem = function(item) { 216 | let buffer = new ByteBuffer(8, ByteBuffer.LITTLE_ENDIAN); 217 | buffer.writeUint64(coerceToLong(item)); 218 | this._send(Language.Delete, null, buffer); 219 | }; 220 | 221 | TeamFortress2.prototype.wrapItem = function(wrapID, itemID) { 222 | let buffer = new ByteBuffer(16, ByteBuffer.LITTLE_ENDIAN); 223 | buffer.writeUint64(coerceToLong(wrapID)); 224 | buffer.writeUint64(coerceToLong(itemID)); 225 | this._send(Language.GiftWrapItem, null, buffer); 226 | }; 227 | 228 | TeamFortress2.prototype.deliverGift = function(gift, steamID) { 229 | if (typeof steamID == 'string') { 230 | steamID = new SteamID(steamID); 231 | } 232 | 233 | let buffer = new ByteBuffer(16, ByteBuffer.LITTLE_ENDIAN); 234 | buffer.writeUint64(coerceToLong(gift)); 235 | buffer.writeUint64(coerceToLong(steamID.getSteamID64())); 236 | this._send(Language.DeliverGift, null, buffer); 237 | }; 238 | 239 | TeamFortress2.prototype.unwrapGift = function(gift) { 240 | let buffer = new ByteBuffer(8, ByteBuffer.LITTLE_ENDIAN); 241 | buffer.writeUint64(coerceToLong(gift)); 242 | this._send(Language.UnwrapGiftRequest, null, buffer); 243 | }; 244 | 245 | TeamFortress2.prototype.useItem = function(item) { 246 | this._send(Language.UseItemRequest, Schema.CMsgUseItem, {"item_id": item}); 247 | }; 248 | 249 | TeamFortress2.prototype.sortBackpack = function(sortType) { 250 | this._send(Language.SortItems, Schema.CMsgSortItems, {"sort_type": sortType}); 251 | }; 252 | 253 | TeamFortress2.prototype.sendProfessorSpeks = function(steamID) { 254 | if (typeof steamID == 'string') { 255 | steamID = new SteamID(steamID); 256 | } 257 | 258 | this._send(Language.FreeTrial_ChooseMostHelpfulFriend, Schema.CMsgTFFreeTrialChooseMostHelpfulFriend, {"account_id_friend": steamID.accountid}); 259 | }; 260 | 261 | TeamFortress2.prototype.createServerIdentity = function() { 262 | this._send(Language.GameServer_CreateIdentity, Schema.CMsgGC_GameServer_CreateIdentity, {"account_id": this._steam.steamID.accountid}); 263 | }; 264 | 265 | TeamFortress2.prototype.getRegisteredServers = function() { 266 | this._send(Language.GameServer_List, Schema.CMsgGC_GameServer_List, {"account_id": this._steam.steamID.accountid}); 267 | }; 268 | 269 | TeamFortress2.prototype.resetServerIdentity = function(id) { 270 | this._send(Language.GameServer_ResetIdentity, Schema.CMsgGC_GameServer_ResetIdentity, {"game_server_account_id": id}); 271 | }; 272 | 273 | TeamFortress2.prototype.openCrate = function(keyID, crateID) { 274 | let buffer = new ByteBuffer(16, ByteBuffer.LITTLE_ENDIAN); 275 | buffer.writeUint64(coerceToLong(keyID)); 276 | buffer.writeUint64(coerceToLong(crateID)); 277 | this._send(Language.UnlockCrate, null, buffer); 278 | }; 279 | 280 | TeamFortress2.prototype.equipItem = function(itemID, classID, slot) { 281 | this._send(Language.AdjustItemEquippedState, Schema.CMsgAdjustItemEquippedState, { 282 | "item_id": itemID, 283 | "new_class": classID, 284 | "new_slot": slot 285 | }); 286 | }; 287 | 288 | TeamFortress2.prototype.requestWarStats = function(warID, callback) { 289 | if (typeof warID === 'function') { 290 | callback = warID; 291 | warID = null; 292 | } 293 | 294 | this._send(Language.War_RequestGlobalStats, Schema.CGCMsgGC_War_RequestGlobalStats, {"war_id": warID || TeamFortress2.War.HeavyVsPyro}); 295 | 296 | if (callback) { 297 | this.once('warStats', callback); 298 | } 299 | }; 300 | 301 | TeamFortress2.prototype._handlers = {}; 302 | 303 | function coerceToLong(num, signed) { 304 | return typeof num === 'string' ? new ByteBuffer.Long.fromString(num, !signed, 10) : num; 305 | } 306 | 307 | require('./enums.js'); 308 | require('./handlers.js'); 309 | -------------------------------------------------------------------------------- /language.js: -------------------------------------------------------------------------------- 1 | // This file contains representations of message IDs 2 | 3 | module.exports = { 4 | // ESOMsg 5 | SO_Create: 21, 6 | SO_Update: 22, 7 | SO_Destroy: 23, 8 | SO_CacheSubscribed: 24, 9 | SO_CacheUnsubscribed: 25, 10 | SO_UpdateMultiple: 26, 11 | SO_CacheSubscriptionCheck: 27, 12 | SO_CacheSubscriptionRefresh: 28, 13 | SO_CacheSubscribedUpToDate: 29, 14 | 15 | // EGCItemMsg 16 | Base: 1000, 17 | SetSingleItemPosition: 1001, 18 | Craft: 1002, 19 | CraftResponse: 1003, 20 | Delete: 1004, 21 | VerifyCacheSubscription: 1005, 22 | NameItem: 1006, 23 | UnlockCrate: 1007, 24 | UnlockCrateResponse: 1008, 25 | PaintItem: 1009, 26 | PaintItemResponse: 1010, 27 | GoldenWrenchBroadcast: 1011, 28 | MOTDRequest: 1012, 29 | MOTDRequestResponse: 1013, 30 | NameBaseItem: 1019, 31 | NameBaseItemResponse: 1020, 32 | RemoveSocketItem_DEPRECATED: 1021, 33 | RemoveSocketItemResponse_DEPRECATED: 1022, 34 | CustomizeItemTexture: 1023, 35 | CustomizeItemTextureResponse: 1024, 36 | UseItemRequest: 1025, 37 | UseItemResponse: 1026, 38 | RespawnPostLoadoutChange: 1029, 39 | RemoveItemName: 1030, 40 | RemoveItemPaint: 1031, 41 | GiftWrapItem: 1032, 42 | GiftWrapItemResponse: 1033, 43 | DeliverGift: 1034, 44 | DeliverGiftResponseReceiver: 1036, 45 | UnwrapGiftRequest: 1037, 46 | UnwrapGiftResponse: 1038, 47 | SetItemStyle: 1039, 48 | UsedClaimCodeItem: 1040, 49 | SortItems: 1041, 50 | RevolvingLootList_DEPRECATED: 1042, 51 | LookupAccount: 1043, 52 | LookupAccountResponse: 1044, 53 | LookupAccountName: 1045, 54 | LookupAccountNameResponse: 1046, 55 | UpdateItemSchema: 1049, 56 | RequestInventoryRefresh: 1050, 57 | RemoveCustomTexture: 1051, 58 | RemoveCustomTextureResponse: 1052, 59 | RemoveMakersMark: 1053, 60 | RemoveMakersMarkResponse: 1054, 61 | RemoveUniqueCraftIndex: 1055, 62 | RemoveUniqueCraftIndexResponse: 1056, 63 | SaxxyBroadcast: 1057, 64 | BackpackSortFinished: 1058, 65 | AdjustItemEquippedState: 1059, 66 | CollectItem: 1061, 67 | ItemAcknowledged: 1062, 68 | Presets_SelectPresetForClass: 1063, 69 | Presets_SetItemPosition: 1064, 70 | ReportAbuse: 1065, 71 | ReportAbuseResponse: 1066, 72 | Presets_SelectPresetForClassReply: 1067, 73 | NameItemNotification: 1068, 74 | ClientDisplayNotification: 1069, 75 | ApplyStrangePart: 1070, 76 | IncrementKillCountAttribute: 1071, 77 | IncrementKillCountResponse: 1072, 78 | RemoveStrangePart: 1073, 79 | ResetStrangeScores: 1074, 80 | GiftedItems: 1075, 81 | ApplyUpgradeCard: 1077, 82 | RemoveUpgradeCard: 1078, 83 | ApplyStrangeRestriction: 1079, 84 | ClientRequestMarketData: 1080, 85 | ClientRequestMarketDataResponse: 1081, 86 | ApplyXifier: 1082, 87 | ApplyXifierResponse: 1083, 88 | TrackUniquePlayerPairEvent: 1084, 89 | FulfillDynamicRecipeComponent: 1085, 90 | FulfillDynamicRecipeComponentResponse: 1086, 91 | SetItemEffectVerticalOffset: 1087, 92 | SetHatEffectUseHeadOrigin: 1088, 93 | ItemEaterRecharger: 1089, 94 | ItemEaterRechargerResponse: 1090, 95 | ApplyBaseItemXifier: 1091, 96 | ApplyClassTransmogrifier: 1092, 97 | ApplyHalloweenSpellbookPage: 1093, 98 | RemoveKillStreak: 1094, 99 | RemoveKillStreakResponse: 1095, 100 | TFSpecificItemBroadcast: 1096, 101 | IncrementKillCountAttribute_Multiple: 1097, 102 | DeliverGiftResponseGiver: 1098, 103 | SetItemPositions: 1100, 104 | LookupMultipleAccountNames: 1101, 105 | LookupMultipleAccountNamesResponse: 1102, 106 | TradingBase: 1500, 107 | Trading_InitiateTradeRequest: 1501, 108 | Trading_InitiateTradeResponse: 1502, 109 | Trading_StartSession: 1503, 110 | Trading_SessionClosed: 1509, 111 | Trading_CancelSession: 1510, 112 | Trading_InitiateTradeRequestResponse: 1514, 113 | ServerBrowser_FavoriteServer: 1601, 114 | ServerBrowser_BlacklistServer: 1602, 115 | ServerRentalsBase: 1700, 116 | ItemPreviewCheckStatus: 1701, 117 | ItemPreviewStatusResponse: 1702, 118 | ItemPreviewRequest: 1703, 119 | ItemPreviewRequestResponse: 1704, 120 | ItemPreviewExpire: 1705, 121 | ItemPreviewExpireNotification: 1706, 122 | ItemPreviewItemBoughtNotification: 1708, 123 | Dev_NewItemRequest: 2001, 124 | Dev_NewItemRequestResponse: 2002, 125 | Dev_DebugRollLootRequest: 2003, 126 | StoreGetUserData: 2500, 127 | StoreGetUserDataResponse: 2501, 128 | StorePurchaseInit_DEPRECATED: 2502, 129 | StorePurchaseInitResponse_DEPRECATED: 2503, 130 | StorePurchaseFinalize: 2512, 131 | StorePurchaseFinalizeResponse: 2513, 132 | StorePurchaseCancel: 2514, 133 | StorePurchaseCancelResponse: 2515, 134 | StorePurchaseQueryTxn: 2508, 135 | StorePurchaseQueryTxnResponse: 2509, 136 | StorePurchaseInit: 2510, 137 | StorePurchaseInitResponse: 2511, 138 | GCToGCDirtySDOCache: 2516, 139 | GCToGCDirtyMultipleSDOCache: 2517, 140 | GCToGCUpdateSQLKeyValue: 2518, 141 | GCToGCBroadcastConsoleCommand: 2521, 142 | ServerVersionUpdated: 2522, 143 | ApplyAutograph: 2523, 144 | GCToGCWebAPIAccountChanged: 2524, 145 | RequestAnnouncements: 2525, 146 | RequestAnnouncementsResponse: 2526, 147 | RequestPassportItemGrant: 2527, 148 | ClientVersionUpdated: 2528, 149 | ItemPurgatory_FinalizePurchase: 2531, 150 | ItemPurgatory_FinalizePurchaseResponse: 2532, 151 | ItemPurgatory_RefundPurchase: 2533, 152 | ItemPurgatory_RefundPurchaseResponse: 2534, 153 | GCToGCPlayerStrangeCountAdjustments: 2535, 154 | RequestStoreSalesData: 2536, 155 | RequestStoreSalesDataResponse: 2537, 156 | RequestStoreSalesDataUpToDateResponse: 2538, 157 | GCToGCPingRequest: 2539, 158 | GCToGCPingResponse: 2540, 159 | GCToGCGetUserSessionServer: 2541, 160 | GCToGCGetUserSessionServerResponse: 2542, 161 | GCToGCGetUserServerMembers: 2543, 162 | GCToGCGetUserServerMembersResponse: 2544, 163 | GCToGCGrantSelfMadeItemToAccount: 2555, 164 | GCToGCThankedByNewUser: 2556, 165 | ShuffleCrateContents: 2557, 166 | 167 | // EGCBaseClientMsg 168 | PingRequest: 3001, 169 | PingResponse: 3002, 170 | ClientWelcome: 4004, 171 | ServerWelcome: 4005, 172 | ClientHello: 4006, 173 | ServerHello: 4007, 174 | ClientGoodbye: 4008, 175 | ServerGoodbye: 4009, 176 | 177 | // EGCBaseMsg 178 | SystemMessage: 4001, 179 | ReplicateConVars: 4002, 180 | ConVarUpdated: 4003, 181 | InviteToParty: 4501, 182 | InvitationCreated: 4502, 183 | PartyInviteResponse: 4503, 184 | KickFromParty: 4504, 185 | LeaveParty: 4505, 186 | ServerAvailable: 4506, 187 | ClientConnectToServer: 4507, 188 | GameServerInfo: 4508, 189 | Error: 4509, 190 | Replay_UploadedToYouTube: 4510, 191 | LANServerAvailable: 4511, 192 | 193 | // ETFGCMsg 194 | ReportWarKill: 5001, 195 | VoteKickBanPlayer: 5018, 196 | VoteKickBanPlayerResult: 5019, 197 | KickPlayer_DEPRECATED: 5020, 198 | StartedTraining_DEPRECATED: 5021, 199 | FreeTrial_ChooseMostHelpfulFriend: 5022, 200 | RequestTF2Friends: 5023, 201 | RequestTF2FriendsResponse: 5024, 202 | Replay_SubmitContestEntry: 5026, 203 | Replay_SubmitContestEntryResponse: 5027, 204 | Saxxy_Awarded: 5029, 205 | FreeTrial_ThankedBySomeone: 5028, 206 | FreeTrial_ThankedSomeone: 5030, 207 | FreeTrial_ConvertedToPremium: 5031, 208 | MeetThePyroSilliness_BananaCraft_DEPRECATED: 5032, 209 | MVMARG_HighFiveSuccessResponse_DEPRECATED: 5033, 210 | MVMARG_HighFiveOnClient_DEPRECATED: 5034, 211 | Coaching_AddToCoaches: 5200, 212 | Coaching_AddToCoachesResponse: 5201, 213 | Coaching_RemoveFromCoaches: 5202, 214 | Coaching_RemoveFromCoachesResponse: 5203, 215 | Coaching_FindCoach: 5204, 216 | Coaching_FindCoachResponse: 5205, 217 | Coaching_AskCoach: 5206, 218 | Coaching_AskCoachResponse: 5207, 219 | Coaching_CoachJoinGame: 5208, 220 | Coaching_CoachJoining: 5209, 221 | Coaching_CoachJoined: 5210, 222 | Coaching_LikeCurrentCoach: 5211, 223 | Coaching_RemoveCurrentCoach: 5212, 224 | Coaching_AlreadyRatedCoach: 5213, 225 | Duel_Request: 5500, 226 | Duel_Response: 5501, 227 | Duel_Results: 5502, 228 | Duel_Status: 5503, 229 | Halloween_ReservedItem_DEPRECATED: 5600, 230 | Halloween_GrantItem_DEPRECATED: 5601, 231 | Halloween_GrantItemResponse_DEPRECATED: 5604, 232 | Halloween_Cheat_QueryResponse_DEPRECATED: 5605, 233 | Halloween_ItemClaimed_DEPRECATED: 5606, 234 | Halloween_ReservedItem: 5607, 235 | Halloween_GrantItem: 5608, 236 | Halloween_GrantItemResponse: 5609, 237 | Halloween_Cheat_QueryResponse_DEPRECATED_2: 5610, 238 | Halloween_ItemClaimed_DEPRECATED_2: 5611, 239 | Halloween_ServerBossEvent: 5612, 240 | Halloween_Merasmus2012: 5613, 241 | Halloween_UpdateMerasmusLootLevel: 5614, 242 | GameServer_LevelInfo: 5700, 243 | GameServer_AuthChallenge: 5701, 244 | GameServer_AuthChallengeResponse: 5702, 245 | GameServer_CreateIdentity: 5703, 246 | GameServer_CreateIdentityResponse: 5704, 247 | GameServer_List: 5705, 248 | GameServer_ListResponse: 5706, 249 | GameServer_AuthResult: 5707, 250 | GameServer_ResetIdentity: 5708, 251 | GameServer_ResetIdentityResponse: 5709, 252 | Client_UseServerModificationItem: 5710, 253 | Client_UseServerModificationItem_Response: 5711, 254 | GameServer_UseServerModificationItem: 5712, 255 | GameServer_UseServerModificationItem_Response: 5713, 256 | GameServer_ServerModificationItemExpired: 5714, 257 | GameServer_ModificationItemState: 5715, 258 | GameServer_AckPolicy: 5716, 259 | GameServer_AckPolicyResponse: 5717, 260 | QP_ScoreServers: 5800, 261 | QP_ScoreServersResponse: 5801, 262 | QP_PlayerJoining: 5802, 263 | PickupItemEligibility_Query_DEPRECATED: 6000, 264 | PickupItemEligibility_Query_DEPRECATED_2: 6001, 265 | IncrementKillCountAttribute_DEPRECATED: 6100, 266 | IncrementKillCountResponse_DEPRECATED: 6101, 267 | GameMatchSignOut: 6204, 268 | CreateOrUpdateParty: 6233, 269 | AbandonCurrentGame: 6235, 270 | EMsgForceSOCacheResend: 6237, 271 | RequestChatChannelList: 6260, 272 | RequestChatChannelListResponse: 6261, 273 | ReadyUp: 6270, 274 | KickedFromMatchmakingQueue: 6271, 275 | LeaverDetected: 6272, 276 | LeaverDetectedResponse: 6287, 277 | PlayerFailedToConnect: 6288, 278 | ExitMatchmaking: 6289, 279 | AcceptInvite: 6291, 280 | AcceptInviteResponse: 6292, 281 | MatchmakingProgress: 6293, 282 | MvMVictoryInfo: 6294, 283 | GameServerMatchmakingStatus: 6295, 284 | CreateOrUpdatePartyReply: 6296, 285 | MvMVictory: 6297, 286 | MvMVictoryReply: 6298, 287 | GameServerKickingLobby: 6299, 288 | LeaveGameAndPrepareToJoinParty: 6300, 289 | RemovePlayerFromLobby: 6301, 290 | SetLobbySafeToLeave: 6302, 291 | UpdatePeriodicEvent: 6400, 292 | ClientVerificationChallenge: 6500, 293 | ClientVerificationChallengeResponse: 6501, 294 | ClientVerificationVerboseResponse: 6502, 295 | ClientSetItemSlotAttribute: 6503, 296 | PlayerSkillRating_Adjustment: 6504, 297 | War_IndividualUpdate: 6505, 298 | War_JoinWar: 6506, 299 | War_RequestGlobalStats: 6507, 300 | War_GlobalStatsResponse: 6508, 301 | Dev_GrantWarKill: 10001 302 | }; 303 | -------------------------------------------------------------------------------- /protobufs/econ_gcmessages.proto: -------------------------------------------------------------------------------- 1 | import "steammessages.proto"; 2 | 3 | option optimize_for = SPEED; 4 | option cc_generic_services = false; 5 | 6 | enum EGCItemMsg { 7 | k_EMsgGCBase = 1000; 8 | k_EMsgGCSetSingleItemPosition = 1001; 9 | k_EMsgGCCraft = 1002; 10 | k_EMsgGCCraftResponse = 1003; 11 | k_EMsgGCDelete = 1004; 12 | k_EMsgGCVerifyCacheSubscription = 1005; 13 | k_EMsgGCNameItem = 1006; 14 | k_EMsgGCUnlockCrate = 1007; 15 | k_EMsgGCUnlockCrateResponse = 1008; 16 | k_EMsgGCPaintItem = 1009; 17 | k_EMsgGCPaintItemResponse = 1010; 18 | k_EMsgGCGoldenWrenchBroadcast = 1011; 19 | k_EMsgGCMOTDRequest = 1012; 20 | k_EMsgGCMOTDRequestResponse = 1013; 21 | k_EMsgGCNameBaseItem = 1019; 22 | k_EMsgGCNameBaseItemResponse = 1020; 23 | k_EMsgGCRemoveSocketItem_DEPRECATED = 1021; 24 | k_EMsgGCRemoveSocketItemResponse_DEPRECATED = 1022; 25 | k_EMsgGCCustomizeItemTexture = 1023; 26 | k_EMsgGCCustomizeItemTextureResponse = 1024; 27 | k_EMsgGCUseItemRequest = 1025; 28 | k_EMsgGCUseItemResponse = 1026; 29 | k_EMsgGCRespawnPostLoadoutChange = 1029; 30 | k_EMsgGCRemoveItemName = 1030; 31 | k_EMsgGCRemoveItemPaint = 1031; 32 | k_EMsgGCGiftWrapItem = 1032; 33 | k_EMsgGCGiftWrapItemResponse = 1033; 34 | k_EMsgGCDeliverGift = 1034; 35 | k_EMsgGCDeliverGiftResponseReceiver = 1036; 36 | k_EMsgGCUnwrapGiftRequest = 1037; 37 | k_EMsgGCUnwrapGiftResponse = 1038; 38 | k_EMsgGCSetItemStyle = 1039; 39 | k_EMsgGCUsedClaimCodeItem = 1040; 40 | k_EMsgGCSortItems = 1041; 41 | k_EMsgGC_RevolvingLootList_DEPRECATED = 1042; 42 | k_EMsgGCLookupAccount = 1043; 43 | k_EMsgGCLookupAccountResponse = 1044; 44 | k_EMsgGCLookupAccountName = 1045; 45 | k_EMsgGCLookupAccountNameResponse = 1046; 46 | k_EMsgGCUpdateItemSchema = 1049; 47 | k_EMsgGCRequestInventoryRefresh = 1050; 48 | k_EMsgGCRemoveCustomTexture = 1051; 49 | k_EMsgGCRemoveCustomTextureResponse = 1052; 50 | k_EMsgGCRemoveMakersMark = 1053; 51 | k_EMsgGCRemoveMakersMarkResponse = 1054; 52 | k_EMsgGCRemoveUniqueCraftIndex = 1055; 53 | k_EMsgGCRemoveUniqueCraftIndexResponse = 1056; 54 | k_EMsgGCSaxxyBroadcast = 1057; 55 | k_EMsgGCBackpackSortFinished = 1058; 56 | k_EMsgGCAdjustItemEquippedState = 1059; 57 | k_EMsgGCCollectItem = 1061; 58 | k_EMsgGCItemAcknowledged = 1062; 59 | k_EMsgGCPresets_SelectPresetForClass = 1063; 60 | k_EMsgGCPresets_SetItemPosition = 1064; 61 | k_EMsgGC_ReportAbuse = 1065; 62 | k_EMsgGC_ReportAbuseResponse = 1066; 63 | k_EMsgGCPresets_SelectPresetForClassReply = 1067; 64 | k_EMsgGCNameItemNotification = 1068; 65 | k_EMsgGCClientDisplayNotification = 1069; 66 | k_EMsgGCApplyStrangePart = 1070; 67 | k_EMsgGC_IncrementKillCountAttribute = 1071; 68 | k_EMsgGC_IncrementKillCountResponse = 1072; 69 | k_EMsgGCRemoveStrangePart = 1073; 70 | k_EMsgGCResetStrangeScores = 1074; 71 | k_EMsgGCGiftedItems = 1075; 72 | k_EMsgGCApplyUpgradeCard = 1077; 73 | k_EMsgGCRemoveUpgradeCard = 1078; 74 | k_EMsgGCApplyStrangeRestriction = 1079; 75 | k_EMsgGCClientRequestMarketData = 1080; 76 | k_EMsgGCClientRequestMarketDataResponse = 1081; 77 | k_EMsgGCApplyXifier = 1082; 78 | k_EMsgGCApplyXifierResponse = 1083; 79 | k_EMsgGC_TrackUniquePlayerPairEvent = 1084; 80 | k_EMsgGCFulfillDynamicRecipeComponent = 1085; 81 | k_EMsgGCFulfillDynamicRecipeComponentResponse = 1086; 82 | k_EMsgGCSetItemEffectVerticalOffset = 1087; 83 | k_EMsgGCSetHatEffectUseHeadOrigin = 1088; 84 | k_EMsgGCItemEaterRecharger = 1089; 85 | k_EMsgGCItemEaterRechargerResponse = 1090; 86 | k_EMsgGCApplyBaseItemXifier = 1091; 87 | k_EMsgGCApplyClassTransmogrifier = 1092; 88 | k_EMsgGCApplyHalloweenSpellbookPage = 1093; 89 | k_EMsgGCRemoveKillStreak = 1094; 90 | k_EMsgGCRemoveKillStreakResponse = 1095; 91 | k_EMsgGCTFSpecificItemBroadcast = 1096; 92 | k_EMsgGC_IncrementKillCountAttribute_Multiple = 1097; 93 | k_EMsgGCDeliverGiftResponseGiver = 1098; 94 | k_EMsgGCSetItemPositions = 1100; 95 | k_EMsgGCLookupMultipleAccountNames = 1101; 96 | k_EMsgGCLookupMultipleAccountNamesResponse = 1102; 97 | k_EMsgGCTradingBase = 1500; 98 | k_EMsgGCTrading_InitiateTradeRequest = 1501; 99 | k_EMsgGCTrading_InitiateTradeResponse = 1502; 100 | k_EMsgGCTrading_StartSession = 1503; 101 | k_EMsgGCTrading_SessionClosed = 1509; 102 | k_EMsgGCTrading_CancelSession = 1510; 103 | k_EMsgGCTrading_InitiateTradeRequestResponse = 1514; 104 | k_EMsgGCServerBrowser_FavoriteServer = 1601; 105 | k_EMsgGCServerBrowser_BlacklistServer = 1602; 106 | k_EMsgGCServerRentalsBase = 1700; 107 | k_EMsgGCItemPreviewCheckStatus = 1701; 108 | k_EMsgGCItemPreviewStatusResponse = 1702; 109 | k_EMsgGCItemPreviewRequest = 1703; 110 | k_EMsgGCItemPreviewRequestResponse = 1704; 111 | k_EMsgGCItemPreviewExpire = 1705; 112 | k_EMsgGCItemPreviewExpireNotification = 1706; 113 | k_EMsgGCItemPreviewItemBoughtNotification = 1708; 114 | k_EMsgGCDev_NewItemRequest = 2001; 115 | k_EMsgGCDev_NewItemRequestResponse = 2002; 116 | k_EMsgGCDev_DebugRollLootRequest = 2003; 117 | k_EMsgGCStoreGetUserData = 2500; 118 | k_EMsgGCStoreGetUserDataResponse = 2501; 119 | k_EMsgGCStorePurchaseInit_DEPRECATED = 2502; 120 | k_EMsgGCStorePurchaseInitResponse_DEPRECATED = 2503; 121 | k_EMsgGCStorePurchaseFinalize = 2512; 122 | k_EMsgGCStorePurchaseFinalizeResponse = 2513; 123 | k_EMsgGCStorePurchaseCancel = 2514; 124 | k_EMsgGCStorePurchaseCancelResponse = 2515; 125 | k_EMsgGCStorePurchaseQueryTxn = 2508; 126 | k_EMsgGCStorePurchaseQueryTxnResponse = 2509; 127 | k_EMsgGCStorePurchaseInit = 2510; 128 | k_EMsgGCStorePurchaseInitResponse = 2511; 129 | k_EMsgGCToGCDirtySDOCache = 2516; 130 | k_EMsgGCToGCDirtyMultipleSDOCache = 2517; 131 | k_EMsgGCToGCUpdateSQLKeyValue = 2518; 132 | k_EMsgGCToGCBroadcastConsoleCommand = 2521; 133 | k_EMsgGCServerVersionUpdated = 2522; 134 | k_EMsgGCApplyAutograph = 2523; 135 | k_EMsgGCToGCWebAPIAccountChanged = 2524; 136 | k_EMsgGCRequestAnnouncements = 2525; 137 | k_EMsgGCRequestAnnouncementsResponse = 2526; 138 | k_EMsgGCRequestPassportItemGrant = 2527; 139 | k_EMsgGCClientVersionUpdated = 2528; 140 | k_EMsgGCItemPurgatory_FinalizePurchase = 2531; 141 | k_EMsgGCItemPurgatory_FinalizePurchaseResponse = 2532; 142 | k_EMsgGCItemPurgatory_RefundPurchase = 2533; 143 | k_EMsgGCItemPurgatory_RefundPurchaseResponse = 2534; 144 | k_EMsgGCToGCPlayerStrangeCountAdjustments = 2535; 145 | k_EMsgGCRequestStoreSalesData = 2536; 146 | k_EMsgGCRequestStoreSalesDataResponse = 2537; 147 | k_EMsgGCRequestStoreSalesDataUpToDateResponse = 2538; 148 | k_EMsgGCToGCPingRequest = 2539; 149 | k_EMsgGCToGCPingResponse = 2540; 150 | k_EMsgGCToGCGetUserSessionServer = 2541; 151 | k_EMsgGCToGCGetUserSessionServerResponse = 2542; 152 | k_EMsgGCToGCGetUserServerMembers = 2543; 153 | k_EMsgGCToGCGetUserServerMembersResponse = 2544; 154 | k_EMsgGCToGCGrantSelfMadeItemToAccount = 2555; 155 | k_EMsgGCToGCThankedByNewUser = 2556; 156 | k_EMsgGCShuffleCrateContents = 2557; 157 | k_EMsgGCQuestObjective_Progress = 2558; 158 | k_EMsgGCQuestCompleted = 2559; 159 | k_EMsgGCApplyDuckToken = 2560; 160 | k_EMsgGCQuestObjective_PointsChange = 2562; 161 | k_EMsgGCQuestObjective_RequestLoanerItems = 2564; 162 | k_EMsgGCQuestObjective_RequestLoanerResponse = 2565; 163 | k_EMsgGCApplyStrangeCountTransfer = 2566; 164 | k_EMsgGCCraftCollectionUpgrade = 2567; 165 | k_EMsgGCCraftHalloweenOffering = 2568; 166 | k_EMsgGCQuestDiscard_Request = 2569; 167 | k_EMsgGCRemoveGiftedBy = 2570; 168 | k_EMsgGCRemoveGiftedByResponse = 2571; 169 | k_EMsgGCRemoveFestivizer = 2572; 170 | k_EMsgGCRemoveFestivizerResponse = 2573; 171 | k_EMsgGCCraftCommonStatClock = 2574; 172 | } 173 | 174 | enum EGCMsgResponse { 175 | k_EGCMsgResponseOK = 0; 176 | k_EGCMsgResponseDenied = 1; 177 | k_EGCMsgResponseServerError = 2; 178 | k_EGCMsgResponseTimeout = 3; 179 | k_EGCMsgResponseInvalid = 4; 180 | k_EGCMsgResponseNoMatch = 5; 181 | k_EGCMsgResponseUnknownError = 6; 182 | k_EGCMsgResponseNotLoggedOn = 7; 183 | k_EGCMsgFailedToCreate = 8; 184 | } 185 | 186 | enum EUnlockStyle { 187 | k_UnlockStyle_Succeeded = 0; 188 | k_UnlockStyle_Failed_PreReq = 1; 189 | k_UnlockStyle_Failed_CantAfford = 2; 190 | k_UnlockStyle_Failed_CantCommit = 3; 191 | k_UnlockStyle_Failed_CantLockCache = 4; 192 | k_UnlockStyle_Failed_CantAffordAttrib = 5; 193 | k_UnlockStyle_Failed_CantAffordGem = 6; 194 | } 195 | 196 | enum EItemPurgatoryResponse_Finalize { 197 | k_ItemPurgatoryResponse_Finalize_Succeeded = 0; 198 | k_ItemPurgatoryResponse_Finalize_Failed_Incomplete = 1; 199 | k_ItemPurgatoryResponse_Finalize_Failed_ItemsNotInPurgatory = 2; 200 | k_ItemPurgatoryResponse_Finalize_Failed_CouldNotFindItems = 3; 201 | k_ItemPurgatoryResponse_Finalize_Failed_NoSOCache = 4; 202 | k_ItemPurgatoryResponse_Finalize_BackpackFull = 5; 203 | } 204 | 205 | enum EItemPurgatoryResponse_Refund { 206 | k_ItemPurgatoryResponse_Refund_Succeeded = 0; 207 | k_ItemPurgatoryResponse_Refund_Failed_ItemNotInPurgatory = 1; 208 | k_ItemPurgatoryResponse_Refund_Failed_CouldNotFindItem = 2; 209 | k_ItemPurgatoryResponse_Refund_Failed_NoSOCache = 3; 210 | k_ItemPurgatoryResponse_Refund_Failed_NoDetail = 4; 211 | k_ItemPurgatoryResponse_Refund_Failed_NexonWebAPI = 5; 212 | } 213 | 214 | message CMsgApplyAutograph { 215 | optional uint64 autograph_item_id = 1; 216 | optional uint64 item_item_id = 2; 217 | } 218 | 219 | message CMsgEconPlayerStrangeCountAdjustment { 220 | message CStrangeCountAdjustment { 221 | optional uint32 event_type = 1; 222 | optional uint64 item_id = 2; 223 | optional uint32 adjustment = 3; 224 | } 225 | 226 | optional uint32 account_id = 1; 227 | repeated .CMsgEconPlayerStrangeCountAdjustment.CStrangeCountAdjustment strange_count_adjustments = 2; 228 | } 229 | 230 | message CMsgRequestItemPurgatory_FinalizePurchase { 231 | repeated uint64 item_ids = 1; 232 | } 233 | 234 | message CMsgRequestItemPurgatory_FinalizePurchaseResponse { 235 | optional uint32 result = 1; 236 | } 237 | 238 | message CMsgRequestItemPurgatory_RefundPurchase { 239 | optional uint64 item_id = 1; 240 | } 241 | 242 | message CMsgRequestItemPurgatory_RefundPurchaseResponse { 243 | optional uint32 result = 1; 244 | } 245 | 246 | message CMsgCraftingResponse { 247 | repeated uint64 item_ids = 1; 248 | } 249 | 250 | message CMsgGCRequestStoreSalesData { 251 | optional uint32 version = 1; 252 | optional uint32 currency = 2; 253 | } 254 | 255 | message CMsgGCRequestStoreSalesDataResponse { 256 | message Price { 257 | optional uint32 item_def = 1; 258 | optional uint32 price = 2; 259 | } 260 | 261 | repeated .CMsgGCRequestStoreSalesDataResponse.Price sale_price = 1; 262 | optional uint32 version = 2; 263 | optional uint32 expiration_time = 3; 264 | } 265 | 266 | message CMsgGCRequestStoreSalesDataUpToDateResponse { 267 | optional uint32 version = 1; 268 | optional uint32 expiration_time = 2; 269 | } 270 | 271 | message CMsgGCToGCPingRequest { 272 | } 273 | 274 | message CMsgGCToGCPingResponse { 275 | } 276 | 277 | message CMsgGCToGCGetUserSessionServer { 278 | optional uint32 account_id = 1; 279 | } 280 | 281 | message CMsgGCToGCGetUserSessionServerResponse { 282 | optional fixed64 server_steam_id = 1; 283 | } 284 | 285 | message CMsgGCToGCGetUserServerMembers { 286 | optional uint32 account_id = 1; 287 | optional uint32 max_spectators = 2; 288 | } 289 | 290 | message CMsgGCToGCGetUserServerMembersResponse { 291 | repeated uint32 member_account_id = 1; 292 | } 293 | 294 | message CMsgLookupMultipleAccountNames { 295 | repeated uint32 accountids = 1 [packed = true]; 296 | } 297 | 298 | message CMsgLookupMultipleAccountNamesResponse { 299 | message Account { 300 | optional uint32 accountid = 1; 301 | optional string persona = 2; 302 | } 303 | 304 | repeated .CMsgLookupMultipleAccountNamesResponse.Account accounts = 1; 305 | } 306 | 307 | message CMsgGCToGCGrantSelfMadeItemToAccount { 308 | optional uint32 item_def_index = 1; 309 | optional uint32 accountid = 2; 310 | } 311 | 312 | message CMsgGCToGCThankedByNewUser { 313 | optional uint32 new_user_accountid = 1; 314 | optional uint32 thanked_user_accountid = 2; 315 | } 316 | 317 | message CMsgGCShuffleCrateContents { 318 | optional uint64 crate_item_id = 1; 319 | optional string user_code_string = 2; 320 | } 321 | 322 | message CMsgGCQuestObjective_Progress { 323 | optional uint64 quest_id = 1; 324 | optional uint32 quest_attrib_index = 2; 325 | optional uint32 delta = 3; 326 | optional fixed64 owner_steamid = 4; 327 | } 328 | 329 | message CMsgGCQuestObjective_PointsChange { 330 | optional uint64 quest_id = 1; 331 | optional fixed64 owner_steamid = 4; 332 | optional bool update_base_points = 5 [default = false]; 333 | optional uint32 points_0 = 6; 334 | optional uint32 points_1 = 7; 335 | optional uint32 points_2 = 8; 336 | } 337 | 338 | message CMsgGCQuestComplete_Request { 339 | optional uint64 quest_id = 1; 340 | } 341 | 342 | message CMsgGCQuestCompleted { 343 | } 344 | 345 | message CMsgGCQuestObjective_RequestLoanerItems { 346 | optional uint64 quest_id = 1; 347 | } 348 | 349 | message CMsgGCQuestObjective_RequestLoanerResponse { 350 | } 351 | 352 | message CMsgCraftCollectionUpgrade { 353 | repeated uint64 item_id = 1; 354 | } 355 | 356 | message CMsgCraftHalloweenOffering { 357 | optional uint64 tool_id = 1; 358 | repeated uint64 item_id = 2; 359 | } 360 | 361 | message CMsgCraftCommonStatClock { 362 | optional uint64 tool_id = 1; 363 | repeated uint64 item_id = 2; 364 | } 365 | 366 | message CMsgGCQuestDiscard_Request { 367 | optional uint64 quest_id = 1; 368 | } 369 | 370 | -------------------------------------------------------------------------------- /handlers.js: -------------------------------------------------------------------------------- 1 | const ByteBuffer = require('bytebuffer'); 2 | const {HttpClient} = require('@doctormckay/stdlib/http'); 3 | const SteamID = require('steamid'); 4 | const VDF = require('kvparser'); 5 | 6 | const TeamFortress2 = require('./index.js'); 7 | const Language = require('./language.js'); 8 | const Schema = require('./protobufs/generated/_load.js'); 9 | 10 | const handlers = TeamFortress2.prototype._handlers; 11 | 12 | // ClientWelcome, ServerWelcome, ClientGoodbye, and ServerGoodbye 13 | handlers[Language.ClientWelcome] = function(body) { 14 | let proto = decodeProto(Schema.CMsgClientWelcome, body); 15 | this.haveGCSession = true; 16 | this.emit('connectedToGC', proto.version); 17 | }; 18 | 19 | handlers[Language.ServerWelcome] = function(body) { 20 | let proto = decodeProto(Schema.CMsgServerWelcome, body); 21 | this.haveGCSession = true; 22 | this.emit('connectedToGC', proto.active_version); 23 | }; 24 | 25 | handlers[Language.ClientGoodbye] = function(body) { 26 | let proto = decodeProto(Schema.CMsgClientGoodbye, body); 27 | 28 | if (this.haveGCSession) { 29 | this._connect(); // Try to reconnect 30 | this.haveGCSession = false; 31 | } 32 | 33 | this.emit('disconnectedFromGC', proto.reason); 34 | }; 35 | 36 | handlers[Language.ServerGoodbye] = function(body) { 37 | let proto = decodeProto(Schema.CMsgServerGoodbye, body); 38 | 39 | if (this.haveGCSession) { 40 | this._connect(); // Try to reconnect 41 | this.haveGCSession = false; 42 | } 43 | 44 | this.emit('disconnectedFromGC', proto.reason); 45 | }; 46 | 47 | // Item schema 48 | handlers[Language.UpdateItemSchema] = async function(body) { 49 | try { 50 | let proto = decodeProto(Schema.CMsgUpdateItemSchema, body); 51 | this.emit('itemSchema', proto.item_schema_version.toString(16).toUpperCase(), proto.items_game_url); 52 | 53 | let client = new HttpClient(); 54 | let result = await client.request({ 55 | method: 'get', 56 | url: proto.items_game_url 57 | }); 58 | 59 | if (result.statusCode != 200) { 60 | throw new Error(`HTTP error ${result.statusCode}`); 61 | } 62 | 63 | this.itemSchema = VDF.parse(result.textBody).items_game; 64 | this.emit('itemSchemaLoaded'); 65 | } catch (err) { 66 | this.emit('debug', `Unable to download items_game.txt: ${err.message}`); 67 | this.emit('itemSchemaError', err); 68 | } 69 | }; 70 | 71 | // Various notifications (why do we need three distinct interfaces??) 72 | handlers[Language.SystemMessage] = function(body) { 73 | let proto = decodeProto(Schema.CMsgSystemBroadcast, body); 74 | this.emit('systemMessage', proto.message); 75 | }; 76 | 77 | handlers[Language.ClientDisplayNotification] = function(body) { 78 | if (!this.lang) { 79 | // We only handle this if we have a localization file 80 | return; 81 | } 82 | 83 | let proto = decodeProto(Schema.CMsgGCClientDisplayNotification, body); 84 | let title = this.lang[proto.notification_title_localization_key.substring(1)]; 85 | let text = (this.lang[proto.notification_body_localization_key.substring(1)] || '').replace(new RegExp('[\u0001|\u0002]', 'g'), ''); 86 | text = text.replace(/\\"/g, '"'); // The vdf parser appears to not properly parse escaped quotes 87 | 88 | let replacement; 89 | for (let i = 0; i < proto.body_substring_keys.length; i++) { 90 | replacement = proto.body_substring_values[i]; 91 | if (replacement.charAt(0) == '#') { 92 | replacement = this.lang[replacement.substring(1)]; 93 | } 94 | 95 | text = text.replace('%' + proto.body_substring_keys[i] + '%', replacement); 96 | } 97 | 98 | this.emit('displayNotification', title, text); 99 | }; 100 | 101 | handlers[Language.TFSpecificItemBroadcast] = function(body) { 102 | let proto = decodeProto(Schema.CMsgGCTFSpecificItemBroadcast, body); 103 | let defindex = proto.item_def_index; 104 | 105 | let message = null; 106 | 107 | if (this.lang && this.itemSchema) { 108 | let item = this.itemSchema.items[defindex] || {}; 109 | let itemNameKey = item.item_name || ''; 110 | let itemName = this.lang[itemNameKey.substring(1)]; 111 | 112 | let localizationKey = proto.was_destruction ? "TF_Event_Item_Deleted" : "TF_Event_Item_Created"; 113 | message = this.lang[localizationKey].replace('%owner%', proto.user_name).replace('%item_name%', itemName); 114 | } 115 | 116 | this.emit('itemBroadcast', message, proto.user_name, proto.was_destruction, defindex); 117 | }; 118 | 119 | // Trading 120 | handlers[Language.Trading_InitiateTradeRequest] = function(body) { 121 | let tradeID = body.readUint32(); 122 | let steamID = new SteamID(body.readUint64().toString()); 123 | this.emit('tradeRequest', steamID, tradeID); 124 | }; 125 | 126 | handlers[Language.Trading_InitiateTradeResponse] = function(body) { 127 | let response = body.readUint32(); 128 | let tradeID = body.readUint32(); 129 | this.emit('debug', "Got trade response " + response + " for " + tradeID); 130 | this.emit('tradeResponse', response, tradeID); 131 | }; 132 | 133 | // SO 134 | handlers[Language.SO_CacheSubscriptionCheck] = function(body) { 135 | this.emit('debug', "Requesting SO cache subscription refresh"); 136 | this._send(Language.SO_CacheSubscriptionRefresh, Schema.CMsgSOCacheSubscriptionRefresh, {"owner": this._steam.steamID.getSteamID64()}); 137 | }; 138 | 139 | handlers[Language.SO_CacheSubscribed] = function(body) { 140 | let proto = decodeProto(Schema.CMsgSOCacheSubscribed, body); 141 | proto.objects.forEach((cache) => { 142 | switch (cache.type_id) { 143 | case 1: 144 | // Backpack 145 | let items = cache.object_data.map((object) => { 146 | let item = decodeProto(Schema.CSOEconItem, object); 147 | let isNew = (item.inventory >>> 30) & 1; 148 | item.position = (isNew ? 0 : item.inventory & 0xFFFF); 149 | return item; 150 | }); 151 | 152 | this.backpack = items; 153 | this.emit('backpackLoaded'); 154 | break; 155 | case 7: 156 | // Account metadata 157 | let data = decodeProto(Schema.CSOEconGameAccountClient, cache.object_data[0]); 158 | this.premium = !data.trial_account; 159 | this.backpackSlots = (data.trial_account ? 50 : 300) + data.additional_backpack_slots; 160 | this.canSendProfessorSpeks = data.need_to_choose_most_helpful_friend; 161 | this.emit('accountLoaded'); 162 | break; 163 | default: 164 | this.emit('debug', "Unknown SO type " + cache.type_id + " with " + cache.object_data.length + " items"); 165 | break; 166 | } 167 | }); 168 | }; 169 | 170 | handlers[Language.SO_Create] = function(body) { 171 | let proto = decodeProto(Schema.CMsgSOSingleObject, body); 172 | if (proto.type_id != 1) { 173 | return; // Not an item 174 | } 175 | 176 | if (!this.backpack) { 177 | return; // We don't have our backpack yet! 178 | } 179 | 180 | let item = decodeProto(Schema.CSOEconItem, proto.object_data); 181 | item.position = item.inventory & 0x0000FFFF; 182 | this.backpack.push(item); 183 | this.emit('itemAcquired', item); 184 | }; 185 | 186 | handlers[Language.SO_Update] = function(body) { 187 | let proto = decodeProto(Schema.CMsgSOSingleObject, body); 188 | this._handleSOUpdate(proto); 189 | }; 190 | 191 | handlers[Language.SO_UpdateMultiple] = function(body) { 192 | let items = decodeProto(Schema.CMsgSOMultipleObjects, body).objects; 193 | 194 | items.forEach((item) => { 195 | this._handleSOUpdate(item); 196 | }); 197 | }; 198 | 199 | TeamFortress2.prototype._handleSOUpdate = function(so) { 200 | switch (so.type_id) { 201 | case 1: 202 | if (!this.backpack) { 203 | return; // We don't have our backpack yet! 204 | } 205 | 206 | let item = decodeProto(Schema.CSOEconItem, so.object_data); 207 | item.position = item.inventory & 0x0000FFFF; 208 | for (let i = 0; i < this.backpack.length; i++) { 209 | if (this.backpack[i].id == item.id) { 210 | let oldItem = this.backpack[i]; 211 | this.backpack[i] = item; 212 | 213 | this.emit('itemChanged', oldItem, item); 214 | break; 215 | } 216 | } 217 | 218 | break; 219 | case 7: 220 | let data = decodeProto(Schema.CSOEconGameAccountClient, so.object_data); 221 | let oldData = { 222 | "premium": this.premium, 223 | "backpackSlots": this.backpackSlots, 224 | "canSendProfessorSpeks": this.canSendProfessorSpeks 225 | }; 226 | 227 | this.premium = !data.trial_account; 228 | this.backpackSlots = (data.trial_account ? 50 : 300) + data.additional_backpack_slots; 229 | this.canSendProfessorSpeks = data.need_to_choose_most_helpful_friend; 230 | 231 | let changed = {}; 232 | let somethingHasChanged = false; 233 | for (let i in oldData) { 234 | if (this[i] != oldData[i]) { 235 | somethingHasChanged = true; 236 | changed[i] = oldData[i]; 237 | } 238 | } 239 | 240 | if (somethingHasChanged) { 241 | // Only emit the event if a property that we're tracking changes 242 | this.emit('accountUpdate', changed); 243 | } 244 | 245 | break; 246 | default: 247 | this.emit('debug', "Unknown SO type " + so.type_id + " updated"); 248 | break; 249 | } 250 | }; 251 | 252 | handlers[Language.SO_Destroy] = function(body) { 253 | let proto = decodeProto(Schema.CMsgSOSingleObject, body); 254 | if (proto.type_id != 1) { 255 | return; // Not an item 256 | } 257 | 258 | if (!this.backpack) { 259 | return; // We don't have our backpack yet 260 | } 261 | 262 | let item = decodeProto(Schema.CSOEconItem, proto.object_data); 263 | let itemData = null; 264 | for (let i = 0; i < this.backpack.length; i++) { 265 | if (this.backpack[i].id == item.id) { 266 | itemData = this.backpack[i]; 267 | this.backpack.splice(i, 1); 268 | break; 269 | } 270 | } 271 | 272 | this.emit('itemRemoved', itemData); 273 | }; 274 | 275 | // Item manipulation 276 | handlers[Language.CraftResponse] = function(body) { 277 | let blueprint = body.readInt16(); // recipe ID 278 | let unknown = body.readUint32(); // always 0 in my experience 279 | 280 | let idCount = body.readUint16(); 281 | let idList = []; // let's form an array of IDs 282 | 283 | for (let i = 0; i < idCount; i++) { 284 | let id = body.readUint64().toString(); // grab the next id 285 | idList.push(id); // item id 286 | } 287 | 288 | this.emit('craftingComplete', blueprint, idList); 289 | }; 290 | 291 | // Professor Speks 292 | handlers[Language.FreeTrial_ThankedBySomeone] = function(body) { 293 | let proto = decodeProto(Schema.CMsgTFThankedBySomeone, body); 294 | this.emit('professorSpeksReceived', new SteamID(proto.thanker_steam_id)); 295 | }; 296 | 297 | handlers[Language.FreeTrial_ThankedSomeone] = function(body) { 298 | this.emit('professorSpeksSent'); 299 | }; 300 | 301 | // Game Servers 302 | handlers[Language.GameServer_CreateIdentityResponse] = function(body) { 303 | let proto = decodeProto(Schema.CMsgGC_GameServer_CreateIdentityResponse, body); 304 | this.emit('createIdentity', proto.status, proto.account_created, proto.game_server_account_id, proto.game_server_identity_token); 305 | }; 306 | 307 | handlers[Language.GameServer_ListResponse] = function(body) { 308 | let proto = decodeProto(Schema.CMsgGC_GameServer_ListResponse, body); 309 | this.emit('registeredServers', proto.owned_game_servers || []); 310 | }; 311 | 312 | handlers[Language.GameServer_ResetIdentityResponse] = function(body) { 313 | let proto = decodeProto(Schema.CMsgGC_GameServer_ResetIdentityResponse, body); 314 | this.emit('resetIdentity', proto.game_server_identity_token_reset, proto.game_server_account_id, proto.game_server_identity_token); 315 | }; 316 | 317 | // Spy vs. Engi War 318 | handlers[Language.War_GlobalStatsResponse] = function(body) { 319 | let proto = decodeProto(Schema.CGCMsgGC_War_GlobalStatsResponse, body); 320 | let mySides = {}; // they are in orbit 321 | (proto.side_scores || []).forEach((side) => { 322 | mySides[side.side] = side.score; 323 | }); 324 | 325 | this.emit('warStats', mySides); 326 | }; 327 | 328 | function decodeProto(proto, encoded) { 329 | if (ByteBuffer.isByteBuffer(encoded)) { 330 | encoded = encoded.toBuffer(); 331 | } 332 | 333 | let decoded = proto.decode(encoded); 334 | let objNoDefaults = proto.toObject(decoded, {"longs": String}); 335 | let objWithDefaults = proto.toObject(decoded, {"defaults": true, "longs": String}); 336 | return replaceDefaults(objNoDefaults, objWithDefaults); 337 | 338 | function replaceDefaults(noDefaults, withDefaults) { 339 | if (Array.isArray(withDefaults)) { 340 | return withDefaults.map((val, idx) => replaceDefaults(noDefaults[idx], val)); 341 | } 342 | 343 | for (let i in withDefaults) { 344 | if (!withDefaults.hasOwnProperty(i)) { 345 | continue; 346 | } 347 | 348 | if (withDefaults[i] && typeof withDefaults[i] === 'object' && !Buffer.isBuffer(withDefaults[i])) { 349 | // Covers both object and array cases, both of which will work 350 | // Won't replace empty arrays, but that's desired behavior 351 | withDefaults[i] = replaceDefaults(noDefaults[i], withDefaults[i]); 352 | } else if (typeof noDefaults[i] === 'undefined' && isReplaceableDefaultValue(withDefaults[i])) { 353 | withDefaults[i] = null; 354 | } 355 | } 356 | 357 | return withDefaults; 358 | } 359 | 360 | function isReplaceableDefaultValue(val) { 361 | if (Buffer.isBuffer(val) && val.length == 0) { 362 | // empty buffer is replaceable 363 | return true; 364 | } 365 | 366 | if (Array.isArray(val)) { 367 | // empty array is not replaceable (empty repeated fields) 368 | return false; 369 | } 370 | 371 | if (val === '0') { 372 | // Zero as a string is replaceable (64-bit integer) 373 | return true; 374 | } 375 | 376 | // Anything falsy is true 377 | return !val; 378 | } 379 | } 380 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Team Fortress 2 for Node.js 2 | [![npm version](https://img.shields.io/npm/v/tf2.svg)](https://npmjs.com/package/tf2) 3 | [![npm downloads](https://img.shields.io/npm/dm/tf2.svg)](https://npmjs.com/package/tf2) 4 | [![license](https://img.shields.io/npm/l/tf2.svg)](https://github.com/DoctorMcKay/node-tf2/blob/master/LICENSE) 5 | [![paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=N36YVAT42CZ4G&item_name=node%2dtf2¤cy_code=USD) 6 | 7 | This module provides a very flexible interface for interacting with the [Team Fortress 2](http://store.steampowered.com) 8 | Game Coordinator. It's designed to work with a [node-steam-user SteamUser](https://github.com/DoctorMcKay/node-steam-user) instance. 9 | 10 | **You will need steam-user v4.2.0 or later and Node.js v14 or later to use tf2 v4.** 11 | You will need steam-user v4.2.0 or later and Node.js v8 or later to use tf2 v3. 12 | 13 | # Setup 14 | 15 | First, install it from npm: 16 | 17 | $ npm install tf2 18 | 19 | Require the module and call its constructor with your SteamUser instance: 20 | 21 | ```js 22 | const SteamUser = require('steam-user'); 23 | const TeamFortress2 = require('tf2'); 24 | 25 | let user = new SteamUser(); 26 | let tf2 = new TeamFortress2(user); 27 | ``` 28 | 29 | To initialize your GC connection, just launch TF2 via SteamUser normally: 30 | 31 | ```js 32 | user.gamesPlayed([440]); 33 | ``` 34 | 35 | node-tf2 will emit a `connectedToGC` event when the game coordinator connection has been successfully established. 36 | You shouldn't try to do anything before you receive that event. 37 | 38 | # Enums 39 | 40 | There are some enums that are used by various methods and events. You can find them in `enums.js`. 41 | 42 | # Properties 43 | 44 | There are a few useful read-only properties available to you. 45 | 46 | ### haveGCSession 47 | 48 | `true` if we're currently connected to the GC, `false` otherwise. You should only call methods when we have an active GC session. 49 | 50 | ### itemSchema 51 | 52 | After `itemSchemaLoaded` is emitted, this is the object representation of the parsed items_game.txt file. Before that point, this is undefined. 53 | 54 | ### backpack 55 | 56 | After `backpackLoaded` is emitted, this is an array containing the contents of our backpack. Before that point, this is undefined. 57 | 58 | ### premium 59 | 60 | `true` if this account is Premium, `false` if it's F2P. This value is defined right before `accountLoaded` is emitted. 61 | 62 | ### backpackSlots 63 | 64 | The maximum number of items your backpack can hold. This value is defined right before `accountLoaded` is emitted. 65 | 66 | ### canSendProfessorSpeks 67 | 68 | `true` if you can call `sendProfessorSpeks` to send the [Professor Speks](http://wiki.teamfortress.com/wiki/Professor_Speks) item to another user. This value is defined right before `accountLoaded` is emitted. 69 | 70 | # Methods 71 | 72 | ### Constructor(steamClient) 73 | 74 | When instantiating your node-tf2 instance, you need to pass your active SteamUser instance as the sole parameter, as shown here: 75 | 76 | ```js 77 | let tf2 = new TeamFortress2(steamUser); 78 | ``` 79 | 80 | ### setLang(localizationFile) 81 | 82 | Call this method with the contents of an up-to-date localization file of your chosen language if you want localized events to be emitted. You can find the localization files under `tf/resource/tf_[language].txt`. 83 | 84 | You can call this at any time, even when disconnected. If you get an updated localization file, you can call this again to update the cached version. 85 | 86 | ### craft(items[, recipe]) 87 | 88 | Craft `items` together into a new item, optionally using a specific `recipe`. The `recipe` parameter is optional and you don't normally need to specify it. `items` should be an array of item IDs to craft. 89 | 90 | ### trade(steamID) 91 | 92 | Sends an in-game trade request to `steamID`. The other player must be playing TF2 currently. Listen for the `tradeResponse` 93 | event for their response. If they accept, node-steam-user will emit 94 | [`tradeRequest`](https://github.com/DoctorMcKay/node-steam-user#traderequest) and you can start the trade with 95 | [node-steam-trade](https://github.com/seishun/node-steam-trade). 96 | 97 | ### cancelTradeRequest() 98 | 99 | Cancels your current pending trade request. You can only send one trade request at a time so there is no need to pass any sort of identifier. 100 | 101 | ### respondToTrade(tradeID, accept) 102 | 103 | Responds to an incoming trade request identified by `tradeID`. Pass `true` for `accept` to accept the trade request, or `false` to decline it. 104 | 105 | ### setStyle(item, style) 106 | 107 | Sets the current `style` of an `item`. The `item` parameter should be an item ID, and the `style` parameter is the index of the desired style. 108 | 109 | ### setPosition(item, position) 110 | 111 | Sets the `position` of an `item` in the backpack. The first slot on page 1 is position 1. `item` should be an item ID. 112 | 113 | ### deleteItem(item) 114 | 115 | Deletes an `item`. The `item` parameter should be the ID of the item to delete. **This is a destructive operation.** 116 | 117 | ### wrapItem(wrapID, itemID) 118 | 119 | Wraps the item with ID `itemID` using the gift wrap with ID `wrapID`. 120 | 121 | ### deliverGift(gift, steamID) 122 | 123 | Sends a `gift` to a recipient with a `steamID`. The recipient doesn't need to be playing TF2. `gift` should be the ID of the wrapped gift item. 124 | 125 | ### unwrapGift(gift) 126 | 127 | Unwraps a `gift`. The `gift` parameter should be the ID of a received wrapped gift item. 128 | 129 | ### useItem(item) 130 | 131 | Generically use an item. The `item` parameter should be an item ID. 132 | 133 | ### sortBackpack(sortType) 134 | 135 | Sorts your backpack. `sortType` is the ID of the type of sort you want. I don't know which sort type is which code, so you'll have to figure that out for yourself. 136 | 137 | ### sendProfessorSpeks(steamID) 138 | 139 | If you're premium and you haven't sent them yet, this will thank a "helpful user" and grant them [Professor Speks](http://wiki.teamfortress.com/wiki/Professor_Speks). If they already have Speks, this will increment their "New Users Helped" counter. 140 | 141 | The `steamID` parameter should be the recipient's 64-bit steamID. The recipient does not need to be on your friends list or in-game. 142 | 143 | ### createServerIdentity() 144 | 145 | Creates a new GC gameserver identity account ID and token. Equivalent to running cl_gameserver_create_identity in the TF2 console. Listen for the `createIdentity` event for a response. 146 | 147 | ### getRegisteredServers() 148 | 149 | Requests a list of your GC gameserver identities. Equivalent to running cl_gameserver_list in the TF2 console. Listen for the `registeredServers` event for the response. 150 | 151 | ### resetServerIdentity(id) 152 | 153 | Resets the token of the server identified by a given `id`. This will make the GC generate a new token, invaliding the old one. Listen for the `resetIdentity` event for the response. 154 | 155 | ### openCrate(keyID, crateID) 156 | 157 | Opens a crate with `crateID` using a key with `keyID`. If successful, you'll get two `itemRemoved` events, one for the key and one for the crate, followed by an `itemAcquired` event for what you received. 158 | 159 | ### requestWarStats([warID][, callback]) 160 | - `warID` - A [war ID](https://github.com/DoctorMcKay/node-tf2/blob/3fa354b2c1224b5885d9b9eb2818d17f76454cd7/enums.js#L78-L80) (defaults to HeavyVsPyro) 161 | - `callback` - Identical to [`warStats`](#warstats) event 162 | 163 | Requests global stats for a particular War. 164 | 165 | # Events 166 | 167 | ### connectedToGC 168 | - `version` - The current version reported by the GC 169 | 170 | Emitted when a GC connection is established. You shouldn't use any methods before you receive this. Note that this may be received (after it's first emitted) without any disconnectedFromGC event being emitted. In this case, the GC simply restarted. 171 | 172 | ### disconnectedFromGC 173 | - `reason` - The reason why we disconnected from the GC. This value is one of the values in the `GCGoodbyeReason` enum. If the value is unknown, you'll get a string representation instead. 174 | 175 | Emitted when we disconnect from the GC. You shouldn't use any methods until `connectedToGC` is emitted. 176 | 177 | ### itemSchema 178 | - `version` - The current version of the schema as a hexadecimal string 179 | - `itemsGameUrl` - The URL to the current items_game.txt 180 | 181 | Emitted when we get an updated item schema from the GC. node-tf2 will automatically download and parse the updated items_game.txt and will emit `itemSchemaLoaded` when complete. 182 | 183 | ### itemSchemaLoaded 184 | 185 | Emitted when the up-to-date items_game.txt has been downloaded and parsed. It's available as `tf2.itemSchema`. 186 | 187 | ### itemSchemaError 188 | - `err` - The error that occurred 189 | 190 | Emitted if there was an error when downloading items_game.txt. 191 | 192 | ### systemMessage 193 | - `message` - The message that was broadcast 194 | 195 | Emitted when a system message is sent by Valve. In the official client, this is displayed as a regular pop-up notification box and in chat, and is accompanied by a beeping sound. 196 | 197 | System messages are broadcast rarely and usually concern item server (GC) downtime. 198 | 199 | ### displayNotification 200 | - `title` - Notification title (currently unused) 201 | - `body` - Notification body text 202 | 203 | Emitted when a GC-to-client notification is sent. In the official client, this is displayed as a regular pop-up notification box. Currently, this is only used for broadcasting Something Special For Someone Special acceptance messages. 204 | 205 | Notifications have a valid and non-empty `title`, but the official client doesn't display it. 206 | 207 | **This won't be emitted unless you call `setLang` with a valid localization file.** 208 | 209 | ### itemBroadcast 210 | - `message` - The message text that is rendered by clients. This will be `null` if you haven't called `setLang` with a valid localization file or if the schema isn't loaded. 211 | - `username` - The name of the user that received/deleted an item 212 | - `wasDestruction` - `true` if the user deleted their item, `false` if they received it 213 | - `defindex` - The definition index of the item that was received/deleted 214 | 215 | Emitted when an item broadcast notification is sent. In the official client, the `message` is displayed as a regular pop-up notification box. Currently, this is only used for broadcasting Golden Frying Pan drops/deletions. 216 | 217 | ### tradeRequest 218 | - `steamID` - A [`SteamID`](https://www.npmjs.com/package/steamid) object of the user who sent a trade request 219 | - `tradeID` - A unique numeric identifier that's used to respond to the request (via `respondToTrade`) 220 | 221 | Emitted when someone sends us a trade request. Use `respondToTrade` to accept or decline it. 222 | 223 | ### tradeResponse 224 | - `response` - The response code. This is a value in the `TradeResponse` enum. 225 | - `tradeID` - If `response` is `TradeResponse.Cancel`, this is the tradeID of the trade request that was canceled. 226 | 227 | Emitted when a response is received to a `trade` call, or someone cancels an incoming trade request. 228 | 229 | ### backpackLoaded 230 | 231 | Emitted when the GC has sent us the contents of our backpack. From this point forward, backpack contents are available as a `tf2.backpack` property, which is an array of item objects. The array is in no particular order, use the `position` property of each item to determine its backpack slot. 232 | 233 | ### accountLoaded 234 | 235 | Emitted when the GC has sent us metadata about our account. Right before this is emitted, node-tf2 will define the `premium`, `backpackSlots`, and `canSendProfessorSpeks` properties. This event indicates that those properties are now available. 236 | 237 | ### accountUpdate 238 | 239 | - `oldData` - An object representing the previous value of whatever properties changed 240 | 241 | Emitted when the GC notifies us that something about our account has changed. One or more of the `premium`, `backpackSlots`, or `canSendProfessorSpeks` properties will have changed right before this event is emitted. The previous value of whatever properties changed is available via `oldData`. 242 | 243 | For example, if our account has just upgraded to premium, this would be `oldData`: 244 | 245 | ```json 246 | { 247 | "premium": false, 248 | "backpackSlots": 50 249 | } 250 | ``` 251 | 252 | The `premium` property of node-tf2 would now be true and the `backpackSlots` property would now be 300. 253 | 254 | ### itemAcquired 255 | - `item` - The item that was acquired 256 | 257 | Emitted when we receive a new item. `item` is the item that we just received, and `tf2.backpack` is updated before the event is emitted. 258 | 259 | ### itemChanged 260 | - `oldItem` - The old item data 261 | - `newItem` - The new item data 262 | 263 | Emitted when an item in our backpack changes (e.g. style update, position changed, etc.). 264 | 265 | ### itemRemoved 266 | - `item` - The item that was removed 267 | 268 | Emitted when an item is removed from our backpack. The `tf2.backpack` property is updated before this is emitted. 269 | 270 | ### craftingComplete 271 | - `recipe` - The ID of the recipe that was used to perform this craft, or -1 on failure 272 | - `itemsGained` - An array of IDs of items that were gained as a result of this craft 273 | 274 | Emitted when a craft initiated by the `craft` method finishes. 275 | 276 | ### professorSpeksReceived 277 | - `steamID` - A [`SteamID`](https://www.npmjs.com/package/steamid) object of the user who sent us Professor Speks 278 | 279 | Emitted when someone else thanks us and sends us Professor Speks (increments our "New Users Helped" counter if we already have them). 280 | 281 | ### professorSpeksSent 282 | 283 | Emitted when we successfully send Professor Speks to someone else. 284 | 285 | ### createIdentity 286 | - `status` - The status of this request, from the values in the enum below. 287 | - `created` - `true` if the identity was successfully created 288 | - `id` - The ID of the newly-created identity 289 | - `token` - The authentication token of the newly-created identity 290 | 291 | Emitted when the GC sends us back the response of a `createServerIdentity()` call. The `status` value will be from the following enum: 292 | 293 | enum EStatus { 294 | kStatus_GenericFailure = 0; 295 | kStatus_TooMany = -1; 296 | kStatus_NoPrivs = -2; 297 | kStatus_Created = 1; 298 | } 299 | 300 | ### registeredServers 301 | - `servers` - An array of objects representing our owned server identities 302 | 303 | Emitted when the GC sends us back the response of a `getRegisteredServers()` call. Each item in the `servers` array will be an object that looks like this: 304 | 305 | ```json 306 | { 307 | "game_server_account_id": 291516, 308 | "game_server_identity_token": "T0aK9zQ6W<)FTzt", 309 | "game_server_standing": 0, 310 | "game_server_standing_trend": 2 311 | } 312 | ``` 313 | 314 | ### resetIdentity 315 | - `reset` - `true` if the token was successfully reset 316 | - `id` - The ID of the identity for which we reset the token 317 | - `token` - The new token associated with the given ID 318 | 319 | Emitted when the GC sends us back the response of a `resetServerIdentity(id)` call. 320 | 321 | ### warStats 322 | - `scores` - An object where the keys are [side indexes](https://github.com/DoctorMcKay/node-tf2/blob/3fa354b2c1224b5885d9b9eb2818d17f76454cd7/enums.js#L82-L85) and values are scores. 323 | 324 | Emitted when the GC sends us back the response of a `requestWarStats()` call. 325 | -------------------------------------------------------------------------------- /protobufs/base_gcmessages.proto: -------------------------------------------------------------------------------- 1 | import "steammessages.proto"; 2 | 3 | option optimize_for = SPEED; 4 | option cc_generic_services = false; 5 | 6 | enum EGCBaseMsg { 7 | k_EMsgGCSystemMessage = 4001; 8 | k_EMsgGCReplicateConVars = 4002; 9 | k_EMsgGCConVarUpdated = 4003; 10 | k_EMsgGCServerAvailable = 4506; 11 | k_EMsgGCClientConnectToServer = 4507; 12 | k_EMsgGCGameServerInfo = 4508; 13 | k_EMsgGCError = 4509; 14 | k_EMsgGCReplay_UploadedToYouTube = 4510; 15 | k_EMsgGCLANServerAvailable = 4511; 16 | } 17 | 18 | enum EGCBaseProtoObjectTypes { 19 | k_EProtoObjectPartyInvite = 1001; 20 | k_EProtoObjectLobbyInvite = 1002; 21 | } 22 | 23 | enum GCGoodbyeReason { 24 | GCGoodbyeReason_GC_GOING_DOWN = 1; 25 | GCGoodbyeReason_NO_SESSION = 2; 26 | } 27 | 28 | message CGCStorePurchaseInit_LineItem { 29 | optional uint32 item_def_id = 1; 30 | optional uint32 quantity = 2; 31 | optional uint32 cost_in_local_currency = 3; 32 | optional uint32 purchase_type = 4; 33 | } 34 | 35 | message CMsgGCStorePurchaseInit { 36 | optional string country = 1; 37 | optional int32 language = 2; 38 | optional int32 currency = 3; 39 | repeated .CGCStorePurchaseInit_LineItem line_items = 4; 40 | } 41 | 42 | message CMsgGCStorePurchaseInitResponse { 43 | optional int32 result = 1; 44 | optional uint64 txn_id = 2; 45 | } 46 | 47 | message CMsgSystemBroadcast { 48 | optional string message = 1; 49 | } 50 | 51 | message CMsgClientHello { 52 | optional uint32 version = 1; 53 | } 54 | 55 | message CMsgServerHello { 56 | optional uint32 version = 1; 57 | } 58 | 59 | message CMsgClientWelcome { 60 | optional uint32 version = 1; 61 | optional bytes game_data = 2; 62 | optional string txn_country_code = 3; 63 | } 64 | 65 | message CMsgServerWelcome { 66 | optional uint32 min_allowed_version = 1; 67 | optional uint32 active_version = 2; 68 | } 69 | 70 | message CMsgClientGoodbye { 71 | optional .GCGoodbyeReason reason = 1 [default = GCGoodbyeReason_GC_GOING_DOWN]; 72 | } 73 | 74 | message CMsgServerGoodbye { 75 | optional .GCGoodbyeReason reason = 1 [default = GCGoodbyeReason_GC_GOING_DOWN]; 76 | } 77 | 78 | message CMsgServerAvailable { 79 | } 80 | 81 | message CMsgLANServerAvailable { 82 | optional fixed64 lobby_id = 1; 83 | } 84 | 85 | message CSOEconGameAccountClient { 86 | optional uint32 additional_backpack_slots = 1 [default = 0]; 87 | optional bool trial_account = 2 [default = false]; 88 | optional bool need_to_choose_most_helpful_friend = 4; 89 | optional bool in_coaches_list = 5; 90 | optional fixed32 trade_ban_expiration = 6; 91 | optional fixed32 duel_ban_expiration = 7; 92 | optional uint32 preview_item_def = 8 [default = 0]; 93 | optional bool phone_verified = 19 [default = false]; 94 | optional uint32 skill_rating_6v6 = 20; 95 | optional uint32 skill_rating_9v9 = 21; 96 | optional bool competitive_access = 23 [default = false]; 97 | optional uint32 matchmaking_ranked_ban_expiration = 18; 98 | optional uint32 matchmaking_ranked_low_priority_expiration = 24; 99 | optional uint32 matchmaking_ranked_ban_last_duration = 25; 100 | optional uint32 matchmaking_ranked_low_priority_last_duration = 26; 101 | optional uint32 matchmaking_casual_ban_expiration = 27; 102 | optional uint32 matchmaking_casual_low_priority_expiration = 28; 103 | optional uint32 matchmaking_casual_ban_last_duration = 29; 104 | optional uint32 matchmaking_casual_low_priority_last_duration = 30; 105 | optional bool phone_identifying = 31 [default = false]; 106 | optional bool disable_party_quest_progress = 32 [default = false]; 107 | optional uint32 quest_reward_credits = 33; 108 | optional uint32 matchmaking_last_casual_excessive_reports_auto_ban_time = 34; 109 | optional uint32 matchmaking_last_comp_excessive_reports_auto_ban_time = 35; 110 | } 111 | 112 | message CSOItemCriteriaCondition { 113 | optional int32 op = 1; 114 | optional string field = 2; 115 | optional bool required = 3; 116 | optional float float_value = 4; 117 | optional string string_value = 5; 118 | } 119 | 120 | message CSOItemCriteria { 121 | optional uint32 item_level = 1; 122 | optional int32 item_quality = 2; 123 | optional bool item_level_set = 3; 124 | optional bool item_quality_set = 4; 125 | optional uint32 initial_inventory = 5; 126 | optional uint32 initial_quantity = 6; 127 | optional bool ignore_enabled_flag = 8; 128 | repeated .CSOItemCriteriaCondition conditions = 9; 129 | optional bool recent_only = 10; 130 | optional string tags = 11; 131 | optional string equip_regions = 12; 132 | } 133 | 134 | message CSOItemRecipe { 135 | optional uint32 def_index = 1; 136 | optional string name = 2; 137 | optional string n_a = 3; 138 | optional string desc_inputs = 4; 139 | optional string desc_outputs = 5; 140 | optional string di_a = 6; 141 | optional string di_b = 7; 142 | optional string di_c = 8; 143 | optional string do_a = 9; 144 | optional string do_b = 10; 145 | optional string do_c = 11; 146 | optional bool requires_all_same_class = 12; 147 | optional bool requires_all_same_slot = 13; 148 | optional int32 class_usage_for_output = 14; 149 | optional int32 slot_usage_for_output = 15; 150 | optional int32 set_for_output = 16; 151 | repeated .CSOItemCriteria input_items_criteria = 20; 152 | repeated .CSOItemCriteria output_items_criteria = 21; 153 | repeated uint32 input_item_dupe_counts = 22; 154 | } 155 | 156 | message CMsgDevNewItemRequest { 157 | optional fixed64 receiver = 1; 158 | optional .CSOItemCriteria criteria = 2; 159 | } 160 | 161 | message CMsgDevDebugRollLootRequest { 162 | optional fixed64 receiver = 1; 163 | optional string loot_list_name = 2; 164 | } 165 | 166 | message CMsgIncrementKillCountAttribute { 167 | optional uint64 killer_steam_id = 1; 168 | optional uint64 victim_steam_id = 2; 169 | optional uint64 item_id = 3; 170 | optional uint32 event_type = 4; 171 | optional uint32 increment_value = 5; 172 | } 173 | 174 | message CMsgIncrementKillCountAttribute_Multiple { 175 | repeated .CMsgIncrementKillCountAttribute msgs = 1; 176 | } 177 | 178 | message CMsgTrackUniquePlayerPairEvent { 179 | optional uint64 killer_steam_id = 1; 180 | optional uint64 victim_steam_id = 2; 181 | optional uint64 item_id = 3; 182 | optional uint32 event_type = 4; 183 | } 184 | 185 | message CMsgApplyStrangeCountTransfer { 186 | optional uint64 tool_item_id = 1; 187 | optional uint64 item_src_item_id = 2; 188 | optional uint64 item_dest_item_id = 3; 189 | } 190 | 191 | message CMsgApplyStrangePart { 192 | optional uint64 strange_part_item_id = 1; 193 | optional uint64 item_item_id = 2; 194 | } 195 | 196 | message CMsgApplyStrangeRestriction { 197 | optional uint64 strange_part_item_id = 1; 198 | optional uint64 item_item_id = 2; 199 | optional uint32 strange_attr_index = 3; 200 | } 201 | 202 | message CMsgApplyUpgradeCard { 203 | optional uint64 upgrade_card_item_id = 1; 204 | optional uint64 subject_item_id = 2; 205 | } 206 | 207 | message CSOEconItemAttribute { 208 | optional uint32 def_index = 1; 209 | optional uint32 value = 2; 210 | optional bytes value_bytes = 3; 211 | } 212 | 213 | message CSOEconItemEquipped { 214 | optional uint32 new_class = 1; 215 | optional uint32 new_slot = 2; 216 | } 217 | 218 | message CSOEconItem { 219 | optional uint64 id = 1; 220 | optional uint32 account_id = 2; 221 | optional uint32 inventory = 3; 222 | optional uint32 def_index = 4; 223 | optional uint32 quantity = 5; 224 | optional uint32 level = 6; 225 | optional uint32 quality = 7; 226 | optional uint32 flags = 8 [default = 0]; 227 | optional uint32 origin = 9; 228 | optional string custom_name = 10; 229 | optional string custom_desc = 11; 230 | repeated .CSOEconItemAttribute attribute = 12; 231 | optional .CSOEconItem interior_item = 13; 232 | optional bool in_use = 14 [default = false]; 233 | optional uint32 style = 15 [default = 0]; 234 | optional uint64 original_id = 16 [default = 0]; 235 | optional bool contains_equipped_state = 17; 236 | repeated .CSOEconItemEquipped equipped_state = 18; 237 | optional bool contains_equipped_state_v2 = 19; 238 | } 239 | 240 | message CMsgAdjustItemEquippedState { 241 | optional uint64 item_id = 1; 242 | optional uint32 new_class = 2; 243 | optional uint32 new_slot = 3; 244 | } 245 | 246 | message CMsgSortItems { 247 | optional uint32 sort_type = 1; 248 | } 249 | 250 | message CSOEconClaimCode { 251 | optional uint32 account_id = 1; 252 | optional uint32 code_type = 2; 253 | optional uint32 time_acquired = 3; 254 | optional string code = 4; 255 | } 256 | 257 | message CMsgStoreGetUserData { 258 | optional fixed32 price_sheet_version = 1; 259 | } 260 | 261 | message CMsgStoreGetUserDataResponse { 262 | optional int32 result = 1; 263 | optional int32 currency = 2; 264 | optional string country = 3; 265 | optional fixed32 price_sheet_version = 4; 266 | optional uint64 experiment_data = 5 [default = 0]; 267 | optional int32 featured_item_idx = 6; 268 | optional bool show_hat_descriptions = 7 [default = true]; 269 | optional bytes price_sheet = 8; 270 | optional int32 default_item_sort = 9 [default = 0]; 271 | repeated uint32 popular_items = 10; 272 | } 273 | 274 | message CMsgUpdateItemSchema { 275 | optional bytes items_game = 1; 276 | optional fixed32 item_schema_version = 2; 277 | optional string items_game_url = 3; 278 | optional bytes signature = 4; 279 | } 280 | 281 | message CMsgGCError { 282 | optional string error_text = 1; 283 | } 284 | 285 | message CMsgRequestInventoryRefresh { 286 | } 287 | 288 | message CMsgConVarValue { 289 | optional string name = 1; 290 | optional string value = 2; 291 | } 292 | 293 | message CMsgReplicateConVars { 294 | repeated .CMsgConVarValue convars = 1; 295 | } 296 | 297 | message CMsgUseItem { 298 | optional uint64 item_id = 1; 299 | optional fixed64 target_steam_id = 2; 300 | repeated uint32 gift__potential_targets = 3; 301 | optional uint32 duel__class_lock = 4; 302 | optional fixed64 initiator_steam_id = 5; 303 | optional bool itempack__ack_immediately = 6; 304 | } 305 | 306 | message CMsgReplayUploadedToYouTube { 307 | optional string youtube_url = 1; 308 | optional string youtube_account_name = 2; 309 | optional uint64 session_id = 3; 310 | } 311 | 312 | message CMsgConsumableExhausted { 313 | optional int32 item_def_id = 1; 314 | } 315 | 316 | message CMsgItemAcknowledged { 317 | optional uint32 account_id = 1; 318 | optional uint32 inventory = 2; 319 | optional uint32 def_index = 3; 320 | optional uint32 quality = 4; 321 | optional uint32 rarity = 5; 322 | optional uint32 origin = 6; 323 | optional uint32 is_strange = 7; 324 | optional uint32 is_unusual = 8; 325 | optional float wear = 9; 326 | } 327 | 328 | message CMsgSetPresetItemPosition { 329 | optional uint32 class_id = 1; 330 | optional uint32 preset_id = 2; 331 | optional uint32 slot_id = 3; 332 | optional uint64 item_id = 4; 333 | } 334 | 335 | message CMsgSetItemPositions { 336 | message ItemPosition { 337 | optional uint64 item_id = 1; 338 | optional uint32 position = 2; 339 | } 340 | 341 | repeated .CMsgSetItemPositions.ItemPosition item_positions = 1; 342 | } 343 | 344 | message CSOEconItemPresetInstance { 345 | optional uint32 class_id = 2 [(key_field) = true]; 346 | optional uint32 preset_id = 3 [(key_field) = true]; 347 | optional uint32 slot_id = 4 [(key_field) = true]; 348 | optional uint64 item_id = 5; 349 | } 350 | 351 | message CMsgSelectPresetForClass { 352 | optional uint32 class_id = 1; 353 | optional uint32 preset_id = 2; 354 | } 355 | 356 | message CSOClassPresetClientData { 357 | optional uint32 account_id = 1; 358 | optional uint32 class_id = 2; 359 | optional uint32 active_preset_id = 3; 360 | } 361 | 362 | message CMsgGCReportAbuse { 363 | optional fixed64 target_steam_id = 1; 364 | optional string description = 4; 365 | optional uint64 gid = 5; 366 | optional uint32 abuse_type = 2; 367 | optional uint32 content_type = 3; 368 | optional fixed32 target_game_server_ip = 6; 369 | optional uint32 target_game_server_port = 7; 370 | } 371 | 372 | message CMsgGCReportAbuseResponse { 373 | optional fixed64 target_steam_id = 1; 374 | optional uint32 result = 2; 375 | optional string error_message = 3; 376 | } 377 | 378 | message CMsgGCNameItemNotification { 379 | optional fixed64 player_steamid = 1; 380 | optional uint32 item_def_index = 2; 381 | optional string item_name_custom = 3; 382 | } 383 | 384 | message CMsgGCClientDisplayNotification { 385 | optional string notification_title_localization_key = 1; 386 | optional string notification_body_localization_key = 2; 387 | repeated string body_substring_keys = 3; 388 | repeated string body_substring_values = 4; 389 | } 390 | 391 | message CMsgGCShowItemsPickedUp { 392 | optional fixed64 player_steamid = 1; 393 | } 394 | 395 | message CMsgUpdatePeriodicEvent { 396 | optional uint32 account_id = 1; 397 | optional uint32 event_type = 2; 398 | optional uint32 amount = 3; 399 | } 400 | 401 | message CMsgGCIncrementKillCountResponse { 402 | optional uint32 killer_account_id = 1 [(key_field) = true]; 403 | optional uint32 num_kills = 2; 404 | optional uint32 item_def = 3; 405 | optional uint32 level_type = 4; 406 | } 407 | 408 | message CMsgGCRemoveStrangePart { 409 | optional uint64 item_id = 1; 410 | optional uint32 strange_part_score_type = 2; 411 | } 412 | 413 | message CMsgGCRemoveUpgradeCard { 414 | optional uint64 item_id = 1; 415 | optional uint32 attribute_index = 2; 416 | } 417 | 418 | message CMsgGCRemoveCustomizationAttributeSimple { 419 | optional uint64 item_id = 1; 420 | } 421 | 422 | message CMsgGCResetStrangeScores { 423 | optional uint64 item_id = 1; 424 | } 425 | 426 | message CMsgGCItemPreviewItemBoughtNotification { 427 | optional uint32 item_def_index = 1; 428 | } 429 | 430 | message CMsgGCStorePurchaseCancel { 431 | optional uint64 txn_id = 1; 432 | } 433 | 434 | message CMsgGCStorePurchaseCancelResponse { 435 | optional uint32 result = 1; 436 | } 437 | 438 | message CMsgGCStorePurchaseFinalize { 439 | optional uint64 txn_id = 1; 440 | } 441 | 442 | message CMsgGCStorePurchaseFinalizeResponse { 443 | optional uint32 result = 1; 444 | repeated uint64 item_ids = 2; 445 | } 446 | 447 | message CMsgGCBannedWordListRequest { 448 | optional uint32 ban_list_group_id = 1; 449 | optional uint32 word_id = 2; 450 | } 451 | 452 | message CMsgGCGiftedItems { 453 | optional uint64 gifter_steam_id = 1; 454 | optional bool was_random_person = 2; 455 | repeated uint32 recipient_account_ids = 3; 456 | } 457 | 458 | message CMsgGCCollectItem { 459 | optional uint64 collection_item_id = 1; 460 | optional uint64 subject_item_id = 2; 461 | } 462 | 463 | message CMsgGCClientMarketDataRequest { 464 | optional uint32 user_currency = 1; 465 | } 466 | 467 | message CMsgGCClientMarketDataEntry { 468 | optional uint32 item_def_index = 1; 469 | optional uint32 item_quality = 2; 470 | optional uint32 item_sell_listings = 3; 471 | optional uint32 price_in_local_currency = 4; 472 | } 473 | 474 | message CMsgGCClientMarketData { 475 | repeated .CMsgGCClientMarketDataEntry entries = 1; 476 | } 477 | 478 | message CMsgApplyToolToItem { 479 | optional uint64 tool_item_id = 1; 480 | optional uint64 subject_item_id = 2; 481 | } 482 | 483 | message CMsgApplyToolToBaseItem { 484 | optional uint64 tool_item_id = 1; 485 | optional uint32 baseitem_def_index = 2; 486 | } 487 | 488 | message CMsgRecipeComponent { 489 | optional uint64 subject_item_id = 1; 490 | optional uint64 attribute_index = 2; 491 | } 492 | 493 | message CMsgFulfillDynamicRecipeComponent { 494 | optional uint64 tool_item_id = 1; 495 | repeated .CMsgRecipeComponent consumption_components = 2; 496 | } 497 | 498 | message CMsgSetItemEffectVerticalOffset { 499 | optional uint64 item_id = 1; 500 | optional float offset = 2; 501 | } 502 | 503 | message CMsgSetHatEffectUseHeadOrigin { 504 | optional uint64 item_id = 1; 505 | optional bool use_head = 2; 506 | } 507 | 508 | message CMsgDeliverGiftResponseGiver { 509 | optional uint32 response_code = 1; 510 | optional string receiver_account_name = 2; 511 | } 512 | 513 | message CSOEconGameAccountForGameServers { 514 | optional bool disable_party_quest_progress = 6 [default = false]; 515 | } 516 | 517 | message CWorkshop_PopulateItemDescriptions_Request { 518 | message SingleItemDescription { 519 | optional uint32 gameitemid = 1; 520 | optional string item_description = 2; 521 | } 522 | 523 | message ItemDescriptionsLanguageBlock { 524 | optional string language = 1; 525 | repeated .CWorkshop_PopulateItemDescriptions_Request.SingleItemDescription descriptions = 2; 526 | } 527 | 528 | optional uint32 appid = 1; 529 | repeated .CWorkshop_PopulateItemDescriptions_Request.ItemDescriptionsLanguageBlock languages = 2; 530 | } 531 | 532 | message CWorkshop_GetContributors_Request { 533 | optional uint32 appid = 1; 534 | optional uint32 gameitemid = 2; 535 | } 536 | 537 | message CWorkshop_GetContributors_Response { 538 | repeated fixed64 contributors = 1; 539 | } 540 | 541 | message CWorkshop_SetItemPaymentRules_Request { 542 | message WorkshopItemPaymentRule { 543 | optional uint64 workshop_file_id = 1; 544 | optional float revenue_percentage = 2; 545 | optional string rule_description = 3; 546 | } 547 | 548 | message PartnerItemPaymentRule { 549 | optional uint32 account_id = 1; 550 | optional float revenue_percentage = 2; 551 | optional string rule_description = 3; 552 | } 553 | 554 | optional uint32 appid = 1; 555 | optional uint32 gameitemid = 2; 556 | repeated .CWorkshop_SetItemPaymentRules_Request.WorkshopItemPaymentRule associated_workshop_files = 3; 557 | repeated .CWorkshop_SetItemPaymentRules_Request.PartnerItemPaymentRule partner_accounts = 4; 558 | } 559 | 560 | message CWorkshop_SetItemPaymentRules_Response { 561 | } 562 | 563 | -------------------------------------------------------------------------------- /protobufs/steammessages.proto: -------------------------------------------------------------------------------- 1 | import "google/protobuf/descriptor.proto"; 2 | 3 | option optimize_for = SPEED; 4 | option cc_generic_services = false; 5 | 6 | extend .google.protobuf.FieldOptions { 7 | optional bool key_field = 60000 [default = false]; 8 | } 9 | 10 | extend .google.protobuf.MessageOptions { 11 | optional int32 msgpool_soft_limit = 60000 [default = 32]; 12 | optional int32 msgpool_hard_limit = 60001 [default = 384]; 13 | } 14 | 15 | enum GCProtoBufMsgSrc { 16 | GCProtoBufMsgSrc_Unspecified = 0; 17 | GCProtoBufMsgSrc_FromSystem = 1; 18 | GCProtoBufMsgSrc_FromSteamID = 2; 19 | GCProtoBufMsgSrc_FromGC = 3; 20 | GCProtoBufMsgSrc_ReplySystem = 4; 21 | } 22 | 23 | message CMsgProtoBufHeader { 24 | option (msgpool_soft_limit) = 256; 25 | option (msgpool_hard_limit) = 1024; 26 | optional fixed64 client_steam_id = 1; 27 | optional int32 client_session_id = 2; 28 | optional uint32 source_app_id = 3; 29 | optional fixed64 job_id_source = 10 [default = 18446744073709551615]; 30 | optional fixed64 job_id_target = 11 [default = 18446744073709551615]; 31 | optional string target_job_name = 12; 32 | optional int32 eresult = 13 [default = 2]; 33 | optional string error_message = 14; 34 | optional .GCProtoBufMsgSrc gc_msg_src = 200 [default = GCProtoBufMsgSrc_Unspecified]; 35 | optional uint32 gc_dir_index_source = 201; 36 | } 37 | 38 | message CMsgWebAPIKey { 39 | optional uint32 status = 1 [default = 255]; 40 | optional uint32 account_id = 2 [default = 0]; 41 | optional uint32 publisher_group_id = 3 [default = 0]; 42 | optional uint32 key_id = 4; 43 | optional string domain = 5; 44 | } 45 | 46 | message CMsgHttpRequest { 47 | message RequestHeader { 48 | optional string name = 1; 49 | optional string value = 2; 50 | } 51 | 52 | message QueryParam { 53 | optional string name = 1; 54 | optional bytes value = 2; 55 | } 56 | 57 | optional uint32 request_method = 1; 58 | optional string hostname = 2; 59 | optional string url = 3; 60 | repeated .CMsgHttpRequest.RequestHeader headers = 4; 61 | repeated .CMsgHttpRequest.QueryParam get_params = 5; 62 | repeated .CMsgHttpRequest.QueryParam post_params = 6; 63 | optional bytes body = 7; 64 | optional uint32 absolute_timeout = 8; 65 | } 66 | 67 | message CMsgWebAPIRequest { 68 | optional string UNUSED_job_name = 1; 69 | optional string interface_name = 2; 70 | optional string method_name = 3; 71 | optional uint32 version = 4; 72 | optional .CMsgWebAPIKey api_key = 5; 73 | optional .CMsgHttpRequest request = 6; 74 | optional uint32 routing_app_id = 7; 75 | } 76 | 77 | message CMsgHttpResponse { 78 | message ResponseHeader { 79 | optional string name = 1; 80 | optional string value = 2; 81 | } 82 | 83 | optional uint32 status_code = 1; 84 | repeated .CMsgHttpResponse.ResponseHeader headers = 2; 85 | optional bytes body = 3; 86 | } 87 | 88 | message CMsgAMFindAccounts { 89 | optional uint32 search_type = 1; 90 | optional string search_string = 2; 91 | } 92 | 93 | message CMsgAMFindAccountsResponse { 94 | repeated fixed64 steam_id = 1; 95 | } 96 | 97 | message CMsgNotifyWatchdog { 98 | optional uint32 source = 1; 99 | optional uint32 alert_type = 2; 100 | optional uint32 alert_destination = 3; 101 | optional bool critical = 4; 102 | optional uint32 time = 5; 103 | optional uint32 appid = 6; 104 | optional string text = 7; 105 | } 106 | 107 | message CMsgAMGetLicenses { 108 | optional fixed64 steamid = 1; 109 | } 110 | 111 | message CMsgPackageLicense { 112 | optional uint32 package_id = 1; 113 | optional uint32 time_created = 2; 114 | optional uint32 owner_id = 3; 115 | } 116 | 117 | message CMsgAMGetLicensesResponse { 118 | repeated .CMsgPackageLicense license = 1; 119 | optional uint32 result = 2; 120 | } 121 | 122 | message CMsgAMGetUserGameStats { 123 | optional fixed64 steam_id = 1; 124 | optional fixed64 game_id = 2; 125 | repeated uint32 stats = 3; 126 | } 127 | 128 | message CMsgAMGetUserGameStatsResponse { 129 | message Stats { 130 | optional uint32 stat_id = 1; 131 | optional uint32 stat_value = 2; 132 | } 133 | 134 | message Achievement_Blocks { 135 | optional uint32 achievement_id = 1; 136 | optional uint32 achievement_bit_id = 2; 137 | optional fixed32 unlock_time = 3; 138 | } 139 | 140 | optional fixed64 steam_id = 1; 141 | optional fixed64 game_id = 2; 142 | optional int32 eresult = 3 [default = 2]; 143 | repeated .CMsgAMGetUserGameStatsResponse.Stats stats = 4; 144 | repeated .CMsgAMGetUserGameStatsResponse.Achievement_Blocks achievement_blocks = 5; 145 | } 146 | 147 | message CMsgGCGetCommandList { 148 | optional uint32 app_id = 1; 149 | optional string command_prefix = 2; 150 | } 151 | 152 | message CMsgGCGetCommandListResponse { 153 | repeated string command_name = 1; 154 | } 155 | 156 | message CGCMsgMemCachedGet { 157 | repeated string keys = 1; 158 | } 159 | 160 | message CGCMsgMemCachedGetResponse { 161 | message ValueTag { 162 | optional bool found = 1; 163 | optional bytes value = 2; 164 | } 165 | 166 | repeated .CGCMsgMemCachedGetResponse.ValueTag values = 1; 167 | } 168 | 169 | message CGCMsgMemCachedSet { 170 | message KeyPair { 171 | optional string name = 1; 172 | optional bytes value = 2; 173 | } 174 | 175 | repeated .CGCMsgMemCachedSet.KeyPair keys = 1; 176 | } 177 | 178 | message CGCMsgMemCachedDelete { 179 | repeated string keys = 1; 180 | } 181 | 182 | message CGCMsgMemCachedStats { 183 | } 184 | 185 | message CGCMsgMemCachedStatsResponse { 186 | optional uint64 curr_connections = 1; 187 | optional uint64 cmd_get = 2; 188 | optional uint64 cmd_set = 3; 189 | optional uint64 cmd_flush = 4; 190 | optional uint64 get_hits = 5; 191 | optional uint64 get_misses = 6; 192 | optional uint64 delete_hits = 7; 193 | optional uint64 delete_misses = 8; 194 | optional uint64 bytes_read = 9; 195 | optional uint64 bytes_written = 10; 196 | optional uint64 limit_maxbytes = 11; 197 | optional uint64 curr_items = 12; 198 | optional uint64 evictions = 13; 199 | optional uint64 bytes = 14; 200 | } 201 | 202 | message CGCMsgSQLStats { 203 | optional uint32 schema_catalog = 1; 204 | } 205 | 206 | message CGCMsgSQLStatsResponse { 207 | optional uint32 threads = 1; 208 | optional uint32 threads_connected = 2; 209 | optional uint32 threads_active = 3; 210 | optional uint32 operations_submitted = 4; 211 | optional uint32 prepared_statements_executed = 5; 212 | optional uint32 non_prepared_statements_executed = 6; 213 | optional uint32 deadlock_retries = 7; 214 | optional uint32 operations_timed_out_in_queue = 8; 215 | optional uint32 errors = 9; 216 | } 217 | 218 | message CMsgAMAddFreeLicense { 219 | optional fixed64 steamid = 1; 220 | optional uint32 ip_public = 2; 221 | optional uint32 packageid = 3; 222 | optional string store_country_code = 4; 223 | } 224 | 225 | message CMsgAMAddFreeLicenseResponse { 226 | optional int32 eresult = 1 [default = 2]; 227 | optional int32 purchase_result_detail = 2; 228 | optional fixed64 transid = 3; 229 | } 230 | 231 | message CGCMsgGetIPLocation { 232 | repeated fixed32 ips = 1; 233 | } 234 | 235 | message CIPLocationInfo { 236 | optional uint32 ip = 1; 237 | optional float latitude = 2; 238 | optional float longitude = 3; 239 | optional string country = 4; 240 | optional string state = 5; 241 | optional string city = 6; 242 | } 243 | 244 | message CGCMsgGetIPLocationResponse { 245 | repeated .CIPLocationInfo infos = 1; 246 | } 247 | 248 | message CGCMsgSystemStatsSchema { 249 | optional uint32 gc_app_id = 1; 250 | optional bytes schema_kv = 2; 251 | } 252 | 253 | message CGCMsgGetSystemStats { 254 | } 255 | 256 | message CGCMsgGetSystemStatsResponse { 257 | optional uint32 gc_app_id = 1; 258 | optional bytes stats_kv = 2; 259 | optional uint32 active_jobs = 3; 260 | optional uint32 yielding_jobs = 4; 261 | optional uint32 user_sessions = 5; 262 | optional uint32 game_server_sessions = 6; 263 | optional uint32 socaches = 7; 264 | optional uint32 socaches_to_unload = 8; 265 | optional uint32 socaches_loading = 9; 266 | optional uint32 writeback_queue = 10; 267 | optional uint32 steamid_locks = 11; 268 | optional uint32 logon_queue = 12; 269 | optional uint32 logon_jobs = 13; 270 | } 271 | 272 | message CMsgAMSendEmail { 273 | message ReplacementToken { 274 | optional string token_name = 1; 275 | optional string token_value = 2; 276 | } 277 | 278 | message PersonaNameReplacementToken { 279 | optional fixed64 steamid = 1; 280 | optional string token_name = 2; 281 | } 282 | 283 | optional fixed64 steamid = 1; 284 | optional uint32 email_msg_type = 2; 285 | optional uint32 email_format = 3; 286 | repeated .CMsgAMSendEmail.PersonaNameReplacementToken persona_name_tokens = 5; 287 | optional uint32 source_gc = 6; 288 | repeated .CMsgAMSendEmail.ReplacementToken tokens = 7; 289 | } 290 | 291 | message CMsgAMSendEmailResponse { 292 | optional uint32 eresult = 1 [default = 2]; 293 | } 294 | 295 | message CMsgGCGetEmailTemplate { 296 | optional uint32 app_id = 1; 297 | optional uint32 email_msg_type = 2; 298 | optional int32 email_lang = 3; 299 | optional int32 email_format = 4; 300 | } 301 | 302 | message CMsgGCGetEmailTemplateResponse { 303 | optional uint32 eresult = 1 [default = 2]; 304 | optional bool template_exists = 2; 305 | optional string template = 3; 306 | } 307 | 308 | message CMsgAMGrantGuestPasses2 { 309 | optional fixed64 steam_id = 1; 310 | optional uint32 package_id = 2; 311 | optional int32 passes_to_grant = 3; 312 | optional int32 days_to_expiration = 4; 313 | optional int32 action = 5; 314 | } 315 | 316 | message CMsgAMGrantGuestPasses2Response { 317 | optional int32 eresult = 1 [default = 2]; 318 | optional int32 passes_granted = 2 [default = 0]; 319 | } 320 | 321 | message CGCSystemMsg_GetAccountDetails { 322 | option (msgpool_soft_limit) = 128; 323 | option (msgpool_hard_limit) = 512; 324 | optional fixed64 steamid = 1; 325 | optional uint32 appid = 2; 326 | } 327 | 328 | message CGCSystemMsg_GetAccountDetails_Response { 329 | option (msgpool_soft_limit) = 128; 330 | option (msgpool_hard_limit) = 512; 331 | optional uint32 eresult_deprecated = 1 [default = 2]; 332 | optional string account_name = 2; 333 | optional string persona_name = 3; 334 | optional bool is_profile_public = 4; 335 | optional bool is_inventory_public = 5; 336 | optional bool is_vac_banned = 7; 337 | optional bool is_cyber_cafe = 8; 338 | optional bool is_school_account = 9; 339 | optional bool is_limited = 10; 340 | optional bool is_subscribed = 11; 341 | optional uint32 package = 12; 342 | optional bool is_free_trial_account = 13; 343 | optional uint32 free_trial_expiration = 14; 344 | optional bool is_low_violence = 15; 345 | optional bool is_account_locked_down = 16; 346 | optional bool is_community_banned = 17; 347 | optional bool is_trade_banned = 18; 348 | optional uint32 trade_ban_expiration = 19; 349 | optional uint32 accountid = 20; 350 | optional uint32 suspension_end_time = 21; 351 | optional string currency = 22; 352 | optional uint32 steam_level = 23; 353 | optional uint32 friend_count = 24; 354 | optional uint32 account_creation_time = 25; 355 | optional bool is_steamguard_enabled = 27; 356 | optional bool is_phone_verified = 28; 357 | optional bool is_two_factor_auth_enabled = 29; 358 | optional uint32 two_factor_enabled_time = 30; 359 | optional uint32 phone_verification_time = 31; 360 | optional uint64 phone_id = 33; 361 | optional bool is_phone_identifying = 34; 362 | optional uint32 rt_identity_linked = 35; 363 | optional uint32 rt_birth_date = 36; 364 | optional string txn_country_code = 37; 365 | } 366 | 367 | message CMsgGCCheckClanMembership { 368 | optional fixed64 steamid = 1; 369 | optional uint32 clanid = 2; 370 | } 371 | 372 | message CMsgGCCheckClanMembership_Response { 373 | optional bool ismember = 1; 374 | } 375 | 376 | message CMsgGCGetPersonaNames { 377 | repeated fixed64 steamids = 1; 378 | } 379 | 380 | message CMsgGCGetPersonaNames_Response { 381 | message PersonaName { 382 | optional fixed64 steamid = 1; 383 | optional string persona_name = 2; 384 | } 385 | 386 | repeated .CMsgGCGetPersonaNames_Response.PersonaName succeeded_lookups = 1; 387 | repeated fixed64 failed_lookup_steamids = 2; 388 | } 389 | 390 | message CMsgGCCheckFriendship { 391 | optional fixed64 steamid_left = 1; 392 | optional fixed64 steamid_right = 2; 393 | } 394 | 395 | message CMsgGCCheckFriendship_Response { 396 | optional bool success = 1; 397 | optional bool found_friendship = 2; 398 | } 399 | 400 | message CMsgGCMsgMasterSetDirectory { 401 | message SubGC { 402 | optional uint32 dir_index = 1; 403 | optional string name = 2; 404 | optional string box = 3; 405 | optional string command_line = 4; 406 | optional string gc_binary = 5; 407 | } 408 | 409 | optional uint32 master_dir_index = 1; 410 | repeated .CMsgGCMsgMasterSetDirectory.SubGC dir = 2; 411 | } 412 | 413 | message CMsgGCMsgMasterSetDirectory_Response { 414 | optional int32 eresult = 1 [default = 2]; 415 | } 416 | 417 | message CMsgGCMsgWebAPIJobRequestForwardResponse { 418 | optional uint32 dir_index = 1; 419 | } 420 | 421 | message CGCSystemMsg_GetPurchaseTrust_Request { 422 | optional fixed64 steamid = 1; 423 | } 424 | 425 | message CGCSystemMsg_GetPurchaseTrust_Response { 426 | optional bool has_prior_purchase_history = 1; 427 | optional bool has_no_recent_password_resets = 2; 428 | optional bool is_wallet_cash_trusted = 3; 429 | optional uint32 time_all_trusted = 4; 430 | } 431 | 432 | message CMsgGCHAccountVacStatusChange { 433 | optional fixed64 steam_id = 1; 434 | optional uint32 app_id = 2; 435 | optional uint32 rtime_vacban_starts = 3; 436 | optional bool is_banned_now = 4; 437 | optional bool is_banned_future = 5; 438 | } 439 | 440 | message CMsgGCHAccountTradeBanStatusChange { 441 | optional fixed64 steamid = 1; 442 | optional uint32 appid = 2; 443 | optional bool is_banned = 3; 444 | optional uint32 time_banned_until = 4; 445 | } 446 | 447 | message CMsgGCHAccountLockStatusChange { 448 | optional fixed64 steamid = 1; 449 | optional uint32 appid = 2; 450 | optional bool is_locked = 3; 451 | } 452 | 453 | message CMsgGCHVacVerificationChange { 454 | optional fixed64 steamid = 1; 455 | optional uint32 appid = 2; 456 | optional bool is_verified = 3; 457 | } 458 | 459 | message CMsgGCHAccountPhoneNumberChange { 460 | optional fixed64 steamid = 1; 461 | optional uint32 appid = 2; 462 | optional uint64 phone_id = 3; 463 | optional bool is_verified = 4; 464 | optional bool is_identifying = 5; 465 | } 466 | 467 | message CMsgGCHAccountTwoFactorChange { 468 | optional fixed64 steamid = 1; 469 | optional uint32 appid = 2; 470 | optional bool twofactor_enabled = 3; 471 | } 472 | 473 | message CMsgGCGetPartnerAccountLink { 474 | optional fixed64 steamid = 1; 475 | } 476 | 477 | message CMsgGCGetPartnerAccountLink_Response { 478 | optional uint32 pwid = 1; 479 | optional uint32 nexonid = 2; 480 | } 481 | 482 | message CMsgGCRoutingInfo { 483 | enum RoutingMethod { 484 | RANDOM = 0; 485 | DISCARD = 1; 486 | CLIENT_STEAMID = 2; 487 | PROTOBUF_FIELD_UINT64 = 3; 488 | WEBAPI_PARAM_UINT64 = 4; 489 | } 490 | 491 | repeated uint32 dir_index = 1; 492 | optional .CMsgGCRoutingInfo.RoutingMethod method = 2 [default = RANDOM]; 493 | optional .CMsgGCRoutingInfo.RoutingMethod fallback = 3 [default = DISCARD]; 494 | optional uint32 protobuf_field = 4; 495 | optional string webapi_param = 5; 496 | } 497 | 498 | message CMsgGCMsgMasterSetWebAPIRouting { 499 | message Entry { 500 | optional string interface_name = 1; 501 | optional string method_name = 2; 502 | optional .CMsgGCRoutingInfo routing = 3; 503 | } 504 | 505 | repeated .CMsgGCMsgMasterSetWebAPIRouting.Entry entries = 1; 506 | } 507 | 508 | message CMsgGCMsgMasterSetClientMsgRouting { 509 | message Entry { 510 | optional uint32 msg_type = 1; 511 | optional .CMsgGCRoutingInfo routing = 2; 512 | } 513 | 514 | repeated .CMsgGCMsgMasterSetClientMsgRouting.Entry entries = 1; 515 | } 516 | 517 | message CMsgGCMsgMasterSetWebAPIRouting_Response { 518 | optional int32 eresult = 1 [default = 2]; 519 | } 520 | 521 | message CMsgGCMsgMasterSetClientMsgRouting_Response { 522 | optional int32 eresult = 1 [default = 2]; 523 | } 524 | 525 | message CMsgGCMsgSetOptions { 526 | message MessageRange { 527 | required uint32 low = 1; 528 | required uint32 high = 2; 529 | } 530 | 531 | enum Option { 532 | NOTIFY_USER_SESSIONS = 0; 533 | NOTIFY_SERVER_SESSIONS = 1; 534 | NOTIFY_ACHIEVEMENTS = 2; 535 | NOTIFY_VAC_ACTION = 3; 536 | } 537 | 538 | enum GCSQLVersion { 539 | GCSQL_VERSION_BASELINE = 1; 540 | GCSQL_VERSION_BOOLTYPE = 2; 541 | } 542 | 543 | repeated .CMsgGCMsgSetOptions.Option options = 1; 544 | repeated .CMsgGCMsgSetOptions.MessageRange client_msg_ranges = 2; 545 | optional .CMsgGCMsgSetOptions.GCSQLVersion gcsql_version = 3 [default = GCSQL_VERSION_BASELINE]; 546 | } 547 | 548 | message CMsgGCHUpdateSession { 549 | message ExtraField { 550 | optional string name = 1; 551 | optional string value = 2; 552 | } 553 | 554 | optional fixed64 steam_id = 1; 555 | optional uint32 app_id = 2; 556 | optional bool online = 3; 557 | optional fixed64 server_steam_id = 4; 558 | optional uint32 server_addr = 5; 559 | optional uint32 server_port = 6; 560 | optional uint32 os_type = 7; 561 | optional uint32 client_addr = 8; 562 | repeated .CMsgGCHUpdateSession.ExtraField extra_fields = 9; 563 | } 564 | 565 | message CMsgNotificationOfSuspiciousActivity { 566 | message MultipleGameInstances { 567 | optional uint32 app_instance_count = 1; 568 | repeated fixed64 other_steamids = 2; 569 | } 570 | 571 | optional fixed64 steamid = 1; 572 | optional uint32 appid = 2; 573 | optional .CMsgNotificationOfSuspiciousActivity.MultipleGameInstances multiple_instances = 3; 574 | } 575 | 576 | -------------------------------------------------------------------------------- /protobufs/steamdatagram_messages.proto: -------------------------------------------------------------------------------- 1 | import "steamdatagram_auth_messages.proto"; 2 | 3 | option cc_generic_services = false; 4 | 5 | enum ESteamDatagramMsgID { 6 | k_ESteamDatagramMsg_Invalid = 0; 7 | k_ESteamDatagramMsg_RouterPingRequest = 1; 8 | k_ESteamDatagramMsg_RouterPingReply = 2; 9 | k_ESteamDatagramMsg_GameserverPingRequest = 3; 10 | k_ESteamDatagramMsg_GameserverPingReply = 4; 11 | k_ESteamDatagramMsg_GameserverSessionRequest = 5; 12 | k_ESteamDatagramMsg_GameserverSessionEstablished = 6; 13 | k_ESteamDatagramMsg_NoSession = 7; 14 | k_ESteamDatagramMsg_Diagnostic = 8; 15 | k_ESteamDatagramMsg_DataClientToRouter = 9; 16 | k_ESteamDatagramMsg_DataRouterToServer = 10; 17 | k_ESteamDatagramMsg_DataServerToRouter = 11; 18 | k_ESteamDatagramMsg_DataRouterToClient = 12; 19 | k_ESteamDatagramMsg_Stats = 13; 20 | k_ESteamDatagramMsg_ClientPingSampleRequest = 14; 21 | k_ESteamDatagramMsg_ClientPingSampleReply = 15; 22 | k_ESteamDatagramMsg_ClientToRouterSwitchedPrimary = 16; 23 | k_ESteamDatagramMsg_RelayHealth = 17; 24 | k_ESteamDatagramMsg_ConnectRequest = 18; 25 | k_ESteamDatagramMsg_ConnectOK = 19; 26 | k_ESteamDatagramMsg_ConnectionClosed = 20; 27 | k_ESteamDatagramMsg_NoConnection = 21; 28 | k_ESteamDatagramMsg_RelayToRelayPingRequest = 22; 29 | k_ESteamDatagramMsg_RelayToRelayPingReply = 23; 30 | k_ESteamDatagramMsg_P2PSessionRequest = 24; 31 | k_ESteamDatagramMsg_P2PSessionEstablished = 25; 32 | } 33 | 34 | enum ESteamNetworkingUDPMsgID { 35 | k_ESteamNetworkingUDPMsg_ChallengeRequest = 32; 36 | k_ESteamNetworkingUDPMsg_ChallengeReply = 33; 37 | k_ESteamNetworkingUDPMsg_ConnectRequest = 34; 38 | k_ESteamNetworkingUDPMsg_ConnectOK = 35; 39 | k_ESteamNetworkingUDPMsg_ConnectionClosed = 36; 40 | k_ESteamNetworkingUDPMsg_NoConnection = 37; 41 | k_ESteamNetworkingUDPMsg_Stats = 38; 42 | } 43 | 44 | message CMsgSteamDatagramRouterPingReply { 45 | message RouteException { 46 | optional fixed32 data_center_id = 1; 47 | optional uint32 flags = 2; 48 | optional uint32 penalty = 3; 49 | } 50 | 51 | optional fixed32 client_timestamp = 1; 52 | repeated fixed32 latency_datacenter_ids = 2 [packed = true]; 53 | repeated uint32 latency_ping_ms = 3 [packed = true]; 54 | optional fixed32 your_public_ip = 4; 55 | optional fixed32 server_time = 5; 56 | optional fixed64 challenge = 6; 57 | optional uint32 seconds_until_shutdown = 7; 58 | optional fixed32 client_cookie = 8; 59 | optional uint32 scoring_penalty_relay_cluster = 9; 60 | repeated .CMsgSteamDatagramRouterPingReply.RouteException route_exceptions = 10; 61 | } 62 | 63 | message CMsgSteamDatagramGameserverPing { 64 | optional uint32 legacy_client_session = 1; 65 | optional fixed64 client_steam_id = 2; 66 | optional fixed32 client_timestamp = 3; 67 | optional fixed32 router_timestamp = 4; 68 | optional uint32 router_gameserver_latency = 5; 69 | optional uint32 seq_number_router = 6; 70 | optional uint32 seq_number_e2e = 7; 71 | optional uint32 relay_session_id = 8; 72 | optional fixed32 connection_id = 9; 73 | } 74 | 75 | message CMsgSteamDatagramRelayToRelayPing { 76 | optional fixed32 request_timestamp = 1; 77 | optional fixed32 request_date = 2; 78 | optional fixed32 my_pop_id = 3; 79 | optional fixed32 your_pop_id = 4; 80 | optional fixed32 checksum = 5; 81 | } 82 | 83 | message CMsgSteamDatagramSessionCryptInfo { 84 | enum EKeyType { 85 | INVALID = 0; 86 | CURVE25519 = 1; 87 | } 88 | 89 | optional .CMsgSteamDatagramSessionCryptInfo.EKeyType key_type = 1 [default = INVALID]; 90 | optional bytes key_data = 2; 91 | optional fixed64 nonce = 3; 92 | optional bool is_snp = 4; 93 | } 94 | 95 | message CMsgSteamDatagramSessionCryptInfoSigned { 96 | optional bytes info = 1; 97 | optional bytes signature = 2; 98 | } 99 | 100 | message CMsgSteamDatagramGameserverSessionRequest { 101 | optional bytes ticket = 1; 102 | optional fixed32 challenge_time = 3; 103 | optional fixed64 challenge = 4; 104 | optional fixed32 client_connection_id = 5; 105 | optional fixed32 server_connection_id = 8; 106 | optional uint32 network_config_version = 6; 107 | optional uint32 protocol_version = 7; 108 | } 109 | 110 | message CMsgSteamDatagramGameserverSessionEstablished { 111 | optional fixed32 connection_id = 1; 112 | optional fixed64 gameserver_steam_id = 3; 113 | optional uint32 seconds_until_shutdown = 4; 114 | optional uint32 legacy_relay_session_id = 5; 115 | optional uint32 seq_num_r2c = 6; 116 | } 117 | 118 | message CMsgSteamDatagramNoSessionRelayToClient { 119 | optional uint32 legacy_relay_session_id = 1; 120 | optional fixed32 connection_id = 7; 121 | optional fixed32 your_public_ip = 2; 122 | optional fixed32 server_time = 3; 123 | optional fixed64 challenge = 4; 124 | optional uint32 seconds_until_shutdown = 5; 125 | } 126 | 127 | message CMsgSteamDatagramNoSessionRelayToServer { 128 | optional uint32 relay_session_id = 1; 129 | optional fixed32 client_connection_id = 7; 130 | optional fixed32 server_connection_id = 8; 131 | optional fixed64 kludge_pad = 99; 132 | } 133 | 134 | message CMsgSteamDatagramDiagnostic { 135 | optional uint32 severity = 1; 136 | optional string text = 2; 137 | } 138 | 139 | message CMsgSteamDatagramDataCenterState { 140 | message Server { 141 | optional string address = 1; 142 | optional uint32 ping_ms = 2; 143 | } 144 | 145 | message DataCenter { 146 | optional string code = 1; 147 | repeated .CMsgSteamDatagramDataCenterState.Server server_sample = 2; 148 | repeated .CMsgSteamDatagramDataCenterState.Server relay_sample = 3; 149 | } 150 | 151 | repeated .CMsgSteamDatagramDataCenterState.DataCenter data_centers = 1; 152 | } 153 | 154 | message CMsgSteamDatagramLinkInstantaneousStats { 155 | optional uint32 out_packets_per_sec_x10 = 1; 156 | optional uint32 out_bytes_per_sec = 2; 157 | optional uint32 in_packets_per_sec_x10 = 3; 158 | optional uint32 in_bytes_per_sec = 4; 159 | optional uint32 ping_ms = 5; 160 | optional uint32 packets_dropped_pct = 6; 161 | optional uint32 packets_weird_sequence_pct = 7; 162 | optional uint32 peak_jitter_usec = 8; 163 | } 164 | 165 | message CMsgSteamDatagramLinkLifetimeStats { 166 | optional uint64 packets_sent = 3; 167 | optional uint64 kb_sent = 4; 168 | optional uint64 packets_recv = 5; 169 | optional uint64 kb_recv = 6; 170 | optional uint64 packets_recv_sequenced = 7; 171 | optional uint64 packets_recv_dropped = 8; 172 | optional uint64 packets_recv_out_of_order = 9; 173 | optional uint64 packets_recv_duplicate = 10; 174 | optional uint64 packets_recv_lurch = 11; 175 | optional uint32 quality_histogram_100 = 21; 176 | optional uint32 quality_histogram_99 = 22; 177 | optional uint32 quality_histogram_97 = 23; 178 | optional uint32 quality_histogram_95 = 24; 179 | optional uint32 quality_histogram_90 = 25; 180 | optional uint32 quality_histogram_75 = 26; 181 | optional uint32 quality_histogram_50 = 27; 182 | optional uint32 quality_histogram_1 = 28; 183 | optional uint32 quality_histogram_dead = 29; 184 | optional uint32 quality_ntile_2nd = 30; 185 | optional uint32 quality_ntile_5th = 31; 186 | optional uint32 quality_ntile_25th = 32; 187 | optional uint32 quality_ntile_50th = 33; 188 | optional uint32 ping_histogram_25 = 41; 189 | optional uint32 ping_histogram_50 = 42; 190 | optional uint32 ping_histogram_75 = 43; 191 | optional uint32 ping_histogram_100 = 44; 192 | optional uint32 ping_histogram_125 = 45; 193 | optional uint32 ping_histogram_150 = 46; 194 | optional uint32 ping_histogram_200 = 47; 195 | optional uint32 ping_histogram_300 = 48; 196 | optional uint32 ping_histogram_max = 49; 197 | optional uint32 ping_ntile_5th = 50; 198 | optional uint32 ping_ntile_50th = 51; 199 | optional uint32 ping_ntile_75th = 52; 200 | optional uint32 ping_ntile_95th = 53; 201 | optional uint32 ping_ntile_98th = 54; 202 | optional uint32 jitter_histogram_negligible = 61; 203 | optional uint32 jitter_histogram_1 = 62; 204 | optional uint32 jitter_histogram_2 = 63; 205 | optional uint32 jitter_histogram_5 = 64; 206 | optional uint32 jitter_histogram_10 = 65; 207 | optional uint32 jitter_histogram_20 = 66; 208 | optional uint32 txspeed_max = 67; 209 | optional uint32 txspeed_histogram_16 = 68; 210 | optional uint32 txspeed_histogram_32 = 69; 211 | optional uint32 txspeed_histogram_64 = 70; 212 | optional uint32 txspeed_histogram_128 = 71; 213 | optional uint32 txspeed_histogram_256 = 72; 214 | optional uint32 txspeed_histogram_512 = 73; 215 | optional uint32 txspeed_histogram_1024 = 74; 216 | optional uint32 txspeed_histogram_max = 75; 217 | optional uint32 txspeed_ntile_5th = 76; 218 | optional uint32 txspeed_ntile_50th = 77; 219 | optional uint32 txspeed_ntile_75th = 78; 220 | optional uint32 txspeed_ntile_95th = 79; 221 | optional uint32 txspeed_ntile_98th = 80; 222 | optional uint32 rxspeed_max = 81; 223 | optional uint32 rxspeed_histogram_16 = 82; 224 | optional uint32 rxspeed_histogram_32 = 83; 225 | optional uint32 rxspeed_histogram_64 = 84; 226 | optional uint32 rxspeed_histogram_128 = 85; 227 | optional uint32 rxspeed_histogram_256 = 86; 228 | optional uint32 rxspeed_histogram_512 = 87; 229 | optional uint32 rxspeed_histogram_1024 = 88; 230 | optional uint32 rxspeed_histogram_max = 89; 231 | optional uint32 rxspeed_ntile_5th = 90; 232 | optional uint32 rxspeed_ntile_50th = 91; 233 | optional uint32 rxspeed_ntile_75th = 92; 234 | optional uint32 rxspeed_ntile_95th = 93; 235 | optional uint32 rxspeed_ntile_98th = 94; 236 | } 237 | 238 | message CMsgSteamDatagramConnectionQuality { 239 | optional .CMsgSteamDatagramLinkInstantaneousStats instantaneous = 1; 240 | optional .CMsgSteamDatagramLinkLifetimeStats lifetime = 2; 241 | } 242 | 243 | message CMsgSteamDatagramConnectionStatsClientToRouter { 244 | enum Flags { 245 | ACK_REQUEST_RELAY = 1; 246 | ACK_REQUEST_E2E = 2; 247 | ACK_REQUEST_IMMEDIATE = 4; 248 | } 249 | 250 | optional .CMsgSteamDatagramConnectionQuality c2r = 1; 251 | optional .CMsgSteamDatagramConnectionQuality c2s = 2; 252 | optional fixed32 legacy_client_timestamp = 3; 253 | repeated fixed32 ack_relay = 4; 254 | repeated fixed32 ack_e2e = 5; 255 | optional uint32 flags = 6; 256 | optional fixed32 client_connection_id = 8; 257 | optional uint32 seq_num_c2r = 9; 258 | optional uint32 seq_num_c2s = 10; 259 | } 260 | 261 | message CMsgSteamDatagramConnectionStatsRouterToClient { 262 | enum Flags { 263 | ACK_REQUEST_RELAY = 1; 264 | ACK_REQUEST_E2E = 2; 265 | ACK_REQUEST_IMMEDIATE = 4; 266 | } 267 | 268 | optional .CMsgSteamDatagramConnectionQuality r2c = 1; 269 | optional .CMsgSteamDatagramConnectionQuality s2c = 2; 270 | optional fixed32 legacy_client_timestamp_from_router = 3; 271 | optional fixed32 legacy_client_timestamp_from_server = 4; 272 | optional uint32 router_gameserver_latency = 5; 273 | optional uint32 seconds_until_shutdown = 6; 274 | optional fixed32 migrate_request_ip = 10; 275 | optional uint32 migrate_request_port = 11; 276 | optional uint32 scoring_penalty_relay_cluster = 12; 277 | repeated fixed32 ack_relay = 13; 278 | repeated fixed32 ack_e2e = 14; 279 | optional uint32 flags = 15; 280 | optional fixed32 client_connection_id = 7; 281 | optional uint32 seq_num_r2c = 8; 282 | optional uint32 seq_num_s2c = 9; 283 | } 284 | 285 | message CMsgSteamDatagramConnectionStatsRouterToServer { 286 | enum Flags { 287 | ACK_REQUEST_RELAY = 1; 288 | ACK_REQUEST_E2E = 2; 289 | ACK_REQUEST_IMMEDIATE = 4; 290 | } 291 | 292 | optional .CMsgSteamDatagramConnectionQuality r2s = 1; 293 | optional .CMsgSteamDatagramConnectionQuality c2s = 2; 294 | optional fixed32 legacy_client_timestamp = 3; 295 | optional fixed32 legacy_router_timestamp = 4; 296 | repeated fixed32 ack_relay = 10; 297 | repeated fixed32 ack_e2e = 11; 298 | optional uint32 flags = 12; 299 | optional uint32 seq_num_r2s = 5; 300 | optional uint32 seq_num_c2s = 6; 301 | optional fixed64 client_steam_id = 7; 302 | optional uint32 relay_session_id = 8; 303 | optional fixed32 client_connection_id = 9; 304 | optional fixed32 server_connection_id = 13; 305 | } 306 | 307 | message CMsgSteamDatagramConnectionStatsServerToRouter { 308 | enum Flags { 309 | ACK_REQUEST_RELAY = 1; 310 | ACK_REQUEST_E2E = 2; 311 | ACK_REQUEST_IMMEDIATE = 4; 312 | } 313 | 314 | optional .CMsgSteamDatagramConnectionQuality s2r = 1; 315 | optional .CMsgSteamDatagramConnectionQuality s2c = 2; 316 | repeated fixed32 ack_relay = 8; 317 | repeated fixed32 ack_e2e = 9; 318 | optional uint32 flags = 10; 319 | optional uint32 seq_num_s2r = 3; 320 | optional uint32 seq_num_s2c = 4; 321 | optional fixed64 client_steam_id = 5; 322 | optional uint32 relay_session_id = 6; 323 | optional fixed32 client_connection_id = 7; 324 | optional fixed32 server_connection_id = 11; 325 | } 326 | 327 | message CMsgSteamDatagramClientPingSampleRequest { 328 | optional fixed32 connection_id = 1; 329 | } 330 | 331 | message CMsgSteamDatagramClientPingSampleReply { 332 | message RoutingCluster { 333 | optional fixed32 id = 1; 334 | optional uint32 front_ping_ms = 2; 335 | optional uint32 e2e_ping_ms = 3; 336 | } 337 | 338 | message DataCenter { 339 | optional fixed32 data_center_id = 1; 340 | optional fixed32 via_relay_id = 2; 341 | optional uint32 e2e_ping_ms = 3; 342 | } 343 | 344 | optional fixed32 connection_id = 1; 345 | repeated .CMsgSteamDatagramClientPingSampleReply.RoutingCluster routing_clusters = 2; 346 | repeated .CMsgSteamDatagramClientPingSampleReply.DataCenter data_centers = 3; 347 | } 348 | 349 | message CMsgSteamDatagramClientSwitchedPrimary { 350 | message RouterQuality { 351 | optional uint32 score = 1; 352 | optional uint32 front_ping = 2; 353 | optional uint32 back_ping = 3; 354 | optional uint32 seconds_until_down = 4; 355 | } 356 | 357 | optional fixed32 connection_id = 1; 358 | optional fixed32 from_ip = 2; 359 | optional uint32 from_port = 3; 360 | optional fixed32 from_router_cluster = 4; 361 | optional uint32 from_active_time = 5; 362 | optional uint32 from_active_packets_recv = 6; 363 | optional string from_dropped_reason = 7; 364 | optional uint32 gap_ms = 8; 365 | optional .CMsgSteamDatagramClientSwitchedPrimary.RouterQuality from_quality_now = 9; 366 | optional .CMsgSteamDatagramClientSwitchedPrimary.RouterQuality to_quality_now = 10; 367 | optional .CMsgSteamDatagramClientSwitchedPrimary.RouterQuality from_quality_then = 11; 368 | optional .CMsgSteamDatagramClientSwitchedPrimary.RouterQuality to_quality_then = 12; 369 | } 370 | 371 | message CMsgSteamDatagramRouterHealth { 372 | message DataCenter { 373 | optional fixed32 datacenter_id = 1; 374 | optional uint32 state = 2; 375 | } 376 | 377 | optional float cpu_load = 1; 378 | optional uint32 active_sessions = 2; 379 | optional uint32 data_pkts_sec = 3; 380 | optional uint32 other_pkts_sec = 4; 381 | optional uint32 seconds_until_shutdown = 5; 382 | optional float cpu_cost_per_user = 8; 383 | optional float cpu_cost_per_packet = 9; 384 | repeated .CMsgSteamDatagramRouterHealth.DataCenter data_centers = 6; 385 | optional fixed64 magic = 7; 386 | } 387 | 388 | message CMsgSteamDatagramConnectRequest { 389 | optional fixed32 connection_id = 1; 390 | optional fixed64 client_steam_id = 3; 391 | optional fixed64 my_timestamp = 4; 392 | optional uint32 ping_est_ms = 5; 393 | optional uint32 virtual_port = 9; 394 | optional uint32 gameserver_relay_session_id = 2; 395 | optional .CMsgSteamDatagramSessionCryptInfoSigned crypt = 6; 396 | optional .CMsgSteamDatagramCertificateSigned cert = 7; 397 | optional uint32 protocol_version = 8; 398 | } 399 | 400 | message CMsgSteamDatagramConnectOK { 401 | optional fixed32 client_connection_id = 1; 402 | optional fixed32 server_connection_id = 7; 403 | optional fixed64 your_timestamp = 3; 404 | optional uint32 delay_time_usec = 4; 405 | optional uint32 gameserver_relay_session_id = 2; 406 | optional .CMsgSteamDatagramSessionCryptInfoSigned crypt = 5; 407 | optional .CMsgSteamDatagramCertificateSigned cert = 6; 408 | optional uint32 protocol_version = 8; 409 | } 410 | 411 | message CMsgSteamDatagramConnectionClosed { 412 | enum ERelayMode { 413 | None = 0; 414 | EndToEnd = 1; 415 | ClosedByPeer = 2; 416 | } 417 | 418 | optional fixed32 legacy_client_connection_id = 1; 419 | optional fixed32 to_connection_id = 7; 420 | optional fixed32 from_connection_id = 8; 421 | optional fixed64 peer_steam_id = 3; 422 | optional uint32 gameserver_relay_session_id = 2; 423 | optional .CMsgSteamDatagramConnectionClosed.ERelayMode relay_mode = 4 [default = None]; 424 | optional string debug = 5; 425 | optional uint32 reason_code = 6; 426 | } 427 | 428 | message CMsgSteamDatagramNoConnection { 429 | optional fixed32 legacy_client_connection_id = 1; 430 | optional fixed32 to_connection_id = 5; 431 | optional fixed32 from_connection_id = 6; 432 | optional uint32 gameserver_relay_session_id = 2; 433 | optional fixed64 peer_steam_id = 3; 434 | optional bool end_to_end = 4; 435 | optional fixed32 dummy_pad = 1023; 436 | } 437 | 438 | message CMsgSteamDatagramP2PSessionRequestBody { 439 | optional fixed32 challenge_time = 1; 440 | optional fixed64 challenge = 2; 441 | optional fixed32 my_connection_id = 3; 442 | optional fixed64 peer_steam_id = 4; 443 | optional fixed32 peer_connection_id = 5; 444 | optional uint32 protocol_version = 8; 445 | optional uint32 network_config_version = 9; 446 | optional fixed32 public_ip = 10; 447 | } 448 | 449 | message CMsgSteamDatagramP2PSessionRequest { 450 | optional .CMsgSteamDatagramCertificateSigned cert = 1; 451 | optional bytes body = 2; 452 | optional bytes signature = 3; 453 | } 454 | 455 | message CMsgSteamDatagramP2PSessionEstablished { 456 | optional fixed32 connection_id = 1; 457 | optional uint32 seconds_until_shutdown = 3; 458 | optional fixed64 relay_routing_id = 4; 459 | optional uint32 seq_num_r2c = 5; 460 | } 461 | 462 | message CMsgSteamDatagramP2PRoutes { 463 | message RelayCluster { 464 | optional fixed32 pop_id = 1; 465 | optional uint32 ping_ms = 2; 466 | optional uint32 score_penalty = 3; 467 | optional fixed64 session_relay_routing_id = 4; 468 | } 469 | 470 | message Route { 471 | optional fixed32 my_pop_id = 1; 472 | optional fixed32 your_pop_id = 2; 473 | optional uint32 score = 3; 474 | } 475 | 476 | repeated .CMsgSteamDatagramP2PRoutes.RelayCluster relay_clusters = 1; 477 | repeated .CMsgSteamDatagramP2PRoutes.Route routes = 2; 478 | optional uint32 revision = 3; 479 | } 480 | 481 | message CMsgSteamDatagramP2PRendezvous { 482 | optional fixed32 to_connection_id = 1; 483 | optional .CMsgSteamDatagramP2PRoutes routes = 2; 484 | optional uint32 ack_peer_routes_revision = 3; 485 | optional .CMsgSteamDatagramConnectRequest connect_request = 4; 486 | optional .CMsgSteamDatagramConnectOK connect_ok = 5; 487 | optional .CMsgSteamDatagramConnectionClosed connection_closed = 6; 488 | } 489 | 490 | message CMsgSteamDatagramConnectionStatsP2PClientToRouter { 491 | enum Flags { 492 | ACK_REQUEST_RELAY = 1; 493 | ACK_REQUEST_E2E = 2; 494 | ACK_REQUEST_IMMEDIATE = 4; 495 | } 496 | 497 | optional .CMsgSteamDatagramConnectionQuality c2r = 1; 498 | optional .CMsgSteamDatagramConnectionQuality c2s = 2; 499 | repeated fixed32 ack_relay = 3; 500 | repeated fixed32 ack_e2e = 4; 501 | optional uint32 flags = 5; 502 | optional fixed64 forward_target_relay_routing_id = 6; 503 | optional uint32 forward_target_revision = 7; 504 | optional .CMsgSteamDatagramP2PRoutes routes = 8; 505 | optional uint32 ack_peer_routes_revision = 9; 506 | optional fixed32 connection_id = 10; 507 | optional uint32 seq_num_c2r = 11; 508 | optional uint32 seq_num_c2s = 12; 509 | } 510 | 511 | message CMsgSteamDatagramConnectionStatsP2PRouterToClient { 512 | enum Flags { 513 | ACK_REQUEST_RELAY = 1; 514 | ACK_REQUEST_E2E = 2; 515 | ACK_REQUEST_IMMEDIATE = 4; 516 | } 517 | 518 | optional .CMsgSteamDatagramConnectionQuality r2c = 1; 519 | optional .CMsgSteamDatagramConnectionQuality p2c = 2; 520 | optional uint32 seconds_until_shutdown = 3; 521 | optional fixed32 migrate_request_ip = 4; 522 | optional uint32 migrate_request_port = 5; 523 | optional uint32 scoring_penalty_relay_cluster = 6; 524 | repeated fixed32 ack_relay = 7; 525 | repeated fixed32 ack_e2e = 8; 526 | optional uint32 flags = 9; 527 | optional uint32 ack_forward_target_revision = 10; 528 | optional .CMsgSteamDatagramP2PRoutes routes = 11; 529 | optional uint32 ack_peer_routes_revision = 12; 530 | optional fixed32 connection_id = 13; 531 | optional uint32 seq_num_r2c = 14; 532 | optional uint32 seq_num_p2c = 15; 533 | } 534 | 535 | message CMsgSteamSockets_UDP_ChallengeRequest { 536 | optional fixed32 connection_id = 1; 537 | optional fixed64 my_timestamp = 3; 538 | optional uint32 protocol_version = 4; 539 | } 540 | 541 | message CMsgSteamSockets_UDP_ChallengeReply { 542 | optional fixed32 connection_id = 1; 543 | optional fixed64 challenge = 2; 544 | optional fixed64 your_timestamp = 3; 545 | optional uint32 protocol_version = 4; 546 | } 547 | 548 | message CMsgSteamSockets_UDP_ConnectRequest { 549 | optional fixed32 client_connection_id = 1; 550 | optional fixed64 challenge = 2; 551 | optional fixed64 client_steam_id = 3; 552 | optional fixed64 my_timestamp = 5; 553 | optional uint32 ping_est_ms = 6; 554 | optional .CMsgSteamDatagramSessionCryptInfoSigned crypt = 7; 555 | optional .CMsgSteamDatagramCertificateSigned cert = 4; 556 | optional uint32 protocol_version = 8; 557 | } 558 | 559 | message CMsgSteamSockets_UDP_ConnectOK { 560 | optional fixed32 client_connection_id = 1; 561 | optional fixed32 server_connection_id = 5; 562 | optional fixed64 server_steam_id = 2; 563 | optional fixed64 your_timestamp = 3; 564 | optional uint32 delay_time_usec = 4; 565 | optional .CMsgSteamDatagramSessionCryptInfoSigned crypt = 7; 566 | optional .CMsgSteamDatagramCertificateSigned cert = 8; 567 | optional uint32 protocol_version = 9; 568 | } 569 | 570 | message CMsgSteamSockets_UDP_ConnectionClosed { 571 | optional fixed32 legacy_client_connection_id = 1; 572 | optional fixed32 to_connection_id = 4; 573 | optional fixed32 from_connection_id = 5; 574 | optional string debug = 2; 575 | optional uint32 reason_code = 3; 576 | } 577 | 578 | message CMsgSteamSockets_UDP_NoConnection { 579 | optional fixed32 legacy_client_connection_id = 1; 580 | optional fixed32 from_connection_id = 2; 581 | optional fixed32 to_connection_id = 3; 582 | } 583 | 584 | message CMsgSteamSockets_UDP_Stats { 585 | enum Flags { 586 | ACK_REQUEST_E2E = 2; 587 | ACK_REQUEST_IMMEDIATE = 4; 588 | } 589 | 590 | optional .CMsgSteamDatagramConnectionQuality stats = 1; 591 | repeated fixed32 ack_e2e = 2; 592 | optional uint32 flags = 3; 593 | optional fixed32 legacy_client_connection_id = 8; 594 | optional fixed32 to_connection_id = 9; 595 | optional fixed32 from_connection_id = 10; 596 | optional uint32 seq_num = 4; 597 | } 598 | 599 | -------------------------------------------------------------------------------- /protobufs/google/protobuf/descriptor.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // http://code.google.com/p/protobuf/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // Based on original Protocol Buffers design by 33 | // Sanjay Ghemawat, Jeff Dean, and others. 34 | // 35 | // The messages in this file describe the definitions found in .proto files. 36 | // A valid .proto file can be translated directly to a FileDescriptorProto 37 | // without any other information (e.g. without reading its imports). 38 | 39 | 40 | 41 | package google.protobuf; 42 | option java_package = "com.google.protobuf"; 43 | option java_outer_classname = "DescriptorProtos"; 44 | 45 | // descriptor.proto must be optimized for speed because reflection-based 46 | // algorithms don't work during bootstrapping. 47 | option optimize_for = SPEED; 48 | 49 | // The protocol compiler can output a FileDescriptorSet containing the .proto 50 | // files it parses. 51 | message FileDescriptorSet { 52 | repeated FileDescriptorProto file = 1; 53 | } 54 | 55 | // Describes a complete .proto file. 56 | message FileDescriptorProto { 57 | optional string name = 1; // file name, relative to root of source tree 58 | optional string package = 2; // e.g. "foo", "foo.bar", etc. 59 | 60 | // Names of files imported by this file. 61 | repeated string dependency = 3; 62 | 63 | // All top-level definitions in this file. 64 | repeated DescriptorProto message_type = 4; 65 | repeated EnumDescriptorProto enum_type = 5; 66 | repeated ServiceDescriptorProto service = 6; 67 | repeated FieldDescriptorProto extension = 7; 68 | 69 | optional FileOptions options = 8; 70 | 71 | // This field contains optional information about the original source code. 72 | // You may safely remove this entire field whithout harming runtime 73 | // functionality of the descriptors -- the information is needed only by 74 | // development tools. 75 | optional SourceCodeInfo source_code_info = 9; 76 | } 77 | 78 | // Describes a message type. 79 | message DescriptorProto { 80 | optional string name = 1; 81 | 82 | repeated FieldDescriptorProto field = 2; 83 | repeated FieldDescriptorProto extension = 6; 84 | 85 | repeated DescriptorProto nested_type = 3; 86 | repeated EnumDescriptorProto enum_type = 4; 87 | 88 | message ExtensionRange { 89 | optional int32 start = 1; 90 | optional int32 end = 2; 91 | } 92 | repeated ExtensionRange extension_range = 5; 93 | 94 | optional MessageOptions options = 7; 95 | } 96 | 97 | // Describes a field within a message. 98 | message FieldDescriptorProto { 99 | enum Type { 100 | // 0 is reserved for errors. 101 | // Order is weird for historical reasons. 102 | TYPE_DOUBLE = 1; 103 | TYPE_FLOAT = 2; 104 | TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers 105 | // take 10 bytes. Use TYPE_SINT64 if negative 106 | // values are likely. 107 | TYPE_UINT64 = 4; 108 | TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers 109 | // take 10 bytes. Use TYPE_SINT32 if negative 110 | // values are likely. 111 | TYPE_FIXED64 = 6; 112 | TYPE_FIXED32 = 7; 113 | TYPE_BOOL = 8; 114 | TYPE_STRING = 9; 115 | TYPE_GROUP = 10; // Tag-delimited aggregate. 116 | TYPE_MESSAGE = 11; // Length-delimited aggregate. 117 | 118 | // New in version 2. 119 | TYPE_BYTES = 12; 120 | TYPE_UINT32 = 13; 121 | TYPE_ENUM = 14; 122 | TYPE_SFIXED32 = 15; 123 | TYPE_SFIXED64 = 16; 124 | TYPE_SINT32 = 17; // Uses ZigZag encoding. 125 | TYPE_SINT64 = 18; // Uses ZigZag encoding. 126 | }; 127 | 128 | enum Label { 129 | // 0 is reserved for errors 130 | LABEL_OPTIONAL = 1; 131 | LABEL_REQUIRED = 2; 132 | LABEL_REPEATED = 3; 133 | // TODO(sanjay): Should we add LABEL_MAP? 134 | }; 135 | 136 | optional string name = 1; 137 | optional int32 number = 3; 138 | optional Label label = 4; 139 | 140 | // If type_name is set, this need not be set. If both this and type_name 141 | // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. 142 | optional Type type = 5; 143 | 144 | // For message and enum types, this is the name of the type. If the name 145 | // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping 146 | // rules are used to find the type (i.e. first the nested types within this 147 | // message are searched, then within the parent, on up to the root 148 | // namespace). 149 | optional string type_name = 6; 150 | 151 | // For extensions, this is the name of the type being extended. It is 152 | // resolved in the same manner as type_name. 153 | optional string extendee = 2; 154 | 155 | // For numeric types, contains the original text representation of the value. 156 | // For booleans, "true" or "false". 157 | // For strings, contains the default text contents (not escaped in any way). 158 | // For bytes, contains the C escaped value. All bytes >= 128 are escaped. 159 | // TODO(kenton): Base-64 encode? 160 | optional string default_value = 7; 161 | 162 | optional FieldOptions options = 8; 163 | } 164 | 165 | // Describes an enum type. 166 | message EnumDescriptorProto { 167 | optional string name = 1; 168 | 169 | repeated EnumValueDescriptorProto value = 2; 170 | 171 | optional EnumOptions options = 3; 172 | } 173 | 174 | // Describes a value within an enum. 175 | message EnumValueDescriptorProto { 176 | optional string name = 1; 177 | optional int32 number = 2; 178 | 179 | optional EnumValueOptions options = 3; 180 | } 181 | 182 | // Describes a service. 183 | message ServiceDescriptorProto { 184 | optional string name = 1; 185 | repeated MethodDescriptorProto method = 2; 186 | 187 | optional ServiceOptions options = 3; 188 | } 189 | 190 | // Describes a method of a service. 191 | message MethodDescriptorProto { 192 | optional string name = 1; 193 | 194 | // Input and output type names. These are resolved in the same way as 195 | // FieldDescriptorProto.type_name, but must refer to a message type. 196 | optional string input_type = 2; 197 | optional string output_type = 3; 198 | 199 | optional MethodOptions options = 4; 200 | } 201 | 202 | // =================================================================== 203 | // Options 204 | 205 | // Each of the definitions above may have "options" attached. These are 206 | // just annotations which may cause code to be generated slightly differently 207 | // or may contain hints for code that manipulates protocol messages. 208 | // 209 | // Clients may define custom options as extensions of the *Options messages. 210 | // These extensions may not yet be known at parsing time, so the parser cannot 211 | // store the values in them. Instead it stores them in a field in the *Options 212 | // message called uninterpreted_option. This field must have the same name 213 | // across all *Options messages. We then use this field to populate the 214 | // extensions when we build a descriptor, at which point all protos have been 215 | // parsed and so all extensions are known. 216 | // 217 | // Extension numbers for custom options may be chosen as follows: 218 | // * For options which will only be used within a single application or 219 | // organization, or for experimental options, use field numbers 50000 220 | // through 99999. It is up to you to ensure that you do not use the 221 | // same number for multiple options. 222 | // * For options which will be published and used publicly by multiple 223 | // independent entities, e-mail kenton@google.com to reserve extension 224 | // numbers. Simply tell me how many you need and I'll send you back a 225 | // set of numbers to use -- there's no need to explain how you intend to 226 | // use them. If this turns out to be popular, a web service will be set up 227 | // to automatically assign option numbers. 228 | 229 | 230 | message FileOptions { 231 | 232 | // Sets the Java package where classes generated from this .proto will be 233 | // placed. By default, the proto package is used, but this is often 234 | // inappropriate because proto packages do not normally start with backwards 235 | // domain names. 236 | optional string java_package = 1; 237 | 238 | 239 | // If set, all the classes from the .proto file are wrapped in a single 240 | // outer class with the given name. This applies to both Proto1 241 | // (equivalent to the old "--one_java_file" option) and Proto2 (where 242 | // a .proto always translates to a single class, but you may want to 243 | // explicitly choose the class name). 244 | optional string java_outer_classname = 8; 245 | 246 | // If set true, then the Java code generator will generate a separate .java 247 | // file for each top-level message, enum, and service defined in the .proto 248 | // file. Thus, these types will *not* be nested inside the outer class 249 | // named by java_outer_classname. However, the outer class will still be 250 | // generated to contain the file's getDescriptor() method as well as any 251 | // top-level extensions defined in the file. 252 | optional bool java_multiple_files = 10 [default=false]; 253 | 254 | // If set true, then the Java code generator will generate equals() and 255 | // hashCode() methods for all messages defined in the .proto file. This is 256 | // purely a speed optimization, as the AbstractMessage base class includes 257 | // reflection-based implementations of these methods. 258 | optional bool java_generate_equals_and_hash = 20 [default=false]; 259 | 260 | // Generated classes can be optimized for speed or code size. 261 | enum OptimizeMode { 262 | SPEED = 1; // Generate complete code for parsing, serialization, 263 | // etc. 264 | CODE_SIZE = 2; // Use ReflectionOps to implement these methods. 265 | LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. 266 | } 267 | optional OptimizeMode optimize_for = 9 [default=SPEED]; 268 | 269 | 270 | 271 | 272 | // Should generic services be generated in each language? "Generic" services 273 | // are not specific to any particular RPC system. They are generated by the 274 | // main code generators in each language (without additional plugins). 275 | // Generic services were the only kind of service generation supported by 276 | // early versions of proto2. 277 | // 278 | // Generic services are now considered deprecated in favor of using plugins 279 | // that generate code specific to your particular RPC system. Therefore, 280 | // these default to false. Old code which depends on generic services should 281 | // explicitly set them to true. 282 | optional bool cc_generic_services = 16 [default=false]; 283 | optional bool java_generic_services = 17 [default=false]; 284 | optional bool py_generic_services = 18 [default=false]; 285 | 286 | // The parser stores options it doesn't recognize here. See above. 287 | repeated UninterpretedOption uninterpreted_option = 999; 288 | 289 | // Clients can define custom options in extensions of this message. See above. 290 | extensions 1000 to max; 291 | } 292 | 293 | message MessageOptions { 294 | // Set true to use the old proto1 MessageSet wire format for extensions. 295 | // This is provided for backwards-compatibility with the MessageSet wire 296 | // format. You should not use this for any other reason: It's less 297 | // efficient, has fewer features, and is more complicated. 298 | // 299 | // The message must be defined exactly as follows: 300 | // message Foo { 301 | // option message_set_wire_format = true; 302 | // extensions 4 to max; 303 | // } 304 | // Note that the message cannot have any defined fields; MessageSets only 305 | // have extensions. 306 | // 307 | // All extensions of your type must be singular messages; e.g. they cannot 308 | // be int32s, enums, or repeated messages. 309 | // 310 | // Because this is an option, the above two restrictions are not enforced by 311 | // the protocol compiler. 312 | optional bool message_set_wire_format = 1 [default=false]; 313 | 314 | // Disables the generation of the standard "descriptor()" accessor, which can 315 | // conflict with a field of the same name. This is meant to make migration 316 | // from proto1 easier; new code should avoid fields named "descriptor". 317 | optional bool no_standard_descriptor_accessor = 2 [default=false]; 318 | 319 | // The parser stores options it doesn't recognize here. See above. 320 | repeated UninterpretedOption uninterpreted_option = 999; 321 | 322 | // Clients can define custom options in extensions of this message. See above. 323 | extensions 1000 to max; 324 | } 325 | 326 | message FieldOptions { 327 | // The ctype option instructs the C++ code generator to use a different 328 | // representation of the field than it normally would. See the specific 329 | // options below. This option is not yet implemented in the open source 330 | // release -- sorry, we'll try to include it in a future version! 331 | optional CType ctype = 1 [default = STRING]; 332 | enum CType { 333 | // Default mode. 334 | STRING = 0; 335 | 336 | CORD = 1; 337 | 338 | STRING_PIECE = 2; 339 | } 340 | // The packed option can be enabled for repeated primitive fields to enable 341 | // a more efficient representation on the wire. Rather than repeatedly 342 | // writing the tag and type for each element, the entire array is encoded as 343 | // a single length-delimited blob. 344 | optional bool packed = 2; 345 | 346 | 347 | // Is this field deprecated? 348 | // Depending on the target platform, this can emit Deprecated annotations 349 | // for accessors, or it will be completely ignored; in the very least, this 350 | // is a formalization for deprecating fields. 351 | optional bool deprecated = 3 [default=false]; 352 | 353 | // EXPERIMENTAL. DO NOT USE. 354 | // For "map" fields, the name of the field in the enclosed type that 355 | // is the key for this map. For example, suppose we have: 356 | // message Item { 357 | // required string name = 1; 358 | // required string value = 2; 359 | // } 360 | // message Config { 361 | // repeated Item items = 1 [experimental_map_key="name"]; 362 | // } 363 | // In this situation, the map key for Item will be set to "name". 364 | // TODO: Fully-implement this, then remove the "experimental_" prefix. 365 | optional string experimental_map_key = 9; 366 | 367 | // The parser stores options it doesn't recognize here. See above. 368 | repeated UninterpretedOption uninterpreted_option = 999; 369 | 370 | // Clients can define custom options in extensions of this message. See above. 371 | extensions 1000 to max; 372 | } 373 | 374 | message EnumOptions { 375 | 376 | // The parser stores options it doesn't recognize here. See above. 377 | repeated UninterpretedOption uninterpreted_option = 999; 378 | 379 | // Clients can define custom options in extensions of this message. See above. 380 | extensions 1000 to max; 381 | } 382 | 383 | message EnumValueOptions { 384 | // The parser stores options it doesn't recognize here. See above. 385 | repeated UninterpretedOption uninterpreted_option = 999; 386 | 387 | // Clients can define custom options in extensions of this message. See above. 388 | extensions 1000 to max; 389 | } 390 | 391 | message ServiceOptions { 392 | 393 | // Note: Field numbers 1 through 32 are reserved for Google's internal RPC 394 | // framework. We apologize for hoarding these numbers to ourselves, but 395 | // we were already using them long before we decided to release Protocol 396 | // Buffers. 397 | 398 | // The parser stores options it doesn't recognize here. See above. 399 | repeated UninterpretedOption uninterpreted_option = 999; 400 | 401 | // Clients can define custom options in extensions of this message. See above. 402 | extensions 1000 to max; 403 | } 404 | 405 | message MethodOptions { 406 | 407 | // Note: Field numbers 1 through 32 are reserved for Google's internal RPC 408 | // framework. We apologize for hoarding these numbers to ourselves, but 409 | // we were already using them long before we decided to release Protocol 410 | // Buffers. 411 | 412 | // The parser stores options it doesn't recognize here. See above. 413 | repeated UninterpretedOption uninterpreted_option = 999; 414 | 415 | // Clients can define custom options in extensions of this message. See above. 416 | extensions 1000 to max; 417 | } 418 | 419 | // A message representing a option the parser does not recognize. This only 420 | // appears in options protos created by the compiler::Parser class. 421 | // DescriptorPool resolves these when building Descriptor objects. Therefore, 422 | // options protos in descriptor objects (e.g. returned by Descriptor::options(), 423 | // or produced by Descriptor::CopyTo()) will never have UninterpretedOptions 424 | // in them. 425 | message UninterpretedOption { 426 | // The name of the uninterpreted option. Each string represents a segment in 427 | // a dot-separated name. is_extension is true iff a segment represents an 428 | // extension (denoted with parentheses in options specs in .proto files). 429 | // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents 430 | // "foo.(bar.baz).qux". 431 | message NamePart { 432 | required string name_part = 1; 433 | required bool is_extension = 2; 434 | } 435 | repeated NamePart name = 2; 436 | 437 | // The value of the uninterpreted option, in whatever type the tokenizer 438 | // identified it as during parsing. Exactly one of these should be set. 439 | optional string identifier_value = 3; 440 | optional uint64 positive_int_value = 4; 441 | optional int64 negative_int_value = 5; 442 | optional double double_value = 6; 443 | optional bytes string_value = 7; 444 | optional string aggregate_value = 8; 445 | } 446 | 447 | // =================================================================== 448 | // Optional source code info 449 | 450 | // Encapsulates information about the original source file from which a 451 | // FileDescriptorProto was generated. 452 | message SourceCodeInfo { 453 | // A Location identifies a piece of source code in a .proto file which 454 | // corresponds to a particular definition. This information is intended 455 | // to be useful to IDEs, code indexers, documentation generators, and similar 456 | // tools. 457 | // 458 | // For example, say we have a file like: 459 | // message Foo { 460 | // optional string foo = 1; 461 | // } 462 | // Let's look at just the field definition: 463 | // optional string foo = 1; 464 | // ^ ^^ ^^ ^ ^^^ 465 | // a bc de f ghi 466 | // We have the following locations: 467 | // span path represents 468 | // [a,i) [ 4, 0, 2, 0 ] The whole field definition. 469 | // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). 470 | // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). 471 | // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). 472 | // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). 473 | // 474 | // Notes: 475 | // - A location may refer to a repeated field itself (i.e. not to any 476 | // particular index within it). This is used whenever a set of elements are 477 | // logically enclosed in a single code segment. For example, an entire 478 | // extend block (possibly containing multiple extension definitions) will 479 | // have an outer location whose path refers to the "extensions" repeated 480 | // field without an index. 481 | // - Multiple locations may have the same path. This happens when a single 482 | // logical declaration is spread out across multiple places. The most 483 | // obvious example is the "extend" block again -- there may be multiple 484 | // extend blocks in the same scope, each of which will have the same path. 485 | // - A location's span is not always a subset of its parent's span. For 486 | // example, the "extendee" of an extension declaration appears at the 487 | // beginning of the "extend" block and is shared by all extensions within 488 | // the block. 489 | // - Just because a location's span is a subset of some other location's span 490 | // does not mean that it is a descendent. For example, a "group" defines 491 | // both a type and a field in a single declaration. Thus, the locations 492 | // corresponding to the type and field and their components will overlap. 493 | // - Code which tries to interpret locations should probably be designed to 494 | // ignore those that it doesn't understand, as more types of locations could 495 | // be recorded in the future. 496 | repeated Location location = 1; 497 | message Location { 498 | // Identifies which part of the FileDescriptorProto was defined at this 499 | // location. 500 | // 501 | // Each element is a field number or an index. They form a path from 502 | // the root FileDescriptorProto to the place where the definition. For 503 | // example, this path: 504 | // [ 4, 3, 2, 7, 1 ] 505 | // refers to: 506 | // file.message_type(3) // 4, 3 507 | // .field(7) // 2, 7 508 | // .name() // 1 509 | // This is because FileDescriptorProto.message_type has field number 4: 510 | // repeated DescriptorProto message_type = 4; 511 | // and DescriptorProto.field has field number 2: 512 | // repeated FieldDescriptorProto field = 2; 513 | // and FieldDescriptorProto.name has field number 1: 514 | // optional string name = 1; 515 | // 516 | // Thus, the above path gives the location of a field name. If we removed 517 | // the last element: 518 | // [ 4, 3, 2, 7 ] 519 | // this path refers to the whole field declaration (from the beginning 520 | // of the label to the terminating semicolon). 521 | repeated int32 path = 1 [packed=true]; 522 | 523 | // Always has exactly three or four elements: start line, start column, 524 | // end line (optional, otherwise assumed same as start line), end column. 525 | // These are packed into a single field for efficiency. Note that line 526 | // and column numbers are zero-based -- typically you will want to add 527 | // 1 to each before displaying to a user. 528 | repeated int32 span = 2 [packed=true]; 529 | 530 | // TODO(kenton): Record comments appearing before and after the 531 | // declaration. 532 | } 533 | } 534 | -------------------------------------------------------------------------------- /protobufs/tf_proto_def_messages.proto: -------------------------------------------------------------------------------- 1 | import "google/protobuf/descriptor.proto"; 2 | 3 | option optimize_for = SPEED; 4 | option cc_generic_services = false; 5 | 6 | extend .google.protobuf.MessageOptions { 7 | optional bool start_expanded = 80000 [default = true]; 8 | } 9 | 10 | extend .google.protobuf.FieldOptions { 11 | optional .ProtoDefTypes valid_type = 70000 [default = DEF_TYPE_QUEST_MAP_NODE]; 12 | optional bool editable = 70001 [default = true]; 13 | optional bool localized = 70002 [default = false]; 14 | optional bool do_not_inherit = 70003 [default = false]; 15 | optional string display_name = 70004; 16 | optional string comment = 70005; 17 | optional uint32 max_count = 70007; 18 | optional bool allow_add = 70008 [default = true]; 19 | optional bool allow_delete = 70009 [default = true]; 20 | optional string panel_class_override = 70010; 21 | optional string message_inherhitance_key_field_name = 70011; 22 | optional bool inherit_reference_variables = 70012 [default = false]; 23 | optional bool self_inherit_only = 70013 [default = false]; 24 | optional .EVarFieldType var_field_type = 70014 [default = VAR_TYPE_INVALID]; 25 | optional bool merging_key_field = 70015 [default = false]; 26 | } 27 | 28 | enum LogicalOperation { 29 | AND = 0; 30 | OR = 1; 31 | NOT = 2; 32 | } 33 | 34 | enum EValueDefinitionSource { 35 | REFERENCE_DEFINES = 0; 36 | PARENT_DEFINES = 1; 37 | THIS_DEFINES = 2; 38 | VARIABLE_DEFINES = 3; 39 | NOT_DEFINED = 4; 40 | } 41 | 42 | enum ProtoDefTypes { 43 | DEF_TYPE_QUEST_MAP_NODE = 0; 44 | DEF_TYPE_QUEST_THEME = 2; 45 | DEF_TYPE_QUEST_MAP_REGION = 3; 46 | DEF_TYPE_QUEST = 4; 47 | DEF_TYPE_QUEST_OBJECTIVE = 5; 48 | DEF_TYPE_PAINTKIT_VARIABLES = 6; 49 | DEF_TYPE_PAINTKIT_OPERATION = 7; 50 | DEF_TYPE_PAINTKIT_ITEM_DEFINITION = 8; 51 | DEF_TYPE_PAINTKIT_DEFINITION = 9; 52 | DEF_TYPE_HEADER_ONLY = 10; 53 | DEF_TYPE_QUEST_MAP_STORE_ITEM = 11; 54 | DEF_TYPE_QUEST_MAP_STAR_TYPE = 12; 55 | } 56 | 57 | enum EQuestPoints { 58 | QUEST_POINTS_NOVICE = 0; 59 | QUEST_POINTS_ADVANCED = 1; 60 | QUEST_POINTS_EXPERT = 2; 61 | } 62 | 63 | enum EVarFieldType { 64 | VAR_TYPE_INVALID = 1; 65 | VAR_TYPE_FLOAT = 2; 66 | VAR_TYPE_DOUBLE = 3; 67 | VAR_TYPE_UINT32 = 4; 68 | VAR_TYPE_UINT64 = 5; 69 | VAR_TYPE_SINT32 = 6; 70 | VAR_TYPE_SINT64 = 7; 71 | VAR_TYPE_BOOL = 8; 72 | VAR_TYPE_STRING = 9; 73 | } 74 | 75 | enum ENodeCashReward { 76 | CASH_REWARD_NONE = 1; 77 | CASH_REWARD_SMALL = 2; 78 | CASH_REWARD_MEDIUM = 3; 79 | CASH_REWARD_LARGE = 4; 80 | } 81 | 82 | message CMsgFieldID { 83 | message CMsgField { 84 | optional uint32 field_number = 1; 85 | optional uint32 repeated_index = 2; 86 | } 87 | 88 | repeated .CMsgFieldID.CMsgField field = 1; 89 | } 90 | 91 | message CMsgUniversalFieldID { 92 | optional .EValueDefinitionSource source_type = 1 [default = REFERENCE_DEFINES]; 93 | optional .CMsgProtoDefID defining_obj_id = 2; 94 | optional .CMsgFieldID field_id = 3; 95 | } 96 | 97 | message CMsgVariableDefinition { 98 | optional string name = 1 [(editable) = false, (allow_add) = false, (allow_delete) = false, (merging_key_field) = true]; 99 | optional bool inherit = 2 [default = true]; 100 | optional string value = 3; 101 | } 102 | 103 | message CMsgProtoDefHeader { 104 | required uint32 defindex = 1 [(editable) = false, (display_name) = "Defindex", (comment) = "Autogenerated", (allow_add) = false, (allow_delete) = false, (self_inherit_only) = true]; 105 | optional string name = 2 [(editable) = false, (display_name) = "Name", (comment) = "Name to show in the editor", (allow_add) = false, (allow_delete) = false, (self_inherit_only) = true]; 106 | repeated .CMsgProtoDefID prefabs = 3 [(editable) = false, (display_name) = "Prefab", (comment) = "Inherit the values of these definitions, in order from top to bottom.", (allow_add) = false, (allow_delete) = false, (panel_class_override) = "CPrefabFieldEditingPanel", (self_inherit_only) = true]; 107 | repeated string tags = 4 [(editable) = false, (display_name) = "Tags", (comment) = "Strings used to describe this definition while searching. ie. 'class', 'shotgun', 'easy'", (allow_add) = false, (allow_delete) = false]; 108 | optional bool prefab_only = 5 [default = false, (editable) = false, (display_name) = "Pure Prefab", (comment) = "If true, this is only a prefab and will not be made into an object", (allow_add) = false, (allow_delete) = false, (self_inherit_only) = true]; 109 | repeated .CMsgVariableDefinition variables = 6 [(editable) = false, (display_name) = "Variables", (comment) = "Variable value definitions", (allow_add) = false, (allow_delete) = false, (message_inherhitance_key_field_name) = "name"]; 110 | } 111 | 112 | message CMsgValidTypes { 113 | repeated .ProtoDefTypes types = 1; 114 | } 115 | 116 | message CMsgProtoDefID { 117 | optional uint32 defindex = 1; 118 | optional .ProtoDefTypes type = 2 [default = DEF_TYPE_QUEST_MAP_NODE]; 119 | oneof instance { 120 | .CMsgQuestMapNodeDef instance_def_type_quest_map_node = 3; 121 | .CMsgQuestTheme instance_def_type_quest_theme = 5; 122 | .CMsgQuestMapRegionDef instance_def_type_quest_map_region = 6; 123 | .CMsgQuestDef instance_def_type_quest = 7; 124 | .CMsgQuestObjectiveDef instance_def_type_quest_objective = 8; 125 | .CMsgPaintKit_Variables instance_def_type_paintkit_variables = 9; 126 | .CMsgPaintKit_Operation instance_def_type_paintkit_operation = 10; 127 | .CMsgPaintKit_ItemDefinition instance_def_type_paintkit_item_definition = 11; 128 | .CMsgPaintKit_Definition instance_def_type_paintkit_definition = 12; 129 | .CMsgHeaderOnly instance_def_type_header_only = 13; 130 | } 131 | } 132 | 133 | message CMsgQuestObjectiveDef { 134 | enum ETF2GameModes { 135 | kGameCategory_Escort = 0; 136 | kGameCategory_CTF = 1; 137 | kGameCategory_AttackDefense = 2; 138 | kGameCategory_Koth = 3; 139 | kGameCategory_CP = 4; 140 | kGameCategory_EscortRace = 5; 141 | kGameCategory_EventMix = 6; 142 | kGameCategory_SD = 7; 143 | kGameCategory_Quickplay = 8; 144 | kGameCategory_Event247 = 9; 145 | kGameCategory_Arena = 10; 146 | kGameCategory_RobotDestruction = 11; 147 | kGameCategory_Powerup = 12; 148 | kGameCategory_Featured = 13; 149 | kGameCategory_Passtime = 14; 150 | kGameCategory_Community_Update = 15; 151 | kGameCategory_Misc = 16; 152 | kGameCategory_Competitive_6v6 = 17; 153 | kGameCategory_Other = 18; 154 | kGameCategory_Halloween = 19; 155 | } 156 | 157 | enum ETF2Conditions { 158 | TF_COND_AIMING = 0; 159 | TF_COND_ZOOMED = 1; 160 | TF_COND_DISGUISING = 2; 161 | TF_COND_DISGUISED = 3; 162 | TF_COND_STEALTHED = 4; 163 | TF_COND_INVULNERABLE = 5; 164 | TF_COND_TELEPORTED = 6; 165 | TF_COND_TAUNTING = 7; 166 | TF_COND_INVULNERABLE_WEARINGOFF = 8; 167 | TF_COND_STEALTHED_BLINK = 9; 168 | TF_COND_SELECTED_TO_TELEPORT = 10; 169 | TF_COND_CRITBOOSTED = 11; 170 | TF_COND_TMPDAMAGEBONUS = 12; 171 | TF_COND_FEIGN_DEATH = 13; 172 | TF_COND_PHASE = 14; 173 | TF_COND_STUNNED = 15; 174 | TF_COND_OFFENSEBUFF = 16; 175 | TF_COND_SHIELD_CHARGE = 17; 176 | TF_COND_DEMO_BUFF = 18; 177 | TF_COND_ENERGY_BUFF = 19; 178 | TF_COND_RADIUSHEAL = 20; 179 | TF_COND_HEALTH_BUFF = 21; 180 | TF_COND_BURNING = 22; 181 | TF_COND_HEALTH_OVERHEALED = 23; 182 | TF_COND_URINE = 24; 183 | TF_COND_BLEEDING = 25; 184 | TF_COND_DEFENSEBUFF = 26; 185 | TF_COND_MAD_MILK = 27; 186 | TF_COND_MEGAHEAL = 28; 187 | TF_COND_REGENONDAMAGEBUFF = 29; 188 | TF_COND_MARKEDFORDEATH = 30; 189 | TF_COND_NOHEALINGDAMAGEBUFF = 31; 190 | TF_COND_SPEED_BOOST = 32; 191 | TF_COND_CRITBOOSTED_PUMPKIN = 33; 192 | TF_COND_CRITBOOSTED_USER_BUFF = 34; 193 | TF_COND_CRITBOOSTED_DEMO_CHARGE = 35; 194 | TF_COND_SODAPOPPER_HYPE = 36; 195 | TF_COND_CRITBOOSTED_FIRST_BLOOD = 37; 196 | TF_COND_CRITBOOSTED_BONUS_TIME = 38; 197 | TF_COND_CRITBOOSTED_CTF_CAPTURE = 39; 198 | TF_COND_CRITBOOSTED_ON_KILL = 40; 199 | TF_COND_CANNOT_SWITCH_FROM_MELEE = 41; 200 | TF_COND_DEFENSEBUFF_NO_CRIT_BLOCK = 42; 201 | TF_COND_REPROGRAMMED = 43; 202 | TF_COND_CRITBOOSTED_RAGE_BUFF = 44; 203 | TF_COND_DEFENSEBUFF_HIGH = 45; 204 | TF_COND_SNIPERCHARGE_RAGE_BUFF = 46; 205 | TF_COND_DISGUISE_WEARINGOFF = 47; 206 | TF_COND_MARKEDFORDEATH_SILENT = 48; 207 | TF_COND_DISGUISED_AS_DISPENSER = 49; 208 | TF_COND_SAPPED = 50; 209 | TF_COND_INVULNERABLE_HIDE_UNLESS_DAMAGED = 51; 210 | TF_COND_INVULNERABLE_USER_BUFF = 52; 211 | TF_COND_HALLOWEEN_BOMB_HEAD = 53; 212 | TF_COND_HALLOWEEN_THRILLER = 54; 213 | TF_COND_RADIUSHEAL_ON_DAMAGE = 55; 214 | TF_COND_CRITBOOSTED_CARD_EFFECT = 56; 215 | TF_COND_INVULNERABLE_CARD_EFFECT = 57; 216 | TF_COND_MEDIGUN_UBER_BULLET_RESIST = 58; 217 | TF_COND_MEDIGUN_UBER_BLAST_RESIST = 59; 218 | TF_COND_MEDIGUN_UBER_FIRE_RESIST = 60; 219 | TF_COND_MEDIGUN_SMALL_BULLET_RESIST = 61; 220 | TF_COND_MEDIGUN_SMALL_BLAST_RESIST = 62; 221 | TF_COND_MEDIGUN_SMALL_FIRE_RESIST = 63; 222 | TF_COND_STEALTHED_USER_BUFF = 64; 223 | TF_COND_MEDIGUN_DEBUFF = 65; 224 | TF_COND_STEALTHED_USER_BUFF_FADING = 66; 225 | TF_COND_BULLET_IMMUNE = 67; 226 | TF_COND_BLAST_IMMUNE = 68; 227 | TF_COND_FIRE_IMMUNE = 69; 228 | TF_COND_PREVENT_DEATH = 70; 229 | TF_COND_MVM_BOT_STUN_RADIOWAVE = 71; 230 | TF_COND_HALLOWEEN_SPEED_BOOST = 72; 231 | TF_COND_HALLOWEEN_QUICK_HEAL = 73; 232 | TF_COND_HALLOWEEN_GIANT = 74; 233 | TF_COND_HALLOWEEN_TINY = 75; 234 | TF_COND_HALLOWEEN_IN_HELL = 76; 235 | TF_COND_HALLOWEEN_GHOST_MODE = 77; 236 | TF_COND_MINICRITBOOSTED_ON_KILL = 78; 237 | TF_COND_OBSCURED_SMOKE = 79; 238 | TF_COND_PARACHUTE_ACTIVE = 80; 239 | TF_COND_BLASTJUMPING = 81; 240 | TF_COND_HALLOWEEN_KART = 82; 241 | TF_COND_HALLOWEEN_KART_DASH = 83; 242 | TF_COND_BALLOON_HEAD = 84; 243 | TF_COND_MELEE_ONLY = 85; 244 | TF_COND_SWIMMING_CURSE = 86; 245 | TF_COND_FREEZE_INPUT = 87; 246 | TF_COND_HALLOWEEN_KART_CAGE = 88; 247 | TF_COND_DONOTUSE_0 = 89; 248 | TF_COND_RUNE_STRENGTH = 90; 249 | TF_COND_RUNE_HASTE = 91; 250 | TF_COND_RUNE_REGEN = 92; 251 | TF_COND_RUNE_RESIST = 93; 252 | TF_COND_RUNE_VAMPIRE = 94; 253 | TF_COND_RUNE_REFLECT = 95; 254 | TF_COND_RUNE_PRECISION = 96; 255 | TF_COND_RUNE_AGILITY = 97; 256 | TF_COND_GRAPPLINGHOOK = 98; 257 | TF_COND_GRAPPLINGHOOK_SAFEFALL = 99; 258 | TF_COND_GRAPPLINGHOOK_LATCHED = 100; 259 | TF_COND_GRAPPLINGHOOK_BLEEDING = 101; 260 | TF_COND_AFTERBURN_IMMUNE = 102; 261 | TF_COND_RUNE_KNOCKOUT = 103; 262 | TF_COND_RUNE_IMBALANCE = 104; 263 | TF_COND_CRITBOOSTED_RUNE_TEMP = 105; 264 | TF_COND_PASSTIME_INTERCEPTION = 106; 265 | TF_COND_SWIMMING_NO_EFFECTS = 107; 266 | TF_COND_PURGATORY = 108; 267 | TF_COND_RUNE_KING = 109; 268 | TF_COND_RUNE_PLAGUE = 110; 269 | TF_COND_RUNE_SUPERNOVA = 111; 270 | TF_COND_PLAGUE = 112; 271 | TF_COND_KING_BUFFED = 113; 272 | TF_COND_TEAM_GLOWS = 114; 273 | TF_COND_KNOCKED_INTO_AIR = 115; 274 | TF_COND_COMPETITIVE_WINNER = 116; 275 | TF_COND_COMPETITIVE_LOSER = 117; 276 | TF_COND_HEALING_DEBUFF = 118; 277 | TF_COND_PASSTIME_PENALTY_DEBUFF = 119; 278 | TF_COND_PARACHUTE_DEPLOYED = 120; 279 | TF_COND_NO_COMBAT_SPEED_BOOST = 121; 280 | TF_COND_TRANQ_SPY_BOOST = 122; 281 | TF_COND_TRANQ_MARKED = 123; 282 | TF_COND_ROCKETPACK = 126; 283 | TF_COND_ROCKETPACK_PASSENGER = 127; 284 | TF_COND_STEALTHED_PHASE = 128; 285 | TF_COND_CLIP_OVERLOAD = 129; 286 | TF_COND_SPY_CLASS_STEAL = 130; 287 | TF_COND_GAS = 131; 288 | } 289 | 290 | enum ETF2Team { 291 | TF_TEAM_RED = 2; 292 | TF_TEAM_BLUE = 3; 293 | } 294 | 295 | required .CMsgProtoDefHeader header = 1; 296 | optional string loc_desctoken = 2 [(editable) = false, (localized) = true, (allow_add) = false, (allow_delete) = false]; 297 | optional uint32 points = 3; 298 | optional uint32 conditions_defindex = 5; 299 | repeated string map = 8 [(editable) = false, (display_name) = "Maps Modifier", (comment) = "If set, the player must be on one of the listed maps to get credit.", (allow_add) = false, (allow_delete) = false]; 300 | repeated .CMsgQuestObjectiveDef.ETF2GameModes game_mode = 9 [(editable) = false, (display_name) = "Game Mode Modifier", (comment) = "If set, the player must be in one of the listed game modes to get credit.", (allow_add) = false, (allow_delete) = false]; 301 | optional .CMsgQuestObjectiveDef.ETF2Team team = 10 [default = TF_TEAM_RED, (editable) = false, (display_name) = "Team Modifier", (comment) = "If set, the player must be on the specified team to get credit.", (allow_add) = false, (allow_delete) = false]; 302 | repeated .CMsgVarField condition_vars = 11 [(editable) = false, (display_name) = "Objective Vars", (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 303 | repeated .CMsgVarField classes_vars = 12 [(editable) = false, (display_name) = "Class Modifier", (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 304 | repeated .CMsgQuestObjectiveDef.ETF2Conditions conditions = 13 [(editable) = false, (display_name) = "Required Conds", (allow_add) = false, (allow_delete) = false]; 305 | optional .LogicalOperation condition_logic = 14 [default = AND, (editable) = false, (display_name) = "Condition Logic", (comment) = "What kind of logic to use when evaluating the player's conditions.", (allow_add) = false, (allow_delete) = false]; 306 | repeated string item_name = 15 [(editable) = false, (display_name) = "Required equipped item", (comment) = "Require that this item be equipped in any slot.", (allow_add) = false, (allow_delete) = false]; 307 | optional .LogicalOperation item_logic = 16 [default = AND, (editable) = false, (display_name) = "Item logic", (comment) = "What kind of logic to use when evaluating the player's items.", (allow_add) = false, (allow_delete) = false]; 308 | optional uint32 jump_state = 17 [(editable) = false, (display_name) = "Jump logic", (comment) = "What state of jumping the player needs to be in.", (allow_add) = false, (allow_delete) = false]; 309 | } 310 | 311 | message CMsgQuestDef { 312 | message MMCriteria { 313 | optional string group_name = 1; 314 | optional string category_name = 2; 315 | optional string map_name = 3; 316 | } 317 | 318 | message ObjectiveInstance { 319 | optional .CMsgProtoDefID objective = 1 [(valid_type) = DEF_TYPE_QUEST_OBJECTIVE, (editable) = false, (allow_add) = false, (allow_delete) = false]; 320 | optional .EQuestPoints point_type = 2 [default = QUEST_POINTS_NOVICE]; 321 | optional uint32 point_value = 3 [(editable) = false, (display_name) = "Points Override", (comment) = "Override value for the point value of the objective. If not set, uses the objective's point value", (allow_add) = false, (allow_delete) = false]; 322 | } 323 | 324 | required .CMsgProtoDefHeader header = 1; 325 | optional uint32 max_points_0 = 2; 326 | optional uint32 max_points_1 = 3; 327 | optional uint32 max_points_2 = 4; 328 | optional string name_loctoken = 5 [(editable) = false, (localized) = true, (allow_add) = false, (allow_delete) = false]; 329 | optional string operation = 7; 330 | optional .CMsgQuestDef.MMCriteria mm_criteria = 8; 331 | optional string node_image = 12 [(editable) = false, (display_name) = "Node Image", (comment) = "Filename of the image to show on the node view", (allow_add) = false, (allow_delete) = false]; 332 | optional string icon_image = 13 [(editable) = false, (display_name) = "Node Icon", (comment) = "Which icon to show on the map", (allow_add) = false, (allow_delete) = false]; 333 | optional .CMsgProtoDefID theme = 14 [(valid_type) = DEF_TYPE_QUEST_THEME, (editable) = false, (allow_add) = false, (allow_delete) = false]; 334 | repeated string loaner_names = 15 [(editable) = false, (display_name) = "Loaners", (comment) = "Names of items to give as loaners", (allow_add) = false, (allow_delete) = false]; 335 | repeated .CMsgQuestDef.ObjectiveInstance objectives = 16; 336 | repeated string map = 17 [(editable) = false, (display_name) = "Maps Modifier", (comment) = "If set, the player must be on one of the listed maps to get credit.", (allow_add) = false, (allow_delete) = false]; 337 | } 338 | 339 | message CMsgQuestMapStoreItem { 340 | required .CMsgProtoDefHeader header = 1; 341 | optional string item_name = 2; 342 | optional string reward_lootlist_name = 6 [(editable) = false, (display_name) = "Reward Lootlist", (comment) = "The name of the lootlist to roll as a reward", (allow_add) = false, (allow_delete) = false]; 343 | optional .CMsgVarField price = 3 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_SINT32]; 344 | optional uint32 purchase_limit = 4 [(editable) = false, (display_name) = "Purchase Limit", (comment) = "How many times this reward can be purchased", (allow_add) = false, (allow_delete) = false]; 345 | optional uint32 sort_group = 5 [(editable) = false, (display_name) = "Sort group", (comment) = "Sort by this group, then alhpabetically", (allow_add) = false, (allow_delete) = false]; 346 | } 347 | 348 | message CMsgQuestMapRegionDef { 349 | message RegionLink { 350 | required .CMsgProtoDefID target_region_defid = 1 [(valid_type) = DEF_TYPE_QUEST_MAP_REGION, (editable) = false, (allow_add) = false, (allow_delete) = false]; 351 | optional uint32 xpos = 2; 352 | optional uint32 ypos = 3; 353 | } 354 | 355 | required .CMsgProtoDefHeader header = 1; 356 | optional string name = 2 [(editable) = false, (localized) = true, (allow_add) = false, (allow_delete) = false]; 357 | optional string resfile = 3; 358 | repeated .CMsgQuestMapRegionDef.RegionLink links = 4; 359 | optional .CMsgProtoDefID return_link = 5 [(valid_type) = DEF_TYPE_QUEST_MAP_REGION, (editable) = false, (display_name) = "Return Link", (comment) = "Which link we go to when right-clicking in this region", (allow_add) = false, (allow_delete) = false]; 360 | optional float radio_freq = 6 [(editable) = false, (display_name) = "Radio Freq.", (comment) = "Where the radio tuner goes on the CYOA PDA when this region is selection", (allow_add) = false, (allow_delete) = false]; 361 | optional float zoom_scale = 7 [(editable) = false, (display_name) = "Zoom Scale", (comment) = "How zoomed in this panel should be. Affects the scale of the map grid lines and node link dashed lines", (allow_add) = false, (allow_delete) = false]; 362 | optional .CMsgProtoDefID star_type = 8 [(valid_type) = DEF_TYPE_QUEST_MAP_STAR_TYPE, (editable) = false, (display_name) = "Star Type", (comment) = "What stars (if any) the nodes within use to unlock", (allow_add) = false, (allow_delete) = false]; 363 | } 364 | 365 | message CMsgVarField { 366 | optional string variable = 1 [(editable) = false, (allow_add) = false, (allow_delete) = false, (merging_key_field) = true]; 367 | oneof value { 368 | float float = 2; 369 | double double = 3; 370 | uint32 uint32 = 4; 371 | uint64 uint64 = 5; 372 | sint32 sint32 = 6; 373 | sint64 sint64 = 7; 374 | bool bool = 8; 375 | string string = 9; 376 | } 377 | } 378 | 379 | message CMsgQuestMapStarType { 380 | required .CMsgProtoDefHeader header = 1; 381 | optional string name = 2 [(editable) = false, (localized) = true, (display_name) = "Type Name", (allow_add) = false, (allow_delete) = false]; 382 | } 383 | 384 | message CMsgQuestMapNodeDef { 385 | required .CMsgProtoDefHeader header = 1; 386 | optional string name_loctoken = 4 [(editable) = false, (localized) = true, (display_name) = "Node Name", (comment) = "The name of this node", (allow_add) = false, (allow_delete) = false]; 387 | optional float x_pos = 6 [(editable) = false, (display_name) = "Map X Pos", (comment) = "X position on the quest map", (allow_add) = false, (allow_delete) = false]; 388 | optional float y_pos = 7 [(editable) = false, (display_name) = "Map Y Pos", (comment) = "Y position on the quest map", (allow_add) = false, (allow_delete) = false]; 389 | optional .CMsgQuestMapNodeCondition condition = 9 [(editable) = false, (display_name) = "Conditions", (comment) = "Logic to unlock this node. Can be nested with logic", (allow_add) = false, (allow_delete) = false]; 390 | optional .CMsgProtoDefID owning_region = 10 [(valid_type) = DEF_TYPE_QUEST_MAP_REGION, (editable) = false, (display_name) = "Region", (comment) = "Which region in the map this node shows up in", (allow_add) = false, (allow_delete) = false]; 391 | repeated .CMsgProtoDefID quest_options = 11 [(valid_type) = DEF_TYPE_QUEST, (editable) = false, (display_name) = "Offered Quests", (comment) = "Which quests this node offers.", (max_count) = 3, (allow_add) = false, (allow_delete) = false]; 392 | optional string associated_operation = 16 [(editable) = false, (display_name) = "Associated Operation", (comment) = "Operation this node is associated with", (allow_add) = false, (allow_delete) = false]; 393 | optional string reward_item_name = 18 [(editable) = false, (display_name) = "Reward Item", (comment) = "The name of an item to give as a reward", (allow_add) = false, (allow_delete) = false]; 394 | optional string reward_lootlist_name = 22 [(editable) = false, (display_name) = "Reward Lootlist", (comment) = "The name of the lootlist to roll as a reward", (allow_add) = false, (allow_delete) = false]; 395 | optional .ENodeCashReward cash_reward = 19 [default = CASH_REWARD_NONE, (editable) = false, (display_name) = "Cash Reward", (comment) = "How much cash to give when completing the primary objective", (allow_add) = false, (allow_delete) = false]; 396 | optional .CMsgProtoDefID star_type = 20 [(valid_type) = DEF_TYPE_QUEST_MAP_STAR_TYPE, (editable) = false, (display_name) = "Star Type", (comment) = "Which type of star this node uses", (allow_add) = false, (allow_delete) = false]; 397 | optional uint32 stars_to_unlock = 21 [default = 1, (editable) = false, (display_name) = "Stars to Unlock", (comment) = "Numbers of stars it costs to unlock", (allow_add) = false, (allow_delete) = false]; 398 | } 399 | 400 | message CMsgPaintKit_Variables { 401 | required .CMsgProtoDefHeader header = 1; 402 | } 403 | 404 | message CMsgPaintKit_Operation_TextureStage { 405 | optional .CMsgVarField texture = 1 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 406 | optional .CMsgVarField texture_red = 2 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 407 | optional .CMsgVarField texture_blue = 3 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 408 | optional .CMsgVarField adjust_black = 4 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 409 | optional .CMsgVarField adjust_offset = 5 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 410 | optional .CMsgVarField adjust_gamma = 6 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 411 | optional .CMsgVarField rotation = 7 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 412 | optional .CMsgVarField translate_u = 8 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 413 | optional .CMsgVarField translate_v = 9 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 414 | optional .CMsgVarField scale_uv = 10 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 415 | optional .CMsgVarField flip_u = 11 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 416 | optional .CMsgVarField flip_v = 12 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 417 | } 418 | 419 | message CMsgPaintKit_Operation_CombineStage { 420 | optional .CMsgVarField adjust_black = 1 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 421 | optional .CMsgVarField adjust_offset = 2 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 422 | optional .CMsgVarField adjust_gamma = 3 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 423 | optional .CMsgVarField rotation = 4 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 424 | optional .CMsgVarField translate_u = 5 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 425 | optional .CMsgVarField translate_v = 6 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 426 | optional .CMsgVarField scale_uv = 7 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 427 | optional .CMsgVarField flip_u = 8 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 428 | optional .CMsgVarField flip_v = 9 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 429 | repeated .CMsgPaintKit_OperationNode operation_node = 11; 430 | } 431 | 432 | message CMsgPaintKit_Operation_SelectStage { 433 | optional .CMsgVarField groups = 1 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 434 | repeated .CMsgVarField select = 2 [(editable) = false, (max_count) = 16, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 435 | } 436 | 437 | message CMsgPaintKit_Operation_Sticker { 438 | optional .CMsgVarField base = 1 [(editable) = false, (comment) = "Name of the base file for the sticker (the albedo)", (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 439 | optional .CMsgVarField weight = 2 [(editable) = false, (comment) = "Random likelihood this one is to be selected", (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 440 | optional .CMsgVarField spec = 3 [(editable) = false, (comment) = "Name of the specular file for the sticker, or if blank we will assume it is baseFilename + _spec + baseExtension", (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 441 | } 442 | 443 | message CMsgPaintKit_Operation_StickerStage { 444 | repeated .CMsgPaintKit_Operation_Sticker sticker = 1; 445 | optional .CMsgVarField dest_tl = 2 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 446 | optional .CMsgVarField dest_tr = 3 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 447 | optional .CMsgVarField dest_bl = 4 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 448 | optional .CMsgVarField adjust_black = 5 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 449 | optional .CMsgVarField adjust_offset = 6 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 450 | optional .CMsgVarField adjust_gamma = 7 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 451 | repeated .CMsgPaintKit_OperationNode operation_node = 9; 452 | } 453 | 454 | message CMsgPaintKit_OperationStage { 455 | oneof stage { 456 | .CMsgPaintKit_Operation_TextureStage texture_lookup = 1; 457 | .CMsgPaintKit_Operation_CombineStage combine_add = 2; 458 | .CMsgPaintKit_Operation_CombineStage combine_lerp = 3; 459 | .CMsgPaintKit_Operation_CombineStage combine_multiply = 4; 460 | .CMsgPaintKit_Operation_SelectStage select = 5; 461 | .CMsgPaintKit_Operation_StickerStage apply_sticker = 6; 462 | } 463 | } 464 | 465 | message CMsgPaintKit_OperationNode { 466 | oneof node { 467 | .CMsgPaintKit_OperationStage stage = 1; 468 | .CMsgProtoDefID operation_template = 2 [(valid_type) = DEF_TYPE_PAINTKIT_OPERATION, (editable) = false, (allow_add) = false, (allow_delete) = false, (inherit_reference_variables) = true]; 469 | } 470 | } 471 | 472 | message CMsgPaintKit_Operation { 473 | required .CMsgProtoDefHeader header = 1; 474 | repeated .CMsgPaintKit_OperationNode operation_node = 2; 475 | } 476 | 477 | message CMsgPaintKit_ItemDefinition { 478 | message Definition { 479 | optional .CMsgProtoDefID operation_template = 1 [(valid_type) = DEF_TYPE_PAINTKIT_OPERATION, (editable) = false, (allow_add) = false, (allow_delete) = false]; 480 | repeated .CMsgVarField variable = 2 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 481 | } 482 | 483 | required .CMsgProtoDefHeader header = 1; 484 | required uint32 item_definition_index = 2; 485 | optional .CMsgProtoDefID variable_template = 3 [(valid_type) = DEF_TYPE_PAINTKIT_VARIABLES, (editable) = false, (allow_add) = false, (allow_delete) = false, (inherit_reference_variables) = true]; 486 | repeated .CMsgPaintKit_ItemDefinition.Definition definition = 4 [(editable) = false, (max_count) = 5, (allow_add) = false, (allow_delete) = false]; 487 | } 488 | 489 | message CMsgPaintKit_Definition { 490 | message Item { 491 | option (start_expanded) = false; 492 | message ItemData { 493 | optional bool can_apply_paintkit = 2 [default = true]; 494 | optional string material_override = 3; 495 | repeated .CMsgVarField variable = 4 [(editable) = false, (allow_add) = false, (allow_delete) = false, (var_field_type) = VAR_TYPE_STRING]; 496 | } 497 | 498 | required .CMsgProtoDefID item_definition_template = 1 [(valid_type) = DEF_TYPE_PAINTKIT_ITEM_DEFINITION, (editable) = false, (allow_add) = false, (allow_delete) = false, (panel_class_override) = "CPaintKitDefIdFieldProtoEditorField"]; 499 | optional .CMsgPaintKit_Definition.Item.ItemData data = 5; 500 | } 501 | 502 | required .CMsgProtoDefHeader header = 1; 503 | optional string loc_desctoken = 2 [(editable) = false, (localized) = true, (allow_add) = false, (allow_delete) = false]; 504 | optional .CMsgProtoDefID operation_template = 3 [(valid_type) = DEF_TYPE_PAINTKIT_OPERATION, (editable) = false, (comment) = "operation template which all items in the list will use unless there's operation_template specified in an item_definition", (allow_add) = false, (allow_delete) = false, (inherit_reference_variables) = true]; 505 | optional bool has_team_textures = 4; 506 | repeated .CMsgPaintKit_Definition.Item item = 5; 507 | optional .CMsgPaintKit_Definition.Item paintkit_tool = 6; 508 | optional .CMsgPaintKit_Definition.Item flamethrower = 7; 509 | optional .CMsgPaintKit_Definition.Item grenadelauncher = 8; 510 | optional .CMsgPaintKit_Definition.Item knife = 9; 511 | optional .CMsgPaintKit_Definition.Item medigun = 10; 512 | optional .CMsgPaintKit_Definition.Item minigun = 11; 513 | optional .CMsgPaintKit_Definition.Item pistol = 12; 514 | optional .CMsgPaintKit_Definition.Item revolver = 13; 515 | optional .CMsgPaintKit_Definition.Item rocketlauncher = 14; 516 | optional .CMsgPaintKit_Definition.Item scattergun = 15; 517 | optional .CMsgPaintKit_Definition.Item shotgun = 16; 518 | optional .CMsgPaintKit_Definition.Item smg = 17; 519 | optional .CMsgPaintKit_Definition.Item sniperrifle = 18; 520 | optional .CMsgPaintKit_Definition.Item stickybomb_launcher = 19; 521 | optional .CMsgPaintKit_Definition.Item ubersaw = 20; 522 | optional .CMsgPaintKit_Definition.Item wrench = 21; 523 | optional .CMsgPaintKit_Definition.Item amputator = 22; 524 | optional .CMsgPaintKit_Definition.Item atom_launcher = 23; 525 | optional .CMsgPaintKit_Definition.Item back_scratcher = 24; 526 | optional .CMsgPaintKit_Definition.Item battleaxe = 25; 527 | optional .CMsgPaintKit_Definition.Item bazaar_sniper = 26; 528 | optional .CMsgPaintKit_Definition.Item blackbox = 27; 529 | optional .CMsgPaintKit_Definition.Item claidheamohmor = 28; 530 | optional .CMsgPaintKit_Definition.Item crusaders_crossbow = 29; 531 | optional .CMsgPaintKit_Definition.Item degreaser = 30; 532 | optional .CMsgPaintKit_Definition.Item demo_cannon = 31; 533 | optional .CMsgPaintKit_Definition.Item demo_sultan_sword = 32; 534 | optional .CMsgPaintKit_Definition.Item detonator = 33; 535 | optional .CMsgPaintKit_Definition.Item gatling_gun = 34; 536 | optional .CMsgPaintKit_Definition.Item holymackerel = 35; 537 | optional .CMsgPaintKit_Definition.Item jag = 36; 538 | optional .CMsgPaintKit_Definition.Item lochnload = 37; 539 | optional .CMsgPaintKit_Definition.Item powerjack = 38; 540 | optional .CMsgPaintKit_Definition.Item quadball = 39; 541 | optional .CMsgPaintKit_Definition.Item reserve_shooter = 40; 542 | optional .CMsgPaintKit_Definition.Item riding_crop = 41; 543 | optional .CMsgPaintKit_Definition.Item russian_riot = 42; 544 | optional .CMsgPaintKit_Definition.Item scimitar = 43; 545 | optional .CMsgPaintKit_Definition.Item scorch_shot = 44; 546 | optional .CMsgPaintKit_Definition.Item shortstop = 45; 547 | optional .CMsgPaintKit_Definition.Item soda_popper = 46; 548 | optional .CMsgPaintKit_Definition.Item tele_shotgun = 47; 549 | optional .CMsgPaintKit_Definition.Item tomislav = 48; 550 | optional .CMsgPaintKit_Definition.Item trenchgun = 49; 551 | optional .CMsgPaintKit_Definition.Item winger_pistol = 50; 552 | } 553 | 554 | message CMsgQuestTheme { 555 | message WeightedString { 556 | optional string string = 1; 557 | optional uint32 weight = 2; 558 | } 559 | 560 | message WeightedStringSet { 561 | repeated .CMsgQuestTheme.WeightedString weighted_strings = 1; 562 | } 563 | 564 | required .CMsgProtoDefHeader header = 1; 565 | optional string notification_res = 2; 566 | optional string quest_item_res = 3; 567 | optional string in_game_tracker_res = 4; 568 | repeated .CMsgQuestTheme.WeightedStringSet give_sounds = 5; 569 | repeated .CMsgQuestTheme.WeightedStringSet complete_sounds = 6; 570 | repeated .CMsgQuestTheme.WeightedStringSet fully_complete_sounds = 7; 571 | optional string reward_sound = 8; 572 | optional string discard_sound = 9; 573 | optional string reveal_sound = 10; 574 | } 575 | 576 | message CMsgQuestMapNodeCondition_NodeState { 577 | optional uint32 bonus_objectives_required = 1 [default = 0, (editable) = false, (display_name) = "Bonus Required", (comment) = "Number of bonus objectives required, on top of the primary objective", (allow_add) = false, (allow_delete) = false]; 578 | required .CMsgProtoDefID target_node_defid = 2 [(editable) = false, (display_name) = "Target Node", (comment) = "Which node is required to have the above number of medals", (allow_add) = false, (allow_delete) = false]; 579 | } 580 | 581 | message CMsgQuestMapNodeCondition_Logic { 582 | required .LogicalOperation operation = 1 [default = AND, (editable) = false, (display_name) = "Logic", (comment) = "Logical operation", (allow_add) = false, (allow_delete) = false]; 583 | repeated .CMsgQuestMapNodeCondition sub_conditions = 2 [(editable) = false, (display_name) = "Operands", (comment) = "Definitions to use in the logical operation", (allow_add) = false, (allow_delete) = false]; 584 | } 585 | 586 | message CMsgQuestMapNodeCondition { 587 | oneof operation { 588 | .CMsgQuestMapNodeCondition_NodeState node_state = 1 [(editable) = false, (display_name) = "Node State Condition", (comment) = "Returns true if a specific node has a required number of medals", (allow_add) = false, (allow_delete) = false]; 589 | .CMsgQuestMapNodeCondition_Logic logical = 2 [(editable) = false, (display_name) = "Logical Condition", (comment) = "Performs a specified logical operation to all sub conditions", (allow_add) = false, (allow_delete) = false]; 590 | } 591 | } 592 | 593 | message CMsgHeaderOnly { 594 | required .CMsgProtoDefHeader header = 1; 595 | } 596 | 597 | --------------------------------------------------------------------------------