From 80946d60ca3ed5b5687c46625c06f62b35c667b7 Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Tue, 11 Oct 2016 15:10:20 +0100 Subject: [PATCH] Workshop publish fixes --- Facepunch.Steamworks.Test/Client/Workshop.cs | 4 +- .../Interfaces/Workshop.Editor.cs | 115 ++++++++++++++---- .../Interop/steam_api_interop.cs | 29 ++++- 3 files changed, 122 insertions(+), 26 deletions(-) diff --git a/Facepunch.Steamworks.Test/Client/Workshop.cs b/Facepunch.Steamworks.Test/Client/Workshop.cs index f2527a4..ec9aeb6 100644 --- a/Facepunch.Steamworks.Test/Client/Workshop.cs +++ b/Facepunch.Steamworks.Test/Client/Workshop.cs @@ -286,7 +286,8 @@ namespace Facepunch.Steamworks.Test var item = client.Workshop.CreateItem( Workshop.ItemType.Microtransaction ); item.Title = "Facepunch.Steamworks Unit test"; - + item.Tags.Add( "Apple" ); + item.Tags.Add( "Banana" ); item.Publish(); while ( item.Publishing ) @@ -297,6 +298,7 @@ namespace Facepunch.Steamworks.Test Assert.IsFalse( item.Publishing ); Assert.AreNotEqual( 0, item.Id ); + Assert.IsNull( item.Error ); Console.WriteLine( "item.Id: {0}", item.Id ); diff --git a/Facepunch.Steamworks/Interfaces/Workshop.Editor.cs b/Facepunch.Steamworks/Interfaces/Workshop.Editor.cs index 0950718..1d51786 100644 --- a/Facepunch.Steamworks/Interfaces/Workshop.Editor.cs +++ b/Facepunch.Steamworks/Interfaces/Workshop.Editor.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Facepunch.Steamworks.Callbacks.Workshop; namespace Facepunch.Steamworks @@ -13,18 +14,84 @@ namespace Facepunch.Steamworks internal SubmitItemUpdate SubmitItemUpdate; public ulong Id { get; internal set; } - public string Title { get; set; } - public string Description { get; set; } + public string Title { get; set; } = null; + public string Description { get; set; } = null; + public string Folder { get; set; } = null; + public List Tags { get; set; } = new List(); public bool Publishing { get; internal set; } public ItemType? Type { get; set; } - + public string Error { get; internal set; } = null; public string ChangeNote { get; set; } = ""; + public enum VisibilityType : int + { + Public = 0, + FriendsOnly = 1, + Private = 2 + } + + public VisibilityType ? Visibility { get; set; } + public bool NeedToAgreeToWorkshopLegal { get; internal set; } + + + public double Progress + { + get + { + if ( !Publishing ) return 1.0; + if ( CreateItem != null ) return 0.0; + if ( SubmitItemUpdate == null ) return 1.0; + + ulong b = 0; + ulong t = 0; + + workshop.steamworks.native.ugc.GetItemUpdateProgress( SubmitItemUpdate.Handle, ref b, ref t ); + + if ( t == 0 ) + return 0; + + return (double)b / (double) t; + } + } + + public int BytesUploaded + { + get + { + if ( !Publishing ) return 0; + if ( CreateItem != null ) return 0; + if ( SubmitItemUpdate == null ) return 0; + + ulong b = 0; + ulong t = 0; + + workshop.steamworks.native.ugc.GetItemUpdateProgress( SubmitItemUpdate.Handle, ref b, ref t ); + return (int) b; + } + } + + public int BytesTotal + { + get + { + if ( !Publishing ) return 0; + if ( CreateItem != null ) return 0; + if ( SubmitItemUpdate == null ) return 0; + + ulong b = 0; + ulong t = 0; + + workshop.steamworks.native.ugc.GetItemUpdateProgress( SubmitItemUpdate.Handle, ref b, ref t ); + return (int)t; + } + } + public void Publish() { Publishing = true; + Error = null; if ( Id == 0 ) { @@ -58,14 +125,12 @@ namespace Facepunch.Steamworks return; } - Console.WriteLine( "File publish error: " + obj ); + Error = "Error creating new file: " + obj.Result.ToString(); Publishing = false; } private void PublishChanges() { - Publishing = false; - ulong UpdateId = workshop.ugc.StartItemUpdate( workshop.steamworks.AppId, Id ); if ( Title != null ) @@ -74,21 +139,26 @@ namespace Facepunch.Steamworks if ( Description != null ) workshop.ugc.SetItemDescription( UpdateId, Description ); - /* - workshop.ugc.SetItemUpdateLanguage( UpdateId, const char *pchLanguage ) = 0; // specify the language of the title or description that will be set - workshop.ugc.SetItemMetadata( UpdateId, const char *pchMetaData ) = 0; // change the metadata of an UGC item (max = k_cchDeveloperMetadataMax) - workshop.ugc.SetItemVisibility( UpdateId, ERemoteStoragePublishedFileVisibility eVisibility ) = 0; // change the visibility of an UGC item - workshop.ugc.SetItemTags( UpdateId, const SteamParamStringArray_t *pTags ) = 0; // change the tags of an UGC item - workshop.ugc.SetItemContent( UpdateId, const char *pszContentFolder ) = 0; // update item content from this local folder - workshop.ugc.SetItemPreview( UpdateId, const char *pszPreviewFile ) = 0; // change preview image file for this item. pszPreviewFile points to local image file, which must be under 1MB in size - workshop.ugc.RemoveItemKeyValueTags( UpdateId, const char *pchKey ) = 0; // remove any existing key-value tags with the specified key - workshop.ugc.AddItemKeyValueTag( UpdateId, const char *pchKey, const char *pchValue ) = 0; // add new key-value tags for the item. Note that there can be multiple values for a tag. - workshop.ugc.AddItemPreviewFile( UpdateId, const char *pszPreviewFile, EItemPreviewType type ) = 0; // add preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size - workshop.ugc.AddItemPreviewVideo( UpdateId, const char *pszVideoID ) = 0; // add preview video for this item - workshop.ugc.UpdateItemPreviewFile( UpdateId, uint32 index, const char *pszPreviewFile ) = 0; // updates an existing preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size - workshop.ugc.UpdateItemPreviewVideo( UpdateId, uint32 index, const char *pszVideoID ) = 0; // updates an existing preview video for this item - workshop.ugc.RemoveItemPreview( UpdateId, uint32 index ) = 0; // remove a preview by index starting at 0 (previews are sorted) + if ( Folder != null ) + workshop.ugc.SetItemContent( UpdateId, Folder ); + if ( Tags != null && Tags.Count > 0 ) + workshop.ugc.SetItemTags( UpdateId, Tags.ToArray() ); + + if ( Visibility.HasValue ) + workshop.ugc.SetItemVisibility( UpdateId, (uint)Visibility.Value ); + + /* + workshop.ugc.SetItemUpdateLanguage( UpdateId, const char *pchLanguage ) = 0; // specify the language of the title or description that will be set + workshop.ugc.SetItemMetadata( UpdateId, const char *pchMetaData ) = 0; // change the metadata of an UGC item (max = k_cchDeveloperMetadataMax) + workshop.ugc.SetItemPreview( UpdateId, const char *pszPreviewFile ) = 0; // change preview image file for this item. pszPreviewFile points to local image file, which must be under 1MB in size + workshop.ugc.RemoveItemKeyValueTags( UpdateId, const char *pchKey ) = 0; // remove any existing key-value tags with the specified key + workshop.ugc.AddItemKeyValueTag( UpdateId, const char *pchKey, const char *pchValue ) = 0; // add new key-value tags for the item. Note that there can be multiple values for a tag. + workshop.ugc.AddItemPreviewFile( UpdateId, const char *pszPreviewFile, EItemPreviewType type ) = 0; // add preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size + workshop.ugc.AddItemPreviewVideo( UpdateId, const char *pszVideoID ) = 0; // add preview video for this item + workshop.ugc.UpdateItemPreviewFile( UpdateId, uint32 index, const char *pszPreviewFile ) = 0; // updates an existing preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size + workshop.ugc.UpdateItemPreviewVideo( UpdateId, uint32 index, const char *pszVideoID ) = 0; // updates an existing preview video for this item + workshop.ugc.RemoveItemPreview( UpdateId, uint32 index ) = 0; // remove a preview by index starting at 0 (previews are sorted) */ SubmitItemUpdate = new SubmitItemUpdate(); @@ -100,14 +170,15 @@ namespace Facepunch.Steamworks private void OnChangesSubmitted( SubmitItemUpdate.Data obj ) { SubmitItemUpdate = null; - NeedToAgreeToWorkshopLegal = obj.NeedsLegalAgreement; + Publishing = false; if ( obj.Result == Callbacks.Result.OK ) { - Publishing = false; return; } + + Error = "Error publishing changes: " + obj.Result.ToString(); } public void Delete() diff --git a/Facepunch.Steamworks/Interop/steam_api_interop.cs b/Facepunch.Steamworks/Interop/steam_api_interop.cs index ad89eec..fd6de03 100644 --- a/Facepunch.Steamworks/Interop/steam_api_interop.cs +++ b/Facepunch.Steamworks/Interop/steam_api_interop.cs @@ -2208,7 +2208,7 @@ namespace Valve.Steamworks internal abstract bool SetItemUpdateLanguage( ulong handle, string pchLanguage ); internal abstract bool SetItemMetadata( ulong handle, string pchMetaData ); internal abstract bool SetItemVisibility( ulong handle, uint eVisibility ); - internal abstract bool SetItemTags( ulong updateHandle, ref SteamParamStringArray_t pTags ); + internal abstract bool SetItemTags( ulong updateHandle, string[] pTags ); internal abstract bool SetItemContent( ulong handle, string pszContentFolder ); internal abstract bool SetItemPreview( ulong handle, string pszPreviewFile ); internal abstract bool RemoveItemKeyValueTags( ulong handle, string pchKey ); @@ -5856,10 +5856,33 @@ namespace Valve.Steamworks bool result = NativeEntrypoints.SteamAPI_ISteamUGC_SetItemVisibility(m_pSteamUGC,handle,eVisibility); return result; } - internal override bool SetItemTags( ulong updateHandle, ref SteamParamStringArray_t pTags ) + internal override bool SetItemTags( ulong updateHandle, string[] pTags ) { CheckIfUsable(); - bool result = NativeEntrypoints.SteamAPI_ISteamUGC_SetItemTags(m_pSteamUGC,updateHandle,ref pTags); + + var nativeStrings = new IntPtr[pTags.Length]; + for ( int i = 0; i < pTags.Length; i++ ) + { + nativeStrings[i] = Marshal.StringToHGlobalAnsi( pTags[i] ); + } + + var size = Marshal.SizeOf( typeof( IntPtr ) ) * nativeStrings.Length; + var nativeArray = Marshal.AllocHGlobal( size ); + Marshal.Copy( nativeStrings, 0, nativeArray, nativeStrings.Length ); + + var tags = new SteamParamStringArray_t(); + tags.m_ppStrings = nativeArray; + tags.m_nNumStrings = pTags.Length; + + bool result = NativeEntrypoints.SteamAPI_ISteamUGC_SetItemTags(m_pSteamUGC,updateHandle,ref tags); + + Marshal.FreeHGlobal( nativeArray ); + + foreach ( var item in nativeStrings ) + { + Marshal.FreeHGlobal( item ); + } + return result; } internal override bool SetItemContent( ulong handle, string pszContentFolder )