Author Topic: Steam API / Steamworks  (Read 16219 times)

xandeck

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 3
  • Posts: 54
    • View Profile
Steam API / Steamworks
« on: September 15, 2015, 02:52:11 PM »
Hello everyone,

Please, anybody has a way of integrating Steam API with TNet?
Aren, do you have? We also are interested buying a solution. Just example scripts to get a game list and/or friends connect, will be enough.
Thank you in advance.
« Last Edit: September 16, 2015, 01:07:47 PM by xandeck »

xandeck

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 3
  • Posts: 54
    • View Profile
Re: Steam API / Steamworks
« Reply #1 on: September 18, 2015, 12:59:04 PM »
Well, no one I guess...
Aren, dont you have anything at all that can just point me in the right path?

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
Re: Steam API / Steamworks
« Reply #2 on: September 18, 2015, 03:03:59 PM »
It kind of seems like you're asking for handouts...

If you truly need a nudge in the right direction: most Unity developers use Steamworks.NET, a wrapper created by Riley Labrecque, and it can be found here: https://github.com/rlabrecque/Steamworks.NET

I think you can download it from the Unity asset store as well. Not sure.

From there, research the wrappers documentation and the documentation that Valve supplies and you should be able to get up and running.

Steamworks API documentation: https://partner.steamgames.com/documentation/api
Wrapper documentation: https://steamworks.github.io/

xandeck

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 3
  • Posts: 54
    • View Profile
Re: Steam API / Steamworks
« Reply #3 on: September 19, 2015, 02:48:27 PM »
Hello @cmifwdll
Thank you for your links.

I am not really asking for "handouts". We already found that wrapper (and it is not in Asset Store, sadly).
But what I am searching it is someone who can help us to get there faster, simple as that. We are also considering in hiring as freelance job for a short time.
All the links you sent we already have... we always look something to learn faster, when possible.
And I really like TNet, just wanted to know if someone already tried something with Steamworks.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Steam API / Steamworks
« Reply #4 on: September 20, 2015, 03:50:29 AM »
Assuming you are asking about integrating steamworks multiplayer functionality, it's completely separate from TNet. Steamworks does its own thing.

In Windward I used TNet for multiplayer and Steamworks for things like cloud saves, achievements and statistics tracking.

xandeck

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 3
  • Posts: 54
    • View Profile
Re: Steam API / Steamworks
« Reply #5 on: September 20, 2015, 08:59:09 AM »
Hello @ArenMook
Thanks for your reply.

Yes, it is about integrating it. We know it is separate from TNet. I am just asking if someone already did something (as it seems you did) to point us in a right direction.
What we want to do is:
- Cloud saving
- Achievements
- We will have some kind of master server. And we want to show the room list in some kind of a lobby. But we want to integrate Steamworks to show this list and make friends to connect through Steam, as many other shooter games does.
Is there any way that you can help us? Sorry to be direct here, but are you available for a quick consulting (paid)?

Thank you all for your help.

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
Re: Steam API / Steamworks
« Reply #6 on: September 23, 2015, 12:59:08 AM »
Hello @ArenMook
Thanks for your reply.

Yes, it is about integrating it. We know it is separate from TNet. I am just asking if someone already did something (as it seems you did) to point us in a right direction.
What we want to do is:
- Cloud saving
- Achievements
- We will have some kind of master server. And we want to show the room list in some kind of a lobby. But we want to integrate Steamworks to show this list and make friends to connect through Steam, as many other shooter games does.
Is there any way that you can help us? Sorry to be direct here, but are you available for a quick consulting (paid)?

Thank you all for your help.

I don't have any experience with adding Steam functionality to a game (yet), but a few minutes of browsing the Steamworks.NET website lead me to this test project: https://github.com/rlabrecque/Steamworks.NET-Test

So, within that project, you can find examples for the things you're asking for:
1. Cloud saving = SteamRemoteStorageTest.cs
2. Achievements = SteamUserStatsTest.cs
3. I'm not sure what you're trying to accomplish with this one. I think you'll need to build the serverlist yourself using TNet (there is code posted in the FAQ). However, for things like displaying the servers your Steam friends are playing on and joining their game via the Steam client I think you'll need bits and pieces from SteamFriendsTest.cs, SteamMatchmakingServersTest.cs, and SteamMatchmakingTest.cs. I'm not entirely sure about the last two, but it's worth fiddling around with.

Joining a game via the Steam client either starts the game with a launch parameter (I think?), or, if the game is already running, the GameRichPresenceJoinRequested_t callback is fired.

Again, no experience with integrating Steamworks in a Unity game, but this is more than enough information to get you - or whoever you hire - started.
Hopefully in providing this starting point you can better estimate the value of the work you're asking for (hint: it's probably not a lot).
Just don't want you to overpay :)

xandeck

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 3
  • Posts: 54
    • View Profile
Re: Steam API / Steamworks
« Reply #7 on: September 23, 2015, 07:58:41 AM »
Thank you @cmifwdll, I appreciate it.
We are checking our options now ;)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Steam API / Steamworks
« Reply #8 on: September 26, 2015, 05:18:22 PM »
I wrote a wrapper around Steamworks.NET for Windward with functions like these:
  1. #define STEAM
  2.  
  3. using System;
  4. using UnityEngine;
  5. using ManagedSteam;
  6. using ManagedSteam.Exceptions;
  7. using ManagedSteam.CallbackStructures;
  8. using ManagedSteam.SteamTypes;
  9. using ManagedSteam.Utility;
  10. using System.Runtime.InteropServices;
  11. using System.Collections.Generic;
  12. using System.IO;
  13.  
  14. public class Steamworks : MonoBehaviour
  15. {
  16.         static Steamworks instance;
  17.         static Steam steam { get; set; }
  18.  
  19.         /// <summary>
  20.         /// The ID of this game.
  21.         /// </summary>
  22.  
  23.         static internal GameID gameID;
  24.  
  25.         /// <summary>
  26.         /// Whether the Steam API is available.
  27.         /// </summary>
  28.  
  29.         static public bool isActive { get { return steam != null; } }
  30.  
  31.         /// <summary>
  32.         /// Steam ID is a fairly long number.
  33.         /// </summary>
  34.  
  35.         static public string steamID { get { return steam != null ? steam.User.GetSteamID().ToString() : (mID ?? SystemInfo.deviceUniqueIdentifier); } }
  36.  
  37.         /// <summary>
  38.         /// Get the Steam username.
  39.         /// </summary>
  40.  
  41.         static public string username
  42.         {
  43.                 get
  44.                 {
  45.                         if (steam == null) return mUsername;
  46.                         return steam.Friends.GetFriendPersonaName(steam.User.GetSteamID());
  47.                 }
  48.         }
  49.  
  50.         static string mID = null;
  51.         static string mUsername = "Guest";
  52.  
  53.         void Awake ()
  54.         {
  55.                 // Makes sure that only one instance of this object is in use at a time
  56.                 if (instance == null)
  57.                 {
  58.                         instance = this;
  59.                         bool error = false;
  60.  
  61.                         try
  62.                         {
  63.                                 Steam.RestartAppIfNecessary(<your App's Steam ID>);
  64.  
  65.                                 try
  66.                                 {
  67.                                         steam = Steam.Initialize();
  68.                                 }
  69.                                 catch (AlreadyLoadedException e)
  70.                                 {
  71.                                         Debug.LogError("The native dll is already loaded, this should not happen if ReleaseManagedResources is used and Steam.Initialize() is only called once.");
  72.                                         Debug.LogError(e.Message, this);
  73.                                         error = true;
  74.                                 }
  75.                                 catch (SteamInitializeFailedException e)
  76.                                 {
  77.                                         Debug.LogError("Could not initialize the native Steamworks API. This is usually caused by a missing steam_appid.txt file or if the Steam client is not running.");
  78.                                         Debug.LogError(e.Message, this);
  79.                                         error = true;
  80.                                 }
  81.                                 catch (SteamInterfaceInitializeFailedException e)
  82.                                 {
  83.                                         Debug.LogError("Could not initialize the wanted versions of the Steamworks API. Make sure that you have the correct Steamworks SDK version. See the documentation for more info.");
  84.                                         Debug.LogError(e.Message, this);
  85.                                         error = true;
  86.                                 }
  87.                                 catch (DllNotFoundException e)
  88.                                 {
  89.                                         Debug.LogError("Could not load a dll file. Make sure that the steam_api.dll/libsteam_api.dylib file is placed at the correct location. See the documentation for more info.");
  90.                                         Debug.LogError(e.Message, this);
  91.                                         error = true;
  92.                                 }
  93.                         }
  94.                         catch (Exception)
  95.                         {
  96.                                 error = true;
  97.                         }
  98.  
  99.                         if (!error)
  100.                         {
  101.                                 gameID = new GameID(steam.AppID.AsUInt64);
  102.                                 RegisterListeners();
  103.                         }
  104.                 }
  105.         }
  106.  
  107.         /// <summary>
  108.         /// Open the specified URL.
  109.         /// </summary>
  110.  
  111.         static public void OpenURL (string url)
  112.         {
  113. #if UNITY_EDITOR
  114.                 Application.OpenURL(url);
  115. #else
  116.                 if (!string.IsNullOrEmpty(url))
  117.                 {
  118.                         if (steam != null) steam.Friends.ActivateGameOverlayToWebPage(url);
  119.                         else Application.OpenURL(url);
  120.                 }
  121. #endif
  122.         }
  123.  
  124.         /// <summary>
  125.         /// Return the specified player's Steam name, or 'null' if the player is not on the friends list.
  126.         /// </summary>
  127.  
  128.         static public string GetFriendName (string steamID)
  129.         {
  130.                 if (isActive)
  131.                 {
  132.                         if (mFriends.Count == 0)
  133.                         {
  134.                                 IFriends fr = steam.Friends;
  135.                                 int count = fr.GetFriendCount(FriendFlags.All);
  136.  
  137.                                 for (int i = 0; i < count; ++i)
  138.                                 {
  139.                                         SteamID sid = fr.GetFriendByIndex(i, FriendFlags.All);
  140.                                         mFriends.Add(sid.ToString(), fr.GetFriendPersonaName(sid));
  141.                                 }
  142.                         }
  143.  
  144.                         string fn;
  145.                         if (mFriends.TryGetValue(steamID, out fn)) return fn;
  146.                 }
  147.                 return null;
  148.         }
  149.  
  150.         /// <summary>
  151.         /// Increment the specified stat.
  152.         /// </summary>
  153.  
  154.         static internal int IncrementStat (string name, bool sync = true)
  155.         {
  156.                 int val = GetInt(name) + 1;
  157.                 SetInt(name, val, sync);
  158.                 return val;
  159.         }
  160.  
  161.         /// <summary>
  162.         /// Get the specified integer-based stat.
  163.         /// </summary>
  164.  
  165.         static internal int GetInt (string name, int val = 0)
  166.         {
  167. #if STEAM
  168.                 if (steam != null)
  169.                 {
  170.                         int i = 0;
  171.                         if (steam.Stats.GetStat(name, out i)) return i;
  172.                 }
  173. #endif
  174.                 return PlayerPrefs.GetInt(name, val);
  175.         }
  176.  
  177.         /// <summary>
  178.         /// Get the specified float-based stat.
  179.         /// </summary>
  180.  
  181.         static internal float GetFloat (string name, float val = 0f)
  182.         {
  183. #if STEAM
  184.                 if (steam != null)
  185.                 {
  186.                         float f = 0f;
  187.                         if (steam.Stats.GetStat(name, out f)) return f;
  188.                 }
  189. #endif
  190.                 return PlayerPrefs.GetFloat(name, val);
  191.         }
  192.  
  193.         /// <summary>
  194.         /// Set the specified stat.
  195.         /// </summary>
  196.  
  197.         static internal void SetInt (string name, int val, bool sync = true)
  198.         {
  199.                 PlayerPrefs.SetInt(name, val);
  200. #if STEAM
  201.                 if (steam != null && steam.Stats.SetStat(name, val) && sync)
  202.                         steam.Stats.StoreStats();
  203. #endif
  204.         }
  205.  
  206.         /// <summary>
  207.         /// Set the specified stat.
  208.         /// </summary>
  209.  
  210.         static internal void SetFloat (string name, float val, bool sync = true)
  211.         {
  212.                 PlayerPrefs.SetFloat(name, val);
  213. #if STEAM
  214.                 if (steam != null && steam.Stats.SetStat(name, val) && sync)
  215.                         steam.Stats.StoreStats();
  216. #endif
  217.         }
  218.  
  219.         /// <summary>
  220.         /// Unlock the specified achievement.
  221.         /// </summary>
  222.  
  223.         static internal bool UnlockAchievement (string name, bool sync = true)
  224.         {
  225. #if STEAM
  226.                 if (steam != null)
  227.                 {
  228.                         if (GetAchievement(name)) return false;
  229.  
  230.                         if (steam.Stats.SetAchievement(name))
  231.                         {
  232.                                 if (sync) steam.Stats.StoreStats();
  233.  #if UNITY_EDITOR
  234.                                 Debug.Log("Unlocked " + name);
  235.  #endif
  236.                                 return true;
  237.                         }
  238.  #if UNITY_EDITOR
  239.                         else Debug.Log("Unable to unlock " + name);
  240.  #endif
  241.                 }
  242. #endif
  243.                 return false;
  244.         }
  245.  
  246.         /// <summary>
  247.         /// Update the specified achievement progress.
  248.         /// </summary>
  249.  
  250.         static internal void ShowAchievementProgress (string name, int current, int max, bool sync = true)
  251.         {
  252. #if STEAM
  253.                 if (steam != null)
  254.                 {
  255.                         if (GetAchievement(name)) return;
  256.  
  257.                         if (steam.Stats.IndicateAchievementProgress(name, (uint)current, (uint)max))
  258.                         {
  259.                                 if (sync) steam.Stats.StoreStats();
  260.                         }
  261.                 }
  262. #endif
  263.         }
  264.  
  265.         /// <summary>
  266.         /// Unlock the specified achievement.
  267.         /// </summary>
  268.  
  269.         static internal void ClearAchievement (string name)
  270.         {
  271. #if STEAM
  272.                 if (steam != null)
  273.                 {
  274.                         steam.Stats.ClearAchievement(name);
  275.                         steam.Stats.StoreStats();
  276.                 }
  277. #endif
  278.         }
  279.  
  280.         /// <summary>
  281.         /// Immediately sync all player stats and achievements.
  282.         /// </summary>
  283.  
  284.         static internal void SyncStatsAndAchievements ()
  285.         {
  286. #if STEAM
  287.                 if (steam != null) steam.Stats.StoreStats();
  288. #endif
  289.         }
  290.  
  291.         /// <summary>
  292.         /// Unlock the specified achievement.
  293.         /// </summary>
  294.  
  295.         static internal bool GetAchievement (string name)
  296.         {
  297. #if STEAM
  298.                 if (steam != null)
  299.                 {
  300.                         StatsGetAchievementResult result = steam.Stats.GetAchievement(name);
  301.                         return (result.result && result.sender);
  302.                 }
  303. #endif
  304.                 return false;
  305.         }
  306.  
  307.         /// <summary>
  308.         /// Show the Steam Overlay.
  309.         /// </summary>
  310.  
  311.         static internal void ShowOverlay ()
  312.         {
  313. #if STEAM
  314.                 steam.Friends.ActivateGameOverlay(OverlayDialog.Friends);
  315. #endif
  316.         }
  317.  
  318.         /// <summary>
  319.         /// Save the specified file to the Steam cloud.
  320.         /// </summary>
  321.  
  322.         static internal bool SaveFile (string filename, byte[] bytes)
  323.         {
  324. #if STEAM
  325.                 if (steam == null) return false;
  326.                 if (bytes != null && bytes.Length > 0)
  327.                 {
  328.                         IntPtr ptr = Marshal.AllocHGlobal(bytes.Length);
  329.                         Marshal.Copy(bytes, 0, ptr, bytes.Length);
  330.                         bool retVal = steam.Cloud.Write(filename, ptr, bytes.Length);
  331.                         Marshal.FreeHGlobal(ptr);
  332.                         return retVal;
  333.                 }
  334.                 else
  335.                 {
  336.                         steam.Cloud.Delete(filename);
  337.                         return true;
  338.                 }
  339. #else
  340.                 return false;
  341. #endif
  342.         }
  343.  
  344.         /// <summary>
  345.         /// Whether the specified file is present or not.
  346.         /// </summary>
  347.  
  348.         static internal bool HasFile (string filename)
  349.         {
  350. #if STEAM
  351.                 string[] list = GetFiles();
  352.                 if (list != null) foreach (string s in list) if (s == filename) return true;
  353. #endif
  354.                 return false;
  355.         }
  356.  
  357.         /// <summary>
  358.         /// Read the specified file from the Steam cloud.
  359.         /// </summary>
  360.  
  361.         static internal byte[] ReadFile (string filename)
  362.         {
  363.                 byte[] bytes = null;
  364. #if STEAM
  365.                 if (steam == null) return bytes;
  366.                 int maxBytes = steam.Cloud.GetSize(filename);
  367.                 if (maxBytes == 0) return bytes;
  368.  
  369.                 IntPtr ptr = Marshal.AllocHGlobal(maxBytes);
  370.                 int bytesRead = steam.Cloud.Read(filename, ptr, maxBytes);
  371.  
  372.                 if (bytesRead > 0)
  373.                 {
  374.                         bytes = new byte[bytesRead];
  375.                         Marshal.Copy(ptr, bytes, 0, bytesRead);
  376.                 }
  377.                 Marshal.FreeHGlobal(ptr);
  378. #endif
  379.                 return bytes;
  380.         }
  381.  
  382.         /// <summary>
  383.         /// Delete the specified file from the Steam cloud.
  384.         /// </summary>
  385.  
  386.         static internal void DeleteFile (string filename)
  387.         {
  388. #if STEAM
  389.                 if (steam != null) steam.Cloud.Delete(filename);
  390. #endif
  391.         }
  392.  
  393.         /// <summary>
  394.         /// Get the list of saved files from Steam.
  395.         /// </summary>
  396.  
  397.         static internal string[] GetFiles ()
  398.         {
  399. #if STEAM
  400.                 if (steam == null || steam.Cloud == null) return null;
  401.                 int count = steam.Cloud.GetFileCount();
  402.                 if (count == 0) return null;
  403.  
  404.                 string[] filenames = new string[count];
  405.  
  406.                 for (int i = 0; i < count; ++i)
  407.                 {
  408.                         CloudGetFileNameAndSizeResult result = steam.Cloud.GetFileNameAndSize(i);
  409.                         filenames[i] = result.result;
  410.                 }
  411.                 return filenames;
  412. #else
  413.                 return null;
  414. #endif
  415.         }
  416.  
  417.         /// <summary>
  418.         /// Command-line argument used to auto-connect an external server.
  419.         /// </summary>
  420.  
  421.         static internal string autoConnectString
  422.         {
  423.                 get
  424.                 {
  425. #if STEAM
  426.                         try
  427.                         {
  428.                                 bool connectStringIsNext = false;
  429.                                 string[] args = System.Environment.GetCommandLineArgs();
  430.  
  431.                                 for (int i = 0; i < args.Length; ++i)
  432.                                 {
  433.                                         string val = args[i];
  434.                                         if (connectStringIsNext) return val;
  435.                                         else if (val == "+connect") connectStringIsNext = true;
  436.                                 }
  437.                         }
  438.                         catch (System.Exception) {}
  439. #endif
  440.                         return null;
  441.                 }
  442.         }
  443.  
  444.         /// <summary>
  445.         /// Set the game status. Friends will be able to right-click and see this status, then possibly join the game.
  446.         /// </summary>
  447.  
  448.         static internal void SetPublicStatus (string status, System.Net.IPEndPoint address = null)
  449.         {
  450. #if STEAM && !UNITY_EDITOR
  451.                 if (steam != null)
  452.                 {
  453.                         steam.Friends.SetRichPresence("status", status);
  454.                         if (address != null) steam.Friends.SetRichPresence("connect", "+connect " + address);
  455.                         else steam.Friends.SetRichPresence("connect", "");
  456.                 }
  457. #endif
  458.         }
  459.  
  460.         void RegisterListeners ()
  461.         {
  462.                 steam.ExceptionThrown += ExceptionThrown;
  463.                 steam.Friends.GameOverlayActivated += OverlayToggle;
  464.                 steam.Friends.GameServerChangeRequested += OnServerChange;
  465.                 steam.Friends.GameRichPresenceJoinRequested += OnJoinRequest;
  466.                 steam.Stats.UserStatsReceived += UserStatsReceived;
  467.                 steam.Stats.UserStatsStored += UserStatsStored;
  468.                 steam.Stats.RequestCurrentStats();
  469.         }
  470.  
  471.         void UnregisterListeners ()
  472.         {
  473.                 steam.ExceptionThrown -= ExceptionThrown;
  474.                 steam.Friends.GameOverlayActivated -= OverlayToggle;
  475.                 steam.Friends.GameServerChangeRequested -= OnServerChange;
  476.                 steam.Friends.GameRichPresenceJoinRequested -= OnJoinRequest;
  477.                 steam.Stats.UserStatsReceived -= UserStatsReceived;
  478.                 steam.Stats.UserStatsStored -= UserStatsStored;
  479.         }
  480.  
  481.         void UserStatsReceived (UserStatsReceived value)
  482.         {
  483. #if UNITY_EDITOR
  484.                 if (value.GameID == gameID)
  485.                 {
  486.                         if (value.Result == ManagedSteam.SteamTypes.Result.OK)
  487.                                 UnityEngine.Debug.Log("Stats downloaded");
  488.                 }
  489. #endif
  490.         }
  491.  
  492.         void UserStatsStored (UserStatsStored value)
  493.         {
  494. #if UNITY_EDITOR
  495.                 if (value.GameID == gameID)
  496.                 {
  497.                         if (value.Result != ManagedSteam.SteamTypes.Result.OK)
  498.                         {
  499.                                 UnityEngine.Debug.Log("Stats saved to the server successfully.");
  500.                         }
  501.                 }
  502. #endif
  503.         }
  504.  
  505.         void OverlayToggle (GameOverlayActivated value)
  506.         {
  507.                 // This method is called when the game overlay is hidden or shown
  508.                 // NOTE: The overlay may not work when a game is run in the Unity editor
  509.                 // Build the game and "publish" it to a local content server and then start the game via the
  510.                 // steam client to make the overlay work.
  511.                 if (value.Active) UIGameWindow.PauseGame();
  512.         }
  513.  
  514.         void OnServerChange (GameServerChangeRequested value)
  515.         {
  516.                 NGUIDebug.Log("OnServerChange: " + value.Server);
  517.         }
  518.  
  519.         void OnJoinRequest (GameRichPresenceJoinRequested req)
  520.         {
  521.                 Debug.Log("Join request: " + req.Connect + "\n" + req.SteamIDFriend);
  522.         }
  523.  
  524.         void ExceptionThrown (Exception e)
  525.         {
  526.                 // This method is called when an exception have been thrown from native code.
  527.                 // We print the exception so we can see what went wrong.
  528.                 NGUIDebug.Log(e.GetType().Name + ": " + e.Message + "\n" + e.StackTrace);
  529.         }
  530.  
  531.         void Update () { if (steam != null) steam.Update(); }
  532.  
  533.         void OnDestroy ()
  534.         {
  535.                 if (instance == this)
  536.                 {
  537.                         instance = null;
  538.                         Cleanup();
  539.                 }
  540.         }
  541.  
  542.         void OnApplicationQuit () { Cleanup(); }
  543.  
  544.         void Cleanup ()
  545.         {
  546.                 if (steam != null)
  547.                 {
  548.                         UnregisterListeners();
  549.  
  550.                         if (Application.isEditor)
  551.                         {
  552.                                 // Only release managed handles if we run from inside the editor. This enables us
  553.                                 // to use the library again without restarting the editor.
  554.                                 steam.ReleaseManagedResources();
  555.                         }
  556.                         else
  557.                         {
  558.                                 // We are running from a standalone build. Shutdown the library completely
  559.                                 steam.Shutdown();
  560.                         }
  561.                         steam = null;
  562.                 }
  563.         }
  564. }
P.S. Note that with the recent Steam client updates it no longer seems to work in the editor. I'm not sure if it's because I use a beta Steam client, or because I run Steam with elevated privileges but not Unity... It doesn't bother me as it works fine in the stand-alone builds.

P.P.S.
  1. Steamworks.SetPublicStatus("Playing on a public server", new System.Net.IPEndPoint(TNet.Tools.externalAddress, 5127));
« Last Edit: September 29, 2015, 04:50:28 PM by ArenMook »

xandeck

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 3
  • Posts: 54
    • View Profile
Re: Steam API / Steamworks
« Reply #9 on: September 28, 2015, 06:47:52 PM »
Thank you very much for this Aren.

EDIT: Just wanted to say... I was testing also Forge, which is a nice networking, but has a lot of flaws still.
It took me one hour to port Forge to TNet (what I had, of course, not whole all game), lol. I used before with some lab games, now we are officially using in production. Thank you Aren.
« Last Edit: September 29, 2015, 09:56:15 AM by xandeck »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Steam API / Steamworks
« Reply #10 on: September 29, 2015, 04:52:05 PM »
Np, glad you like it. One of these days I'll get around to finally creating a proper set of tutorials for it... there have been many cool features added (like DataNode and auto-sync'd player data) that simply aren't covered anywhere.

xandeck

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 3
  • Posts: 54
    • View Profile
Re: Steam API / Steamworks
« Reply #11 on: September 30, 2015, 08:16:17 AM »
Aren, trust me, I have experience with Photon (I made of the first tutorials to connect Photon with an external database and using PHP), SmartFoxServer, Unity native Networking, Forge, uLink... and TNet is the easiest way of implemeting network and it does work good ;) although I am not "the expert" in those systems, I already made many tests and labs, TNet is the easiest way for sure.