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 );