From 2108dc3b76894b5fe890ce4c7658a50654b43b65 Mon Sep 17 00:00:00 2001 From: Matthew Oldfield Date: Mon, 10 Jul 2017 15:15:53 +0100 Subject: [PATCH 01/15] Implemented Workshop Item Subscription Added subscribing to items as well as the UGC interfaces GetNumSubscribedItems and GetSubscribedItems. Edited SteamUGC Method GetSubscribedItems to accept array instead of a ptr to allow c# calling --- .../Interfaces/Workshop.Item.cs | 13 ++++++++ Facepunch.Steamworks/Interfaces/Workshop.cs | 31 +++++++++++++++++++ .../SteamNative/SteamNative.SteamUGC.cs | 7 +++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Facepunch.Steamworks/Interfaces/Workshop.Item.cs b/Facepunch.Steamworks/Interfaces/Workshop.Item.cs index 5045028..21d943d 100644 --- a/Facepunch.Steamworks/Interfaces/Workshop.Item.cs +++ b/Facepunch.Steamworks/Interfaces/Workshop.Item.cs @@ -63,6 +63,19 @@ public void Download( bool highPriority = true ) workshop.OnItemInstalled += OnItemInstalled; } + public void Subscribe() + { + workshop.ugc.SubscribeItem(Id); + SubscriptionCount++; + } + + public void UnSubscribe() + { + workshop.ugc.UnsubscribeItem(Id); + SubscriptionCount--; + } + + private void OnFileDownloaded( ulong fileid, Callbacks.Result result ) { if ( fileid != Id ) return; diff --git a/Facepunch.Steamworks/Interfaces/Workshop.cs b/Facepunch.Steamworks/Interfaces/Workshop.cs index 27e04e1..a9bde30 100644 --- a/Facepunch.Steamworks/Interfaces/Workshop.cs +++ b/Facepunch.Steamworks/Interfaces/Workshop.cs @@ -123,6 +123,37 @@ public Item GetItem( ulong itemid ) return new Item( itemid, this ); } + /// + /// The amount of item's the user is subscribed to for this App + /// + public uint GetAmountSubsribed() + { + return ugc.GetNumSubscribedItems(); + } + /// + /// Creates a list of all item's that the user is currently subscribed + /// to for this App. This does not query titles or descriptions but + /// allows you to get the directories, state and ID of any subscribed Item. + /// This is mostly useful for getting all subscribed items install location. + /// + public Item[] GetSubscribedItems(uint amount) + { + Item[] items; + PublishedFileId_t[] vecSubscribedItems = new PublishedFileId_t[amount]; + uint subAmount = ugc.GetSubscribedItems(vecSubscribedItems, amount); + + if (subAmount < amount) + items = new Item[subAmount]; + else + items = new Item[amount]; + + for(int i =0, length = items.Length; i /// How a query should be ordered. diff --git a/Facepunch.Steamworks/SteamNative/SteamNative.SteamUGC.cs b/Facepunch.Steamworks/SteamNative/SteamNative.SteamUGC.cs index 7c5650f..d44321b 100644 --- a/Facepunch.Steamworks/SteamNative/SteamNative.SteamUGC.cs +++ b/Facepunch.Steamworks/SteamNative/SteamNative.SteamUGC.cs @@ -284,9 +284,12 @@ public bool GetQueryUGCStatistic( UGCQueryHandle_t handle /*UGCQueryHandle_t*/, } // uint - public uint GetSubscribedItems( PublishedFileId_t* pvecPublishedFileID /*PublishedFileId_t **/, uint cMaxEntries /*uint32*/ ) + public uint GetSubscribedItems( PublishedFileId_t[] pvecPublishedFileID /*PublishedFileId_t **/, uint cMaxEntries /*uint32*/ ) { - return platform.ISteamUGC_GetSubscribedItems( (IntPtr) pvecPublishedFileID, cMaxEntries ); + fixed (PublishedFileId_t* pvecPublishedFileID_ptr = pvecPublishedFileID) + { + return platform.ISteamUGC_GetSubscribedItems((IntPtr)pvecPublishedFileID_ptr, cMaxEntries); + } } // SteamAPICall_t From 27f640fd5ad3c4c213d50e9eaad48640a8babfd3 Mon Sep 17 00:00:00 2001 From: Matthew Oldfield Date: Mon, 10 Jul 2017 19:15:36 +0100 Subject: [PATCH 02/15] Updated from feedback given --- Facepunch.Steamworks/Interfaces/Workshop.cs | 20 +++++++++---------- .../SteamNative/SteamNative.SteamUGC.cs | 7 ++----- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/Facepunch.Steamworks/Interfaces/Workshop.cs b/Facepunch.Steamworks/Interfaces/Workshop.cs index a9bde30..cdbe3a8 100644 --- a/Facepunch.Steamworks/Interfaces/Workshop.cs +++ b/Facepunch.Steamworks/Interfaces/Workshop.cs @@ -123,25 +123,23 @@ public Item GetItem( ulong itemid ) return new Item( itemid, this ); } - /// - /// The amount of item's the user is subscribed to for this App - /// - public uint GetAmountSubsribed() - { - return ugc.GetNumSubscribedItems(); - } /// /// Creates a list of all item's that the user is currently subscribed /// to for this App. This does not query titles or descriptions but /// allows you to get the directories, state and ID of any subscribed Item. - /// This is mostly useful for getting all subscribed items install location. + /// This is mostly useful for getting all subscribed items install location + /// on initial load to load all workshop content /// - public Item[] GetSubscribedItems(uint amount) + public unsafe Item[] GetSubscribedItems() { Item[] items; + uint subAmount; + var amount = ugc.GetNumSubscribedItems(); PublishedFileId_t[] vecSubscribedItems = new PublishedFileId_t[amount]; - uint subAmount = ugc.GetSubscribedItems(vecSubscribedItems, amount); - + fixed (PublishedFileId_t* vecSubscribedItems_ptr = vecSubscribedItems) + { + subAmount = ugc.GetSubscribedItems(vecSubscribedItems_ptr, amount); + } if (subAmount < amount) items = new Item[subAmount]; else diff --git a/Facepunch.Steamworks/SteamNative/SteamNative.SteamUGC.cs b/Facepunch.Steamworks/SteamNative/SteamNative.SteamUGC.cs index d44321b..7c5650f 100644 --- a/Facepunch.Steamworks/SteamNative/SteamNative.SteamUGC.cs +++ b/Facepunch.Steamworks/SteamNative/SteamNative.SteamUGC.cs @@ -284,12 +284,9 @@ public bool GetQueryUGCStatistic( UGCQueryHandle_t handle /*UGCQueryHandle_t*/, } // uint - public uint GetSubscribedItems( PublishedFileId_t[] pvecPublishedFileID /*PublishedFileId_t **/, uint cMaxEntries /*uint32*/ ) + public uint GetSubscribedItems( PublishedFileId_t* pvecPublishedFileID /*PublishedFileId_t **/, uint cMaxEntries /*uint32*/ ) { - fixed (PublishedFileId_t* pvecPublishedFileID_ptr = pvecPublishedFileID) - { - return platform.ISteamUGC_GetSubscribedItems((IntPtr)pvecPublishedFileID_ptr, cMaxEntries); - } + return platform.ISteamUGC_GetSubscribedItems( (IntPtr) pvecPublishedFileID, cMaxEntries ); } // SteamAPICall_t From a2972098d97a53884fba7b3ca4487b9f409fa470 Mon Sep 17 00:00:00 2001 From: Rich Date: Wed, 12 Jul 2017 17:17:26 -0400 Subject: [PATCH 03/15] Added AppId check to Workshop.onItemInstalled, like with onDownloadResult --- Facepunch.Steamworks/Interfaces/Workshop.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Facepunch.Steamworks/Interfaces/Workshop.cs b/Facepunch.Steamworks/Interfaces/Workshop.cs index a305af2..504e3d5 100644 --- a/Facepunch.Steamworks/Interfaces/Workshop.cs +++ b/Facepunch.Steamworks/Interfaces/Workshop.cs @@ -67,7 +67,7 @@ public void Dispose() private void onItemInstalled( SteamNative.ItemInstalled_t obj, bool failed ) { - if ( OnItemInstalled != null ) + if ( OnItemInstalled != null && obj.AppID == Client.Instance.AppId ) OnItemInstalled( obj.PublishedFileId ); } From c9d36eb4acf4a40f3f2cab07d295db31977ed348 Mon Sep 17 00:00:00 2001 From: Rich Date: Wed, 12 Jul 2017 17:18:29 -0400 Subject: [PATCH 04/15] Made OnItemInstalled event public so it can be used to handle workshop items being subscribed to in-game --- Facepunch.Steamworks/Interfaces/Workshop.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Facepunch.Steamworks/Interfaces/Workshop.cs b/Facepunch.Steamworks/Interfaces/Workshop.cs index 504e3d5..8280851 100644 --- a/Facepunch.Steamworks/Interfaces/Workshop.cs +++ b/Facepunch.Steamworks/Interfaces/Workshop.cs @@ -39,7 +39,7 @@ public partial class Workshop : IDisposable /// because of a call to Download or because of a subscription triggered /// via the browser/app. /// - internal event Action OnItemInstalled; + public event Action OnItemInstalled; internal Workshop( BaseSteamworks steamworks, SteamNative.SteamUGC ugc, SteamNative.SteamRemoteStorage remoteStorage ) { From bf7ab5598b87611c666c232ee2569b0cd6640dc8 Mon Sep 17 00:00:00 2001 From: Rich Date: Wed, 12 Jul 2017 17:19:55 -0400 Subject: [PATCH 05/15] Modified summary for OnFileDownloaded to more accurately represent my experience with the event. --- Facepunch.Steamworks/Interfaces/Workshop.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Facepunch.Steamworks/Interfaces/Workshop.cs b/Facepunch.Steamworks/Interfaces/Workshop.cs index 8280851..9491e2e 100644 --- a/Facepunch.Steamworks/Interfaces/Workshop.cs +++ b/Facepunch.Steamworks/Interfaces/Workshop.cs @@ -29,8 +29,7 @@ public partial class Workshop : IDisposable /// /// Called when an item has been downloaded. This could have been - /// because of a call to Download or because of a subscription triggered - /// via the browser/app. + /// because of a call to Download. /// public event Action OnFileDownloaded; From e6c395b2f67472cc4446c25a69971965aec4994f Mon Sep 17 00:00:00 2001 From: Matthew Oldfield Date: Wed, 12 Jul 2017 23:21:33 +0100 Subject: [PATCH 06/15] Removed GetSubscribedItems, could not find a nice way to change to property --- Facepunch.Steamworks/Interfaces/Workshop.cs | 30 --------------------- 1 file changed, 30 deletions(-) diff --git a/Facepunch.Steamworks/Interfaces/Workshop.cs b/Facepunch.Steamworks/Interfaces/Workshop.cs index cdbe3a8..a0122e7 100644 --- a/Facepunch.Steamworks/Interfaces/Workshop.cs +++ b/Facepunch.Steamworks/Interfaces/Workshop.cs @@ -123,36 +123,6 @@ public Item GetItem( ulong itemid ) return new Item( itemid, this ); } - /// - /// Creates a list of all item's that the user is currently subscribed - /// to for this App. This does not query titles or descriptions but - /// allows you to get the directories, state and ID of any subscribed Item. - /// This is mostly useful for getting all subscribed items install location - /// on initial load to load all workshop content - /// - public unsafe Item[] GetSubscribedItems() - { - Item[] items; - uint subAmount; - var amount = ugc.GetNumSubscribedItems(); - PublishedFileId_t[] vecSubscribedItems = new PublishedFileId_t[amount]; - fixed (PublishedFileId_t* vecSubscribedItems_ptr = vecSubscribedItems) - { - subAmount = ugc.GetSubscribedItems(vecSubscribedItems_ptr, amount); - } - if (subAmount < amount) - items = new Item[subAmount]; - else - items = new Item[amount]; - - for(int i =0, length = items.Length; i /// How a query should be ordered. /// From 1c04459cdb01913f5375e87782ce6d22795cc451 Mon Sep 17 00:00:00 2001 From: James King Date: Fri, 28 Jul 2017 15:38:07 +0100 Subject: [PATCH 07/15] Calls on an unresolved leaderboard are deferred Applies to: * AddScore( bool onlyIfBeatsOldScore, int score, params int[] subscores ) * AddScore( bool onlyIfBeatsOldScore, int score, int[] subscores = null, AddScoreCallback onSuccess = null, FailureCallback onFailure = null ) * AttachRemoteFile( RemoteFile file, AttachRemoteFileCallback onSuccess = null, FailureCallback onFailure = null ) * FetchScores( RequestType RequestType, int start, int end, FetchScoresCallback onSuccess, FailureCallback onFailure = null ) --- Facepunch.Steamworks/Client/Leaderboard.cs | 52 +++++++++++++++++----- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/Facepunch.Steamworks/Client/Leaderboard.cs b/Facepunch.Steamworks/Client/Leaderboard.cs index 440477e..a454c1e 100644 --- a/Facepunch.Steamworks/Client/Leaderboard.cs +++ b/Facepunch.Steamworks/Client/Leaderboard.cs @@ -35,6 +35,8 @@ public enum RequestType internal ulong BoardId; internal Client client; + private readonly Queue _onCreated = new Queue(); + /// /// The results from the last query. Can be null. /// @@ -77,21 +79,45 @@ public void Dispose() client = null; } + private void DispatchOnCreatedCallbacks() + { + while ( _onCreated.Count > 0 ) + { + _onCreated.Dequeue()(); + } + } + + private bool DeferOnCreated( Action onValid, FailureCallback onFailure = null ) + { + if ( IsValid || IsError ) return false; + + _onCreated.Enqueue( () => + { + if ( IsValid ) onValid(); + else onFailure?.Invoke( Callbacks.Result.Fail ); + } ); + + return true; + } + internal void OnBoardCreated( LeaderboardFindResult_t result, bool error ) { if ( error || ( result.LeaderboardFound == 0 ) ) { IsError = true; - return; } - - BoardId = result.SteamLeaderboard; - - if ( IsValid ) + else { - Name = client.native.userstats.GetLeaderboardName( BoardId ); - TotalEntries = client.native.userstats.GetLeaderboardEntryCount( BoardId ); + BoardId = result.SteamLeaderboard; + + if ( IsValid ) + { + Name = client.native.userstats.GetLeaderboardName( BoardId ); + TotalEntries = client.native.userstats.GetLeaderboardEntryCount( BoardId ); + } } + + DispatchOnCreatedCallbacks(); } /// @@ -103,7 +129,8 @@ internal void OnBoardCreated( LeaderboardFindResult_t result, bool error ) /// public bool AddScore( bool onlyIfBeatsOldScore, int score, params int[] subscores ) { - if ( !IsValid ) return false; + if ( IsError ) return false; + if ( !IsValid ) return DeferOnCreated( () => AddScore( onlyIfBeatsOldScore, score, subscores ) ); var flags = LeaderboardUploadScoreMethod.ForceUpdate; if ( onlyIfBeatsOldScore ) flags = LeaderboardUploadScoreMethod.KeepBest; @@ -142,7 +169,8 @@ public struct AddScoreResult /// public bool AddScore( bool onlyIfBeatsOldScore, int score, int[] subscores = null, AddScoreCallback onSuccess = null, FailureCallback onFailure = null ) { - if ( !IsValid ) return false; + if ( IsError ) return false; + if ( !IsValid ) return DeferOnCreated( () => AddScore( onlyIfBeatsOldScore, score, subscores, onSuccess, onFailure ), onFailure ); if ( subscores == null ) subscores = new int[0]; @@ -182,7 +210,8 @@ public bool AddScore( bool onlyIfBeatsOldScore, int score, int[] subscores = nul /// True if the file attachment process has started public bool AttachRemoteFile( RemoteFile file, AttachRemoteFileCallback onSuccess = null, FailureCallback onFailure = null ) { - if ( !IsValid ) return false; + if ( IsError ) return false; + if ( !IsValid ) return DeferOnCreated( () => AttachRemoteFile( file, onSuccess, onFailure ), onFailure ); if ( file.IsShared ) { @@ -260,7 +289,8 @@ private unsafe void ReadScores( LeaderboardScoresDownloaded_t result, ListReturns true if we have started the query public bool FetchScores( RequestType RequestType, int start, int end, FetchScoresCallback onSuccess, FailureCallback onFailure = null ) { - if ( !IsValid ) return false; + if ( IsError ) return false; + if ( !IsValid ) return DeferOnCreated( () => FetchScores( RequestType, start, end, onSuccess, onFailure ), onFailure ); client.native.userstats.DownloadLeaderboardEntries( BoardId, (LeaderboardDataRequest) RequestType, start, end, ( result, error ) => { From a26ae696c2bc60e5be92afeb0232e9a5b21e3ae6 Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Fri, 28 Jul 2017 17:03:12 +0100 Subject: [PATCH 08/15] Don't StoreStats achievement on trigger if already unlocked --- Facepunch.Steamworks/Client/Achievements.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Facepunch.Steamworks/Client/Achievements.cs b/Facepunch.Steamworks/Client/Achievements.cs index a661f13..09e489d 100644 --- a/Facepunch.Steamworks/Client/Achievements.cs +++ b/Facepunch.Steamworks/Client/Achievements.cs @@ -50,14 +50,10 @@ public Achievement Find( string identifier ) /// public bool Trigger( string identifier, bool apply = true ) { - var r = client.native.userstats.SetAchievement( identifier ); + var a = Find( identifier ); + if ( a == null ) return false; - if ( apply ) - { - client.Stats.StoreStats(); - } - - return r; + return a.Trigger( apply ); } /// @@ -159,6 +155,9 @@ public Achievement( Client client, int index ) /// public bool Trigger( bool apply = true ) { + if ( State ) + return false; + State = true; UnlockTime = DateTime.Now; From c6cb8a2f81f912309b6b35936eba44e127b52869 Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Fri, 28 Jul 2017 17:03:35 +0100 Subject: [PATCH 09/15] Refresh achievements on startup --- Facepunch.Steamworks/Client/Achievements.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Facepunch.Steamworks/Client/Achievements.cs b/Facepunch.Steamworks/Client/Achievements.cs index 09e489d..bc34225 100644 --- a/Facepunch.Steamworks/Client/Achievements.cs +++ b/Facepunch.Steamworks/Client/Achievements.cs @@ -21,6 +21,8 @@ internal Achievements( Client c ) All = new Achievement[0]; SteamNative.UserStatsReceived_t.RegisterCallback( c, UserStatsReceived ); + + Refresh(); } public void Refresh() From 61268b973ed071de9fd07070650af4ddf7374a41 Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Fri, 28 Jul 2017 17:04:18 +0100 Subject: [PATCH 10/15] Added Achievments.OnAchievementStateChanged --- Facepunch.Steamworks/Client/Achievements.cs | 58 +++++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/Facepunch.Steamworks/Client/Achievements.cs b/Facepunch.Steamworks/Client/Achievements.cs index bc34225..472aeb4 100644 --- a/Facepunch.Steamworks/Client/Achievements.cs +++ b/Facepunch.Steamworks/Client/Achievements.cs @@ -13,23 +13,52 @@ public class Achievements : IDisposable public Achievement[] All { get; private set; } public event Action OnUpdated; + public event Action OnAchievementStateChanged; + + private List unlockedRecently = new List(); internal Achievements( Client c ) { client = c; All = new Achievement[0]; - SteamNative.UserStatsReceived_t.RegisterCallback( c, UserStatsReceived ); + SteamNative.UserStatsStored_t.RegisterCallback( c, UserStatsStored ); Refresh(); } public void Refresh() { + var old = All; + All = Enumerable.Range( 0, (int)client.native.userstats.GetNumAchievements() ) - .Select( x => new Achievement( client, x ) ) + .Select( x => + { + if ( old != null ) + { + var name = client.native.userstats.GetAchievementName( (uint)x ); + var found = old.FirstOrDefault( y => y.Id == name ); + if ( found != null ) + { + if ( found.Refresh() ) + { + unlockedRecently.Add( found ); + } + return found; + } + } + + return new Achievement( client, x ); + } ) .ToArray(); + + foreach ( var i in unlockedRecently ) + { + OnAchievementStateChanged?.Invoke( i ); + } + + unlockedRecently.Clear(); } public void Dispose() @@ -74,6 +103,15 @@ private void UserStatsReceived( UserStatsReceived_t stats, bool isError ) OnUpdated?.Invoke(); } + + private void UserStatsStored( UserStatsStored_t stats, bool isError ) + { + if ( isError ) return; + + Refresh(); + + OnUpdated?.Invoke(); + } } public class Achievement @@ -95,6 +133,7 @@ public class Achievement public DateTime UnlockTime { get; private set; } private int iconId { get; set; } = -1; + private int refreshCount = 0; /// /// If this achievement is linked to a stat this will return the progress. @@ -186,10 +225,12 @@ public bool Reset() /// /// Refresh the unlock state. You shouldn't need to call this manually - /// but it's here if you have to for some reason. + /// but it's here if you have to for some reason. Retuns true if state changed (meaning, probably unlocked) /// - public void Refresh() + public bool Refresh() { + bool previousState = State; + bool state = false; uint unlockTime; @@ -200,6 +241,15 @@ public void Refresh() State = state; UnlockTime = Utility.Epoch.ToDateTime( unlockTime ); } + + refreshCount++; + + if ( previousState != State && refreshCount > 1 ) + { + return true; + } + + return false; } } From 84954436f75553bb20d77be8158752500dc50b9d Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Fri, 28 Jul 2017 17:04:29 +0100 Subject: [PATCH 11/15] Check GameId on achievement callbacks --- Facepunch.Steamworks/Client/Achievements.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Facepunch.Steamworks/Client/Achievements.cs b/Facepunch.Steamworks/Client/Achievements.cs index 472aeb4..07e3f04 100644 --- a/Facepunch.Steamworks/Client/Achievements.cs +++ b/Facepunch.Steamworks/Client/Achievements.cs @@ -98,6 +98,7 @@ public bool Reset( string identifier ) private void UserStatsReceived( UserStatsReceived_t stats, bool isError ) { if ( isError ) return; + if ( stats.GameID != client.AppId ) return; Refresh(); @@ -107,6 +108,7 @@ private void UserStatsReceived( UserStatsReceived_t stats, bool isError ) private void UserStatsStored( UserStatsStored_t stats, bool isError ) { if ( isError ) return; + if ( stats.GameID != client.AppId ) return; Refresh(); From 7bd8aaa793e75159ccd73efeada69bf684421bb4 Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Mon, 31 Jul 2017 10:31:04 +0100 Subject: [PATCH 12/15] OnAchievementStateChanged nicer --- Facepunch.Steamworks/Client/Achievements.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Facepunch.Steamworks/Client/Achievements.cs b/Facepunch.Steamworks/Client/Achievements.cs index 07e3f04..ce80fd1 100644 --- a/Facepunch.Steamworks/Client/Achievements.cs +++ b/Facepunch.Steamworks/Client/Achievements.cs @@ -55,12 +55,17 @@ public void Refresh() foreach ( var i in unlockedRecently ) { - OnAchievementStateChanged?.Invoke( i ); + OnUnlocked( i ); } unlockedRecently.Clear(); } + internal void OnUnlocked( Achievement a ) + { + OnAchievementStateChanged?.Invoke( a ); + } + public void Dispose() { client = null; @@ -211,6 +216,8 @@ public bool Trigger( bool apply = true ) client.Stats.StoreStats(); } + client.Achievements.OnUnlocked( this ); + return r; } From b62f7f6b872ccb262d70bd15105227548db4ab6a Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Mon, 31 Jul 2017 12:56:15 +0100 Subject: [PATCH 13/15] Server stats callback include client steamid --- Facepunch.Steamworks.Test/Server/Stats.cs | 2 +- Facepunch.Steamworks/Server/Stats.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Facepunch.Steamworks.Test/Server/Stats.cs b/Facepunch.Steamworks.Test/Server/Stats.cs index a877f82..e870ff1 100644 --- a/Facepunch.Steamworks.Test/Server/Stats.cs +++ b/Facepunch.Steamworks.Test/Server/Stats.cs @@ -19,7 +19,7 @@ public void StatsGet() bool GotStats = false; - server.Stats.Refresh( MySteamId, success => + server.Stats.Refresh( MySteamId, (steamid, success) => { GotStats = true; Assert.IsTrue( success ); diff --git a/Facepunch.Steamworks/Server/Stats.cs b/Facepunch.Steamworks/Server/Stats.cs index 3234f76..b7f18bf 100644 --- a/Facepunch.Steamworks/Server/Stats.cs +++ b/Facepunch.Steamworks/Server/Stats.cs @@ -31,7 +31,7 @@ public struct StatsReceived /// this will be called when the stats are recieved, the bool will signify whether /// it was successful or not. /// - public void Refresh( ulong steamid, Action Callback = null ) + public void Refresh( ulong steamid, Action Callback = null ) { if ( Callback == null ) { @@ -41,7 +41,7 @@ public void Refresh( ulong steamid, Action Callback = null ) server.native.gameServerStats.RequestUserStats( steamid, ( o, failed ) => { - Callback( o.Result == SteamNative.Result.OK && !failed ); + Callback( steamid, o.Result == SteamNative.Result.OK && !failed ); } ); } @@ -50,7 +50,7 @@ public void Refresh( ulong steamid, Action Callback = null ) /// You can do that using this function. The callback will let you know if /// your action succeeded, but most of the time you can fire and forget. /// - public void Commit( ulong steamid, Action Callback = null ) + public void Commit( ulong steamid, Action Callback = null ) { if ( Callback == null ) { @@ -60,7 +60,7 @@ public void Commit( ulong steamid, Action Callback = null ) server.native.gameServerStats.StoreUserStats( steamid, ( o, failed ) => { - Callback( o.Result == SteamNative.Result.OK && !failed ); + Callback( steamid, o.Result == SteamNative.Result.OK && !failed ); } ); } From 72c5427be652e46cab35d8fa536eb59d73d373d8 Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Mon, 31 Jul 2017 12:56:54 +0100 Subject: [PATCH 14/15] Changed Server.Stats.Set to SetInt/SetFloat --- Facepunch.Steamworks/Server/Stats.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Facepunch.Steamworks/Server/Stats.cs b/Facepunch.Steamworks/Server/Stats.cs index b7f18bf..0a28aa4 100644 --- a/Facepunch.Steamworks/Server/Stats.cs +++ b/Facepunch.Steamworks/Server/Stats.cs @@ -68,7 +68,7 @@ public void Commit( ulong steamid, Action Callback = null ) /// Set the named stat for this user. Setting stats should follow the rules /// you defined in Steamworks. /// - public bool Set( ulong steamid, string name, int stat ) + public bool SetInt( ulong steamid, string name, int stat ) { return server.native.gameServerStats.SetUserStat( steamid, name, stat ); } @@ -77,7 +77,7 @@ public bool Set( ulong steamid, string name, int stat ) /// Set the named stat for this user. Setting stats should follow the rules /// you defined in Steamworks. /// - public bool Set( ulong steamid, string name, float stat ) + public bool SetFloat( ulong steamid, string name, float stat ) { return server.native.gameServerStats.SetUserStat0( steamid, name, stat ); } From ba3281718367f83b48a2a30b386c85c9b74b672f Mon Sep 17 00:00:00 2001 From: James King Date: Mon, 7 Aug 2017 12:13:16 +0100 Subject: [PATCH 15/15] Added Screenshots.Write( rgbData, width, height ) --- Facepunch.Steamworks/Client/Screenshots.cs | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Facepunch.Steamworks/Client/Screenshots.cs b/Facepunch.Steamworks/Client/Screenshots.cs index fa75b35..a0a9f2b 100644 --- a/Facepunch.Steamworks/Client/Screenshots.cs +++ b/Facepunch.Steamworks/Client/Screenshots.cs @@ -35,5 +35,36 @@ public void Trigger() client.native.screenshots.TriggerScreenshot(); } + public unsafe void Write( byte[] rgbData, int width, int height ) + { + if ( rgbData == null ) + { + throw new ArgumentNullException( nameof(rgbData) ); + } + + if ( width < 1 ) + { + throw new ArgumentOutOfRangeException( nameof(width), width, + $"Expected {nameof(width)} to be at least 1." ); + } + + if ( height < 1 ) + { + throw new ArgumentOutOfRangeException( nameof(height), height, + $"Expected {nameof(height)} to be at least 1." ); + } + + var size = width * height * 3; + if ( rgbData.Length < size ) + { + throw new ArgumentException( nameof(rgbData), + $"Expected {nameof(rgbData)} to contain at least {size} elements (actual size: {rgbData.Length})." ); + } + + fixed ( byte* ptr = rgbData ) + { + client.native.screenshots.WriteScreenshot( (IntPtr) ptr, (uint) rgbData.Length, width, height ); + } + } } }