1- // MIT License - Copyright (c) 2024 BUCK Design LLC - https://github.com/buck-co
1+ // MIT License - Copyright (c) 2025 BUCK Design LLC - https://github.com/buck-co
22
33using System ;
44using UnityEngine ;
@@ -63,10 +63,18 @@ protected virtual void ValidatePath(string pathOrFilename)
6363 /// </code>
6464 /// </summary>
6565 /// <param name="pathOrFilename">The path or filename of the file that will be combined with the persistent data path.</param>
66- protected string GetPartialPath ( string pathOrFilename )
66+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
67+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
68+ protected string GetPartialPath ( string pathOrFilename , int saveSlotIndex = - 1 )
6769 {
6870 ValidatePath ( pathOrFilename ) ;
69- return $ "{ pathOrFilename } { FilenameSuffix } { FileExtension } ";
71+
72+ string path = $ "{ pathOrFilename } { FilenameSuffix } { FileExtension } ";
73+
74+ if ( saveSlotIndex > - 1 )
75+ return Path . Combine ( $ "slot{ saveSlotIndex } ", path ) ;
76+
77+ return path ;
7078 }
7179
7280 /// <summary>
@@ -77,8 +85,10 @@ protected string GetPartialPath(string pathOrFilename)
7785 /// </code>
7886 /// </summary>
7987 /// <param name="pathOrFilename">The path or filename of the file that will be combined with the persistent data path.</param>
80- protected virtual string GetFullPath ( string pathOrFilename )
81- => Path . Combine ( m_persistentDataPath , GetPartialPath ( pathOrFilename ) ) ;
88+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
89+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
90+ protected virtual string GetFullPath ( string pathOrFilename , int saveSlotIndex = - 1 )
91+ => Path . Combine ( m_persistentDataPath , GetPartialPath ( pathOrFilename , saveSlotIndex ) ) ;
8292
8393 /// <summary>
8494 /// Returns true if a file exists at the given path or filename.
@@ -88,9 +98,11 @@ protected virtual string GetFullPath(string pathOrFilename)
8898 /// </code>
8999 /// </summary>
90100 /// <param name="pathOrFilename">The path or filename of the file to check.</param>
101+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
102+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
91103 /// <returns>True if the file exists; otherwise, false.</returns>
92- public virtual bool Exists ( string pathOrFilename )
93- => File . Exists ( GetFullPath ( pathOrFilename ) ) ;
104+ public virtual bool Exists ( string pathOrFilename , int saveSlotIndex = - 1 )
105+ => File . Exists ( GetFullPath ( pathOrFilename , saveSlotIndex ) ) ;
94106
95107 /// <summary>
96108 /// Writes the given content to a file at the given path or filename.
@@ -102,18 +114,18 @@ public virtual bool Exists(string pathOrFilename)
102114 /// <param name="pathOrFilename">The path or filename of the file to write.</param>
103115 /// <param name="content">The string to write to the file.</param>
104116 /// <param name="cancellationToken">The cancellation token should be the same one from the calling MonoBehaviour.</param>
105- public virtual async Task WriteFile ( string pathOrFilename , string content , CancellationToken cancellationToken )
117+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
118+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
119+ public virtual async Task WriteFile ( string pathOrFilename , string content , CancellationToken cancellationToken , int saveSlotIndex = - 1 )
106120 {
107- string fullPath = GetFullPath ( pathOrFilename ) ;
121+ string fullPath = GetFullPath ( pathOrFilename , saveSlotIndex ) ;
108122
109123 // Get the directory path from the full file path
110124 string directoryPath = Path . GetDirectoryName ( fullPath ) ;
111125
112126 // Create the directory structure if it doesn't exist
113127 if ( ! string . IsNullOrEmpty ( directoryPath ) )
114- {
115128 Directory . CreateDirectory ( directoryPath ) ;
116- }
117129
118130 await File . WriteAllTextAsync ( fullPath , content , cancellationToken ) . ConfigureAwait ( false ) ;
119131 }
@@ -127,8 +139,10 @@ public virtual async Task WriteFile(string pathOrFilename, string content, Cance
127139 /// </summary>
128140 /// <param name="pathOrFilename">The path or filename of the file to write.</param>
129141 /// <param name="content">The string to write to the file.</param>
130- public virtual async Task WriteFile ( string pathOrFilename , string content )
131- => await WriteFile ( pathOrFilename , content , CancellationToken . None ) ;
142+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
143+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
144+ public virtual async Task WriteFile ( string pathOrFilename , string content , int saveSlotIndex = - 1 )
145+ => await WriteFile ( pathOrFilename , content , CancellationToken . None , saveSlotIndex ) ;
132146
133147 /// <summary>
134148 /// Returns the contents of a file at the given path or filename.
@@ -139,23 +153,31 @@ public virtual async Task WriteFile(string pathOrFilename, string content)
139153 /// </summary>
140154 /// <param name="pathOrFilename">The path or filename of the file to read.</param>
141155 /// <param name="cancellationToken">The cancellation token should be the same one from the calling MonoBehaviour.</param>
142- public virtual async Task < string > ReadFile ( string pathOrFilename , CancellationToken cancellationToken )
156+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
157+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
158+ public virtual async Task < string > ReadFile ( string pathOrFilename , CancellationToken cancellationToken , int saveSlotIndex = - 1 )
143159 {
144160 try
145161 {
162+ string fullPath = GetFullPath ( pathOrFilename , saveSlotIndex ) ;
163+
146164 // If the file does not exist, return an empty string and log a warning.
147- if ( ! Exists ( pathOrFilename ) )
165+ if ( ! Exists ( pathOrFilename , saveSlotIndex ) )
148166 {
149- Debug . LogWarning ( $ "FileHandler: File does not exist at path or filename \" { pathOrFilename } \" . This may be expected if the file has not been created yet.") ;
167+ Debug . LogWarning ( $ "FileHandler: File does not exist at path \" { fullPath } \" . This may be expected if the file has not been created yet.") ;
150168 return string . Empty ;
151169 }
152170
153- string fileContent = await File . ReadAllTextAsync ( GetFullPath ( pathOrFilename ) , cancellationToken ) . ConfigureAwait ( false ) ;
171+ string fileContent = await File . ReadAllTextAsync ( GetFullPath ( pathOrFilename , saveSlotIndex ) , cancellationToken ) . ConfigureAwait ( false ) ;
154172
155173 // If the file is empty, return an empty string and log a warning.
156174 if ( string . IsNullOrEmpty ( fileContent ) )
157175 {
158- Debug . LogWarning ( $ "FileHandler: The file \" { pathOrFilename } \" was empty. This may be expected if the file has been erased.") ;
176+ if ( saveSlotIndex > - 1 )
177+ Debug . LogWarning ( $ "FileHandler: The file \" { pathOrFilename } \" in slot index { saveSlotIndex } was empty. This may be expected if the file has been erased.") ;
178+ else
179+ Debug . LogWarning ( $ "FileHandler: The file \" { pathOrFilename } \" was empty. This may be expected if the file has been erased.") ;
180+
159181 return string . Empty ;
160182 }
161183
@@ -181,8 +203,10 @@ public virtual async Task<string> ReadFile(string pathOrFilename, CancellationTo
181203 /// </code>
182204 /// </summary>
183205 /// <param name="pathOrFilename">The path or filename of the file to read.</param>
184- public virtual async Task < string > ReadFile ( string pathOrFilename )
185- => await ReadFile ( pathOrFilename , CancellationToken . None ) ;
206+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
207+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
208+ public virtual async Task < string > ReadFile ( string pathOrFilename , int saveSlotIndex = - 1 )
209+ => await ReadFile ( pathOrFilename , CancellationToken . None , saveSlotIndex ) ;
186210
187211 /// <summary>
188212 /// Erases a file at the given path or filename. The file will still exist on disk, but it will be empty.
@@ -194,8 +218,10 @@ public virtual async Task<string> ReadFile(string pathOrFilename)
194218 /// </summary>
195219 /// <param name="pathOrFilename">The path or filename of the file to erase.</param>
196220 /// <param name="cancellationToken">The cancellation token should be the same one from the calling MonoBehaviour.</param>
197- public virtual async Task Erase ( string pathOrFilename , CancellationToken cancellationToken )
198- => await WriteFile ( pathOrFilename , string . Empty , cancellationToken ) ;
221+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
222+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
223+ public virtual async Task Erase ( string pathOrFilename , CancellationToken cancellationToken , int saveSlotIndex = - 1 )
224+ => await WriteFile ( pathOrFilename , string . Empty , cancellationToken , saveSlotIndex ) ;
199225
200226 /// <summary>
201227 /// Erases a file at the given path or filename. The file will still exist on disk, but it will be empty.
@@ -206,8 +232,10 @@ public virtual async Task Erase(string pathOrFilename, CancellationToken cancell
206232 /// </code>
207233 /// </summary>
208234 /// <param name="pathOrFilename">The path or filename of the file to erase.</param>
209- public virtual async Task Erase ( string pathOrFilename )
210- => await Erase ( pathOrFilename , CancellationToken . None ) ;
235+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
236+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
237+ public virtual async Task Erase ( string pathOrFilename , int saveSlotIndex = - 1 )
238+ => await Erase ( pathOrFilename , CancellationToken . None , saveSlotIndex ) ;
211239
212240 /// <summary>
213241 /// Deletes a file at the given path or filename. This will remove the file from disk.
@@ -219,9 +247,11 @@ public virtual async Task Erase(string pathOrFilename)
219247 /// </summary>
220248 /// <param name="pathOrFilename">The path or filename of the file to delete.</param>
221249 /// <param name="cancellationToken">The cancellation token should be the same one from the calling MonoBehaviour.</param>
222- public virtual async Task Delete ( string pathOrFilename , CancellationToken cancellationToken )
250+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
251+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
252+ public virtual async Task Delete ( string pathOrFilename , CancellationToken cancellationToken , int saveSlotIndex = - 1 )
223253 {
224- string fullPath = GetFullPath ( pathOrFilename ) ;
254+ string fullPath = GetFullPath ( pathOrFilename , saveSlotIndex ) ;
225255 if ( File . Exists ( fullPath ) )
226256 await Task . Run ( ( ) => File . Delete ( fullPath ) , cancellationToken ) . ConfigureAwait ( false ) ;
227257 }
@@ -235,7 +265,9 @@ public virtual async Task Delete(string pathOrFilename, CancellationToken cancel
235265 /// </code>
236266 /// </summary>
237267 /// <param name="pathOrFilename">The path or filename of the file to delete.</param>
238- public virtual async Task Delete ( string pathOrFilename )
239- => await Delete ( pathOrFilename , CancellationToken . None ) ;
268+ /// <param name="saveSlotIndex">The save slot index to use. Passing in anything below 0 will not
269+ /// use a slot, which can be good for things like settings files or for projects that don't use save slots.</param>
270+ public virtual async Task Delete ( string pathOrFilename , int saveSlotIndex = - 1 )
271+ => await Delete ( pathOrFilename , CancellationToken . None , saveSlotIndex ) ;
240272 }
241273}
0 commit comments