mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-01-24 12:38:00 +03:00
Create/Publish/Delete workshop files
This commit is contained in:
parent
3ff2b304a5
commit
d4eb325606
@ -38,7 +38,7 @@ namespace Facepunch.Steamworks.Test
|
|||||||
Console.WriteLine( "Searching" );
|
Console.WriteLine( "Searching" );
|
||||||
|
|
||||||
Query.Order = Workshop.Order.RankedByTextSearch;
|
Query.Order = Workshop.Order.RankedByTextSearch;
|
||||||
Query.QueryType = Workshop.QueryType.Items_Mtx;
|
Query.QueryType = Workshop.QueryType.MicrotransactionItems;
|
||||||
Query.SearchText = "shit";
|
Query.SearchText = "shit";
|
||||||
Query.RequireTags.Add( "LongTShirt Skin" );
|
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||||
Query.Run();
|
Query.Run();
|
||||||
@ -237,5 +237,34 @@ namespace Facepunch.Steamworks.Test
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[TestCategory( "Run Manually" )]
|
||||||
|
public void CreatePublish()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
var item = client.Workshop.CreateItem( Workshop.ItemType.Microtransaction );
|
||||||
|
|
||||||
|
item.Title = "Facepunch.Steamworks Unit test";
|
||||||
|
|
||||||
|
item.Publish();
|
||||||
|
|
||||||
|
while ( item.Publishing )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
Thread.Sleep( 100 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsFalse( item.Publishing );
|
||||||
|
Assert.AreNotEqual( 0, item.Id );
|
||||||
|
|
||||||
|
Console.WriteLine( "item.Id: {0}", item.Id );
|
||||||
|
|
||||||
|
item.Delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ namespace Facepunch.Steamworks
|
|||||||
{
|
{
|
||||||
Networking = new Steamworks.Networking( this, native.networking );
|
Networking = new Steamworks.Networking( this, native.networking );
|
||||||
Inventory = new Steamworks.Inventory( native.inventory, IsGameServer );
|
Inventory = new Steamworks.Inventory( native.inventory, IsGameServer );
|
||||||
Workshop = new Steamworks.Workshop( this, native.ugc );
|
Workshop = new Steamworks.Workshop( this, native.ugc, native.remoteStorage );
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsValid
|
public bool IsValid
|
||||||
@ -88,12 +88,14 @@ namespace Facepunch.Steamworks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call results are results to specific actions
|
/// Call results are results to specific actions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void AddCallResult( CallResult c )
|
internal void AddCallResult( CallResult call )
|
||||||
{
|
{
|
||||||
if ( FinishCallback( c ) )
|
if ( call == null ) throw new ArgumentNullException( "call" );
|
||||||
|
|
||||||
|
if ( FinishCallback( call ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Callbacks.Add( c );
|
Callbacks.Add( call );
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunCallbackQueue()
|
void RunCallbackQueue()
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System.Runtime.InteropServices;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using Facepunch.Steamworks.Interop;
|
using Facepunch.Steamworks.Interop;
|
||||||
|
|
||||||
namespace Facepunch.Steamworks.Callbacks.Workshop
|
namespace Facepunch.Steamworks.Callbacks.Workshop
|
||||||
@ -32,8 +28,6 @@ namespace Facepunch.Steamworks.Callbacks.Workshop
|
|||||||
public const int CallbackId = Index.UGC + 6;
|
public const int CallbackId = Index.UGC + 6;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal class QueryCompleted : CallResult<QueryCompleted.Data>
|
internal class QueryCompleted : CallResult<QueryCompleted.Data>
|
||||||
{
|
{
|
||||||
public override int CallbackId { get { return Index.UGC + 1; } }
|
public override int CallbackId { get { return Index.UGC + 1; } }
|
||||||
@ -50,5 +44,30 @@ namespace Facepunch.Steamworks.Callbacks.Workshop
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class CreateItem : CallResult<CreateItem.Data>
|
||||||
|
{
|
||||||
|
public override int CallbackId { get { return Index.UGC + 3; } }
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
|
internal struct Data
|
||||||
|
{
|
||||||
|
internal Result Result;
|
||||||
|
internal ulong FileId;
|
||||||
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
|
internal bool NeedsLegalAgreement;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class SubmitItemUpdate : CallResult<SubmitItemUpdate.Data>
|
||||||
|
{
|
||||||
|
public override int CallbackId { get { return Index.UGC + 4; } }
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
|
internal struct Data
|
||||||
|
{
|
||||||
|
internal Result Result;
|
||||||
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
|
internal bool NeedsLegalAgreement;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,9 @@
|
|||||||
<Compile Include="Config.cs" />
|
<Compile Include="Config.cs" />
|
||||||
<Compile Include="Callbacks\Networking.cs" />
|
<Compile Include="Callbacks\Networking.cs" />
|
||||||
<Compile Include="Interfaces\Workshop.cs" />
|
<Compile Include="Interfaces\Workshop.cs" />
|
||||||
|
<Compile Include="Interfaces\Workshop.Editor.cs" />
|
||||||
<Compile Include="Interfaces\Workshop.Item.cs" />
|
<Compile Include="Interfaces\Workshop.Item.cs" />
|
||||||
|
<Compile Include="Interfaces\Workshop.Query.cs" />
|
||||||
<Compile Include="Interop\Callback.cs" />
|
<Compile Include="Interop\Callback.cs" />
|
||||||
<Compile Include="Interop\CallResult.cs" />
|
<Compile Include="Interop\CallResult.cs" />
|
||||||
<Compile Include="Interop\Native.cs" />
|
<Compile Include="Interop\Native.cs" />
|
||||||
|
@ -98,10 +98,7 @@ namespace Facepunch.Steamworks
|
|||||||
|
|
||||||
int[] ids;
|
int[] ids;
|
||||||
if ( !inventory.GetItemDefinitionIDs( out ids ) )
|
if ( !inventory.GetItemDefinitionIDs( out ids ) )
|
||||||
{
|
|
||||||
Console.WriteLine( "Couldn't load definitions" );
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
Definitions = ids.Select( x =>
|
Definitions = ids.Select( x =>
|
||||||
{
|
{
|
||||||
|
120
Facepunch.Steamworks/Interfaces/Workshop.Editor.cs
Normal file
120
Facepunch.Steamworks/Interfaces/Workshop.Editor.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
using System;
|
||||||
|
using Facepunch.Steamworks.Callbacks.Workshop;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Workshop
|
||||||
|
{
|
||||||
|
public class Editor
|
||||||
|
{
|
||||||
|
internal Workshop workshop;
|
||||||
|
|
||||||
|
internal CreateItem CreateItem;
|
||||||
|
internal SubmitItemUpdate SubmitItemUpdate;
|
||||||
|
|
||||||
|
public ulong Id { get; internal set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public bool Publishing { get; internal set; }
|
||||||
|
public ItemType? Type { get; set; }
|
||||||
|
|
||||||
|
public string ChangeNote { get; set; } = "";
|
||||||
|
|
||||||
|
public bool NeedToAgreeToWorkshopLegal { get; internal set; }
|
||||||
|
|
||||||
|
public void Publish()
|
||||||
|
{
|
||||||
|
Publishing = true;
|
||||||
|
|
||||||
|
if ( Id == 0 )
|
||||||
|
{
|
||||||
|
StartCreatingItem();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PublishChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartCreatingItem()
|
||||||
|
{
|
||||||
|
if ( !Type.HasValue )
|
||||||
|
throw new System.Exception( "Editor.Type must be set when creating a new item!" );
|
||||||
|
|
||||||
|
CreateItem = new CreateItem();
|
||||||
|
CreateItem.Handle = workshop.ugc.CreateItem( workshop.steamworks.AppId, (uint)Type );
|
||||||
|
CreateItem.OnResult = OnItemCreated;
|
||||||
|
workshop.steamworks.AddCallResult( CreateItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnItemCreated( CreateItem.Data obj )
|
||||||
|
{
|
||||||
|
NeedToAgreeToWorkshopLegal = obj.NeedsLegalAgreement;
|
||||||
|
CreateItem = null;
|
||||||
|
|
||||||
|
if ( obj.Result == Callbacks.Result.OK )
|
||||||
|
{
|
||||||
|
Id = obj.FileId;
|
||||||
|
PublishChanges();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine( "File publish error: " + obj );
|
||||||
|
Publishing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PublishChanges()
|
||||||
|
{
|
||||||
|
Publishing = false;
|
||||||
|
|
||||||
|
ulong UpdateId = workshop.ugc.StartItemUpdate( workshop.steamworks.AppId, Id );
|
||||||
|
|
||||||
|
if ( Title != null )
|
||||||
|
workshop.ugc.SetItemTitle( UpdateId, Title );
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
SubmitItemUpdate = new SubmitItemUpdate();
|
||||||
|
SubmitItemUpdate.Handle = workshop.ugc.SubmitItemUpdate( UpdateId, ChangeNote );
|
||||||
|
SubmitItemUpdate.OnResult = OnChangesSubmitted;
|
||||||
|
workshop.steamworks.AddCallResult( SubmitItemUpdate );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnChangesSubmitted( SubmitItemUpdate.Data obj )
|
||||||
|
{
|
||||||
|
SubmitItemUpdate = null;
|
||||||
|
|
||||||
|
NeedToAgreeToWorkshopLegal = obj.NeedsLegalAgreement;
|
||||||
|
|
||||||
|
if ( obj.Result == Callbacks.Result.OK )
|
||||||
|
{
|
||||||
|
Publishing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete()
|
||||||
|
{
|
||||||
|
workshop.remoteStorage.DeletePublishedFile( Id );
|
||||||
|
Id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
150
Facepunch.Steamworks/Interfaces/Workshop.Query.cs
Normal file
150
Facepunch.Steamworks/Interfaces/Workshop.Query.cs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using Facepunch.Steamworks.Callbacks.Networking;
|
||||||
|
using Facepunch.Steamworks.Callbacks.Workshop;
|
||||||
|
using Facepunch.Steamworks.Interop;
|
||||||
|
using Valve.Steamworks;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Workshop
|
||||||
|
{
|
||||||
|
public class Query : IDisposable
|
||||||
|
{
|
||||||
|
internal ulong Handle;
|
||||||
|
internal QueryCompleted Callback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The AppId you're querying. This defaults to this appid.
|
||||||
|
/// </summary>
|
||||||
|
public uint AppId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The AppId of the app used to upload the item. This defaults to 0
|
||||||
|
/// which means all/any.
|
||||||
|
/// </summary>
|
||||||
|
public uint UploaderAppId { get; set; }
|
||||||
|
|
||||||
|
public QueryType QueryType { get; set; } = QueryType.Items;
|
||||||
|
public Order Order { get; set; } = Order.RankedByVote;
|
||||||
|
|
||||||
|
public string SearchText { get; set; }
|
||||||
|
|
||||||
|
public Item[] Items { get; set; }
|
||||||
|
|
||||||
|
public int TotalResults { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Page starts at 1 !!
|
||||||
|
/// </summary>
|
||||||
|
public int Page { get; set; } = 1;
|
||||||
|
internal Workshop workshop;
|
||||||
|
|
||||||
|
public unsafe void Run()
|
||||||
|
{
|
||||||
|
if ( Callback != null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( Page <= 0 )
|
||||||
|
throw new System.Exception( "Page should be 1 or above" );
|
||||||
|
|
||||||
|
if ( FileId.Count != 0 )
|
||||||
|
{
|
||||||
|
var fileArray = FileId.ToArray();
|
||||||
|
|
||||||
|
fixed ( ulong* array = fileArray )
|
||||||
|
{
|
||||||
|
Handle = workshop.ugc.CreateQueryUGCDetailsRequest( (IntPtr)array, (uint)fileArray.Length );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Handle = workshop.ugc.CreateQueryAllUGCRequest( (uint)Order, (uint)QueryType, UploaderAppId, AppId, (uint)Page );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !string.IsNullOrEmpty( SearchText ) )
|
||||||
|
workshop.ugc.SetSearchText( Handle, SearchText );
|
||||||
|
|
||||||
|
foreach ( var tag in RequireTags )
|
||||||
|
workshop.ugc.AddRequiredTag( Handle, tag );
|
||||||
|
|
||||||
|
if ( RequireTags.Count > 0 )
|
||||||
|
workshop.ugc.SetMatchAnyTag( Handle, RequireAllTags );
|
||||||
|
|
||||||
|
foreach ( var tag in ExcludeTags )
|
||||||
|
workshop.ugc.AddExcludedTag( Handle, tag );
|
||||||
|
|
||||||
|
Callback = new QueryCompleted();
|
||||||
|
Callback.Handle = workshop.ugc.SendQueryUGCRequest( Handle );
|
||||||
|
Callback.OnResult = OnResult;
|
||||||
|
workshop.steamworks.AddCallResult( Callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnResult( QueryCompleted.Data data )
|
||||||
|
{
|
||||||
|
Items = new Item[data.m_unNumResultsReturned];
|
||||||
|
for ( int i = 0; i < data.m_unNumResultsReturned; i++ )
|
||||||
|
{
|
||||||
|
SteamUGCDetails_t details = new SteamUGCDetails_t();
|
||||||
|
workshop.ugc.GetQueryUGCResult( data.Handle, (uint)i, ref details );
|
||||||
|
|
||||||
|
Items[i] = Item.From( details, workshop );
|
||||||
|
}
|
||||||
|
|
||||||
|
TotalResults = (int)data.m_unTotalMatchingResults;
|
||||||
|
|
||||||
|
Callback.Dispose();
|
||||||
|
Callback = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRunning
|
||||||
|
{
|
||||||
|
get { return Callback != null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only return items with these tags
|
||||||
|
/// </summary>
|
||||||
|
public List<string> RequireTags { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, return items that have all RequireTags
|
||||||
|
/// If false, return items that have any tags in RequireTags
|
||||||
|
/// </summary>
|
||||||
|
public bool RequireAllTags { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Don't return any items with this tag
|
||||||
|
/// </summary>
|
||||||
|
public List<string> ExcludeTags { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If you're querying for a particular file or files, add them to this.
|
||||||
|
/// </summary>
|
||||||
|
public List<ulong> FileId { get; set; } = new List<ulong>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Don't call this in production!
|
||||||
|
/// </summary>
|
||||||
|
public void Block()
|
||||||
|
{
|
||||||
|
workshop.steamworks.Update();
|
||||||
|
|
||||||
|
while ( IsRunning )
|
||||||
|
{
|
||||||
|
System.Threading.Thread.Sleep( 10 );
|
||||||
|
workshop.steamworks.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// ReleaseQueryUGCRequest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using Facepunch.Steamworks.Callbacks.Workshop;
|
using Facepunch.Steamworks.Callbacks.Workshop;
|
||||||
using Facepunch.Steamworks.Interop;
|
|
||||||
using Valve.Steamworks;
|
using Valve.Steamworks;
|
||||||
|
|
||||||
namespace Facepunch.Steamworks
|
namespace Facepunch.Steamworks
|
||||||
@ -16,35 +11,47 @@ namespace Facepunch.Steamworks
|
|||||||
|
|
||||||
internal ISteamUGC ugc;
|
internal ISteamUGC ugc;
|
||||||
internal BaseSteamworks steamworks;
|
internal BaseSteamworks steamworks;
|
||||||
|
internal ISteamRemoteStorage remoteStorage;
|
||||||
|
|
||||||
internal event Action<ulong, Callbacks.Result> OnFileDownloaded;
|
internal event Action<ulong, Callbacks.Result> OnFileDownloaded;
|
||||||
internal event Action<ulong> OnItemInstalled;
|
internal event Action<ulong> OnItemInstalled;
|
||||||
|
|
||||||
internal Workshop( BaseSteamworks sw, ISteamUGC ugc )
|
internal Workshop( BaseSteamworks steamworks, ISteamUGC ugc, ISteamRemoteStorage remoteStorage )
|
||||||
{
|
{
|
||||||
this.ugc = ugc;
|
this.ugc = ugc;
|
||||||
this.steamworks = sw;
|
this.steamworks = steamworks;
|
||||||
|
this.remoteStorage = remoteStorage;
|
||||||
|
|
||||||
sw.AddCallback<DownloadResult>( onDownloadResult, DownloadResult.CallbackId );
|
steamworks.AddCallback<DownloadResult>( onDownloadResult, DownloadResult.CallbackId );
|
||||||
sw.AddCallback<ItemInstalled>( onItemInstalled, ItemInstalled.CallbackId );
|
steamworks.AddCallback<ItemInstalled>( onItemInstalled, ItemInstalled.CallbackId );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onItemInstalled( ItemInstalled obj )
|
private void onItemInstalled( ItemInstalled obj )
|
||||||
{
|
{
|
||||||
Console.WriteLine( "OnItemInstalled" );
|
|
||||||
|
|
||||||
if ( OnItemInstalled != null )
|
if ( OnItemInstalled != null )
|
||||||
OnItemInstalled( obj.FileId );
|
OnItemInstalled( obj.FileId );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDownloadResult( DownloadResult obj )
|
private void onDownloadResult( DownloadResult obj )
|
||||||
{
|
{
|
||||||
Console.WriteLine( "onDownloadResult" );
|
|
||||||
|
|
||||||
if ( OnFileDownloaded != null )
|
if ( OnFileDownloaded != null )
|
||||||
OnFileDownloaded( obj.FileId, obj.Result );
|
OnFileDownloaded( obj.FileId, obj.Result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Query CreateQuery()
|
||||||
|
{
|
||||||
|
return new Query()
|
||||||
|
{
|
||||||
|
AppId = steamworks.AppId,
|
||||||
|
workshop = this
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Editor CreateItem( ItemType type )
|
||||||
|
{
|
||||||
|
return new Editor() { workshop = this, Type = type };
|
||||||
|
}
|
||||||
|
|
||||||
public enum Order
|
public enum Order
|
||||||
{
|
{
|
||||||
RankedByVote = 0,
|
RankedByVote = 0,
|
||||||
@ -64,9 +71,18 @@ namespace Facepunch.Steamworks
|
|||||||
|
|
||||||
public enum QueryType
|
public enum QueryType
|
||||||
{
|
{
|
||||||
Items = 0, // both mtx items and ready-to-use items
|
/// <summary>
|
||||||
Items_Mtx = 1,
|
/// Both MicrotransactionItems and subscriptionItems
|
||||||
Items_ReadyToUse = 2,
|
/// </summary>
|
||||||
|
Items = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Workshop item that is meant to be voted on for the purpose of selling in-game
|
||||||
|
/// </summary>
|
||||||
|
MicrotransactionItems = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// normal Workshop item that can be subscribed to
|
||||||
|
/// </summary>
|
||||||
|
subscriptionItems = 2,
|
||||||
Collections = 3,
|
Collections = 3,
|
||||||
Artwork = 4,
|
Artwork = 4,
|
||||||
Videos = 5,
|
Videos = 5,
|
||||||
@ -79,146 +95,27 @@ namespace Facepunch.Steamworks
|
|||||||
GameManagedItems = 12, // game managed items (not managed by users)
|
GameManagedItems = 12, // game managed items (not managed by users)
|
||||||
};
|
};
|
||||||
|
|
||||||
public WorkshopQuery CreateQuery()
|
public enum ItemType
|
||||||
{
|
{
|
||||||
var q = new WorkshopQuery();
|
Community = 0, // normal Workshop item that can be subscribed to
|
||||||
q.AppId = steamworks.AppId;
|
Microtransaction = 1, // Workshop item that is meant to be voted on for the purpose of selling in-game
|
||||||
q.workshop = this;
|
Collection = 2, // a collection of Workshop or Greenlight items
|
||||||
return q;
|
Art = 3, // artwork
|
||||||
}
|
Video = 4, // external video
|
||||||
|
Screenshot = 5, // screenshot
|
||||||
|
Game = 6, // Greenlight game entry
|
||||||
|
Software = 7, // Greenlight software entry
|
||||||
|
Concept = 8, // Greenlight concept
|
||||||
|
WebGuide = 9, // Steam web guide
|
||||||
|
IntegratedGuide = 10, // application integrated guide
|
||||||
|
Merch = 11, // Workshop merchandise meant to be voted on for the purpose of being sold
|
||||||
|
ControllerBinding = 12, // Steam Controller bindings
|
||||||
|
SteamworksAccessInvite = 13, // internal
|
||||||
|
SteamVideo = 14, // Steam video
|
||||||
|
GameManagedItem = 15, // managed completely by the game, not the user, and not shown on the web
|
||||||
|
};
|
||||||
|
|
||||||
public class WorkshopQuery : IDisposable
|
|
||||||
{
|
|
||||||
internal ulong Handle;
|
|
||||||
internal QueryCompleted Callback;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The AppId you're querying. This defaults to this appid.
|
|
||||||
/// </summary>
|
|
||||||
public uint AppId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The AppId of the app used to upload the item. This defaults to 0
|
|
||||||
/// which means all/any.
|
|
||||||
/// </summary>
|
|
||||||
public uint UploaderAppId { get; set; }
|
|
||||||
|
|
||||||
public QueryType QueryType { get; set; } = QueryType.Items;
|
|
||||||
public Order Order { get; set; } = Order.RankedByVote;
|
|
||||||
|
|
||||||
public string SearchText { get; set; }
|
|
||||||
|
|
||||||
public Item[] Items { get; set; }
|
|
||||||
|
|
||||||
public int TotalResults { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Page starts at 1 !!
|
|
||||||
/// </summary>
|
|
||||||
public int Page { get; set; } = 1;
|
|
||||||
internal Workshop workshop;
|
|
||||||
|
|
||||||
public unsafe void Run()
|
|
||||||
{
|
|
||||||
if ( Callback != null )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( Page <= 0 )
|
|
||||||
throw new System.Exception( "Page should be 1 or above" );
|
|
||||||
|
|
||||||
if ( FileId.Count != 0 )
|
|
||||||
{
|
|
||||||
var fileArray = FileId.ToArray();
|
|
||||||
|
|
||||||
fixed ( ulong* array = fileArray )
|
|
||||||
{
|
|
||||||
Handle = workshop.ugc.CreateQueryUGCDetailsRequest( (IntPtr) array, (uint)fileArray.Length );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Handle = workshop.ugc.CreateQueryAllUGCRequest( (uint)Order, (uint)QueryType, UploaderAppId, AppId, (uint)Page );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !string.IsNullOrEmpty( SearchText ) )
|
|
||||||
workshop.ugc.SetSearchText( Handle, SearchText );
|
|
||||||
|
|
||||||
foreach ( var tag in RequireTags )
|
|
||||||
workshop.ugc.AddRequiredTag( Handle, tag );
|
|
||||||
|
|
||||||
if ( RequireTags.Count > 0 )
|
|
||||||
workshop.ugc.SetMatchAnyTag( Handle, RequireAllTags );
|
|
||||||
|
|
||||||
foreach ( var tag in ExcludeTags )
|
|
||||||
workshop.ugc.AddExcludedTag( Handle, tag );
|
|
||||||
|
|
||||||
Callback = new QueryCompleted();
|
|
||||||
Callback.Handle = workshop.ugc.SendQueryUGCRequest( Handle );
|
|
||||||
Callback.OnResult = OnResult;
|
|
||||||
workshop.steamworks.AddCallResult( Callback );
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnResult( QueryCompleted.Data data )
|
|
||||||
{
|
|
||||||
Items = new Item[data.m_unNumResultsReturned];
|
|
||||||
for ( int i = 0; i < data.m_unNumResultsReturned; i++ )
|
|
||||||
{
|
|
||||||
SteamUGCDetails_t details = new SteamUGCDetails_t();
|
|
||||||
workshop.ugc.GetQueryUGCResult( data.Handle, (uint) i, ref details );
|
|
||||||
|
|
||||||
Items[i] = Item.From( details, workshop );
|
|
||||||
}
|
|
||||||
|
|
||||||
TotalResults = (int) data.m_unTotalMatchingResults;
|
|
||||||
|
|
||||||
Callback.Dispose();
|
|
||||||
Callback = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsRunning
|
|
||||||
{
|
|
||||||
get { return Callback != null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Only return items with these tags
|
|
||||||
/// </summary>
|
|
||||||
public List<string> RequireTags { get; set; } = new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, return items that have all RequireTags
|
|
||||||
/// If false, return items that have any tags in RequireTags
|
|
||||||
/// </summary>
|
|
||||||
public bool RequireAllTags { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Don't return any items with this tag
|
|
||||||
/// </summary>
|
|
||||||
public List<string> ExcludeTags { get; set; } = new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If you're querying for a particular file or files, add them to this.
|
|
||||||
/// </summary>
|
|
||||||
public List<ulong> FileId { get; set; } = new List<ulong>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Don't call this in production!
|
|
||||||
/// </summary>
|
|
||||||
public void Block()
|
|
||||||
{
|
|
||||||
workshop.steamworks.Update();
|
|
||||||
|
|
||||||
while ( IsRunning )
|
|
||||||
{
|
|
||||||
System.Threading.Thread.Sleep( 10 );
|
|
||||||
workshop.steamworks.Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// ReleaseQueryUGCRequest
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ namespace Facepunch.Steamworks.Interop
|
|||||||
internal Valve.Steamworks.ISteamUGC ugc;
|
internal Valve.Steamworks.ISteamUGC ugc;
|
||||||
internal Valve.Steamworks.ISteamGameServer gameServer;
|
internal Valve.Steamworks.ISteamGameServer gameServer;
|
||||||
internal Valve.Steamworks.ISteamGameServerStats gameServerStats;
|
internal Valve.Steamworks.ISteamGameServerStats gameServerStats;
|
||||||
|
internal Valve.Steamworks.ISteamRemoteStorage remoteStorage;
|
||||||
|
|
||||||
internal bool InitClient()
|
internal bool InitClient()
|
||||||
{
|
{
|
||||||
@ -75,6 +76,7 @@ namespace Facepunch.Steamworks.Interop
|
|||||||
servers = client.GetISteamMatchmakingServers( huser, hpipe, "SteamMatchMakingServers002" );
|
servers = client.GetISteamMatchmakingServers( huser, hpipe, "SteamMatchMakingServers002" );
|
||||||
userstats = client.GetISteamUserStats( huser, hpipe, "STEAMUSERSTATS_INTERFACE_VERSION011" );
|
userstats = client.GetISteamUserStats( huser, hpipe, "STEAMUSERSTATS_INTERFACE_VERSION011" );
|
||||||
screenshots = client.GetISteamScreenshots( huser, hpipe, "STEAMSCREENSHOTS_INTERFACE_VERSION002" );
|
screenshots = client.GetISteamScreenshots( huser, hpipe, "STEAMSCREENSHOTS_INTERFACE_VERSION002" );
|
||||||
|
remoteStorage = client.GetISteamRemoteStorage( huser, hpipe, "STEAMREMOTESTORAGE_INTERFACE_VERSION013" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -2513,7 +2513,7 @@ namespace Valve.Steamworks
|
|||||||
{
|
{
|
||||||
CheckIfUsable();
|
CheckIfUsable();
|
||||||
IntPtr result = NativeEntrypoints.SteamAPI_ISteamClient_GetISteamRemoteStorage(m_pSteamClient,hSteamUser,hSteamPipe,pchVersion);
|
IntPtr result = NativeEntrypoints.SteamAPI_ISteamClient_GetISteamRemoteStorage(m_pSteamClient,hSteamUser,hSteamPipe,pchVersion);
|
||||||
return (ISteamRemoteStorage)Marshal.PtrToStructure( result, typeof( ISteamRemoteStorage ) );
|
return new CSteamRemoteStorage( result );
|
||||||
}
|
}
|
||||||
internal override ISteamScreenshots GetISteamScreenshots( int hSteamUser, int hSteamPipe, string pchVersion )
|
internal override ISteamScreenshots GetISteamScreenshots( int hSteamUser, int hSteamPipe, string pchVersion )
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user