diff --git a/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj b/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj index a2a2ee0..1db34fb 100644 --- a/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj +++ b/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj @@ -90,6 +90,7 @@ + diff --git a/Facepunch.Steamworks.Test/RemoteStorageTest.cs b/Facepunch.Steamworks.Test/RemoteStorageTest.cs new file mode 100644 index 0000000..a47d180 --- /dev/null +++ b/Facepunch.Steamworks.Test/RemoteStorageTest.cs @@ -0,0 +1,78 @@ +using System; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Steamworks.Data; + +namespace Steamworks +{ + [TestClass] + [DeploymentItem( "steam_api64.dll" )] + public class RemoteStorageTest + { + [TestMethod] + public async Task Quotas() + { + Console.WriteLine( $"SteamRemoteStorage.QuotaBytes: {SteamRemoteStorage.QuotaBytes}" ); + Console.WriteLine( $"SteamRemoteStorage.QuotaRemainingBytes: {SteamRemoteStorage.QuotaRemainingBytes}" ); + Console.WriteLine( $"SteamRemoteStorage.QuotaUsedBytes: {SteamRemoteStorage.QuotaUsedBytes}" ); + } + + [TestMethod] + public async Task IsCloudEnabled() + { + Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabled: {SteamRemoteStorage.IsCloudEnabled}" ); + Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabledForAccount: {SteamRemoteStorage.IsCloudEnabledForAccount}" ); + Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabledForApp: {SteamRemoteStorage.IsCloudEnabledForApp}" ); + } + + [TestMethod] + public void FileWrite() + { + var rand = new Random(); + var testFile = new byte[1024 * 1024 * 100]; + + for( int i=0; i< testFile.Length; i++ ) + { + testFile[i] = (byte) i; + } + + var written = SteamRemoteStorage.FileWrite( "testfile", testFile ); + + Assert.IsTrue( written ); + Assert.IsTrue( SteamRemoteStorage.FileExists( "testfile" ) ); + Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), testFile.Length ); + } + + [TestMethod] + public void FileRead() + { + FileWrite(); + + var data = SteamRemoteStorage.FileRead( "testfile" ); + + Assert.IsNotNull( data ); + + for ( int i = 0; i < data.Length; i++ ) + { + Assert.AreEqual( data[i], (byte)i ); + } + + Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), data.Length ); + Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), 1024 * 1024 * 100 ); + } + + [TestMethod] + public void Files() + { + foreach ( var file in SteamRemoteStorage.Files ) + { + Console.WriteLine( $"{file} ({SteamRemoteStorage.FileSize(file)} {SteamRemoteStorage.FileTime( file )})" ); + } + + } + } + +} diff --git a/Facepunch.Steamworks/SteamRemoteStorage.cs b/Facepunch.Steamworks/SteamRemoteStorage.cs new file mode 100644 index 0000000..0dbb720 --- /dev/null +++ b/Facepunch.Steamworks/SteamRemoteStorage.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Steamworks.Data; + +namespace Steamworks +{ + /// + /// Undocumented Parental Settings + /// + public static class SteamRemoteStorage + { + static ISteamRemoteStorage _internal; + internal static ISteamRemoteStorage Internal + { + get + { + if ( _internal == null ) + _internal = new ISteamRemoteStorage(); + + return _internal; + } + } + + /// + /// Creates a new file, writes the bytes to the file, and then closes the file. + /// If the target file already exists, it is overwritten + /// + public unsafe static bool FileWrite( string filename, byte[] data ) + { + fixed ( byte* ptr = data ) + { + return Internal.FileWrite( filename, (IntPtr) ptr, data.Length ); + } + } + + /// + /// Opens a binary file, reads the contents of the file into a byte array, and then closes the file. + /// + public unsafe static byte[] FileRead( string filename ) + { + var size = FileSize( filename ); + if ( size <= 0 ) return null; + var buffer = new byte[size]; + + fixed ( byte* ptr = buffer ) + { + var readsize = Internal.FileRead( filename, (IntPtr)ptr, size ); + return buffer; + } + } + + /// + /// Checks whether the specified file exists. + /// + public static bool FileExists( string filename ) => Internal.FileExists( filename ); + + /// + /// Checks if a specific file is persisted in the steam cloud. + /// + public static bool FilePersisted( string filename ) => Internal.FilePersisted( filename ); + + /// + /// Gets the specified file's last modified date/time. + /// + public static DateTime FileTime( string filename ) => Epoch.ToDateTime( Internal.GetFileTimestamp( filename ) ); + + /// + /// Gets the specified files size in bytes. 0 if not exists. + /// + public static int FileSize( string filename ) => Internal.GetFileSize( filename ); + + /// + /// Deletes the file from remote storage, but leaves it on the local disk and remains accessible from the API. + /// + public static bool FileForget( string filename ) => Internal.FileForget( filename ); + + /// + /// Deletes a file from the local disk, and propagates that delete to the cloud. + /// + public static bool FileDelete( string filename ) => Internal.FileDelete( filename ); + + + /// + /// Number of bytes total + /// + public static ulong QuotaBytes + { + get + { + ulong t = 0, a = 0; + Internal.GetQuota( ref t, ref a ); + return t; + } + } + + /// + /// Number of bytes used + /// + public static ulong QuotaUsedBytes + { + get + { + ulong t = 0, a = 0; + Internal.GetQuota( ref t, ref a ); + return t - a; + } + } + + /// + /// Number of bytes remaining until your quota is used + /// + public static ulong QuotaRemainingBytes + { + get + { + ulong t = 0, a = 0; + Internal.GetQuota( ref t, ref a ); + return a; + } + } + + /// + /// returns true if IsCloudEnabledForAccount && IsCloudEnabledForApp + /// + public static bool IsCloudEnabled => IsCloudEnabledForAccount && IsCloudEnabledForApp; + + /// + /// Checks if the account wide Steam Cloud setting is enabled for this user + /// or if they disabled it in the Settings->Cloud dialog. + /// + public static bool IsCloudEnabledForAccount => Internal.IsCloudEnabledForAccount(); + + /// + /// Checks if the per game Steam Cloud setting is enabled for this user + /// or if they disabled it in the Game Properties->Update dialog. + /// + /// This must only ever be set as the direct result of the user explicitly + /// requesting that it's enabled or not. This is typically accomplished with + /// a checkbox within your in-game options + /// + public static bool IsCloudEnabledForApp + { + get => Internal.IsCloudEnabledForApp(); + set => Internal.SetCloudEnabledForApp( value ); + } + + /// + /// Gets the total number of local files synchronized by Steam Cloud. + /// + public static int FileCount => Internal.GetFileCount(); + + /// + /// Get a list of filenames synchronized by Steam Cloud + /// + public static IEnumerable Files + { + get + { + int _ = 0; + for( int i=0; i