Asset - Extension File Manager (for Windows, macOS, and Ubuntu)

S

Sam (Deleted User)

Guest

[Made for GameMaker Studio 2]

Function Documentation (PDF)

This extension is for Windows, macOS, and Ubuntu.

Manage files/folders without a sandbox; overrides GameMaker Studio 2's built-in functions.

Each function that does not return a string, will return true on success, and false on failure.

Functions included:
  • real file_copy(string fname, string newname)
  • real file_rename(string oldname, string newname)
  • real file_exists(string fname)
  • real file_delete(string fname)
  • real file_size(string fname)
  • real directory_create(string dname)
  • real directory_copy(string dname, string newname)
  • real directory_rename(string oldname, string newname)
  • real directory_exists(string dname)
  • real directory_destroy(string dname)
  • real directory_size(string dname)
  • string filename_absolute(string fname)
  • string filename_canonical(string fname)
  • string filename_equivalent(string fname1, string fname2)
  • string environment_get_variable(string name)
  • real environment_get_variable_exists(string name)
  • real environment_set_variable(string name, string value)
  • real environment_unset_variable(string name)
  • string environment_expand_variables(string str) // ${VARIABLE}
  • string directory_get_current_working()
  • real directory_set_current_working(string dname)
  • string executable_get_directory()
  • string directory_get_temporary_path()
  • string directory_get_desktop_path()
  • string directory_get_documents_path()
  • string directory_get_downloads_path()
  • string directory_get_music_path()
  • string directory_get_pictures_path()
  • string directory_get_videos_path()
  • string executable_get_filename()
  • string executable_get_pathname()
  • real hardlink_create(string fname, string newname)
  • real file_numblinks(string fname)
  • real file_bin_numblinks(real fd)
  • real symlink_create(string fname, string newname)
  • real symlink_copy(string fname, string newname)
  • real symlink_exists(string fname)
  • real file_get_date_created_year(string fname)
  • real file_get_date_created_month(string fname)
  • real file_get_date_created_day(string fname)
  • real file_get_date_created_hour(string fname)
  • real file_get_date_created_minute(string fname)
  • real file_get_date_created_second(string fname)
  • real file_get_date_accessed_year(string fname)
  • real file_get_date_accessed_month(string fname)
  • real file_get_date_accessed_day(string fname)
  • real file_get_date_accessed_hour(string fname)
  • real file_get_date_accessed_minute(string fname)
  • real file_get_date_accessed_second(string fname)
  • real file_get_date_modified_year(string fname)
  • real file_get_date_modified_month(string fname)
  • real file_get_date_modified_day(string fname)
  • real file_get_date_modified_hour(string fname)
  • real file_get_date_modified_minute(string fname)
  • real file_get_date_modified_second(string fname)
  • real file_bin_get_date_created_year(real fd)
  • real file_bin_get_date_created_month(real fd)
  • real file_bin_get_date_created_day(real fd)
  • real file_bin_get_date_created_hour(real fd)
  • real file_bin_get_date_created_minute(real fd)
  • real file_bin_get_date_created_second(real fd)
  • real file_bin_get_date_accessed_year(real fd)
  • real file_bin_get_date_accessed_month(real fd)
  • real file_bin_get_date_accessed_day(real fd)
  • real file_bin_get_date_accessed_hour(real fd)
  • real file_bin_get_date_accessed_minute(real fd)
  • real file_bin_get_date_accessed_second(real fd)
  • real file_bin_get_date_modified_year(real fd)
  • real file_bin_get_date_modified_month(real fd)
  • real file_bin_get_date_modified_day(real fd)
  • real file_bin_get_date_modified_hour(real fd)
  • real file_bin_get_date_modified_minute(real fd)
  • real file_bin_get_date_modified_second(real fd)
  • string directory_contents_first(string dname, string pattern, real includedirs, real recursive)
  • real directory_contents_first_async(string dname, string pattern, real includedirs, real recursive)
  • string directory_contents_next()
  • real directory_contents_get_length()
  • real directory_contents_get_order()
  • real directory_contents_set_order(real order)
  • real directory_contents_get_cntfiles()
  • real directory_contents_get_maxfiles()
  • real directory_contents_set_maxfiles(real maxfiles)
  • real directory_contents_get_completion_status()
  • real directory_contents_set_completion_status(real complete)
  • real directory_contents_close()
  • real file_bin_open(string fname, real mode)
  • real file_bin_rewrite(real fd)
  • real file_bin_close(real fd)
  • real file_bin_size(real fd)
  • real file_bin_position(real fd)
  • real file_bin_seek(real fd, real pos)
  • real file_bin_read_byte(real fd)
  • real file_bin_write_byte(real fd, real byte)
  • real file_text_open_read(string fname)
  • real file_text_open_write(string fname)
  • real file_text_open_append(string fname)
  • real file_text_write_real(real fd, real val)
  • real file_text_write_string(real fd, string str)
  • real file_text_writeln(real fd)
  • real file_text_eoln(real fd)
  • real file_text_eof(real fd)
  • real file_text_read_real(real fd)
  • string file_text_read_string(real fd)
  • string file_text_readln(real fd)
  • string file_text_read_all(real fd)
  • real file_text_open_from_string(string str)
  • string file_bin_hardlinks(real fd, string dnames, real recursive)
  • real file_text_close(real fd)
The DLL's full source code included.

Very big thanks to Josh Ventura, for writing the widen() and shorten() scripts, enabling UTF-8 support on Windows.

Download Free for GameMaker Studio 2
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Added directory functions.
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Just wanted to point out that new to version 1.0.2, directory_delete_fmns is now recursive, meaning that it can delete non-empty directories.

Mac users will have to compile the dylib using the provided source code. Contact me either by a private message or the marketplace contact form if you need further assistance.

Be aware that sandboxing is a requirement of the Mac App Store, so if you manage files outside the sandbox, you will need to release your game outside of the Mac App Store.
 
S

Sam (Deleted User)

Guest
Added function program_directory_fmns(). Unlike the built-in program_directory variable, program_directory_fmns() returns a string that includes the final slash at the end, ("\" on Windows and "/" on Linux/Mac). program_directory_fmns() should also be more reliable than program_directory, as program_directory has been broken several times in the past...
 
S

Sam (Deleted User)

Guest
Ok so I don't know why I didn't think to implement this originally, but now these functions have a return value that determines either success or failure of the given operation, (1 or 0):

file_copy_fmns
file_move_fmns
file_rename_fmns
file_delete_fmns
directory_create_fmns
directory_delete_fmns

Be sure to replace the scripts and included files in your existing projects to apply the changes made in this important update.
 
S

Sam (Deleted User)

Guest
Added functions:
  • real directory_copy_fmns(string dname,string newname)

  • real directory_move_fmns(string oldname,string newname)

  • real directory_rename_fmns(string oldname,string newname)
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
I updated this extension so that it no longer uses SHFileOperation for directory_copy_fmns and directory_delete_fmns. This mean all functions now support both absolute and relative paths.

As usual, to apply this update to your existing projects, replace your current scripts and included/data files with the newest versions thereof. :)
 
J

johnny-o

Guest
Ok so I don't know why I didn't think to implement this originally, but now these functions have a return value that determines either success or failure of the given operation, (1 or 0):
Thanks for the fantastic extension. I'm using it everywhere!

I didn't realize it was continually being updated. Having a return value would have saved me some time this week. :-D
 

rIKmAN

Member
Hey @Samuel Venable, I checked this asset out a few days ago and the reviews were very entertaining.

You basically were arguing with customers who reported issues with the extension, even going so far as to call one a troll and liar.

I check back today to see how things had developed and both the reviews in question have been edited to 5* reviews with no text and your replies also gone - both edited on the same date.

Am I to believe 2 random people having issues with your extension, and then who you abused for reporting these issues in the replies, both decided on the exact same date that actually - this asset deserves 5* after all?

Smells fishy, what's going on?

It's pretty bad either way, but I hope you are deleting / editing feedback yourself and this selective / falsifying of reviews isn't being done by YYG?
 
J

johnny-o

Guest
Hey @Samuel Venable,
Smells fishy, what's going on?

It's pretty bad either way, but I hope you are deleting / editing feedback yourself and this selective / falsifying of reviews isn't being done by YYG?
What you're saying makes no sense. Why would YYG have an incentive to mess around with reviews of a free extension? and why would the developer?

I left a negative review for a different extension and after a discussion with the developer he ironed out the problems and I changed it to 5 stars. @Samuel Venable probably solved a problem that both reviewers had received emails at the same time about an update and they decided to edit their reviews because they had received *FREE* support on a ****FREE*** extension
 

rIKmAN

Member
What you're saying makes no sense. Why would YYG have an incentive to mess around with reviews of a free extension? and why would the developer?
You have no idea why the developer would want to remove negative feedback from his asset?
Are you being serious?

I don't have a seller account so I have no idea whether a dev can edit his own feedback or not - seems odd if they could.
If not then YYG must had to have changed it - which also seems quite odd as what's the point in feedback at all if it can be edited at will to only make things seem super positive?
I left a negative review for a different extension and after a discussion with the developer he ironed out the problems and I changed it to 5 stars. @Samuel Venable probably solved a problem that both reviewers had received emails at the same time about an update and they decided to edit their reviews because they had received *FREE* support on a ****FREE*** extension
That's great for you, and look at you shouting in just your 3rd whole post - congrats.
Also in your case the dev fixed your issues and was more than likely civil - in the replies I am talking about Sam was downright accusing "customers" of being liars and trolls when reporting issues and generally acting like an abusive idiot towards them. Big difference.

Being free or not is irrelevant, and whether or not the asset worked after his "support" - if a dev spoke to me the way Samual replied to his customers on his asset page I can tell you now I would not be leaving a 5* review.
If the reviews had just disappeared altogether then I could believe Sam had regrets about how he acted (seems to be a common theme for Sam lately) and deleted them, but for them both to change to 5* reviews on the same day? Not a chance, so as I said it smells fishy.

Hopefully Sam will find time to explain things, because it looks like either devs or YYG can just edit feedback to make something appear to be something it isn't. As a customer I'd like to know which of those scenarios it is.
 
S

Sam (Deleted User)

Guest
In under 48 hours I recieved 3 zero-star ratings on the same asset (2 of which were a couple hours apart I think), sounded just as fishy to me at the time, which was why I had the doubtless impression I was being trolled. Whether I was or not - I still don't know - but that is irrelevant. I should've not lashed out regardless. If they were being trolls - I was feeding them. If they weren't being trolls - I was the first one to be a jerk. In any case, in times past I have been trolled with over HUNDREDS of 1-star ratings by people who didn't like me and admitted that's why they rated - to get on my nerves - so it should be nothing but understandable why I was quick to make this assumption, but I still should've kept it to myself.

YYG resolved all this and their exact words to me: "I can see why you are annoyed". I asked them in my helpdesk ticket to test it and verify my extension works. That's why they removed the original reviews and my comments. They are aware of the things I said and were nice enough to try to cover that up for me as an act of forgiveness. Believe me, I'll think twice before making that mistake again because if I did I could get in trouble for it, and that's on top of it not being the right thing to do. Whether people are being nice, descriptive, or otherwise in reviews, I need to not make a scene and make sure I respond well.

@johnny-o You're welcome! Thanks for the appreciation. It's appreciated. :)
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Added support for UTF-8 encoding in file and path names on Windows, for those of you who need special characters. Before this update, Linux was the only platform to support UTF-8. But anyway, now Windows supports it as well. program_directory_fmns() also works with UTF-8, as of v1.5.0, which means all functions support it on all platforms. :D
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Now that I finally have a Mac, I am able to compile and test DYLIB's on my own...

Version 1.9.3 Released!

Please replace all Scripts and Included Files in your existing projects to apply this update!!!
  • Added support for macOS.
  • Added function working_directory_fmns().
  • file_rename_fmns() can now both rename and move files, therefore file_move_fmns() was removed.
  • directory_delete_fmns() was renamed to directory_destroy_fmns().
  • Bug fixed with program_directory_fmns() on Windows and Linux.
The new screenshots will be uploaded within the next couple days.
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Version 1.9.9 Released!
  • Added function set_working_directory_fmns().
Note: working_directory_fmns() is not the same thing as GM's internal working_directory constant. For instance, if you change the value of working_directory_fmns() with set_working_directory_fmns(), GM's internal working_directory will not be effected, as it is a constant, not a variable or function. Depending on the target platform, GM's working_directory and the extension's working_directory_fmns() will not equal the same value by default even if working_directory_fmns() hasn't been changed by set_working_directory_fmns() yet. This is because the extension has its own working directory separate from the game, and when a relative path is given, the the value of working_directory_fmns() is assumed as a starting point for the relative path.

Setting the value of working_directory_fmns() with set_working_directory_fmns() is known to currently cause problems on Linux such as your included files no longer being readable, this is because on Linux YoYoGames forgot to make the game's default working_directory sandboxed, which means it can be modified by my extension. The value of GM's working_directory on Linux will always equal the relative path "assets/" but unfortunately, my extension does in fact modify where the game looks for that "assets" folder on Linux. I have reported this bug to YoYoGames. Windows and Mac are not effected by this issue.
 
S

Sam (Deleted User)

Guest
Version 2.4.0 Released!
  • [macOS] [Ubuntu] Fixed a safety issue with the use of the POSIX functions dirname() and basename().
 
S

Sam (Deleted User)

Guest
Version 3.0.0 Released!
  • [All Platforms] Added function temp_directory_fmns().
 
S

Sam (Deleted User)

Guest
<post removed>
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Version 4.5.0 Released!

Please REMOVE all Scripts and Included Files in your existing projects, that came from older versions of this asset, to apply this update!!!
  • [All Plaforms] Removed the *_fmns() suffix from function names. Now the extension overrides the built-in functions, and no longer uses any script resources. Please remove that suffix from all of your functions that have it from this extension in your projects.
 
S

Sam (Deleted User)

Guest
Version 6.0.0 Released!
  • [All Plaforms] Added function environment_set_variable(). (Set an environment variable to an empty string to remove it completely).
 
R

RobotoSkunk

Guest
The extension is not working in Game Maker Studio 2
Code:
switch(os_type){
    case os_windows:
        if(!directory_exists("\\users\\<username>\\documents\\PixelMan files\\")){
            directory_create("\\users\\<username>\\documents\\PixelMan files\\");
        }
        docu_directory = "\\users\\<username>\\documents\\PixelMan files\\";
        break;
}
 
S

Sam (Deleted User)

Guest
Are you using environment_get_variable to get the documents folder? It's working for me just fine, although I am either using relative paths or including the drive letter and colon, i.e. "C:" in the beginning of relative paths. You mind giving more information on what you are doing in your code? Is it just the functions in that snippet that aren't working or is other stuff not working as well?

are you literally trying it without listing the current drive and are you actually putting your username or are you literally using the text "<username>" in your string? You need the drive and correct username, which can be gotten with the correct environment variable.

As a general rule of thumb, never assume, regardless of who made it, that an extension doesn't work until you can verify with the developer whether or not you are using it correctly. The only exception being if they refuse to get back to you when you contact them for support after an unreasonable period of time. If more people did this, there would be much less misleading reviews or comments being left. You might be right that it doesn't work in your case, but we don't know that for sure without working together and doing a little debugging. :)

P.S. what runtime are you using?

I'm trying this, and it works fine for me:
Code:
if (os_type == os_windows)
  f = get_open_filename_ext(
  "Saved Game Files (*.sav)|*.sav",
  environment_get_variable("USERPROFILE") + "Untitled.sav",
  environment_get_variable("USERPROFILE"),
  "Load a Previously Saved Game File");

if (os_type == os_macosx || os_type == os_linux)
  f = get_open_filename_ext(
  "Saved Game Files (*.sav)|*.sav",
  "Untitled.sav",environment_get_variable("HOME"),
  "Load a Previously Saved Game File");

if (file_exists(f))
{
  file_copy(f,game_save_id + filename_name(f));
 
  ini_open(game_save_id + filename_name(f));
  c = ini_read_real("savegame","color",c_white);
  score = ini_read_real("savegame","score",0);
  ini_close();
 
  file_copy(game_save_id + filename_name(f),f);
 
  room_goto(rm_main);
}
Note that I'm also using Dialog Module which overrides get_open_filename and does not break the sandbox without the help of File Manager.

On Windows, to get the Documents folder you may do:
Code:
environment_get_variable("USERPROFILE") + "Documents\\"
On Mac and Linux, you may use this OS equivalent:
Code:
environment_get_variable("HOME") + "Documents/"
Also, be aware, if you or the end-user changed the environment variable to something that is not the system's default, this code will not work, and there is no universal workaround. It will be whatever folder it was set to, if the folder exists.
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
I added this important information to the extension's description:
get_working_directory() will return the Unix working directory on Mac, which defaults to your system root "/". At the beginning of your game, you may change this to whatever you like, but I recommend your app bundle's "Resources" folder, which you may set it to with the GML Script - generate_working_directory():
Code:
if (os_type == os_macosx) {
  /*
    This function will set the working directory to the app bundle's Resources folder 
    like GM4Mac 7.5, GMStudio 1.4, GMS 2.x and most Mac apps do, if the executable is in
    an app bundle. If the executable is not in an app bundle, use the getcwd function
   
    ONLY use get_working_directory() for loading read-only included files! When SAVING, use game_save_id
   
    *_bname = base name - removes the full path from the string leaving just the file or folder name
    *_dname = directory name - removes final slash and base name from full path to file or folder name
    *_pname = path name - removes the base name from a full path while keeping the dir and final slash
    *_ename = extension name - includes everything in bname at and following the period if one exists
  */
 
  var success = false; 
  var exe_pname = get_program_directory();             // = "/Path/To/YourAppBundle.app/Contents/MacOS/";
  var macos_dname = filename_dir(exe_pname);           // = "/Path/To/YourAppBundle.app/Contents/MacOS";
  var macos_bname = filename_name(macos_dname);        // = "MacOS";
  var contents_dname = filename_dir(macos_dname);      // = "/Path/To/YourAppBundle.app/Contents";
  var contents_bname = filename_name(contents_dname);  // = "Contents";
  var app_dname = filename_dir(contents_dname);        // = "/Path/To/YourAppBundle.app";
  var app_ename = filename_ext(app_dname);             // = ".app";
  var contents_pname = filename_path(macos_dname);     // = "/Path/To/YourAppBundle.app/Contents/";
  var resources_pname = contents_pname + "Resources/"; // = "/Path/To/YourAppBundle.app/Contents/Resources/";
 
  // if "/Path/To/YourAppBundle.app/Contents/MacOS/YourExe" and "/Path/To/YourAppBundle.app/Contents/Resources/" exists
  if (macos_bname == "MacOS" && contents_bname == "Contents" && app_ename == ".app" && directory_exists(resources_pname)) {
    // set working directory to "/Path/To/YourAppBundle.app/Contents/Resources/" and allow loading normal included files
    success = set_working_directory(resources_pname);
  }
 
  /*
    if (success) show_message("Success!"); else show_message("Failure!");
    get_string_async("The current value of working_directory equals:", get_working_directory()); 
  */
}
 
Last edited by a moderator:
R

RobotoSkunk

Guest
OOOHHHHHHHH!!!! IT WORKS!!!!! THX SO MUCH!!! <3

Code:
if (os_type == os_windows){
    if(!directory_exists(environment_get_variable("USERPROFILE") + "\\documents\\PMTEST"))
    directory_create(environment_get_variable("USERPROFILE") + "\\documents\\PMTEST");
 
}
 
S

Sam (Deleted User)

Guest
As @RobotoSkunk pointed out in a private message to me, I want to make it clear to everyone that set_working_directory() does not effect the value of GameMaker's built-in variables such as game_save_id (the sandbox write directory) and working_directory (included files directory). It only effects the value of get_working_directory() provided by the extension, so when saving files you will still need to copy or move them over to get_working_directory() regardless of what value you set it to. :/ On mac please make sure you never modify the app bundle and only save and/or modify files outside of it.
 
S

Sam (Deleted User)

Guest
Today I've been working on the first update for this extension in a while, which includes the following improvements:

1) Significantly smaller DLL file size on Windows.

2) New function: string directory_contents(string dname). Returns the absolute path to all files and folders in the specified directory, separated by a new line character.

3) Return the mac app bundle "Resources" directory on macOS, if it exists, otherwise return executable directory (via the function get_working_directory).

This update will be published in a couple days if all goes well. Dialog Module will also be updated as a result of having this extension bundled with it.

Edit:

Windows and Linux ports are now done. Going to do the Mac version next and then it'll be ready to publish!

Edit2:

Just finished the Mac port. I'm going to take a few minute break then I'll publish it.

Edit3:

The aforementioned File Manager and Dialog Module update is now published!
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Environment variables are now supported in every function on all platforms.

In this example, you may create a new folder inside your home folder on Windows, Mac, and Linux.

GML:
if (os_type == os_windows) {
  directory_create("${HOMEDRIVE}${HOMEPATH}/New Folder");
} else {
  directory_create("${HOME}/New Folder");
}

Edit:

Source code now available on github:
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Added functions:
  • real file_size(string fname)
  • real directory_size(string dname)
  • string filename_canonical(string fname)
  • string environment_expand_variables(string str) // ${VARIABLE}
 
S

Sam (Deleted User)

Guest
Added the following functions on GitHub:
  • file_get_date_accessed_year(fname)
  • file_get_date_accessed_month(fname)
  • file_get_date_accessed_day(fname)
  • file_get_date_accessed_hour(fname)
  • file_get_date_accessed_minute(fname)
  • file_get_date_accessed_second(fname)
  • file_get_date_modified_year(fname)
  • file_get_date_modified_month(fname)
  • file_get_date_modified_day(fname)
  • file_get_date_modified_hour(fname)
  • file_get_date_modified_minute(fname)
  • file_get_date_modified_second(fname)
  • directory_contents_first(dname,pattern,includedirs,recursive)
  • directory_contents_next()
  • directory_contents_close()
And I removed the following functions:
  • directory_contents(dname)
  • directory_contents_ext(dname,pattern,includedirs)
Commits:
I will be updating the marketplace and itch.io assets soon. Keep an eye out for it!

Also note - the benefit of `directory_contents_first/next/close` over `file_find_first/next/close` is that you may use more than one file extension pattern for the search, as well as choose to include/exclude directories in the return values, while remaining cross-platform on desktops. `file_find_first/next/close` can only use one file type pattern, and is limited to file attributes, such as whether to include or filter out directories would be Windows-only. The functions work mostly the in terms of how you get the return values as well as freeing memory when done.

The usefulness of the timestamp functions allows you to get the date and time a file was last modified or accessed. Using this information, you may choose to re-order an array of filenames based on that info. Great for creating your own custom version of `get_open_filename`.
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
This extension now overrides the following:
  • real file_bin_open(string fname, real mode)
  • real file_bin_rewrite(real fd)
  • real file_bin_close(real fd)
  • real file_bin_size(real fd)
  • real file_bin_position(real fd)
  • real file_bin_seek(real fd, real pos)
  • real file_bin_read_byte(real fd)
  • real file_bin_write_byte(real fd, real byte)
  • real file_text_open_read(string fname)
  • real file_text_open_write(string fname)
  • real file_text_open_append(string fname)
  • real file_text_write_real(real fd, real val)
  • real file_text_write_string(real fd, string str)
  • real file_text_writeln(real fd)
  • real file_text_eoln(real fd)
  • real file_text_eof(real fd)
  • real file_text_read_real(real fd)
  • string file_text_read_string(real fd)
  • string file_text_readln(real fd)
  • string file_text_read_all(real fd)
  • real file_text_open_from_string(string str)
  • real file_text_close(real fd)
Which allows you to take advantage of several improvements available in the new functions:
  1. file_bin_open's mode argument now supports append-only(=3) as well as append+read(=4).
  2. Environment variables can be passed to the path arguments of these functions, for example: ${TMP}
  3. new lines are treated as just a line feed (excludes carriage return which is windows-only for new lines)
  4. The file handles created are real file descriptors that can be passed to and used by other extensions
  5. The limitation: "You can only have a maximum of 32 files open at any one time." no longer applies
  6. file_text_open_from_string's file descriptor can be read by multiple processes, without writing to disk
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
One thing I forgot to mention about these functions, when overridden by my extension, is that they may be used interchangeably:
  • real file_bin_open(string fname, real mode)
  • real file_bin_rewrite(real fd)
  • real file_bin_close(real fd)
  • real file_bin_size(real fd)
  • real file_bin_position(real fd)
  • real file_bin_seek(real fd, real pos)
  • real file_bin_read_byte(real fd)
  • real file_bin_write_byte(real fd, real byte)
  • real file_text_open_read(string fname)
  • real file_text_open_write(string fname)
  • real file_text_open_append(string fname)
  • real file_text_write_real(real fd, real val)
  • real file_text_write_string(real fd, string str)
  • real file_text_writeln(real fd)
  • real file_text_eoln(real fd)
  • real file_text_eof(real fd)
  • real file_text_read_real(real fd)
  • string file_text_read_string(real fd)
  • string file_text_readln(real fd)
  • string file_text_read_all(real fd)
  • real file_text_open_from_string(string str)
  • real file_text_close(real fd)
So that means you can return a file descriptor from file_bin_open(), file_text_open_read(), file_text_open_write(), file_text_open_append(), or file_text_open_from_string(), and pass that return value to any of the other file_bin_* and/or file_text_* functions and they work together seamlessly. You can open a file with file_bin_open() for example and write to it with file_text_write_string(), or use the returned value of file_text_open_from_string() stored in a variable and change the seek position while you read from it with file_bin_seek(). Keep in mind that file_text_open_from_string() returns a read-only file descriptor still, as the documentation mentions for GameMaker Studio, and it can't be written or appended to once it has been created.
 
Last edited by a moderator:

Alabard

Member
Hey, thanks for the awesome extension, just a little heads up, the one in the yoyo marketplace isn't at the latest version, it's missing the file_get_date_*, file_bin_*, and file_text_* functions.

The one in your itch.io has those functions, so I assume that it is updated to the latest version.
 
S

Sam (Deleted User)

Guest
Hey, thanks for the awesome extension, just a little heads up, the one in the yoyo marketplace isn't at the latest version, it's missing the file_get_date_*, file_bin_*, and file_text_* functions.

The one in your itch.io has those functions, so I assume that it is updated to the latest version.
That's unfortunate news. I thought that only one of my extensions in specific (not this one) had that issue. Seems the marketplace uploader is just broken in general. In that case, get it from itch.io instead for the foreseeable future. Thanks for letting me know!
 
S

Sam (Deleted User)

Guest
Added the function:
  • string get_filedescriptor_pathname(real fd)
Returns the absolute path and filename associated with a particular file descriptor. Only works correctly if the file descriptor actually refers to a regular file on the filesystem and not something else (for example, the file descriptor might refer to a pipe, in which case the return value won't be very useful). The main reason I introduced this function is because I changed the behavior of file_text_open_from_string() so that the temp file it creates is no longer deleted automatically after its file descriptor is closed; this gives the developer more say in the lifetime of the file and lets them choose whether it should be deleted at that point or at some point afterward, i.e. let them choose by doing it manually. The file will eventually be removed anyway, since it is saved to the system's temp directory, so you don't have to worry about too many of them accumulating over time so much.
 
S

Sam (Deleted User)

Guest
Note any mention of multi-threading in this post is intended for C++ developers who intend to reuse the source code of this extension and does not apply to GMS users outside of C++ GMS extension developers. I will be creating static libraries in the near future for C++ developers who may wish to use my code outside of the GameMaker universe for any reason.

3 new functions to use alongside the directory iterator functions:


real directory_contents_get_cntfiles()

The function returns the number of counted files and/or directories that were iterated through from a previous call to directory_contents_first(). Note a call to directory_contents_first() will store the entire array of files and directories that match the given criteria in advance to predetermine the return value of later calls to directory_contents_next() thereafter, and directory_contents_get_cntfiles() will return the entire number of files and directories that were iterated through by the call to directory_contents_first() internally. directory_contents_get_cntfiles() will return the same result regardless of whether it is called before or after any number of calls to directory_contents_next().

The thing to remember is it needs to be called after at least one call to directory_contents_first() and it will already return the value you need at that point. directory_contents_get_cntfiles() does not return the value of the number of files or directories that match the criteria specified by directory_contents_first(). It returns every single file and/or directory in the search provided by directory_contents_first(), regardless of the amount of files and/or directories which matched the criteria. The default return value is one. If more than one file and/or directory is searched through, the return value is increased to be that total number of files and/or directories which were iterated through in the search.


real directory_contents_get_maxfiles()

The function returns the maximum number of files and/or directories to search through in a call to directory_contents_first() before ending the search that is looking for the specified criteria in the arguments passed to directory_contents_first(). Returns zero by default. The return value of this function may be set by directory_contents_set_maxfiles().


real directory_contents_set_maxfiles(real maxfiles)

The function sets the maximum number of files to search through for testing against whether they match the criteria of the arguments passed to directory_contents_first(). Pass zero to the maxfiles argument to represent no maximum value and allow for there to be zero limitations in place. Using no limitation can cause a search to take a very long time when searching directories with many files or directories in them, so it is preferred to set a limitation of some kind in applications that shall block the main thread while the search is being performed by directory_contents_first().

Otherwise, the user might mistake the search for the program not responding or get tired of waiting for it to finish. The directory_contents_first() and directory_contents_next() functions are not thread-safe and should only be called from a single-thread at a time. In a multi-threaded application, you may provide a progress indicator using an implementation of your choosing but you it is wise to allow for a means to cancel the search and force the thread to quit its execution while also being asynchronous and non-blocking when possible.


Test for equality, (and not less-than, less-than-or-equal-to, greater-than-or-equal-to, etc.), between directory_contents_get_cntfiles() and directory_contents_get_maxfiles(), and, if the two are equal, let this be a means to cancel the operation of looping through following calls to directory_contents_next(), which will apply the proper limitations set by directory_contents_set_maxfiles() and prevent undesirable hanging of the main thread when running in a single- threaded application or program. This will helps improve user experience where such behavior in an application is at all acceptable. Otherwise, it is in most cases better to write a multi-threaded application. This function has no return value.
 
Last edited by a moderator:

space_sauce

Member
I just tried to add File Manager to my project via GameMaker's 'MyLibrary' window and it says "failed to verify package" :(

When we get an extension from Itch how do we add it to our project?
 
S

Sam (Deleted User)

Guest
Added several new functions that will be rolling out on itch.io soon.

C++:
char *directory_get_desktop_path();
char *directory_get_documents_path();
char *directory_get_downloads_path();
char *directory_get_music_path();
char *directory_get_pictures_path();
char *directory_get_videos_path();
They do exactly what you'd expect regardless of the locale your OS is translated under and yes it works on Windows, Mac, and Linux. :D


I just tried to add File Manager to my project via GameMaker's 'MyLibrary' window and it says "failed to verify package" :(

When we get an extension from Itch how do we add it to our project?
right click on the resource tree and "add existing resource" -> select the *.yy file from the extensions folder of the project. I recommend testing and looking at the example project for clarity.
 
S

Sam (Deleted User)

Guest
OOOHHHHHHHH!!!! IT WORKS!!!!! THX SO MUCH!!! <3

Code:
if (os_type == os_windows){
    if(!directory_exists(environment_get_variable("USERPROFILE") + "\\documents\\PMTEST"))
    directory_create(environment_get_variable("USERPROFILE") + "\\documents\\PMTEST");

}
I know this post is a bit old, just wanted to let you know that code should probably be updated to something more reliable, for example. if the user's documents folder is not using the english locale, it needs to be the locale their machine is using.

This can be done with:
Code:
if (os_type == os_windows){
  if (!directory_exists(directory_get_documents_path() + "\\PMTEST"))
    directory_create(directory_get_documents_path() + "\\PMTEST");
}
Additionally, i am in the process of publishing an update which allows the new functions i added in the last update (including directory_get_documents_path() and similar) to return the full path along with a trailing slash at the end to save you one less character to write. It's not a huge difference but i wanted to do this for consistency with some functions that have been around much longer.
 
Top