about summary refs log tree commit diff
path: root/src/engine/shared/storage.cpp
diff options
context:
space:
mode:
authoroy <Tom_Adams@web.de>2010-10-06 23:07:35 +0200
committeroy <Tom_Adams@web.de>2010-10-06 23:07:35 +0200
commit3a98f7a048c044ce0d870320fc0b1def0db4f7fb (patch)
tree7dfa1826e537355b37d00e77558ca623a915bac2 /src/engine/shared/storage.cpp
parenta62a7413d1ff25c8e07657b96a485f001004619a (diff)
downloadzcatch-3a98f7a048c044ce0d870320fc0b1def0db4f7fb.tar.gz
zcatch-3a98f7a048c044ce0d870320fc0b1def0db4f7fb.zip
added mod system. Closes #34
Diffstat (limited to 'src/engine/shared/storage.cpp')
-rw-r--r--src/engine/shared/storage.cpp290
1 files changed, 187 insertions, 103 deletions
diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp
index 8785a5bf..cfe64e4b 100644
--- a/src/engine/shared/storage.cpp
+++ b/src/engine/shared/storage.cpp
@@ -3,6 +3,7 @@
 #include <base/system.h>
 #include <engine/storage.h>
 #include "engine.h"
+#include "linereader.h"
 
 // compiled-in data-dir path
 #define DATA_DIR "data"
@@ -10,36 +11,29 @@
 class CStorage : public IStorage
 {
 public:
-	char m_aApplicationSavePath[512];
-	char m_aDatadir[512];
+	enum
+	{
+		MAX_PATHS = 16,
+		MAX_PATH_LENGTH = 512
+	};
+
+	char m_aaStoragePaths[MAX_PATHS][MAX_PATH_LENGTH];
+	int m_NumPaths;
+	char m_aDatadir[MAX_PATH_LENGTH];
+	char m_aUserdir[MAX_PATH_LENGTH];
 	
 	CStorage()
 	{
-		m_aApplicationSavePath[0] = 0;
+		mem_zero(m_aaStoragePaths, sizeof(m_aaStoragePaths));
+		m_NumPaths = 0;
 		m_aDatadir[0] = 0;
+		m_aUserdir[0] = 0;
 	}
 	
 	int Init(const char *pApplicationName, int NumArgs, const char **ppArguments)
 	{
-		char aPath[1024] = {0};
-		fs_storage_path(pApplicationName, m_aApplicationSavePath, sizeof(m_aApplicationSavePath));
-		if(fs_makedir(m_aApplicationSavePath) == 0)
-		{		
-			str_format(aPath, sizeof(aPath), "%s/screenshots", m_aApplicationSavePath);
-			fs_makedir(aPath);
-
-			str_format(aPath, sizeof(aPath), "%s/maps", m_aApplicationSavePath);
-			fs_makedir(aPath);
-
-			str_format(aPath, sizeof(aPath), "%s/dumps", m_aApplicationSavePath);
-			fs_makedir(aPath);
-
-			str_format(aPath, sizeof(aPath), "%s/downloadedmaps", m_aApplicationSavePath);
-			fs_makedir(aPath);
-
-			str_format(aPath, sizeof(aPath), "%s/demos", m_aApplicationSavePath);
-			fs_makedir(aPath);
-		}
+		// get userdir
+		fs_storage_path(pApplicationName, m_aUserdir, sizeof(m_aUserdir));
 
 		// check for datadir override
 		for(int i = 1; i < NumArgs; i++)
@@ -50,54 +44,160 @@ public:
 				break;
 			}
 		}
-		
-		return FindDatadir(ppArguments[0]);
+		// get datadir
+		FindDatadir(ppArguments[0]);
+
+		// load paths from storage.cfg
+		LoadPaths(ppArguments[0]);
+
+		if(!m_NumPaths)
+		{
+			dbg_msg("storage", "using standard paths");
+			AddDefaultPaths();
+		}
+
+		// add save directories
+		if(m_NumPaths && (!m_aaStoragePaths[TYPE_SAVE][0] || !fs_makedir(m_aaStoragePaths[TYPE_SAVE])))
+		{
+			char aPath[MAX_PATH_LENGTH];
+			fs_makedir(GetPath(TYPE_SAVE, "screenshots", aPath, sizeof(aPath)));
+			fs_makedir(GetPath(TYPE_SAVE, "maps", aPath, sizeof(aPath)));
+			fs_makedir(GetPath(TYPE_SAVE, "dumps", aPath, sizeof(aPath)));
+			fs_makedir(GetPath(TYPE_SAVE, "downloadedmaps", aPath, sizeof(aPath)));
+			fs_makedir(GetPath(TYPE_SAVE, "demos", aPath, sizeof(aPath)));
+		}
+
+		return m_NumPaths ? 0 : 1;
+	}
+
+	void LoadPaths(const char *pArgv0)
+	{
+		// check current directory
+		IOHANDLE File = io_open("storage.cfg", IOFLAG_READ);
+		if(!File)
+		{
+			// check usable path in argv[0]
+			unsigned int Pos = ~0U;
+			for(unsigned i = 0; pArgv0[i]; i++)
+				if(pArgv0[i] == '/' || pArgv0[i] == '\\')
+					Pos = i;
+			if(Pos < MAX_PATH_LENGTH)
+			{
+				char aBuffer[MAX_PATH_LENGTH];
+				str_copy(aBuffer, pArgv0, Pos+1);
+				str_append(aBuffer, "/storage.cfg", sizeof(aBuffer));
+				File = io_open(aBuffer, IOFLAG_READ);
+			}
+			
+			if(Pos >= MAX_PATH_LENGTH || !File)
+			{
+				dbg_msg("storage", "couldn't open storage.cfg");
+				return;
+			}
+		}
+
+		char *pLine;
+		CLineReader LineReader;
+		LineReader.Init(File);
+
+		while((pLine = LineReader.Get()))
+		{
+			if(str_length(pLine) > 9 && !str_comp_num(pLine, "add_path ", 9))
+				AddPath(pLine+9);
+		}
+
+		io_close(File);
+
+		if(!m_NumPaths)
+			dbg_msg("storage", "no paths found in storage.cfg");
+	}
+
+	void AddDefaultPaths()
+	{
+		AddPath("$USERDIR");
+		AddPath("$DATADIR");
+		AddPath("$CURRENTDIR");
+	}
+
+	void AddPath(const char *pPath)
+	{
+		if(m_NumPaths >= MAX_PATHS || !pPath[0])
+			return;
+
+		int OldNum = m_NumPaths;
+
+		if(!str_comp(pPath, "$USERDIR"))
+		{
+			if(m_aUserdir[0])
+				str_copy(m_aaStoragePaths[m_NumPaths++], m_aUserdir, MAX_PATH_LENGTH);
+		}
+		else if(!str_comp(pPath, "$DATADIR"))
+		{
+			if(m_aDatadir[0])
+				str_copy(m_aaStoragePaths[m_NumPaths++], m_aDatadir, MAX_PATH_LENGTH);
+		}
+		else if(!str_comp(pPath, "$CURRENTDIR"))
+		{
+			m_aaStoragePaths[m_NumPaths++][0] = 0;
+		}
+		else
+		{
+			if(fs_is_dir(pPath))
+				str_copy(m_aaStoragePaths[m_NumPaths++], pPath, MAX_PATH_LENGTH);
+		}
+
+		if(OldNum != m_NumPaths)
+			dbg_msg("storage", "added path '%s'", pPath);
 	}
 		
-	int FindDatadir(const char *pArgv0)
+	void FindDatadir(const char *pArgv0)
 	{
 		// 1) use provided data-dir override
 		if(m_aDatadir[0])
 		{
-			if(fs_is_dir(m_aDatadir))
-				return 0;
-			else
+			char aBuffer[MAX_PATH_LENGTH];
+			str_format(aBuffer, sizeof(aBuffer), "%s/mapres", m_aDatadir);
+			if(!fs_is_dir(aBuffer))
 			{
-				dbg_msg("engine/datadir", "specified data-dir '%s' does not exist", m_aDatadir);
-				return -1;
+				dbg_msg("storage", "specified data directory '%s' does not exist", m_aDatadir);
+				m_aDatadir[0] = 0;
 			}
+			else
+				return;
 		}
 		
 		// 2) use data-dir in PWD if present
 		if(fs_is_dir("data/mapres"))
 		{
 			str_copy(m_aDatadir, "data", sizeof(m_aDatadir));
-			return 0;
+			return;
 		}
 		
 		// 3) use compiled-in data-dir if present
-		if (fs_is_dir(DATA_DIR "/mapres"))
+		if(fs_is_dir(DATA_DIR "/mapres"))
 		{
 			str_copy(m_aDatadir, DATA_DIR, sizeof(m_aDatadir));
-			return 0;
+			return;
 		}
 		
 		// 4) check for usable path in argv[0]
 		{
 			unsigned int Pos = ~0U;
 			for(unsigned i = 0; pArgv0[i]; i++)
-				if(pArgv0[i] == '/')
+				if(pArgv0[i] == '/' || pArgv0[i] == '\\')
 					Pos = i;
 			
-			if (Pos < sizeof(m_aDatadir))
+			if(Pos < MAX_PATH_LENGTH)
 			{
-				char aBaseDir[sizeof(m_aDatadir)];
-				str_copy(aBaseDir, pArgv0, Pos);
-				aBaseDir[Pos] = '\0';
+				char aBaseDir[MAX_PATH_LENGTH];
+				str_copy(aBaseDir, pArgv0, Pos+1);
 				str_format(m_aDatadir, sizeof(m_aDatadir), "%s/data", aBaseDir);
+				str_append(aBaseDir, "/data/mapres", sizeof(aBaseDir));
 				
-				if (fs_is_dir(m_aDatadir))
-					return 0;
+				if(fs_is_dir(aBaseDir))
+					return;
+				else
+					m_aDatadir[0] = 0;
 			}
 		}
 		
@@ -105,11 +205,11 @@ public:
 		// 5) check for all default locations
 		{
 			const char *aDirs[] = {
-				"/usr/share/teeworlds/data",
-				"/usr/share/games/teeworlds/data",
-				"/usr/local/share/teeworlds/data",
-				"/usr/local/share/games/teeworlds/data",
-				"/opt/teeworlds/data"
+				"/usr/share/teeworlds/data/mapres",
+				"/usr/share/games/teeworlds/data/mapres",
+				"/usr/local/share/teeworlds/data/mapres",
+				"/usr/local/share/games/teeworlds/data/mapres",
+				"/opt/teeworlds/data/mapres"
 			};
 			const int DirsCount = sizeof(aDirs) / sizeof(aDirs[0]);
 			
@@ -119,55 +219,41 @@ public:
 				if (fs_is_dir(aDirs[i]))
 				{
 					str_copy(m_aDatadir, aDirs[i], sizeof(m_aDatadir));
-					return 0;
+					return;
 				}
 			}
 		}
 	#endif
 		
 		// no data-dir found
-		dbg_msg("engine/datadir", "warning no data directory found");
-		return -1;
+		dbg_msg("storage", "warning no data directory found");
 	}
 
-	virtual void ListDirectory(int Types, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser)
+	virtual void ListDirectory(int Type, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser)
 	{
-		char aBuffer[1024];
-		
-		// list current directory
-		if(Types&TYPE_CURRENT)
+		char aBuffer[MAX_PATH_LENGTH];
+		if(Type == TYPE_ALL)
 		{
-			fs_listdir(pPath, pfnCallback, TYPE_CURRENT, pUser);
+			// list all available directories
+			for(int i = 0; i < m_NumPaths; ++i)
+				fs_listdir(GetPath(i, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, i, pUser);
 		}
-		
-		// list users directory
-		if(Types&TYPE_SAVE)
+		else if(Type >= 0 && Type < m_NumPaths)
 		{
-			str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aApplicationSavePath, pPath);
-			fs_listdir(aBuffer, pfnCallback, TYPE_SAVE, pUser);
+			// list wanted directory
+			fs_listdir(GetPath(Type, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, Type, pUser);
 		}
-		
-		// list datadir directory
-		if(Types&TYPE_DATA)
-		{
-			str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aDatadir, pPath);
-			fs_listdir(aBuffer, pfnCallback, TYPE_DATA, pUser);
-		}		
 	}
 
-	virtual const char *GetDirectory(int Type) const
+	const char *GetPath(int Type, const char *pDir, char *pBuffer, unsigned BufferSize)
 	{
-		switch(Type)
-		{
-		case TYPE_SAVE: return m_aApplicationSavePath;
-		case TYPE_DATA: return m_aDatadir;
-		default: return "";
-		}
+		str_format(pBuffer, BufferSize, "%s%s%s", m_aaStoragePaths[Type], !m_aaStoragePaths[Type][0] ? "" : "/", pDir);
+		return pBuffer;
 	}
 	
-	virtual IOHANDLE OpenFile(const char *pFilename, int Flags, char *pBuffer = 0, int BufferSize = 0)
+	virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0)
 	{
-		char aBuffer[1024];
+		char aBuffer[MAX_PATH_LENGTH];
 		if(!pBuffer)
 		{
 			pBuffer = aBuffer;
@@ -176,45 +262,42 @@ public:
 		
 		if(Flags&IOFLAG_WRITE)
 		{
-			str_format(pBuffer, BufferSize, "%s/%s", m_aApplicationSavePath, pFilename);
-			return io_open(pBuffer, Flags);
+			return io_open(GetPath(TYPE_SAVE, pFilename, pBuffer, BufferSize), Flags);
 		}
 		else
 		{
 			IOHANDLE Handle = 0;
-			
-			// check current directory
-			Handle = io_open(pFilename, Flags);
-			if(Handle)
-				return Handle;
-				
-			// check user directory
-			str_format(pBuffer, BufferSize, "%s/%s", m_aApplicationSavePath, pFilename);
-			Handle = io_open(pBuffer, Flags);
-			if(Handle)
-				return Handle;
-				
-			// check normal data directory
-			str_format(pBuffer, BufferSize, "%s/%s", m_aDatadir, pFilename);
-			Handle = io_open(pBuffer, Flags);
-			if(Handle)
-				return Handle;
+
+			if(Type == TYPE_ALL)
+			{
+				// check all available directories
+				for(int i = 0; i < m_NumPaths; ++i)
+				{
+					Handle = io_open(GetPath(i, pFilename, pBuffer, BufferSize), Flags);
+					if(Handle)
+						return Handle;
+				}
+			}
+			else if(Type >= 0 && Type < m_NumPaths)
+			{
+				// check wanted directory
+				Handle = io_open(GetPath(Type, pFilename, pBuffer, BufferSize), Flags);
+				if(Handle)
+					return Handle;
+			}
 		}
 		
 		pBuffer[0] = 0;
 		return 0;		
 	}
  	
-	virtual bool RemoveFile(const char *pFilename)
+	virtual bool RemoveFile(const char *pFilename, int Type)
 	{
-		char aBuffer[1024];
-		str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aApplicationSavePath, pFilename);
-		bool Fail = remove(aBuffer);
-		
-		if(Fail)
-			Fail = remove(pFilename);
-		
-		return !Fail;
+		if(Type < 0 || Type >= m_NumPaths)
+			return false;
+
+		char aBuffer[MAX_PATH_LENGTH];
+		return remove(GetPath(Type, pFilename, aBuffer, sizeof(aBuffer)));
 	}
 
 	static IStorage *Create(const char *pApplicationName, int NumArgs, const char **ppArguments)
@@ -222,6 +305,7 @@ public:
 		CStorage *p = new CStorage();
 		if(p && p->Init(pApplicationName, NumArgs, ppArguments))
 		{
+			dbg_msg("storage", "initialisation failed");
 			delete p;
 			p = 0;
 		}