PDA

View Full Version : Saving a game in the user's home directory.



jasonf
09-10-2006, 03:44 PM
So, I want to save the players progress... I also want to save the player's config.

So I need a fairly cross platform approach to getting the user's home directory..

e.g. /home/jason/cbco/guns reloaded/save
or
c:\Documents and Settings\Jason\CBCO\Guns Reloaded\Save

How are you guys doing this at the moment?

dmantione
09-10-2006, 04:09 PM
It doesn't exist yet. I think this should give you good results:


function get_homedir:string;

begin
{$ifdef unix}
get_homedir:=getenv('HOME'); {All Unixes.}
{$else}
{$ifdef windows}
get_homedir:=getenv('HOMEPATH'); {Windows NT}
if get_homedir='' then
{$endif}
get_homedir:='c:\'; {Windows 9x, MSDOS, OS/2}
{$endif}
end;

WILL
09-10-2006, 04:30 PM
I'd simply use the relative approach. But first use IFDEFs to figure out what the local directory slashes where first.

So like Daniel's in a way, I'd instead do...

{$ifdef unix}
dir_slashes := '/';
{$else}
dir_slashes := '\';
{$endif}

So now to save it to your 'savegames' folder you'd simply run your...

SaveGame_Func(FileName + dir_slashes);


Of course I'd be hoping that the UNIX clause would cover all *BSD and Mac platforms aswell.

Oh and if you're going to make a GBA port aswell... you're gonna have to change your savegame algorithm anyhow. ;) But I'm sure it's doable to have it all in one codeset, just have to be creative with the IFDEFs.

jasonf
09-10-2006, 04:52 PM
The relative approach works fine as long as your Exe is being run from the game's DIR.. if the game is compiled for Linux, the exe might go into /usr/local/games/bin or something like that.. The regular user doesn't have rights to save in there.. so it needs to save in their home dir.

I've not written the save Algorithm yet, I wanted to make sure I could get a reasonably consistant approach to getting the Home DIR first..

..and now I've got something to be getting along with.

Cheers Guys 8)

WILL
09-10-2006, 05:00 PM
Ah... just got it...

"RTFQ" :P

I've been doing too much PHP coding. :o I'm due to crack open Lazarus again sometime real soon! :lol:

savage
09-10-2006, 08:26 PM
I believe the correct way under Windows is to use the API rather than the environment variable. I did have some code somewhere that did that, but I can't find it right now.

michalis
09-10-2006, 09:28 PM
FreePascal RTL has excellent functions for doing just that. See GetAppConfigDir, GetAppConfigFile and related things inside FPC docs: http://www.freepascal.org/docs-html/rtl/sysutils/getappconfigdir.html.

This is cross-platform, can be configured by callbacks, and by default uses the most appropriate way for each platform. Under Unix this follows http://freedesktop.org/Standards/basedir-spec, which means $XDG_CONFIG_HOME or $HOME/.config/, under Windows it uses proper WinAPI function (SHGetFolderPath if I remember right). In short, this is what you should use.

If you want to have a subdir there like ".../cbco/guns reloaded/save", then just take GetAppConfigDir and create a subdirectory there using a function like ForceDirectories.

Ah, and a constant similar to proposed dir_slashes is already available in PathDelim (that's under Delphi too), so you never should define something like this yourself.

And one last remark: the problem with user not having the permissions to write inside game's bin directory is the same under Windows. After all, Windows since a long time tries to be a multi-user system and has file/dir permissions working. Many poor Windows programs ignore this issue (making it impossible to install them system-wide and use from non-admin account), but that's another story.

jasonf
10-10-2006, 11:40 PM
And one last remark: the problem with user not having the permissions to write inside game's bin directory is the same under Windows. After all, Windows since a long time tries to be a multi-user system and has file/dir permissions working. Many poor Windows programs ignore this issue (making it impossible to install them system-wide and use from non-admin account), but that's another story.

This is exactly the reason why I want "The Best" way of saving to the users home directory.

I'm mostly concerned with Win32 at the moment though, I'm writing using Delphi Explorer. But I would like a Linux and MacOS version in the future.. no sense in alienating potential customers. But I'm focussing on Windows, developing and testing it as much as is possible.. then I'll compile on Linux test and fix.. followed by MacOS (I don't have access to a Mac at the moment though) This way I can focus on the task at hand and make the project as stable as possible, whilst keeping an eye on the changes I'll need for Linux and Mac.

savage
11-10-2006, 01:54 AM
This is roughly what is should be under Win32...


function DefaultSaveLocation: string;
var
P: PChar;
begin
P := nil;
try
P := AllocMem(MAX_PATH);
if SHGetFolderPath(0, CSIDL_PERSONAL, 0, 0, P) = S_OK then
Result := P
else
Result := GetCurrentDir;
finally
FreeMem(P);
end;
end;

savage
11-10-2006, 01:57 AM
Or Maybe...


function GetSpecialFolderPath(SpecialFolder : Integer) : String;
{
SpecialFolder is one of these:
CSIDL_BITBUCKET Recycle bin ¾ file system directory containing file
objects in the user's recycle bin. The location of this directory is not
in the registry; it is marked with the hidden and system attributes to
prevent the user from moving or deleting it.
CSIDL_CONTROLS Control Panel ¾ virtual folder containing icons for
the control panel applications.
CSIDL_DESKTOP Windows desktop ¾ virtual folder at the root of the name
space.
CSIDL_DESKTOPDIRECTORY File system directory used to physically
store file objects on the desktop (not to be confused with the desktop
folder itself).
CSIDL_DRIVES My Computer ¾ virtual folder containing everything on the
local computer: storage devices, printers, and Control Panel. The folder
may also contain mapped network drives.
CSIDL_FONTS Virtual folder containing fonts.
CSIDL_NETHOOD Directory containing objects that appear in the network
neighborhood.
CSIDL_NETWORK Network Neighborhood ¾ virtual folder representing the top
level of the network hierarchy.
CSIDL_PERSONAL Directory that serves as a common respository for
documents.
CSIDL_PRINTERS Printers folder ¾ virtual folder containing
installed printers.
CSIDL_PROGRAMS Directory that contains user's program groups (which
are also file system directories).
CSIDL_RECENT Directory that contains user's most recently used
documents.
CSIDL_SENDTO Directory that contains Send To menu items.
CSIDL_STARTMENU Directory containing Start menu items.
CSIDL_STARTUP Directory that corresponds to user's Startup program group.
CSIDL_TEMPLATES Directory that serves as a common repository for
document templates.
}
var
ThePidl: PItemIDList;
ThePath: array[0..MAX_PATH] of Char;
begin
SHGetSpecialFolderLocation(0, SpecialFolder, ThePidl);
SHGetPathFromIDList(ThePidl, ThePath);
Result := ThePath;
end;