Write mod data correctly. Fixes #1940.

This was SVN commit r13472.
This commit is contained in:
leper 2013-06-11 20:50:09 +00:00
parent 15e75cdfbd
commit 2567fee329
8 changed files with 83 additions and 20 deletions

View File

@ -0,0 +1,11 @@
;
; Developer configuration file
;
; NOTE: This is not read by the config system currently.
;
; This file is used by the engine to decide which mods are mounted, and in what
; order. The precense of this file suppresses loading of mods in the user mod
; path (see http://trac.wildfiregames.com/wiki/GameDataPaths) if the same mod is
; present in binaries/data/mods. It also implies -noUserMod.
; This is done to make saved maps end up in the right mod folder (and in the
; game-relative data path) to commit them later on.

View File

@ -158,9 +158,13 @@ cp -v ../../binaries/system/libCollada.dylib ${BUNDLE_FRAMEWORKS}
# Copy data
echo "\nCopying non-archived game data\n"
# Removing it now and restoring it later, cp has no exclusion switch
# and using find is a bit over-the-top
rm ../../binaries/data/config/dev.cfg
cp -v ../resources/0ad.icns ${BUNDLE_RESOURCES}
cp -R -v ../../binaries/data/config ${BUNDLE_RESOURCES}/data/
cp -R -v ../../binaries/data/tools ${BUNDLE_RESOURCES}/data/
svn revert ../../binaries/data/config/dev.cfg
# Copy license/readmes
# TODO: Also want copies in the DMG - decide on layout

View File

@ -132,7 +132,7 @@ public:
{
ScopedLock s;
VfsDirectory* directory;
WARN_RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0, VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE));
WARN_RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0, VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE|VFS_LOOKUP_CREATE_ALWAYS));
const PRealDirectory& realDirectory = directory->AssociatedDirectory();
const OsPath name = pathname.Filename();

View File

@ -65,7 +65,16 @@ enum VfsMountFlags
* ".DELETED" suffix will still apply.
* (the default behavior is to hide both the suffixed and unsuffixed files)
**/
VFS_MOUNT_KEEP_DELETED = 8
VFS_MOUNT_KEEP_DELETED = 8,
/**
* mark a directory replaceable, so that when writing a file to this path
* new real directories will be created instead of reusing already existing
* ones mounted at a subpath of the VFS path.
* (the default behaviour is to write to the real directory associated
* with the VFS directory that was last mounted to this path (or subpath))
**/
VFS_MOUNT_REPLACEABLE = 16
};
// (member functions are thread-safe after the instance has been

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2010 Wildfire Games
/* Copyright (c) 2013 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -74,7 +74,8 @@ Status vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDire
const bool addMissingDirectories = (flags & VFS_LOOKUP_ADD) != 0;
const bool createMissingDirectories = (flags & VFS_LOOKUP_CREATE) != 0;
const bool skipPopulate = (flags & VFS_LOOKUP_SKIP_POPULATE) != 0;
ENSURE((flags & ~(VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE|VFS_LOOKUP_SKIP_POPULATE)) == 0);
const bool createAlways = (flags & VFS_LOOKUP_CREATE_ALWAYS) != 0;
ENSURE((flags & ~(VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE|VFS_LOOKUP_SKIP_POPULATE|VFS_LOOKUP_CREATE_ALWAYS)) == 0);
directory = startDirectory;
if(pfile)
@ -111,7 +112,8 @@ Status vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDire
return ERR::VFS_DIR_NOT_FOUND; // NOWARN
}
if(createMissingDirectories && !subdirectory->AssociatedDirectory())
if(createMissingDirectories && (!subdirectory->AssociatedDirectory()
|| (createAlways && (subdirectory->AssociatedDirectory()->Flags() & VFS_MOUNT_REPLACEABLE) != 0)))
{
OsPath currentPath;
if(directory->AssociatedDirectory()) // (is NULL when mounting into root)

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2010 Wildfire Games
/* Copyright (c) 2013 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -49,7 +49,12 @@ enum VfsLookupFlags
// don't populate the directories encountered. this makes sense
// when adding files from an archive, which would otherwise
// cause nearly every directory to be populated.
VFS_LOOKUP_SKIP_POPULATE = 4
VFS_LOOKUP_SKIP_POPULATE = 4,
// even create directories if they are already present, this is
// useful to write new files to the directory that was attached
// last, if the directory wasn't mounted with VFS_MOUNT_REPLACEABLE
VFS_LOOKUP_CREATE_ALWAYS = 8
};
/**

View File

@ -421,6 +421,20 @@ ErrorReactionInternal psDisplayError(const wchar_t* UNUSED(text), size_t UNUSED(
return ERI_NOT_IMPLEMENTED;
}
static std::vector<CStr> GetMods(const CmdLineArgs& args, bool dev)
{
std::vector<CStr> mods = args.GetMultiple("mod");
// TODO: It would be nice to remove this hard-coding
mods.insert(mods.begin(), "public");
// Add the user mod if not explicitly disabled or we have a dev copy so
// that saved files end up in version control and not in the user mod.
if (!dev && !args.Has("noUserMod"))
mods.push_back("user");
return mods;
}
static void InitVfs(const CmdLineArgs& args)
{
TIMER(L"InitVfs");
@ -441,28 +455,44 @@ static void InitVfs(const CmdLineArgs& args)
const size_t cacheSize = ChooseCacheSize();
g_VFS = CreateVfs(cacheSize);
// Work out whether we are a dev version to make sure saved files
// (maps, etc) end up in version control.
const OsPath readonlyConfig = paths.RData()/"config"/"";
g_VFS->Mount(L"config/", readonlyConfig);
bool dev = (g_VFS->GetFileInfo(L"config/dev.cfg", NULL) == INFO::OK);
std::vector<CStr> mods = args.GetMultiple("mod");
mods.insert(mods.begin(), "public");
if (!args.Has("noUserMod"))
mods.push_back("user");
const std::vector<CStr> mods = GetMods(args, dev);
OsPath modPath = paths.RData()/"mods";
OsPath modUserPath = paths.UserData()/"mods";
for (size_t i = 0; i < mods.size(); ++i)
{
size_t priority = i+1; // mods are higher priority than regular mountings, which default to priority 0
size_t flags = VFS_MOUNT_WATCH|VFS_MOUNT_ARCHIVABLE|VFS_MOUNT_MUST_EXIST;
size_t priority = (i+1)*2; // mods are higher priority than regular mountings, which default to priority 0
size_t userFlags = VFS_MOUNT_WATCH|VFS_MOUNT_ARCHIVABLE|VFS_MOUNT_REPLACEABLE;
size_t flags = userFlags|VFS_MOUNT_MUST_EXIST;
OsPath modName(mods[i]);
g_VFS->Mount(L"", modPath / modName/"", flags, priority);
g_VFS->Mount(L"", modUserPath / modName/"", flags, priority);
if (dev)
{
// We are running a dev copy, so only mount mods in the user mod path
// if the mod does not exist in the data path.
if (DirectoryExists(modPath / modName/""))
g_VFS->Mount(L"", modPath / modName/"", flags, priority);
else
g_VFS->Mount(L"", modUserPath / modName/"", userFlags, priority);
}
else
{
g_VFS->Mount(L"", modPath / modName/"", flags, priority);
// Ensure that user modified files are loaded, if they are present
g_VFS->Mount(L"", modUserPath / modName/"", userFlags, priority+1);
}
}
// We mount these dirs last as otherwise writing could result in files being placed in a mod's dir.
g_VFS->Mount(L"screenshots/", paths.UserData()/"screenshots"/"");
g_VFS->Mount(L"saves/", paths.UserData()/"saves"/"", VFS_MOUNT_WATCH);
const OsPath readonlyConfig = paths.RData()/"config"/"";
// Mounting with highest priority, so that a mod supplied user.cfg is harmless
g_VFS->Mount(L"config/", readonlyConfig, 0, (size_t)-1);
if(readonlyConfig != paths.Config())
@ -889,13 +919,13 @@ void Init(const CmdLineArgs& args, int UNUSED(flags))
// g_ConfigDB, command line args, globals
CONFIG_Init(args);
// before scripting
if (g_JSDebuggerEnabled)
g_DebuggingServer = new CDebuggingServer();
InitScripting(); // before GUI
g_ConfigDB.RegisterJSConfigDB(); // after scripting
// Optionally start profiler HTTP output automatically

View File

@ -39,7 +39,9 @@ tar cf $PREFIX-unix-build.tar \
--exclude='libraries/source/fcollada/src/FCollada/FColladaTest' \
--exclude='libraries/source/spidermonkey/include-win32' \
${PREFIX}/{source,build,libraries/source,binaries/system/readme.txt,binaries/data/tests,binaries/data/mods/_test.*,*.txt}
tar cf $PREFIX-unix-data.tar ${PREFIX}/binaries/data/{config,mods/public/public.zip,tools}
tar cf $PREFIX-unix-data.tar \
--exclude='binaries/data/config/dev.cfg' \
${PREFIX}/binaries/data/{config,mods/public/public.zip,tools}
# TODO: ought to include generated docs in here, perhaps?
# Compress