How to run games on non-Administrator accounts
by Pavel Tovarys · in Torque Game Engine · 02/22/2008 (10:33 am) · 9 replies
Hello, I try to support non-Administrator accounts to run our games, because there are
a lot of users who cannot run games as Administrators on Macs. Is there any way how to
do it?
For example is any way how to export $prefs:: to directories ~/Library/Application Support/MyGame ?
Thank you,
Tovy..
a lot of users who cannot run games as Administrators on Macs. Is there any way how to
do it?
For example is any way how to export $prefs:: to directories ~/Library/Application Support/MyGame ?
Thank you,
Tovy..
#2
02/22/2008 (12:50 pm)
I didn't notice that this was posted in the Mac forum, sorry, or I wouldn't have discussed all the Windows specific changes past the change to ResManager::openFileForWrite to write them out elsewhere.
#3
I tried to modify ResManager::isValidWriteFileName and did changes in expandScriptFilename function.
It works in Windows - I can use path as f.e. C:\path.
But when I use ~ in Mac, it always starts from the game directory. The path is ok (I disabled changing ~/
in expandScriptFilename), but in case I try to open/create file for example ~/Library/Application Support/test it creates a directory ~/Library/... in the game directory.
Any idea?
02/22/2008 (4:36 pm)
Matthew: thanks for helpI tried to modify ResManager::isValidWriteFileName and did changes in expandScriptFilename function.
It works in Windows - I can use path as f.e. C:\path.
But when I use ~ in Mac, it always starts from the game directory. The path is ok (I disabled changing ~/
in expandScriptFilename), but in case I try to open/create file for example ~/Library/Application Support/test it creates a directory ~/Library/... in the game directory.
Any idea?
#4
This will work even on non-English systems, since the underlying unix file path for /Users/{username}/Library/ is always the same, it's just localized in the finder display.
It may be more robust to call the Mac API FSFindFolder() routine with kCurrentUserFolderType, but then you have to convert the FSRef into a path and append /Library. The conversion to a path is a pain and it doesn't seem worth it (you can find sample code to do this if you really want on the Apple developer site.)
Here's the docs on FSFindFolder
02/23/2008 (4:14 am)
The ~ to specify users home directory isn't widely supported by API calls. You have to build it yourself, by calling a function to get the user's name, and then assembling the path string:char* username = getlogin(); // declared in <unistd.h> sprintf(path, "/Users/$s/Library/", username);
This will work even on non-English systems, since the underlying unix file path for /Users/{username}/Library/ is always the same, it's just localized in the finder display.
It may be more robust to call the Mac API FSFindFolder() routine with kCurrentUserFolderType, but then you have to convert the FSRef into a path and append /Library. The conversion to a path is a pain and it doesn't seem worth it (you can find sample code to do this if you really want on the Apple developer site.)
Here's the docs on FSFindFolder
#5
Another thing to look into is porting over the TGB file i/o stuff into TGE. Sure it needs a bit of work, but it probably does most of what you need to do.
02/23/2008 (10:08 am)
Or you can just use Cocoa.NSString* path = [NSString stringWithUTF8String:"~/Library/"]; NSString* expandedPath = [path stringByExpandingTildeInPath] const char* file = [expandedPath UTF8String];
Another thing to look into is porting over the TGB file i/o stuff into TGE. Sure it needs a bit of work, but it probably does most of what you need to do.
#6
Anyone find a simple solution for this problem?
It's also relevant when you want to make a singleplayer game and you don't want your customers to lose previously saved datas while updating his game.
08/04/2008 (12:06 pm)
I'm fighting since two days on this one.Anyone find a simple solution for this problem?
It's also relevant when you want to make a singleplayer game and you don't want your customers to lose previously saved datas while updating his game.
#7
You cannot use "~/" for home directory of the player, so I changed it to "!/"
after #include
console.cc line 820 in expandScriptFilename after if (dStrlen(src) > size) {}
So you can use "!/" now as the player home directory. For example for our game Larva Mortus on Mac I use:
$save_directory = "!/Library/Application Support/Larva Mortus/saves/";
08/04/2008 (1:07 pm)
I solved it - it's a bit curious, but very simple and it works well ;)You cannot use "~/" for home directory of the player, so I changed it to "!/"
after #include
// Tovy #include <stdlib.h> // Tovy END
console.cc line 820 in expandScriptFilename after if (dStrlen(src) > size) {}
// Tovy
if (dStrncmp(src, "!/", 1) == 0)
{
const char * dir = getenv( "HOME" );
int len = dStrlen(dir);
dStrncpy(filename, dir, len);
dStrcpy(filename+len, src+1);
return true;
}
// Tovy ENDSo you can use "!/" now as the player home directory. For example for our game Larva Mortus on Mac I use:
$save_directory = "!/Library/Application Support/Larva Mortus/saves/";
#8
This code is likely to overflow. Changing that second dStrcpy to dStrncpy(filename+len, src+1, size - (len + 1)); would fix it, but it's still overflowable if len>size [eg, people with braindamaged $HOME environment variables]. My usual favorite way of dealing with this is snprintf:
Gary (-;
08/04/2008 (1:53 pm)
if (dStrncmp(src, "!/", 1) == 0)
{
const char * dir = getenv( "HOME" );
int len = dStrlen(dir);
dStrncpy(filename, dir, len);
dStrcpy(filename+len, src+1);
return true;
}This code is likely to overflow. Changing that second dStrcpy to dStrncpy(filename+len, src+1, size - (len + 1)); would fix it, but it's still overflowable if len>size [eg, people with braindamaged $HOME environment variables]. My usual favorite way of dealing with this is snprintf:
if (dStrncmp(src, "!/", 1) == 0)
{
const char * dir = getenv( "HOME" );
if(dStrlen(dir) + dStrlen(src+2) > size) return false;
dSprintf(filename, size, "%s/%s", dir, src+2);
return true;
}Gary (-;
#9
I just made the follwing change in addition to yours and it's working. :)
Edit: and thanks Gary for being everywhere we need you.
08/04/2008 (2:20 pm)
That was fast and simple! Thank you so much Pavel.I just made the follwing change in addition to yours and it's working. :)
bool ResManager::isValidWriteFileName (const char *fn)
{
// all files must be based off the VFS
if (( fn[0] == '/' && !dStrstr(fn, "/Library/Application Support/") ) || dStrchr (fn, ':')) //MF old: if (fn[0] == '/' || dStrchr (fn, ':'))
return false;Edit: and thanks Gary for being everywhere we need you.
Torque 3D Owner Matthew Jessick
TGE 1.5.2 needs a lot of rework to do this, unfortunately. Hopefully this is a core capability that will be in the stock version of Torque 2. (On Windows, these kind of guidelines have been around since Windows XP for Limited User Accounts (LUA).)
This is a big deal for me as I'm involved with children's games on Windows at the moment and a lot of users have limited user accounts set up for their children. It is a pain for the parent to have to do a "run as" every time the child wants to start the game. Vista/non-admin may actually work better currently for TGE when admin-installed into the "program files" heirarchy, I imagine, because of virtualization than WinXP/LUA does.
I am slowly working on:
1. redirecting all output to a specified location (on Windows, the CSIDL locations, e.g.: CSIDL_LOCAL_APPDATA which the user is guarenteed to have write priviledges for.)
This includes the console.log (if kept), and also prefs.cs type files, and also script compilation to dso files for these preference files, if desired. This requires a patch into the resource manager (ResManager::openFileForWrite) to redirect the outputs. I redirect all outputs when this system is on.
Additional patches that add these output directories into the paths for the engine to search for config and pref scripts if it can't find them in the install folder. ResManager::setModPaths adds another searchPath call for the new output folder heirarchy. (as mentioned below, I decided not to add the long absolute paths to the existing valid paths system.)
I short circuited ResManager::isValidWriteFileName to true for paths that appear to be my special paths because just adding the new paths to the valid paths system can result in overrunning the 1500 byte network packet size limit for the path data.
I had a hard time getting the prefs and configs to be read from the new paths.
I ended up adding a block into ResManager::find similar to the existing #ifndef TORQUE_SHIPPING functionality to search the new paths (only for prefs.cs, configs.cs, etc. - the normal config files.)
2. I just noticed that TGE creates a "sandbox" for script created files, but forces it to remain under the executable folder. This would have to be moved also.
3. I see that I effectively turn off this system for Windows versions earlier than WinXP.
4. whatever other problems I run into as I get more experience running this fairly deep change.
What is unfortunate about this is that I expect that TorqueX has some of this capability already, though perhaps it is implemented in such a way as to make it hard to retrofit back to TGE/TSEA, and not cross platform.
I still have problems during developing when all the normal scripts aren't compiled yet (so I usually turn the system off at this stage), and I have to hack in and turn the system off in my automated build routine to keep everything in the usual places while a "compile all" process runs during the build.