Steam

Introduction

FlatRedball games can be distributed on Steam with or without adding code to handle Steam integration. Steam integration can be added using the Steamworks.NET library. This includes support for achievements and responding to the Steam overlay being shown.

Adding Steamworks.NET Library

To add Steamworks.NET library to your project:

  1. Download the latest release standalone

  2. Unzip the downloaded file

  3. Link the Steamworks.NET.dll file in your project

    1. If you are targeting .NET 6, use the 64 bit version.

    2. If you are making a Desktop GL (.NET Framework) project, be sure to link to the x86 version as this version of FlatRedBall does not support 64 bit builds

  4. Copy the steam_api64.dll or steam_api.dll file to the same folder as your game's .csproj (and .gluj) depending on whether you linked to the 64 bit version of Steamworks.NET.dll

  5. Add the steam_api file to your project in Visual Studio and mark it as Copy if Newer so that the file ends up in your game's bin folder next to the built .exe.

  6. Add your steam_appid.txt file to the folder where your game's exe is located.

  7. When testing, be sure to have Steam running or else your tests won't work.

Adding SteamManager

Once the Steamworks library is added to your project, you can interact directly with the library to award achievements and respond to the tab overlay being shown. If you would like to work directly with this library, you can find additional information on the Steamworks github page. The documentation is focused on Unity but many of the concepts apply. Alternatively, the following SteamManager class can be used to set up a project quickly. Note that this is provided to help get a project set up quickly. Future versions of FlatRedBall may provide more integrated solutions such as code gen:

    #region Achievement Class

    abstract class AchievementBase
    {

    }

    class BoolAchievement : AchievementBase
    {
        string AchievementName;
        Func<bool> GetCurrentValue;

        public BoolAchievement(string achievementName, Func<bool> getCurrentValue)
        {
            AchievementName = achievementName;
            GetCurrentValue = getCurrentValue;

        }

        public void TryApply()
        {
            if(GetCurrentValue())
            {
                SteamManager.Self.AwardAchievement(AchievementName);
            }
        }
    }

    class NumericAchievement : AchievementBase
    {
        string ProgressStat;
        Func<long> GetCurrentValue;

        public NumericAchievement(string progressStat, Func<long> getCurrentValue)
        {
            ProgressStat = progressStat;
            GetCurrentValue = getCurrentValue;
        }

        public void TryApply()
        {
            SteamManager.Self.SetStat(ProgressStat, GetCurrentValue());
        }
    }

    #endregion

    #region Achievements list
    class Achievements
    {

        //// start level select screen
        //public static NumericAchievement ExampleAchievement = new NumericAchievement(
        //    "star_one_count", // This is the variable of the achievement
        //    () => MyGameObject.GetCurrentValue() // This is value that the player has obtained so far, like the number of powerups collected
        //    );

    }

    #endregion

    #region SteamManager
    class SteamManager : IManager
    {
        static SteamManager self;
        public static SteamManager Self
        {
            get
            {
                if (self == null) self = new SteamManager();
                return self;
            }
        }

        static bool isInitialized;
        static AppId_t appId;

        static Callback<GameOverlayActivated_t> gameOverlayActivatedCallback;
        static Callback<UserStatsReceived_t> userStatsReceivedCallback;
        static Callback<UserStatsStored_t> userStatsStoredCallback;
        static Callback<UserAchievementStored_t> userAchievementStoredCallback;

        public static Action<bool> SteamOverlayVisibilityChanged;

        public void Initialize()
        {
            // this requires steam_appid.txt in the bin folder, and also that Steam is running
            isInitialized = Steamworks.SteamAPI.Init();


            if (isInitialized)
            {
                //var name = Steamworks.SteamFriends.GetPersonaName();

                appId = Steamworks.SteamUtils.GetAppID();

                SteamUserStats.RequestCurrentStats();

                gameOverlayActivatedCallback = Callback<GameOverlayActivated_t>.Create(HandleOverlayActivated);
                userStatsReceivedCallback = Callback<UserStatsReceived_t>.Create(HandleUserStatsReceived);
                userStatsStoredCallback = Callback<UserStatsStored_t>.Create(HandleUserStatsStored);
                userAchievementStoredCallback = Callback<UserAchievementStored_t>.Create(HandleUserAchievementStored);