diff --git a/SteamKit2/SteamKit2/Steam/Handlers/SteamApps/Callbacks.cs b/SteamKit2/SteamKit2/Steam/Handlers/SteamApps/Callbacks.cs index 7d8c868e1..0584443f6 100644 --- a/SteamKit2/SteamKit2/Steam/Handlers/SteamApps/Callbacks.cs +++ b/SteamKit2/SteamKit2/Steam/Handlers/SteamApps/Callbacks.cs @@ -292,7 +292,7 @@ internal VACStatusCallback( MsgClientVACBanStatus msg, byte[] payload ) using ( var ms = new MemoryStream( payload ) ) using ( var br = new BinaryReader( ms ) ) { - for ( int x = 0 ; x < msg.NumBans ; x++ ) + for ( int x = 0; x < msg.NumBans; x++ ) { tempList.Add( br.ReadUInt32() ); } @@ -481,7 +481,7 @@ public sealed class PICSProductInfo /// public Uri? HttpUri { get; private set; } - internal PICSProductInfo( CMsgClientPICSProductInfoResponse parentResponse, CMsgClientPICSProductInfoResponse.AppInfo app_info) + internal PICSProductInfo( CMsgClientPICSProductInfoResponse parentResponse, CMsgClientPICSProductInfoResponse.AppInfo app_info ) { this.ID = app_info.appid; this.ChangeNumber = app_info.change_number; @@ -502,13 +502,13 @@ internal PICSProductInfo( CMsgClientPICSProductInfoResponse parentResponse, CMsg this.OnlyPublic = app_info.only_public; // We should have all these fields set for the response to a metadata-only request, but guard here just in case. - if (this.SHAHash != null && this.SHAHash.Length > 0 && !string.IsNullOrEmpty(parentResponse.http_host)) + if ( this.SHAHash != null && this.SHAHash.Length > 0 && !string.IsNullOrEmpty( parentResponse.http_host ) ) { - var shaString = BitConverter.ToString(this.SHAHash) - .Replace("-", string.Empty) + var shaString = BitConverter.ToString( this.SHAHash ) + .Replace( "-", string.Empty ) .ToLower(); - var uriString = string.Format("http://{0}/appinfo/{1}/sha/{2}.txt.gz", parentResponse.http_host, this.ID, shaString); - this.HttpUri = new Uri(uriString); + var uriString = string.Format( "http://{0}/appinfo/{1}/sha/{2}.txt.gz", parentResponse.http_host, this.ID, shaString ); + this.HttpUri = new Uri( uriString ); } this.UseHttp = this.HttpUri != null && app_info.size >= parentResponse.http_min_size; @@ -532,7 +532,7 @@ internal PICSProductInfo( CMsgClientPICSProductInfoResponse.PackageInfo package_ // see: CPackageInfo::UpdateFromBuffer(CSHA const&,uint,CUtlBuffer &) // todo: we've apparently ignored this with zero ill effects, but perhaps we want to respect it? br.ReadUInt32(); - + this.KeyValues.TryReadAsBinary( ms ); } } @@ -627,6 +627,70 @@ internal GuestPassListCallback( MsgClientUpdateGuestPassesList msg, Stream paylo } } + /// + /// This callback is received in response to activating a guest pass or a gift. + /// + public sealed class RedeemGuestPassResponseCallback : CallbackMsg + { + /// + /// Result of the operation + /// + public EResult Result { get; set; } + /// + /// Package ID which was activated. + /// + public uint PackageID { get; set; } + /// + /// App ID which must be owned to activate this guest pass. + /// + public uint MustOwnAppID { get; set; } + + + internal RedeemGuestPassResponseCallback( JobID jobID, CMsgClientRedeemGuestPassResponse msg ) + { + JobID = jobID; + Result = ( EResult )msg.eresult; + PackageID = msg.package_id; + MustOwnAppID = msg.must_own_appid; + } + } + + /// + /// This callback is received in a response to activating a Steam key. + /// + public sealed class PurchaseResponseCallback : CallbackMsg + { + /// + /// Result of the operation + /// + public EResult Result { get; set; } + /// + /// Purchase result of the operation + /// + public EPurchaseResultDetail PurchaseResultDetail { get; set; } + /// + /// Purchase receipt of the operation + /// + public KeyValue PurchaseReceiptInfo { get; set; } + + + internal PurchaseResponseCallback( JobID jobID, CMsgClientPurchaseResponse msg ) + { + JobID = jobID; + Result = ( EResult )msg.eresult; + PurchaseResultDetail = ( EPurchaseResultDetail )msg.purchase_result_details; + PurchaseReceiptInfo = new KeyValue(); + + if ( msg.purchase_receipt_info == null ) + { + return; + } + + using var ms = new MemoryStream( msg.purchase_receipt_info ); + PurchaseReceiptInfo.TryReadAsBinary( ms ); + } + } + /// /// This callback is received when a CDN auth token is received /// diff --git a/SteamKit2/SteamKit2/Steam/Handlers/SteamApps/SteamApps.cs b/SteamKit2/SteamKit2/Steam/Handlers/SteamApps/SteamApps.cs index e3e348b55..4fb27c09a 100644 --- a/SteamKit2/SteamKit2/Steam/Handlers/SteamApps/SteamApps.cs +++ b/SteamKit2/SteamKit2/Steam/Handlers/SteamApps/SteamApps.cs @@ -53,6 +53,8 @@ internal SteamApps() { { EMsg.ClientLicenseList, HandleLicenseList }, { EMsg.ClientRequestFreeLicenseResponse, HandleFreeLicense }, + { EMsg.ClientPurchaseResponse, HandlePurchaseResponse }, + { EMsg.ClientRedeemGuestPassResponse, HandleRedeemGuestPassResponse }, { EMsg.ClientGameConnectTokens, HandleGameConnectTokens }, { EMsg.ClientVACBanStatus, HandleVACBanStatus }, { EMsg.ClientGetAppOwnershipTicketResponse, HandleAppOwnershipTicketResponse }, @@ -379,6 +381,20 @@ void HandleFreeLicense( IPacketMsg packetMsg ) var callback = new FreeLicenseCallback( grantedLicenses.TargetJobID, grantedLicenses.Body ); this.Client.PostCallback( callback ); } + void HandlePurchaseResponse( IPacketMsg packetMsg ) + { + var purchaseResponse = new ClientMsgProtobuf( packetMsg ); + + var callback = new PurchaseResponseCallback( purchaseResponse.TargetJobID, purchaseResponse.Body ); + this.Client.PostCallback( callback ); + } + void HandleRedeemGuestPassResponse( IPacketMsg packetMsg ) + { + var redeemedGuestPass = new ClientMsgProtobuf( packetMsg ); + + var callback = new RedeemGuestPassResponseCallback( redeemedGuestPass.TargetJobID, redeemedGuestPass.Body ); + this.Client.PostCallback( callback ); + } void HandleVACBanStatus( IPacketMsg packetMsg ) { var vacStatus = new ClientMsg( packetMsg );