HomeWildfire Games

Write mod data correctly. Fixes #1940.
Concern RaisedrP13472


Write mod data correctly. Fixes #1940.


leperJun 11 2013, 10:50 PM
rP13471: Updated some building tooltips.

Event Timeline

elexis raised a concern with this commit.Apr 3 2019, 7:01 AM
elexis added a subscriber: elexis.
  1. The comment is wrong https://wildfiregames.com/forum/index.php?/topic/25579-cannot-play-custom-maps-please-help/&do=findComment&comment=371878
  1. We may want to reconsider whether the feature design is ideal. From https://trac.wildfiregames.com/ticket/1940#comment:3

I don't really like the inconsistency in the dev and non-dev cases, in terms of mounting the read-only and user-writable mods

This surprise has resulted in problems before, for example for mod-version checks that have to hardcode a "user" exclusion.

  1. The special "user" mod behavior is not documented anywhere other than being buried in the middle of a C++ code file.
  1. One may reconsider whether it is actually necessary to write to a "user/" mod folder instead of a "public/" folder, i.e. whether adding a "user" mod was necessary to begin with and not adding a solution for the right problem in the wrong level of the code.


This commit now has outstanding concerns.Apr 3 2019, 7:01 AM
lyv added a subscriber: lyv.Apr 7 2019, 5:51 PM
lyv added inline comments.

How is the comment wrong?

lyv added inline comments.Apr 7 2019, 6:14 PM

Oh..that one specific word. Yes, it is incorrect. Incorrect like a typo in my opinion. If you are only reading the comment and not the code relating to it, you are doing something wrong.
The purpose of the dev check is to have maps saved in a dev copy to end up in the source. So, what is the point of having a "noUserMod" option in a dev copy.

elexis added inline comments.Apr 7 2019, 8:05 PM

If you are only reading the comment and not the code relating to it, you are doing something wrong.

It's precisely because I read the code relating to it that I noticed the comment to be slightly incorrect and lacking explanation as to why the code is doing what it does. The purpose of comments is to (1) summarize the code behavior and (2) state the reasons behind the code behavior.

Oh..that one specific word. Yes, it is incorrect. Incorrect like a typo in my opinion.

The first of these four points typo-grade indeed.
I had hoped that the forum posts communicated some of my thoughts, I don't mind clarifying or repeating if it helps resolve the case.

The purpose of the dev check is to have maps saved in a dev copy to end up in the source.

That is what the code does, but not a reason as to why it should do that.

From the two trac tickets, it seems this was only done to address one single error stack:


  1. Open map
  2. Edit map
  3. Save map
  4. Close map
  5. Open map

Expected Result:

  1. Notice previous edits

Actual Result:

  1. Previous edits absent because Atlas loads from the wrong path

So that was the historic stack trace that needed to be fixed and _not_ any further design decision, at least not printed anywhere, not in the code, not in the two tickets. The only thing we find in the ticket is someone claiming that he thinks that precisely the different behavior for release-code and dev code is more bothersome than desirable and is recommended for revision.

There are a number of solutions, they should all be evaluated without prejudice before rushing one solution, or we should at least be able to later reevaluate instead of claiming a temporary fix to be the obvious best solution.

I mentioned the alternative on the forums already: .local/share/0ad/mods/public/ instead of .local/share/0ad/mods/user/,
where public is the topmost mod that launched the file into the VFS, or the topmost mod if the file does not exist.

The solution would have the following advantages over the existing:

  • fixing the Atlas and equivalent problems equally
  • not inserting an alternative C++ code path to launch a mod
  • not defining Mod and VFS logic in GameSetup.cpp to fix the case
  • not removing the workaround by adding more workarounds elsewhere to account for the first workaround (not having to spread and keep in sync N mod version checks across the JS and C++ codebase)
  • not adding a mod that is not defined by mod.json (consistency)
  • not adding a mod (least complexity)
  • not missing documentation on a magic modname in the Mod C++ classes.
  • if done right, not missing documentation in the VFS C++ classes on behavior of writing files.
  • not missing documentation on a magic modname in the wiki modding pages
  • keeping all content relating to one mod in the same write-folder of that mod (consistency)
  • having the program only refer to mods that were defined by mod folders (simplicity)
  • making the release code not behave differently from development code (consistency)
  • if not refuted, it would implement the concerns of the reviewer and auditor.
  • might cost more bananas to implement the code though.
lyv added inline comments.Apr 7 2019, 8:12 PM

(To clarify: “you” was meant in a collective context. Not specific to anyone.)
Apart from that, I really don’t have much to say.

This also relates to D2781, where I noticed that we apparently didn't understand our own code.

If I try to summarise the issue:

  • we mount the user mod in non-dev copies, to have a writable-for-sure folder to store Atlas stuff.
  • it's not needed in dev copies, so we don't mount it.

I assume we can't name the mod public, because it would overwrite possibly the actual public mod, though that should be checked.
Having a specific path for user-content actually seems somewhat sensible. Not loading it in dev... not brilliant imo, but dev copies should definitely not _write_ there.
I think at the time of #1940 we only loaded public and not mod as well, which is special in its own regard. So the hardcoding would now be for two folders.

Where it gets really funky is that if one loads a mod and saves a custom map, it will probably end up in the user mod anyways. When it should go in the "user-content" part of the mod itself, I suppose.

Truthfully not a very easy fix. IMO the atlas custom maps should simply be stored in a non-mod different folder in the user directory (after all, we have folders for screenshots and such). I don't believe we have a lot of other custom "writing" content. We could load the user mod always, and explicitly change the "write" directory in dev-mode, but that is arguably not fixing the issues with mod support. Indeed, "user" should not contain stuff that can change the simulation... So imo not making it a mod is best.

This plays into sharing custom content over MP, such as a host wanting to play a custom map. But maybe we could then create a mod file and temporarily load it, or just have two paths for that. Seems neater anyhow.

The "dev-copy" story should probably be renamed to a more explicit name.

wraitii raised a concern with this commit.EditedDec 12 2020, 5:36 PM

I fear this is quite broken.

First, there is a subtle, but pernicious behaviour change here.
rP13167 made it possible to have mods in the user data path, which has ever since been the 'real' location of mods, with the binaries/bundle folder being for 'dev' and 'official' stuff only. However, the original diff didn't have the user special mod that's introduced here. This actually makes the game duplicate all loaded "official" mods to the user's data path, but they're not used, since in dev-copies we write to binaries, and otherwise we write to the user mod.

I think this was mostly because the first version of the diff didn't have the user special folder. This comment mentions that, but it doesn't make _much_ sense to have the same mod in two places. User mods would need to be loaded, indeed. To the VFS, it's the same thing anyways so it's not like we can even differentiate the two. So we end up with an empty mod and public folder.

That particular duplication of folder should be reverted to avoid confusing users.

The presence of the user mod itself... Is hardcoded, but has a purpose. It's writable, it's for user data, and given that we might have several mods, I don't find obviously better writing to the current-highest-priority-mod, which might even be zipped. I would say elexis' suggested approach above is thus not better.

IMO, what we should do is have a "usermaps" folder inside the user data path, and store maps there in non-dev copies.

VFS_MOUNT_REPLACEABLE is a weird concept. Directories marked "replaceable" will be overwritten in "create_always" mode, so that subdirectories of the root path point where expected on disk.
The real trouble is that "CreateFile" for the VFS can do something... Extremely arbitrary. The real directory of a sub-path can be anywhere. When reading files, that's fine, but when writing it's really odd and unexpected.
Indeed, mods can hijack paths. The problem is that mods mount at "", which is also the root path for everything else, so a mod containing a "cache" folder will shadow the real cache folder. This is what I tried to fix in D2781, but I think I can't efficiently account for subfolders. Itms noted this for the user config (see #2553).

IMO, it would be better if CreateFile just looked at the real directory of the first path's component, and then simply wrote wherever the absolute path of that (+ concat the rest) point. It's essentially the same thing, but not as confusing. The VFS would have explicitly different lookup rules for reading and writing, but at least it's predictable, and resists 'hijacking' of paths in weird ways.

It would probably not be a bad idea to namespace mods to some subfolder instead of just mounting them at root, too.

See rP15677 for the story of the user mod and A23's release lag.

wraitii resigned from this commit.Jul 6 2022, 9:17 AM