Permalink
Browse files

Fix mod priority. Add user mod support. Fixes #1838.

git-svn-id: http://svn.wildfiregames.com/public/ps/trunk@13167 3db68df2-c116-0410-a063-a993310a9797
  • Loading branch information...
1 parent 49b31ee commit 824463f78039f66bd72ad5e247f07a76cc020ab4 leper committed Feb 14, 2013
View
3 binaries/system/readme.txt
@@ -22,10 +22,11 @@ Random maps only:
-autostart-players=NUMBER NUMBER of players on random map
Configuration:
--conf:KEY=VALUE set a config value (overrides the contents of system.cfg)
+-conf=KEY:VALUE set a config value
-g=F set the gamma correction to 'F' (default 1.0)
-nosound disable audio
-onlyPublicFiles force game to use only the public (default) mod
+-noUserMod disable loading of the user mod
-shadows enable shadows
-vsync enable VSync, i.e. lock FPS to monitor refresh rate
-xres=N set screen X resolution to 'N'
View
65 source/lib/file/vfs/tests/test_vfs_tree.h
@@ -0,0 +1,65 @@
+/* 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
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "lib/self_test.h"
+
+#include "lib/file/vfs/vfs_tree.h"
+#include "lib/file/common/file_loader.h"
+
+class MockLoader : public IFileLoader
+{
+private:
+ size_t m_Precedence;
+public:
+ MockLoader(size_t precedence) :
+ m_Precedence(precedence)
+ {
+ }
+
+ size_t Precedence() const { return m_Precedence; }
+ wchar_t LocationCode() const { return L'\0'; }
+ OsPath Path() const { return L"";}
+ Status Load(const OsPath& UNUSED(name), const shared_ptr<u8>& UNUSED(buf), size_t UNUSED(size)) const {return INFO::OK; }
+};
+
+class TestVfsTree : public CxxTest::TestSuite
+{
+public:
+ void test_replacement()
+ {
+ VfsDirectory dir;
+ PIFileLoader loader(new MockLoader(1));
+
+ VfsFile file0("a", 0, 0, 0, loader);
+ VfsFile file1("a", 0, 20, 0, loader);
+ VfsFile file2("a", 0, 10, 1, loader);
+
+ // Modification time
+ TS_ASSERT_EQUALS(dir.AddFile(file0)->MTime(), file0.MTime());
+ TS_ASSERT_EQUALS(dir.AddFile(file1)->MTime(), file1.MTime());
+ TS_ASSERT_EQUALS(dir.AddFile(file0)->MTime(), file1.MTime());
+
+ // Priority
+ TS_ASSERT_EQUALS(dir.AddFile(file2)->MTime(), file2.MTime());
+ TS_ASSERT_EQUALS(dir.AddFile(file1)->MTime(), file2.MTime());
+ }
+};
View
33 source/lib/file/vfs/vfs.cpp
@@ -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
@@ -46,7 +46,7 @@ static pthread_mutex_t vfs_mutex = PTHREAD_MUTEX_INITIALIZER;
struct ScopedLock
{
ScopedLock() { pthread_mutex_lock(&vfs_mutex); }
- ~ScopedLock() { pthread_mutex_unlock(&vfs_mutex); }
+ ~ScopedLock() { pthread_mutex_unlock(&vfs_mutex); }
};
class VFS : public IVFS
@@ -149,6 +149,35 @@ class VFS : public IVFS
return INFO::OK;
}
+ virtual Status ReplaceFile(const VfsPath& pathname, const shared_ptr<u8>& fileContents, size_t size)
+ {
+ ScopedLock s;
+ VfsDirectory* directory;
+ VfsFile* file;
+ Status st;
+ st = vfs_Lookup(pathname, &m_rootDirectory, directory, &file, VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE);
+
+ // There is no such file, create it.
+ if (st == ERR::VFS_FILE_NOT_FOUND)
+ {
+ s.~ScopedLock();
+ return CreateFile(pathname, fileContents, size);
+ }
+ else
+ WARN_RETURN_STATUS_IF_ERR(st);
+
+ RealDirectory realDirectory(file->Loader()->Path(), file->Priority(), directory->AssociatedDirectory()->Flags());
+ RETURN_STATUS_IF_ERR(realDirectory.Store(pathname.Filename(), fileContents, size));
+
+ // See comment in CreateFile
+ m_fileCache.Remove(pathname);
+
+ directory->AddFile(*file);
+
+ m_trace->NotifyStore(pathname, size);
+ return INFO::OK;
+ }
+
virtual Status LoadFile(const VfsPath& pathname, shared_ptr<u8>& fileContents, size_t& size)
{
ScopedLock s;
View
13 source/lib/file/vfs/vfs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 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
@@ -138,6 +138,17 @@ struct IVFS
virtual Status CreateFile(const VfsPath& pathname, const shared_ptr<u8>& fileContents, size_t size) = 0;
/**
+ * Replace a file with the given contents.
+ *
+ * @see CreateFile
+ *
+ * Used to replace a file if it is already present (even if the file is not
+ * in the attached vfs directory). Calls CreateFile if the file doesn't yet
+ * exist.
+ **/
+ virtual Status ReplaceFile(const VfsPath& pathname, const shared_ptr<u8>& fileContents, size_t size) = 0;
+
+ /**
* Read an entire file into memory.
*
* @param pathname
View
4 source/lib/file/vfs/vfs_tree.cpp
@@ -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
@@ -55,6 +55,8 @@ static bool ShouldReplaceWith(const VfsFile& previousFile, const VfsFile& newFil
// 1) priority (override mods)
if(newFile.Priority() < previousFile.Priority())
return false;
+ if(newFile.Priority() > previousFile.Priority())
+ return true;
// 2) timestamp
{
View
1 source/main.cpp
@@ -460,6 +460,7 @@ static void RunGameOrAtlas(int argc, const char* argv[])
// run non-visual simulation replay if requested
if (args.Has("replay"))
{
+ // TODO: Support mods
Paths paths(args);
g_VFS = CreateVfs(20 * MiB);
g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE);
View
30 source/ps/GameSetup/GameSetup.cpp
@@ -448,30 +448,38 @@ static void InitVfs(const CmdLineArgs& args)
const size_t cacheSize = ChooseCacheSize();
g_VFS = CreateVfs(cacheSize);
- 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"/"";
- g_VFS->Mount(L"config/", readonlyConfig);
- if(readonlyConfig != paths.Config())
- g_VFS->Mount(L"config/", paths.Config());
- g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE); // (adding XMBs to archive speeds up subsequent reads)
-
std::vector<CStr> mods = args.GetMultiple("mod");
- mods.push_back("public");
- if(!args.Has("onlyPublicFiles"))
- mods.push_back("internal");
+ if (!args.Has("onlyPublicFiles"))
+ mods.insert(mods.begin(), "internal");
+ mods.insert(mods.begin(), "public");
+
+ if (!args.Has("noUserMod"))
+ mods.push_back("user");
OsPath modArchivePath = paths.Cache()/"mods";
OsPath modLoosePath = 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;
OsPath modName(mods[i]);
g_VFS->Mount(L"", modLoosePath / modName/"", flags, priority);
g_VFS->Mount(L"", modArchivePath / modName/"", flags, priority);
+ g_VFS->Mount(L"", modUserPath / modName/"", flags, priority);
}
+ // 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, -1);
+ if(readonlyConfig != paths.Config())
+ g_VFS->Mount(L"config/", paths.Config(), 0, -1);
+
+ g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE); // (adding XMBs to archive speeds up subsequent reads)
+
// note: don't bother with g_VFS->TextRepresentation - directories
// haven't yet been populated and are empty.
}

0 comments on commit 824463f

Please sign in to comment.