mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-26 06:35:49 +03:00
Added some workshop API members for Chunks
Currently OnItemCreated doesn't seem to get called
This commit is contained in:
parent
ba32817183
commit
524c687b83
@ -254,7 +254,7 @@ public void QueryCallback()
|
||||
{
|
||||
var gotCallback = false;
|
||||
|
||||
Query.OnResult = ( q ) =>
|
||||
Query.OnResult += ( q ) =>
|
||||
{
|
||||
Assert.AreEqual( q.Items.Length, 1 );
|
||||
Console.WriteLine( "Query.TotalResults: {0}", q.TotalResults );
|
||||
|
@ -27,8 +27,24 @@ internal RemoteStorage( Client c )
|
||||
{
|
||||
client = c;
|
||||
native = client.native.remoteStorage;
|
||||
|
||||
RemoteStoragePublishedFileSubscribed_t.RegisterCallback( c, onRemoteStoragePublishedFileSubscribed );
|
||||
RemoteStoragePublishedFileUnsubscribed_t.RegisterCallback( c, onRemoteStoragePublishedFileUnsubscribed );
|
||||
}
|
||||
|
||||
private void onRemoteStoragePublishedFileSubscribed( RemoteStoragePublishedFileSubscribed_t value, bool ioFailure )
|
||||
{
|
||||
if ( ItemSubscribed != null && value.AppID == client.AppId ) ItemSubscribed( value.PublishedFileId );
|
||||
}
|
||||
|
||||
private void onRemoteStoragePublishedFileUnsubscribed( RemoteStoragePublishedFileUnsubscribed_t value, bool ioFailure )
|
||||
{
|
||||
if ( ItemUnsubscribed != null && value.AppID == client.AppId ) ItemUnsubscribed( value.PublishedFileId );
|
||||
}
|
||||
|
||||
public event Action<ulong> ItemSubscribed;
|
||||
public event Action<ulong> ItemUnsubscribed;
|
||||
|
||||
/// <summary>
|
||||
/// True if Steam Cloud is currently enabled by the current user.
|
||||
/// </summary>
|
||||
|
@ -20,6 +20,7 @@ public class Editor
|
||||
public string Folder { get; set; } = null;
|
||||
public string PreviewImage { get; set; } = null;
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public Dictionary<string, string> KeyValueTags { get; set; } = new Dictionary<string, string>();
|
||||
public bool Publishing { get; internal set; }
|
||||
public ItemType? Type { get; set; }
|
||||
public string Error { get; internal set; } = null;
|
||||
@ -36,60 +37,63 @@ public enum VisibilityType : int
|
||||
|
||||
public bool NeedToAgreeToWorkshopLegal { get; internal set; }
|
||||
|
||||
public event Action<Editor> PublishSucceeded;
|
||||
public event Action<Editor> PublishFailed;
|
||||
|
||||
private PublishStatus _publishStatus;
|
||||
public PublishStatus PublishStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
UpdatePublishProgress();
|
||||
return _publishStatus;
|
||||
}
|
||||
}
|
||||
|
||||
public double Progress
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( !Publishing ) return 1.0;
|
||||
if ( CreateItem != null ) return 0.0;
|
||||
if ( SubmitItemUpdate == null ) return 1.0;
|
||||
if ( CreateItem != null ) return 0d;
|
||||
if ( SubmitItemUpdate == null ) return 1d;
|
||||
if ( !Publishing ) return 1d;
|
||||
|
||||
ulong b = 0;
|
||||
ulong t = 0;
|
||||
|
||||
workshop.steamworks.native.ugc.GetItemUpdateProgress( UpdateHandle, out b, out t );
|
||||
|
||||
if ( t == 0 )
|
||||
return 0;
|
||||
|
||||
return (double)b / (double) t;
|
||||
UpdatePublishProgress();
|
||||
return _bytesTotal > 0 ? _bytesUploaded / (double) _bytesTotal : 0d;
|
||||
}
|
||||
}
|
||||
|
||||
private ulong _bytesUploaded;
|
||||
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( UpdateHandle, out b, out t );
|
||||
return (int) b;
|
||||
UpdatePublishProgress();
|
||||
return (int) _bytesUploaded;
|
||||
}
|
||||
}
|
||||
|
||||
private ulong _bytesTotal;
|
||||
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( UpdateHandle, out b, out t );
|
||||
return (int)t;
|
||||
UpdatePublishProgress();
|
||||
return (int) _bytesTotal;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePublishProgress()
|
||||
{
|
||||
if ( SubmitItemUpdate == null )
|
||||
{
|
||||
_publishStatus = PublishStatus.Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
_publishStatus = (PublishStatus) workshop.steamworks.native.ugc.GetItemUpdateProgress( UpdateHandle, out _bytesUploaded, out _bytesTotal );
|
||||
}
|
||||
|
||||
public void Publish()
|
||||
{
|
||||
Publishing = true;
|
||||
@ -109,13 +113,17 @@ private void StartCreatingItem()
|
||||
if ( !Type.HasValue )
|
||||
throw new System.Exception( "Editor.Type must be set when creating a new item!" );
|
||||
|
||||
System.Diagnostics.Debug.WriteLine( "StartCreatingItem()" );
|
||||
CreateItem = workshop.ugc.CreateItem( workshop.steamworks.AppId, (SteamNative.WorkshopFileType)(uint)Type, OnItemCreated );
|
||||
}
|
||||
|
||||
private void OnItemCreated( SteamNative.CreateItemResult_t obj, bool Failed )
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine( $"OnItemCreated({obj.PublishedFileId}, {Failed})" );
|
||||
|
||||
NeedToAgreeToWorkshopLegal = obj.UserNeedsToAcceptWorkshopLegalAgreement;
|
||||
CreateItem.Dispose();
|
||||
CreateItem = null;
|
||||
|
||||
if ( obj.Result == SteamNative.Result.OK && !Failed )
|
||||
{
|
||||
@ -126,6 +134,8 @@ private void OnItemCreated( SteamNative.CreateItemResult_t obj, bool Failed )
|
||||
|
||||
Error = "Error creating new file: " + obj.Result.ToString() + "("+ obj.PublishedFileId+ ")";
|
||||
Publishing = false;
|
||||
|
||||
PublishFailed?.Invoke( this );
|
||||
}
|
||||
|
||||
private void PublishChanges()
|
||||
@ -151,6 +161,14 @@ private void PublishChanges()
|
||||
if ( Tags != null && Tags.Count > 0 )
|
||||
workshop.ugc.SetItemTags( UpdateHandle, Tags.ToArray() );
|
||||
|
||||
if ( KeyValueTags != null )
|
||||
{
|
||||
foreach ( var keyValue in KeyValueTags )
|
||||
{
|
||||
workshop.ugc.AddItemKeyValueTag( UpdateHandle, keyValue.Key, keyValue.Value );
|
||||
}
|
||||
}
|
||||
|
||||
if ( Visibility.HasValue )
|
||||
workshop.ugc.SetItemVisibility( UpdateHandle, (SteamNative.RemoteStoragePublishedFileVisibility)(uint)Visibility.Value );
|
||||
|
||||
@ -185,7 +203,10 @@ private void PublishChanges()
|
||||
private void OnChangesSubmitted( SteamNative.SubmitItemUpdateResult_t obj, bool Failed )
|
||||
{
|
||||
if ( Failed )
|
||||
throw new System.Exception( "CreateItemResult_t Failed" );
|
||||
{
|
||||
if ( PublishFailed != null ) PublishFailed( this );
|
||||
else throw new System.Exception( "CreateItemResult_t Failed" );
|
||||
}
|
||||
|
||||
SubmitItemUpdate = null;
|
||||
NeedToAgreeToWorkshopLegal = obj.UserNeedsToAcceptWorkshopLegalAgreement;
|
||||
@ -193,10 +214,12 @@ private void OnChangesSubmitted( SteamNative.SubmitItemUpdateResult_t obj, bool
|
||||
|
||||
if ( obj.Result == SteamNative.Result.OK )
|
||||
{
|
||||
PublishSucceeded?.Invoke( this );
|
||||
return;
|
||||
}
|
||||
|
||||
Error = "Error publishing changes: " + obj.Result.ToString() + " ("+ NeedToAgreeToWorkshopLegal + ")";
|
||||
PublishFailed?.Invoke( this );
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
@ -205,5 +228,15 @@ public void Delete()
|
||||
Id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public enum PublishStatus : int
|
||||
{
|
||||
Invalid = 0,
|
||||
PreparingConfig = 1,
|
||||
PreparingContent = 2,
|
||||
UploadingContent = 3,
|
||||
UploadingPreviewFile = 4,
|
||||
CommittingChanges = 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,19 +48,20 @@ internal static Item From( SteamNative.SteamUGCDetails_t details, Workshop works
|
||||
return item;
|
||||
}
|
||||
|
||||
public void Download( bool highPriority = true )
|
||||
public bool Download( bool highPriority = true )
|
||||
{
|
||||
if ( Installed ) return;
|
||||
if ( Downloading ) return;
|
||||
if ( Installed ) return false;
|
||||
if ( Downloading ) return false;
|
||||
|
||||
if ( !workshop.ugc.DownloadItem( Id, highPriority ) )
|
||||
{
|
||||
Console.WriteLine( "Download Failed" );
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
workshop.OnFileDownloaded += OnFileDownloaded;
|
||||
workshop.OnItemInstalled += OnItemInstalled;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Subscribe()
|
||||
@ -109,8 +110,7 @@ public double DownloadProgress
|
||||
public bool Subscribed { get { return ( State & ItemState.Subscribed ) != 0; } }
|
||||
public bool NeedsUpdate { get { return ( State & ItemState.NeedsUpdate ) != 0; } }
|
||||
|
||||
private SteamNative.ItemState State { get { return ( SteamNative.ItemState) workshop.ugc.GetItemState( Id ); } }
|
||||
|
||||
public ItemState State { get { return (ItemState) workshop.ugc.GetItemState( Id ); } }
|
||||
|
||||
private DirectoryInfo _directory;
|
||||
|
||||
@ -118,33 +118,55 @@ public DirectoryInfo Directory
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _directory != null )
|
||||
return _directory;
|
||||
|
||||
if ( !Installed )
|
||||
return null;
|
||||
|
||||
ulong sizeOnDisk;
|
||||
string folder;
|
||||
uint timestamp;
|
||||
|
||||
if ( workshop.ugc.GetItemInstallInfo( Id, out sizeOnDisk, out folder, out timestamp ) )
|
||||
{
|
||||
_directory = new DirectoryInfo( folder );
|
||||
Size = sizeOnDisk;
|
||||
|
||||
if ( !_directory.Exists )
|
||||
{
|
||||
// Size = 0;
|
||||
// _directory = null;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateInstallInfo();
|
||||
return _directory;
|
||||
}
|
||||
}
|
||||
|
||||
public ulong Size { get; private set; }
|
||||
private ulong _size;
|
||||
|
||||
public ulong Size
|
||||
{
|
||||
get
|
||||
{
|
||||
UpdateInstallInfo();
|
||||
return _size;
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime _timestamp;
|
||||
|
||||
public DateTime Timestamp
|
||||
{
|
||||
get
|
||||
{
|
||||
UpdateInstallInfo();
|
||||
return _timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateInstallInfo()
|
||||
{
|
||||
if ( _directory != null ) return;
|
||||
if ( !Installed ) return;
|
||||
|
||||
ulong sizeOnDisk;
|
||||
string folder;
|
||||
uint timestamp;
|
||||
|
||||
if ( workshop.ugc.GetItemInstallInfo( Id, out sizeOnDisk, out folder, out timestamp ) )
|
||||
{
|
||||
_directory = new DirectoryInfo( folder );
|
||||
_size = sizeOnDisk;
|
||||
_timestamp = Utility.Epoch.ToDateTime( timestamp );
|
||||
|
||||
if ( !_directory.Exists )
|
||||
{
|
||||
// Size = 0;
|
||||
// _directory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ulong _BytesDownloaded, _BytesTotal;
|
||||
|
||||
@ -227,5 +249,17 @@ public string OwnerName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ItemState
|
||||
{
|
||||
None = 0,
|
||||
Subscribed = 1,
|
||||
LegacyItem = 2,
|
||||
Installed = 4,
|
||||
NeedsUpdate = 8,
|
||||
Downloading = 16,
|
||||
DownloadPending = 32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SteamNative;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
@ -44,9 +45,15 @@ public class Query : IDisposable
|
||||
public UserQueryType UserQueryType { get; set; } = UserQueryType.Published;
|
||||
|
||||
/// <summary>
|
||||
/// Called when the query finishes
|
||||
/// Called when the query succeeds
|
||||
/// </summary>
|
||||
public Action<Query> OnResult;
|
||||
public event Action<Query> OnResult;
|
||||
|
||||
/// <summary>
|
||||
/// Called when the query fails. An exception will be thrown on IO failure
|
||||
/// if no callbacks are added to this event.
|
||||
/// </summary>
|
||||
public event Action<Query, Callbacks.Result> OnFailure;
|
||||
|
||||
/// <summary>
|
||||
/// Page starts at 1 !!
|
||||
@ -105,15 +112,27 @@ unsafe void RunInternal()
|
||||
if ( !string.IsNullOrEmpty( SearchText ) )
|
||||
workshop.ugc.SetSearchText( Handle, SearchText );
|
||||
|
||||
foreach ( var tag in RequireTags )
|
||||
workshop.ugc.AddRequiredTag( Handle, tag );
|
||||
if ( RequireTags != null )
|
||||
{
|
||||
foreach ( var tag in RequireTags )
|
||||
workshop.ugc.AddRequiredTag( Handle, tag );
|
||||
|
||||
if ( RequireTags.Count > 0 )
|
||||
workshop.ugc.SetMatchAnyTag( Handle, !RequireAllTags );
|
||||
if ( RequireTags.Count > 0 )
|
||||
workshop.ugc.SetMatchAnyTag( Handle, !RequireAllTags );
|
||||
}
|
||||
|
||||
if ( RequireKeyValueTags != null )
|
||||
{
|
||||
foreach ( var keyValue in RequireKeyValueTags )
|
||||
workshop.ugc.AddRequiredKeyValueTag( Handle, keyValue.Key, keyValue.Value );
|
||||
}
|
||||
|
||||
if ( RankedByTrendDays > 0 )
|
||||
workshop.ugc.SetRankedByTrendDays( Handle, (uint) RankedByTrendDays );
|
||||
|
||||
if ( MaxCachedAge > TimeSpan.Zero )
|
||||
workshop.ugc.SetAllowCachedResponse( Handle, (uint) MaxCachedAge.TotalSeconds );
|
||||
|
||||
foreach ( var tag in ExcludeTags )
|
||||
workshop.ugc.AddExcludedTag( Handle, tag );
|
||||
|
||||
@ -122,8 +141,14 @@ unsafe void RunInternal()
|
||||
|
||||
void ResultCallback( SteamNative.SteamUGCQueryCompleted_t data, bool bFailed )
|
||||
{
|
||||
if ( bFailed )
|
||||
throw new System.Exception( "bFailed!" );
|
||||
if ( bFailed || OnFailure != null && data.Result != Result.OK )
|
||||
{
|
||||
// This used to always throw (before OnFailure was added), so for backwards
|
||||
// compatibility it will still throw if OnFailure isn't subscribed to.
|
||||
|
||||
if ( OnFailure != null ) OnFailure( this, bFailed ? Callbacks.Result.IOFailure : (Callbacks.Result) data.Result );
|
||||
else if ( bFailed ) throw new System.Exception( "bFailed!" );
|
||||
}
|
||||
|
||||
var gotFiles = 0;
|
||||
for ( int i = 0; i < data.NumResultsReturned; i++ )
|
||||
@ -177,6 +202,7 @@ void ResultCallback( SteamNative.SteamUGCQueryCompleted_t data, bool bFailed )
|
||||
else
|
||||
{
|
||||
Items = _results.ToArray();
|
||||
IsCachedData = data.CachedData;
|
||||
|
||||
if ( OnResult != null )
|
||||
{
|
||||
@ -199,11 +225,18 @@ public bool IsRunning
|
||||
get { return Callback != null; }
|
||||
}
|
||||
|
||||
public bool IsCachedData { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Only return items with these tags
|
||||
/// </summary>
|
||||
public List<string> RequireTags { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Only return items with these key-value tags
|
||||
/// </summary>
|
||||
public Dictionary<string, string> RequireKeyValueTags { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// If true, return items that have all RequireTags
|
||||
/// If false, return items that have any tags in RequireTags
|
||||
@ -220,7 +253,10 @@ public bool IsRunning
|
||||
/// </summary>
|
||||
public List<ulong> FileId { get; set; } = new List<ulong>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Maximum age of a previously cached item. Zero by default, so items are not cached.
|
||||
/// </summary>
|
||||
public TimeSpan MaxCachedAge { get; set; } = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Don't call this in production!
|
||||
|
@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using SteamNative;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
@ -40,6 +43,12 @@ public partial class Workshop : IDisposable
|
||||
/// </summary>
|
||||
public event Action<ulong> OnItemInstalled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total number of items the current user is subscribed to for
|
||||
/// the game or application. Returns 0 if called from a game server.
|
||||
/// </summary>
|
||||
public int NumSubscribedItems => (int) ugc.GetNumSubscribedItems();
|
||||
|
||||
internal Workshop( BaseSteamworks steamworks, SteamNative.SteamUGC ugc, SteamNative.SteamRemoteStorage remoteStorage )
|
||||
{
|
||||
this.ugc = ugc;
|
||||
@ -76,6 +85,50 @@ private void onDownloadResult( SteamNative.DownloadItemResult_t obj, bool failed
|
||||
OnFileDownloaded( obj.PublishedFileId, (Callbacks.Result) obj.Result );
|
||||
}
|
||||
|
||||
[ThreadStatic]
|
||||
private static ulong[] _sItemBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all of the items the current user is subscribed to for the current game. The
|
||||
/// IDs for each item are written into <paramref name="destIds"/>.
|
||||
/// </summary>
|
||||
/// <param name="destIds">
|
||||
/// Destination array to write the item IDs to. Should typically be large enough to fit
|
||||
/// <see cref="NumSubscribedItems"/>.</param>
|
||||
/// <returns>
|
||||
/// The number of subscribed workshop items that were populated into <paramref name="destIds"/>.
|
||||
/// </returns>
|
||||
public unsafe int GetSubscribedItems( ulong[] destIds )
|
||||
{
|
||||
var count = Math.Min( destIds.Length, NumSubscribedItems );
|
||||
|
||||
fixed ( ulong* ptr = destIds )
|
||||
{
|
||||
ugc.GetSubscribedItems( (PublishedFileId_t*) ptr, (uint) count );
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all of the items the current user is subscribed to for the current game. The
|
||||
/// IDs for each item are appended to <paramref name="destIds"/>.
|
||||
/// </summary>
|
||||
/// <param name="destIds">
|
||||
/// Destination list to append the item IDs to.</param>
|
||||
/// <returns>
|
||||
/// The number of subscribed workshop items that were populated into <paramref name="destIds"/>.
|
||||
/// </returns>
|
||||
public int GetSubscribedItems( List<ulong> destIds )
|
||||
{
|
||||
var items = Utility.EnsureBufferCapacity( ref _sItemBuffer, NumSubscribedItems );
|
||||
var count = GetSubscribedItems( items );
|
||||
|
||||
destIds.AddRange( items.Take( count ) );
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a query object, which is used to get a list of items.
|
||||
///
|
||||
|
@ -15,6 +15,19 @@ static internal uint SwapBytes( uint x )
|
||||
( ( x & 0xff000000 ) >> 24 );
|
||||
}
|
||||
|
||||
static internal int NextPowerOf2( int x )
|
||||
{
|
||||
var po2 = 1;
|
||||
while ( po2 < x ) po2 <<= 1;
|
||||
return po2;
|
||||
}
|
||||
|
||||
static internal T[] EnsureBufferCapacity<T>( ref T[] buffer, int size )
|
||||
{
|
||||
if ( buffer == null || buffer.Length < size ) buffer = new T[NextPowerOf2( size )];
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static internal class Epoch
|
||||
{
|
||||
private static readonly DateTime epoch = new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc );
|
||||
|
Loading…
Reference in New Issue
Block a user