You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at Dota2.GC.DotaGCHandler.<.ctor>b__45_0(Object stateInfo)
at System.Threading.TimerQueueTimer.<>c.<.cctor>b__23_0(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.TimerQueueTimer.CallCallback(Boolean isThreadPool)
at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool)
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback(Int32 id)
Process finished with exit code 6.
I initialized steam cli before starting and all looking good in this instance, but i dont know what is it
mac os
part of code:
using System;
using System.Collections.Generic;
using System.Threading;
using SteamKit2;
using SteamKit2.Internal; // brings in our protobuf client messages
using SteamKit2.GC; // brings in the GC related classes
using SteamKit2.GC.Dota.Internal; // brings in dota specific protobuf messages
using System.IO;
using System.Security.Cryptography;
using SteamKit2.Unified.Internal;
using Dota2;
using Dota2.GC;
namespace DotaAPIConsole
{
public class SteamAgent
{
public static SteamClient client;
public static SteamUser user;
SteamGameCoordinator gameCoordinator;
// public static Dota2.GC.DotaGCHandler dota;
SteamApps steamApps;
public static SteamFriends steamFriends;
CallbackManager callbackMgr;
public static bool isRunning;
bool gotMatch;
public int matchId;
static SteamUnifiedMessages steamUnifiedMessages;
static SteamUnifiedMessages.UnifiedService<IPlayer> playerService;
static JobID badgeRequest = JobID.Invalid;
public CMsgDOTAMatch Match { get; private set; }
const int APPID = 570;
public static string userName { get; private set; }
public static string password { get; private set; }
public static string authCode, twoFactorAuth;
public static byte[] sentryHash;
public SteamAgent()
{
DebugLog.AddListener(new SteamDebugListener());
DebugLog.Enabled = true;
userName =*;
password = *;
var configuration = SteamConfiguration.Create(b => b.WithProtocolTypes(ProtocolTypes.Tcp));
client = new SteamClient(configuration);
// get our handlers
callbackMgr = new CallbackManager( client );
// get the steamuser handler, which is used for logging on after successfully connecting
user = client.GetHandler<SteamUser>();
steamApps = client.GetHandler<SteamApps>();
steamFriends = client.GetHandler<SteamFriends>();
user = client.GetHandler<SteamUser>();
this.gameCoordinator = client.GetHandler<SteamGameCoordinator>();
// get the steam unified messages handler, which is used for sending and receiving responses from the unified service api
steamUnifiedMessages = client.GetHandler<SteamUnifiedMessages>();
// we also want to create our local service interface, which will help us build requests to the unified api
playerService = steamUnifiedMessages.CreateService<IPlayer>();
// setup callbacks
callbackMgr = new CallbackManager( client );
callbackMgr.Subscribe<SteamClient.ConnectedCallback>( OnConnected );
callbackMgr.Subscribe<SteamClient.DisconnectedCallback>( OnDisconnected );
callbackMgr.Subscribe<SteamUser.LoggedOnCallback>( OnLoggedOn );
callbackMgr.Subscribe<SteamUser.LoggedOffCallback>( OnLoggedOff );
callbackMgr.Subscribe<SteamGameCoordinator.MessageCallback>( OnGCMessage );
callbackMgr.Subscribe<SteamUser.UpdateMachineAuthCallback>( OnMachineAuth );
callbackMgr.Subscribe<SteamUser.AccountInfoCallback>( OnAccountInfo );
callbackMgr.Subscribe<SteamFriends.FriendsListCallback>( OnFriendsList );
callbackMgr.Subscribe<SteamFriends.PersonaStateCallback>( OnPersonaState );
callbackMgr.Subscribe<SteamFriends.FriendAddedCallback>( OnFriendAdded );
}
public void Connect()
{
Logger.Send("Connecting to Steam...", 1);
// begin the connection to steam
client.Connect();
isRunning = true;
DotaGCHandler.Bootstrap(client);
DotaGCHandler dota = client.GetHandler<DotaGCHandler>();
// Logger.Send($"Dota: {dota.GetType()}", 1);
// Logger.Send($"Dota is ready: {dota.Ready}", 1);
}
public void Wait()
{
while ( isRunning )
{
// continue running callbacks until we get match details
callbackMgr.RunWaitCallbacks( TimeSpan.FromSeconds( 1 ) );
Logger.Send("DotaClient Looking callbacks...", 1);
}
}
static void OnConnected( SteamClient.ConnectedCallback callback )
{
Logger.Send($"Connected to Steam! Logging in {userName}", 1);
if ( File.Exists( "sentry.bin" ) )
{
// if we have a saved sentry file, read and sha-1 hash it
byte[] sentryFile = File.ReadAllBytes( "sentry.bin" );
sentryHash = CryptoHelper.SHAHash( sentryFile );
}
user.LogOn( new SteamUser.LogOnDetails
{
Username = userName,
Password = password,
// in this sample, we pass in an additional authcode
// this value will be null (which is the default) for our first logon attempt
AuthCode = authCode,
// if the account is using 2-factor auth, we'll provide the two factor code instead
// this will also be null on our first logon attempt
TwoFactorCode = twoFactorAuth,
// our subsequent logons use the hash of the sentry file as proof of ownership of the file
// this will also be null for our first (no authcode) and second (authcode only) logon attempts
SentryFileHash = sentryHash,
} );
}
static void OnDisconnected( SteamClient.DisconnectedCallback callback )
{
// after recieving an AccountLogonDenied, we'll be disconnected from steam
// so after we read an authcode from the user, we need to reconnect to begin the logon flow again
Logger.Send($"Disconnected from Steam, reconnecting in 5...", 1);
Thread.Sleep( TimeSpan.FromSeconds( 5 ) );
client.Connect();
}
void OnLoggedOn( SteamUser.LoggedOnCallback callback )
{
bool isSteamGuard = callback.Result == EResult.AccountLogonDenied;
bool is2FA = callback.Result == EResult.AccountLoginDeniedNeedTwoFactor;
if ( isSteamGuard || is2FA )
{
Logger.Send($"This account is SteamGuard protected!", 1);
if ( is2FA )
{
Logger.Send("Please enter your 2 factor auth code from your authenticator app: ", 3);
twoFactorAuth = Console.ReadLine();
}
else
{
Logger.Send($"Please enter the auth code sent to the email at {callback.EmailDomain}: ", 3);
authCode = Console.ReadLine();
}
return;
}
if ( callback.Result != EResult.OK )
{
Logger.Send($"Unable to logon to Steam: {callback.Result} / {callback.ExtendedResult}", 1);
isRunning = false;
return;
}
Logger.Send("Successfully logged on! Launching DOTA...", 1);
// var playGame = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayedWithDataBlob);
// playGame.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed
// {
// game_id = (ulong) GameId,
// game_extra_info = "Dota 2",
// game_data_blob = null,
// streaming_provider_id = 0,
// game_flags = (uint) Engine,
// owner_id = Client.SteamID.AccountID
// });
// playGame.Body.client_os_type = 16;
//
// Client.Send(playGame);
// we've logged into the account
// now we need to inform the steam server that we're playing dota (in order to receive GC messages)
// steamkit doesn't expose the "play game" message through any handler, so we'll just send the message manually
// var playGame = new ClientMsgProtobuf<CMsgClientGamesPlayed>( EMsg.ClientGamesPlayed );
//
// playGame.Body.games_played.Add( new CMsgClientGamesPlayed.GamePlayed
// {
// game_id = new GameID( APPID ), // or game_id = APPID,
// } );
//
// // send it off
// // notice here we're sending this message directly using the SteamClient
// client.Send( playGame );
// delay a little to give steam some time to establish a GC connection to us
Thread.Sleep( 5000 );
// inform the dota GC that we want a session
var clientHello = new ClientGCMsgProtobuf<CMsgClientHello>( ( uint )EGCBaseClientMsg.k_EMsgGCClientHello );
clientHello.Body.engine = ESourceEngine.k_ESE_Source2;
gameCoordinator.Send( clientHello, APPID );
}
// called when a gamecoordinator (GC) message arrives
// these kinds of messages are designed to be game-specific
// in this case, we'll be handling dota's GC messages
void OnGCMessage( SteamGameCoordinator.MessageCallback callback )
{
// setup our dispatch table for messages
// this makes the code cleaner and easier to maintain
var messageMap = new Dictionary<uint, Action<IPacketGCMsg>>
{
{ ( uint )EGCBaseClientMsg.k_EMsgGCClientWelcome, OnClientWelcome },
{ ( uint )EDOTAGCMsg.k_EMsgGCMatchDetailsResponse, OnMatchDetails },
};
Action<IPacketGCMsg> func;
if ( !messageMap.TryGetValue( callback.EMsg, out func ) )
{
// this will happen when we recieve some GC messages that we're not handling
// this is okay because we're handling every essential message, and the rest can be ignored
return;
}
func( callback.Message );
}
// this message arrives when the GC welcomes a client
// this happens after telling steam that we launched dota (with the ClientGamesPlayed message)
// this can also happen after the GC has restarted (due to a crash or new version)
void OnClientWelcome( IPacketGCMsg packetMsg )
{
// in order to get at the contents of the message, we need to create a ClientGCMsgProtobuf from the packet message we recieve
// note here the difference between ClientGCMsgProtobuf and the ClientMsgProtobuf used when sending ClientGamesPlayed
// this message is used for the GC, while the other is used for general steam messages
var msg = new ClientGCMsgProtobuf<CMsgClientWelcome>( packetMsg );
Console.WriteLine( "GC is welcoming us. Version: {0}", msg.Body.version );
Console.WriteLine( "Requesting details of match {0}", matchId );
// at this point, the GC is now ready to accept messages from us
// so now we'll request the details of the match we're looking for
// var requestMatch = new ClientGCMsgProtobuf<CMsgGCMatchDetailsRequest>( ( uint )EDOTAGCMsg.k_EMsgGCMatchDetailsRequest );
// requestMatch.Body.match_id = matchId;
//
// gameCoordinator.Send( requestMatch, APPID );
}
// this message arrives after we've requested the details for a match
void OnMatchDetails( IPacketGCMsg packetMsg )
{
var msg = new ClientGCMsgProtobuf<CMsgGCMatchDetailsResponse>( packetMsg );
EResult result = ( EResult )msg.Body.result;
if ( result != EResult.OK )
{
Console.WriteLine( "Unable to request match details: {0}", result );
}
gotMatch = true;
Match = msg.Body.match;
// we've got everything we need, we can disconnect from steam now
client.Disconnect();
}
static void OnMethodResponse( SteamUnifiedMessages.ServiceMethodResponse callback )
{
if ( callback.JobID != badgeRequest )
{
// always double check the jobid of the response to ensure you're matching to your original request
return;
}
// and check for success
if ( callback.Result != EResult.OK )
{
Console.WriteLine( $"Unified service request failed with {callback.Result}" );
return;
}
// retrieve the deserialized response for the request we made
// notice the naming pattern
// for requests: CMyService_Method_Request
// for responses: CMyService_Method_Response
CPlayer_GetGameBadgeLevels_Response resp = callback.GetDeserializedResponse<CPlayer_GetGameBadgeLevels_Response>();
Console.WriteLine( $"Our player level is {resp.player_level}" );
foreach ( var badge in resp.badges )
{
Console.WriteLine( $"Badge series {badge.series} is level {badge.level}" );
}
badgeRequest = JobID.Invalid;
// now that we've completed our task, lets log off
user.LogOff();
}
static void OnLoggedOff( SteamUser.LoggedOffCallback callback )
{
Logger.Send($"Logged off of Steam: {callback.Result}", 1);
}
static void OnMachineAuth( SteamUser.UpdateMachineAuthCallback callback )
{
Logger.Send("Updating sentryfile...", 1);
// write out our sentry file
// ideally we'd want to write to the filename specified in the callback
// but then this sample would require more code to find the correct sentry file to read during logon
// for the sake of simplicity, we'll just use "sentry.bin"
int fileSize;
using ( var fs = File.Open( "sentry.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite ) )
{
fs.Seek( callback.Offset, SeekOrigin.Begin );
fs.Write( callback.Data, 0, callback.BytesToWrite );
fileSize = ( int )fs.Length;
fs.Seek( 0, SeekOrigin.Begin );
using ( var sha = SHA1.Create() )
{
sentryHash = sha.ComputeHash( fs );
}
}
// inform the steam servers that we're accepting this sentry file
user.SendMachineAuthResponse( new SteamUser.MachineAuthDetails
{
JobID = callback.JobID,
FileName = callback.FileName,
BytesWritten = callback.BytesToWrite,
FileSize = fileSize,
Offset = callback.Offset,
Result = EResult.OK,
LastError = 0,
OneTimePassword = callback.OneTimePassword,
SentryFileHash = sentryHash,
} );
Logger.Send("Done!", 1);
}
static void OnAccountInfo( SteamUser.AccountInfoCallback callback )
{
// before being able to interact with friends, you must wait for the account info callback
// this callback is posted shortly after a successful logon
// at this point, we can go online on friends, so lets do that
steamFriends.SetPersonaState( EPersonaState.Online );
}
static void OnFriendsList( SteamFriends.FriendsListCallback callback )
{
// at this point, the client has received it's friends list
int friendCount = steamFriends.GetFriendCount();
Logger.Send($"We have {friendCount} friends", 1);
for ( int x = 0 ; x < friendCount ; x++ )
{
// steamids identify objects that exist on the steam network, such as friends, as an example
SteamID steamIdFriend = steamFriends.GetFriendByIndex( x );
// we'll just display the STEAM_ rendered version
Logger.Send($"Friend: {steamIdFriend.Render()}", 1);
}
// we can also iterate over our friendslist to accept or decline any pending invites
foreach ( var friend in callback.FriendList )
{
if (friend.Relationship == EFriendRelationship.RequestRecipient)
{
// this user has added us, let's add him back
steamFriends.AddFriend(friend.SteamID);
}
}
}
static void OnFriendAdded( SteamFriends.FriendAddedCallback callback)
{
// someone accepted our friend request, or we accepted one
Logger.Send($"{callback.PersonaName} is now a friend", 1);
}
static void OnPersonaState( SteamFriends.PersonaStateCallback callback )
{
// this callback is received when the persona state (friend information) of a friend changes
// for this sample we'll simply display the names of the friends
Logger.Send($"State change: {callback.Name}", 1);
}
// this is a utility function to transform a uint emsg into a string that can be used to display the name
static string GetEMsgDisplayString( uint eMsg )
{
Type[] eMsgEnums =
{
typeof( EGCBaseClientMsg ),
typeof( EDOTAGCMsg ),
typeof( EGCBaseMsg ),
typeof( EGCItemMsg ),
typeof( ESOMsg ),
};
foreach ( var enumType in eMsgEnums )
{
if ( Enum.IsDefined( enumType, ( int )eMsg ) )
return Enum.GetName( enumType, ( int )eMsg );
}
return eMsg.ToString();
}
}
}
The text was updated successfully, but these errors were encountered:
When i trying use this example:
DotaGCHandler.Bootstrap(client);
DotaGCHandler dota = client.GetHandler();
I got exception:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at Dota2.GC.DotaGCHandler.<.ctor>b__45_0(Object stateInfo)
at System.Threading.TimerQueueTimer.<>c.<.cctor>b__23_0(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.TimerQueueTimer.CallCallback(Boolean isThreadPool)
at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool)
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback(Int32 id)
Process finished with exit code 6.
I initialized steam cli before starting and all looking good in this instance, but i dont know what is it
mac os
part of code:
using System;
using System.Collections.Generic;
using System.Threading;
using SteamKit2;
using SteamKit2.Internal; // brings in our protobuf client messages
using SteamKit2.GC; // brings in the GC related classes
using SteamKit2.GC.Dota.Internal; // brings in dota specific protobuf messages
using System.IO;
using System.Security.Cryptography;
using SteamKit2.Unified.Internal;
using Dota2;
using Dota2.GC;
namespace DotaAPIConsole
{
public class SteamAgent
{
public static SteamClient client;
}
The text was updated successfully, but these errors were encountered: