godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.15k stars 97 forks source link

Add a res:// and user:// style notation for the folder the executable resides in #6850

Open Sooshiko opened 1 year ago

Sooshiko commented 1 year ago

Describe the project you are working on

I am working on a video game with a custom error handler.

Describe the problem or limitation you are having in your project

"res://" is read only and "user://" is not portable. I recently turned on logs and I'd like to output my logs to a folder next to the executable instead so it is easier for my players to find them and send them to me.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I think the easiest and best way to fix my problem would be to add a notation for the folder the executable is in. This would allow me to set the log path to something next to the executable.

I've seen a few old proposals that came close to this that were closed. Some of them had a lot of likes but I guess felt out of scope or something, but what I haven't seen anyone mention is that Log path does not take function calls like "ProjectSettings.globalize_path()" or anything like that.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

I don't know what you would call it but something like "folder://" or "parent://" might work. assuming "res://" stands for resource you could contract it like "par://" or "fol://" (or "dir://") but those don't sound particularly descriptive. I've never used a mac before so I don't know how it would work but assuming you can edit the inside of a mac bundle, "folder://" would point to the inside of the bundle so doing "folder://Logs/Log.txt" would create a directory of logs inside the bundle nex to the dlls or whatever they are called under mac.

If this enhancement will not be used often, can it be worked around with a few lines of script?

I don't think it's possible as Log path does not accept function calls or any other work around i can use in script. I'm bound to the built-in terms like "user://"

Is there a reason why this should be core and not an add-on in the asset library?

I don't think it can be done with addons. My biggest argument is that project settings don't accept the "globalize_path" type of functions so there isn't much other choice.

Sooshiko commented 1 year ago

Also, you cannot change the log path at any point while the game is running. And if somehow this feature exists in godot 4. I want this post changed for a port request instead, but I'm pretty sure it's not in godot 4.

RedMser commented 1 year ago
Sooshiko commented 1 year ago
  • Implement custom resource path support #6307 seems like a more flexible version of this proposal.
  • Is it possible to override the log directory Project Setting (debug/file_logging/log_path) via override.cfg?
  • Relative paths like ./logs/godot.log work very similarly in most cases.
  1. FileAccess.add_resource_path() would be called from code, meaning it would not be valid at the time of loading in ProjectSettings.
  2. I don't think override files can use dynamic function calls. even if i made one with script it wouldn't kick in until next restart and if you moved the game folder it would be wrong again until the next restart.
  3. I can't get relative paths to work in ProjectSettings.

None of these solutions work for what I want.

Sooshiko commented 1 year ago

If there is a way to set the ProjectSettings' Log Path of an exported game through script and have it stick, I haven't found it, but that would fix my problem. Another solution would be to be able to use relative paths in project settings like "res://../Logs/Log.txt" or something, but I don't think you can put ".." in the middle of paths like that.

timothyqiu commented 1 year ago

"user://" is not portable

It depends on what you mean by "portable". user:// works on all platforms, it uses the directory recommended by the OS for placing user data.

The folder the executable is in is not portable. The folder is usually read-only or unavailable on platforms other than desktop platforms. e.g. Android / iOS / Web / Console.

Calinou commented 1 year ago

You can use OS.get_executable_path().path_join("some_file.txt") (plus_file() in 3.x) already. This will point to some_file.txt in the folder the executable is located in.

In general, loading files (and especially saving files) in the executable path is considered a bad idea as it's not portable to Android, iOS, HTML5 and macOS (with sandboxing or path randomization in place). Saving files is not guaranteed to be feasible depending on where the executable is located on both Windows and Linux. Therefore, I wouldn't add an alias to not encourage using this over user://.

I recently turned on logs and I'd like to output my logs to a folder next to the executable instead so it is easier for my players to find them and send them to me.

Maybe add a button in the game to open the log file directly? You can do this by having the button's pressed signal connected to a method that calls OS.shell_open(ProjectSettings.globalize_path("user://path/to/log.txt")).

If the game is not able to be opened, include a README.txt file next to your executable with instructions on finding the log file.

Sooshiko commented 1 year ago

Again, you can't use function calls like OS.get_executable_path().path_join("some_file.txt") in the project settings. and changing the log path in script doesn't work as project settings only load at the beginning once.

And by portable i meant self-contained, most programs come with a portable mode. including godot by the way. altho it involves putting a file named sc in the folder for some reason.

writing to the same directory as the executable should always work in linux and windows. I don't know about mac but I'm ok with it pointing to inside the bundle. I know nothing of other platforms but those would be the use cases. I already tried all the other solutions and none of them will work.

I only plan to release on Windows and Linux, altho Mac isn't out of question later on. I wouldn't mind setting up the Log Path manually in script if it was possible but the project settings don't stick once the script kicks in. They only load once at the beginning and can't be changed (most of them anyway). Plus I assume the logs would still go to the original location if the game crashed on startup which might be a problem at some point. Another thing that would work is relative paths like "User://../Logs" or something, with ".." in the middle of it. Then all i would need to do is override them for each platform im targetting.