XDG-compliant

XDG-compliant

Postby Edward_Lii » 21 Feb 2012, 16:18

Hello all,

I just read FreeGamer - Game Developers: Standardize Custom User Files Path on Mac OS X and Linux Now!
At first I thought this could easily be done by changing the datapath on *nix based systems to $HOME/.config/meandmyshadow/
But this isn't going to work, if we want to be 100% XDG-compliant we should place the levels and levelpacks in $HOME/.local/share/meandmyshadow.
(And the downloaded addon list in $HOME/.cache/meandmyshadow)

So should we change it?
It would requires us to make two userPath for *nix based systems and choosing the right one when saving certain stuff. :think:
From,
Edward_Lii
User avatar
Edward_Lii
MnMS Moderator
 
Posts: 777
Joined: 20 Dec 2010, 16:46

Re: XDG-compliant

Postby Knitter » 21 Feb 2012, 16:29

Since I'm a OS X user I would say: yes please :)

But as a developer I understand that we need to reach a compromise between what we want to have and what we can have, so, how easy/hard would it be to change considering the current goals (is a new release to come anytime soon?) and manpower?
Knitter
 
Posts: 237
Joined: 03 Jul 2011, 22:52
Location: Portugal

Re: XDG-compliant

Postby Edward_Lii » 21 Feb 2012, 16:39

Hello Knitter,

Knitter {l Wrote}:But as a developer I understand that we need to reach a compromise between what we want to have and what we can have, so, how easy/hard would it be to change considering the current goals (is a new release to come anytime soon?) and manpower?

I think I'll give it a shot, my idea is to change the getUserPath() function to accept a boolean as parameter.
When running Windows it will ignore it, just return the userpath.
But on the other platforms it will return the config path (bool=true) or the data path (bool=false).

EDIT: Forgot that to be 100% compliant meandmyshadow should first look at $XDG_CONFIG_HOME and $XDG_DATA_HOME
And if it's empty use the $HOME+./config/meandmyshadow, etc...
From,
Edward_Lii
User avatar
Edward_Lii
MnMS Moderator
 
Posts: 777
Joined: 20 Dec 2010, 16:46

Re: XDG-compliant

Postby Edward_Lii » 21 Feb 2012, 19:05

Hello all,

It should be done now. (svn rev. 274)
Note that you have to move your files by hand (no automatic updating).

Quick overview:
    .config/meandmyshadow:
    - Config file (meandmyshadow.cfg)
    - Installed addons.

    .local/share/meandmyshadow
    - Addon levels/levelpacks/themes
    - Custom levels/levelpacks
    - Progress
    - Recordings

    .cache/meandmyshadow
    - Zip files for levelpack/themes addons
    - Downloaded addons list.

Please test it and report back if you encounter any bugs. :)
From,
Edward_Lii
User avatar
Edward_Lii
MnMS Moderator
 
Posts: 777
Joined: 20 Dec 2010, 16:46

Re: XDG-compliant

Postby MCMic » 23 Feb 2012, 15:32

Would you be able to do a clean C++ class file that could be used by all projects that intend to store data in user folder?
It would need to be multi-platform and have the name of the application in only one place.

I would use it for Genetic Invasion for sure.
User avatar
MCMic
 
Posts: 723
Joined: 05 Jan 2010, 17:40

Re: XDG-compliant

Postby Edward_Lii » 23 Feb 2012, 18:09

Hello MCMic,

MCMic {l Wrote}:Would you be able to do a clean C++ class file that could be used by all projects that intend to store data in user folder?
It would need to be multi-platform and have the name of the application in only one place.

I would use it for Genetic Invasion for sure.

Not sure it is really that special, I'll just post some code snippets of how meandmyshadow does it.

First of all the three different paths (under Linux):
//Under Windows there's just one userpath.
#ifdef WIN32
string userPath;
#else
//But on other platforms we make a difference between the userPath (config files) and the userDataPath (data files).
//Finally there's the path for cache data userCachePath.
string userPath,userDataPath,userCachePath;
#endif


Now we set the userpaths according to the XDG Base Directory specification.
In your case just replace meandmyshadow with a string that you set before calling this method.
...
        //TODO: Check if the userpath is empty before setting userPath???
        //Check if the userPath is empty.
        if(getUserPath().empty()){
#ifdef WIN32
                //Get the userPath.
                char s[1024];
                SHGetSpecialFolderPathA(NULL,s,CSIDL_PERSONAL,1);
                userPath=s;
                userPath+="\\My Games\\meandmyshadow\\";                
#else
                //Temp variable that is used to prevent NULL assignement.
                char* env;
                
                //First get the $XDG_CONFIG_HOME env var.
                env=getenv("XDG_CONFIG_HOME");
                //If it's null set userPath to $HOME/.config/.
                if(env!=NULL){
                        userPath=env;
                }else{
                        userPath=getenv("HOME");
                        userPath+="/.config";
                }
                //And add meandmyshadow to it.
                userPath+="/meandmyshadow/";
                
                //Now get the $XDG_DATA_HOME env var.
                env=getenv("XDG_DATA_HOME");
                //If it's null set userDataPath to $HOME/.local/share.
                if(env!=NULL){
                        userDataPath=env;
                }else{
                        userDataPath=getenv("HOME");
                        userDataPath+="/.local/share";
                }
                //And add meandmyshadow to it.
                userDataPath+="/meandmyshadow/";
                
                //Now get the $XDG_CACHE_HOME env var.
                env=getenv("XDG_CACHE_HOME");
                //If it's null set userCachePath to $HOME/.cache.
                if(env!=NULL){
                        userCachePath=env;
                }else{
                        userCachePath=getenv("HOME");
                        userCachePath+="/.cache";
                }
                //And add meandmyshadow to it.
                userCachePath+="/meandmyshadow/";
                
                //Set env null.
                env=NULL;
#endif
                
                //Print the userPath.
                cout<<"User preferences will be fetched from: "<<userPath<<endl;
#ifndef WIN32
                //In case of a non-Windows computer show the user data path.
                cout<<"User data will be fetched from: "<<userDataPath<<endl;
#endif
        }
...

Now meandmyshadow will create the directories to make sure they exist before writing in them.
This isn't really relevant, just make sure it exists.

Here's the code for retrieving the userPath:
The advantage of a method is that you can give what type of userPath you want without making a difference between different OSes.
...
//Enum containing the different userPath types.
//NOTE: They are only needed for the non-Windows platform..
enum UserPaths{
         //The userpath containing the config files.
         //Default $HOME/.config/meandmyshadow/
         USER_CONFIG,
         //The userpath containing the user data.
         //Default $HOME/.local/share/meandmyshadow/
         USER_DATA,
         //The userpath containing the temporary files.
         //Default $HOME/.cache/meandmyshadow/
         USER_CACHE
};

...

//Method for retrieving the userPath.
//type: The type of userpath to return, only used on non-Windows platforms.
//Returns: The userPath.
inline const std::string& getUserPath(int type=0){
#ifdef WIN32
         return userPath;
#else
         switch(type){
                  case USER_CONFIG:
                           return userPath;
                           break;
                  case USER_DATA:
                           return userDataPath;
                           break;
                  case USER_CACHE:
                           return userCachePath;
                           break;
                  default:
                           std::cerr<<"WARNING: Illegal userpath type, returning user config path."<<std::endl;
                           return userPath;
                           break;
         }
#endif
}

...

Just realized that it isn't 100% XDG-compliant because it doesn't check the $XDG_DATA_DIRS and $XDG_CONFIG_DIRS environment variables.
But IMHO this isn't such a big problem. :)

Note that this code is only tested only works for Windows and Linux.
Other OSes will probably work, but haven't been tested.

As you can see it isn't that hard to implement, if you've got any questions feel free to ask. ;)
From,
Edward_Lii
User avatar
Edward_Lii
MnMS Moderator
 
Posts: 777
Joined: 20 Dec 2010, 16:46

Re: XDG-compliant

Postby MCMic » 23 Feb 2012, 18:22

I know it's not that hard, I just felt like having a common class is the right thing to do. (and that way be sure to eradicate problems like bad handling of empty env variable and so on)
User avatar
MCMic
 
Posts: 723
Joined: 05 Jan 2010, 17:40

Re: XDG-compliant

Postby Edward_Lii » 24 Feb 2012, 14:51

Hello MCMic,

MCMic {l Wrote}:I know it's not that hard, I just felt like having a common class is the right thing to do. (and that way be sure to eradicate problems like bad handling of empty env variable and so on)

I understand what you mean, but I think it won't really work.
IMHO it isn't enough to fill a complete class file, especially for smaller projects with not that much source files.

And besides the current code isn't tested on other platforms than Windows and Linux.

But since it's an open-source project anyone you needs it or wants to know how to implement it can easily copy/look at the source.
Borrowing and learning from other projects is one of the key parts of free open-source software. ;)
From,
Edward_Lii
User avatar
Edward_Lii
MnMS Moderator
 
Posts: 777
Joined: 20 Dec 2010, 16:46

Who is online

Users browsing this forum: No registered users and 1 guest

cron