Another fucking c# Steamworks implementation
Go to file
2019-04-30 17:11:45 +01:00
Facepunch.Steamworks ISteamCallback was a nice idea but IL2CPP support makes it unfeasible 2019-04-30 16:43:27 +01:00
Facepunch.Steamworks.Test CheckFileSignature => CheckFileSignatureAsync 2019-04-30 14:27:54 +01:00
Generator ISteamCallback was a nice idea but IL2CPP support makes it unfeasible 2019-04-30 16:43:27 +01:00
UnityPlugin UnityPlugin base 2019-04-30 16:52:47 +01:00
.gitattributes 💥🐫 Added .gitattributes & .gitignore files 2016-07-06 17:36:50 +01:00
.gitignore Compile fixes, netstandard2.0 2017-08-30 23:10:55 +01:00
Facepunch.Steamworks.sln Compile fixes, netstandard2.0 2017-08-30 23:10:55 +01:00
Jenkinsfile Update Jenkinsfile 2019-04-30 17:11:45 +01:00
LICENSE Update license with company/year 2016-10-11 07:40:42 -04:00
README.md Update README.md 2019-04-30 12:58:47 +01:00

Facepunch.Steamworks

Another fucking c# Steamworks implementation

Build Status

Features

Feature Supported
Windows
Linux
MacOS
Unity Support
Unity IL2CPP Support
Async Callbacks (steam callresults)
Events (steam callbacks)
Single C# dll (no native requirements apart from Steam)
Open Source
MIT license
Any 32bit OS

Why

The Steamworks C# implementations I found that were compatible with Unity have worked for a long time. But I hate them all. For a number of different reasons.

  • They're not C#, they're just a collection of functions.
  • They're not up to date.
  • They require a 3rd party native dll.
  • They can't be compiled into a standalone dll (in Unity).
  • They're not free
  • They have a restrictive license.

C# is meant to make things easier. So lets try to wrap it up in a way that makes it all easier.

What

Get your own information

SteamClient.SteamId // Your SteamId
SteamClient.Name // Your Name

View your friends list

foreach ( var friend in SteamFriends.GetFriends() )
{
    Console.WriteLine( "{friend.Id}: {friend.Name}" );
    Console.WriteLine( "{friend.IsOnline} / {friend.SteamLevel}" );
    
    friend.SendMessage( "Hello Friend" );
}

But what if you want to get a list of friends playing the same game that we're playing?

foreach ( var friend in client.Friends.All.Where( x => x.IsPlayingThisGame ) )
{
    // 
}

App Info

Console.WriteLine( SteamApps.GameLanguage ); // Print the current game language
var installDir = SteamApps.AppInstallDir( 4000 ); // Get the path to the Garry's Mod install folder

var fileinfo = await SteamApps.GetFileDetailsAsync( "hl2.exe" ); // async get file details
DoSomething( fileinfo.SizeInBytes, fileinfo.Sha1 );

Get Avatars

var image = await SteamFriends.GetLargeAvatarAsync( steamid );
if ( !image.HasValue ) return DefaultImage;

return MakeTextureFromRGBA( image.Data, image.Width, image.Height );

Get a list of servers

using ( var list = new ServerList.Internet() )
{
    list.AddFilter( "map", "de_dust" );
    await list.RunQueryAsync();

    foreach ( var server in list.Responsive )
    {
        Console.WriteLine( $"{server.Address} {server.Name}" );
    }
}

Achievements

List them

foreach ( var a in SteamUserStats.Achievements )
{
    Console.WriteLine( $"{a.Name} ({a.State}})" );
}	

Unlock them

var ach = new Achievement( "GM_PLAYED_WITH_GARRY" );
ach.Trigger();

Voice


SteamUser.VoiceRecord = KeyDown( "V" );

if ( SteamUser.HasVoiceData )
{
    var bytesrwritten = SteamUser.ReadVoiceData( stream );
    // Send Stream Data To Server or Something
}

Auth


// Client sends ticket data to server somehow
var ticket = SteamUser.GetAuthSessionTicket();


// server listens to event
SteamServer.OnValidateAuthTicketResponse += ( steamid, ownerid, rsponse ) =>
{
    if ( rsponse == AuthResponse.OK )
        TellUserTheyCanBeOnServer( steamid );
    else
        KickUser( steamid );
};

// server gets ticket data from client, calls this function.. which either returns
// false straight away, or will issue a TicketResponse.
if ( !SteamServer.BeginAuthSession( ticketData, clientSteamId ) )
{
    KickUser( clientSteamId );
}

//
// Client is leaving, cancels their ticket OnValidateAuth is called on the server again
// this time with AuthResponse.AuthTicketCanceled
//
ticket.Cancel();

Utils

SteamUtils.SecondsSinceAppActive;
SteamUtils.SecondsSinceComputerActive;
SteamUtils.IpCountry;
SteamUtils.UsingBatteryPower;
SteamUtils.CurrentBatteryPower;
SteamUtils.AppId;
SteamUtils.IsOverlayEnabled;
SteamUtils.IsSteamRunningInVR;
SteamUtils.IsSteamInBigPictureMode;

Usage

Client

To initialize a client you can do this.

using Steamworks;

// ...

try 
{
    SteamClient.Init( 4000 );
}
catch ( System.Exception e )
{
    // Couldn't init for some reason (steam is closed etc)
}

Replace 4000 with the appid of your game. You shouldn't call any Steam functions before you initialize.

When you're done, when you're closing your game, just shutdown.

SteamClient.Shutdown();

Server

To create a server do this.

var serverInit = new SteamServerInit( "gmod", "Garry Mode" )
{
    GamePort = 28015,
    Secure = true,
    QueryPort = 28016
};

try
{
    Steamworks.SteamServer.Init( 4000, serverInit );
}
catch ( System.Exception )
{
    // Couldn't init for some reason (dll errors, blocked ports)
}

Help

Wanna help? Go for it, pull requests, bug reports, yes, do it.

You can also hit up the Steamworks Thread for help/discussion.

License

MIT - do whatever you want.