about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/base/system.c37
-rw-r--r--src/base/system.h17
-rw-r--r--src/engine/client/ec_client.c24
-rw-r--r--src/engine/e_engine.c106
-rw-r--r--src/engine/e_engine.h2
-rw-r--r--src/engine/e_map.c2
-rw-r--r--src/engine/server/es_server.c20
-rw-r--r--src/game/client/components/mapimages.cpp2
-rw-r--r--src/game/client/components/menus.cpp2
-rw-r--r--src/game/client/components/skins.cpp4
-rw-r--r--src/game/client/gameclient.cpp2
-rw-r--r--src/game/editor/ed_editor.cpp28
-rw-r--r--src/game/editor/ed_io.cpp2
13 files changed, 201 insertions, 47 deletions
diff --git a/src/base/system.c b/src/base/system.c
index d2f4614a..e2c37bbd 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -909,6 +909,43 @@ int fs_makedir(const char *path)
 #endif
 }
 
+int fs_is_dir(const char *path)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+	/* TODO: do this smarter */
+	WIN32_FIND_DATA finddata;
+	HANDLE handle;
+	char buffer[1024*2];
+	str_format(buffer, sizeof(buffer), "%s/*", path);
+
+	if ((handle = FindFirstFileA(buffer, &finddata)) == INVALID_HANDLE_VALUE)
+		return 0;
+
+	FindClose(handle);
+	return 1;
+#else
+	struct stat sb;
+	if (stat(path, &sb) == -1)
+		return 0;
+	
+	if (S_ISDIR(sb.st_mode))
+		return 1;
+	else
+		return 0;
+#endif
+}
+
+int fs_chdir(const char *path)
+{
+	if (fs_is_dir(path))
+	{
+		chdir(path);
+		return 0;
+	}
+	else
+		return 1;
+}
+
 void swap_endian(void *data, unsigned elem_size, unsigned num)
 {
 	char *src = (char*) data;
diff --git a/src/base/system.h b/src/base/system.h
index 9a556341..fdbfe72d 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -824,6 +824,23 @@ int fs_makedir(const char *path);
 */
 int fs_storage_path(const char *appname, char *path, int max);
 
+/*
+	Function: fs_is_dir
+		Checks if directory exists
+	
+	Returns:
+		Returns 1 on success, 0 on failure.
+*/
+int fs_is_dir(const char *path);
+
+/*
+	Function: fs_chdir
+		Changes current working directory
+	
+	Returns:
+		Returns 0 on success, 1 on failure.
+*/
+int fs_chdir(const char *path);
 
 /*
 	Group: Undocumented
diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c
index 1ae1d51a..1a6a24f1 100644
--- a/src/engine/client/ec_client.c
+++ b/src/engine/client/ec_client.c
@@ -550,7 +550,7 @@ void client_disconnect()
 
 static int client_load_data()
 {
-	debug_font = gfx_load_texture("data/debug_font.png", IMG_AUTO, TEXLOAD_NORESAMPLE);
+	debug_font = gfx_load_texture("debug_font.png", IMG_AUTO, TEXLOAD_NORESAMPLE);
 	return 1;
 }
 
@@ -698,7 +698,7 @@ static const char *client_load_map_search(const char *mapname, int wanted_crc)
 	client_set_state(CLIENTSTATE_LOADING);
 	
 	/* try the normal maps folder */
-	str_format(buf, sizeof(buf), "data/maps/%s.map", mapname);
+	str_format(buf, sizeof(buf), "maps/%s.map", mapname);
 	error = client_load_map(buf, wanted_crc);
 	if(!error)
 		return error;
@@ -1601,18 +1601,6 @@ void client_save_line(const char *line)
 
 int main(int argc, char **argv)
 {
-#if defined(CONF_PLATFORM_MACOSX)
-	char buffer[512];
-	unsigned pos = strrchr(argv[0], '/') - argv[0];
-
-	if(pos >= 512)
-		return -1;
-
-	strncpy(buffer, argv[0], 511);
-	buffer[pos] = 0;
-	chdir(buffer);
-#endif
-
 	/* init the engine */
 	dbg_msg("client", "starting...");
 	engine_init("Teeworlds");
@@ -1624,6 +1612,14 @@ int main(int argc, char **argv)
 	/* parse the command line arguments */
 	engine_parse_arguments(argc, argv);
 	
+	/* change into data-dir */
+	if (!engine_chdir_datadir(argv[0]))
+	{
+		dbg_msg("client", "fatal error: data-dir cannot be found");
+		gui_messagebox("Error", "The data-dir cannot be found.");
+		return -1;
+	}
+	
 	/* run the client*/
 	client_run();
 	
diff --git a/src/engine/e_engine.c b/src/engine/e_engine.c
index 45eecfe3..3afd9ff9 100644
--- a/src/engine/e_engine.c
+++ b/src/engine/e_engine.c
@@ -13,6 +13,9 @@
 #include <engine/e_network.h>
 #include "e_linereader.h"
 
+/* compiled-in data-dir path */
+#define DATA_DIR "data"
+
 static JOBPOOL hostlookuppool;
 
 static void con_dbg_dumpmem(void *result, void *user_data)
@@ -22,6 +25,7 @@ static void con_dbg_dumpmem(void *result, void *user_data)
 
 
 static char application_save_path[512] = {0};
+char *datadir_override;
 
 const char *engine_savepath(const char *filename, char *buffer, int max)
 {
@@ -89,6 +93,11 @@ void engine_parse_arguments(int argc, char **argv)
 			abs = 1;
 			i++;
 		}
+		else if(argv[i][0] == '-' && argv[i][1] == 'd' && argv[i][2] == 0 && argc - i > 1)
+		{
+			datadir_override = argv[i+1];
+			i++;
+		}
 	}
 
 	if(abs)
@@ -405,3 +414,100 @@ void engine_hostlookup(HOSTLOOKUP *lookup, const char *hostname)
 	jobs_add(&hostlookuppool, &lookup->job, hostlookup_thread, lookup);
 }
 
+int engine_chdir_datadir(char *argv0)
+{
+#if defined(CONF_FAMILY_UNIX)
+	static const char *sdirs[] = {
+		"/usr/share/teeworlds",
+		"/usr/local/share/teeworlds"
+	};
+	static const int sdirs_count = sizeof(sdirs) / sizeof(sdirs[0]);
+#endif
+
+	int found = 0;
+	char data_dir[1024*2];
+	
+	/* 1) use provided data-dir override */
+	if (datadir_override)
+	{
+		if (fs_is_dir(datadir_override))
+		{
+			str_copy(data_dir, datadir_override, sizeof(data_dir));
+			dbg_msg("engine/datadir", "using override '%s'", data_dir);
+			found = 1;
+		}
+		else
+		{
+			dbg_msg("engine/datadir",
+				"specified data-dir '%s' does not exist",
+				datadir_override);
+			return 0;
+		}
+	}
+	
+#if defined(CONF_FAMILY_UNIX)
+	/* 2) use data-dir in PWD if present */
+	if (!found && fs_is_dir("data"))
+	{
+		strcpy(data_dir, "data");
+		found = 1;
+	}
+	
+	/* 3) use compiled-in data-dir if present */
+	if (!found && fs_is_dir(DATA_DIR))
+	{
+		strcpy(data_dir, DATA_DIR);
+		found = 1;
+	}
+	
+	/* 4) check for usable path in argv[0] */
+	if (!found)
+	{
+		unsigned int pos = strrchr(argv0, '/') - argv0;
+		
+		if (pos < sizeof(data_dir))
+		{
+			char basedir[sizeof(data_dir)];
+			strncpy(basedir, argv0, pos);
+			basedir[pos] = '\0';
+			str_format(data_dir, sizeof(data_dir),
+				"%s/data", basedir);
+			
+			if (fs_is_dir(data_dir))
+				found = 1;
+		}
+	}
+
+	/* 5) check for all default locations */
+	if (!found)
+	{
+		int i;
+		for (i = 0; i < sdirs_count; i++)
+		{
+			if (fs_is_dir(sdirs[i]))
+			{
+				strcpy(data_dir, sdirs[i]);
+				found = 1;
+				break;
+			}
+		}
+	}
+#elif defined(CONF_FAMILY_WINDOWS)
+	/* FIXME: any alternative directories to search? %PROGRAM_FILES%/.../ */
+	if (!found && fs_is_dir("data"))
+	{
+		strcpy(data_dir, "data");
+		found = 1;
+	}
+#endif
+	
+	if (found)
+	{
+		dbg_msg("engine/datadir", "using '%s'", data_dir);
+		
+		/* change working directory to data-dir */
+		fs_chdir(data_dir);
+	}
+	
+	return found;
+}
diff --git a/src/engine/e_engine.h b/src/engine/e_engine.h
index dfe2f6f5..5db7a4dd 100644
--- a/src/engine/e_engine.h
+++ b/src/engine/e_engine.h
@@ -10,6 +10,8 @@ int engine_config_write_start();
 void engine_config_write_line(const char *line);
 void engine_config_write_stop();
 
+int engine_chdir_datadir(char *argv0);
+
 int engine_stress(float probability);
 
 typedef struct HOSTLOOKUP
diff --git a/src/engine/e_map.c b/src/engine/e_map.c
index c33868d7..a2048310 100644
--- a/src/engine/e_map.c
+++ b/src/engine/e_map.c
@@ -53,7 +53,7 @@ int map_is_loaded()
 int map_load(const char *mapname)
 {
 	char buf[512];
-	str_format(buf, sizeof(buf), "data/maps/%s.map", mapname);
+	str_format(buf, sizeof(buf), "maps/%s.map", mapname);
 	map = datafile_load(buf);
 	return map != 0;
 }
diff --git a/src/engine/server/es_server.c b/src/engine/server/es_server.c
index 6cdf835f..58866e09 100644
--- a/src/engine/server/es_server.c
+++ b/src/engine/server/es_server.c
@@ -882,7 +882,7 @@ static int server_load_map(const char *mapname)
 {
 	DATAFILE *df;
 	char buf[512];
-	str_format(buf, sizeof(buf), "data/maps/%s.map", mapname);
+	str_format(buf, sizeof(buf), "maps/%s.map", mapname);
 	df = datafile_load(buf);
 	if(!df)
 		return 0;
@@ -1145,17 +1145,6 @@ static void server_register_commands()
 
 int main(int argc, char **argv)
 {
-#if defined(CONF_PLATFORM_MACOSX)
-	char buffer[512];
-	unsigned pos = strrchr(argv[0], '/') - argv[0];
-
-	if(pos >= 512)
-		return -1;
-
-	strncpy(buffer, argv[0], 511);
-	buffer[pos] = 0;
-	chdir(buffer);
-#endif
 #if defined(CONF_FAMILY_WINDOWS)
 	int i;
 	for(i = 1; i < argc; i++)
@@ -1181,6 +1170,13 @@ int main(int argc, char **argv)
 	/* parse the command line arguments */
 	engine_parse_arguments(argc, argv);
 	
+	/* change into data-dir */
+	if (!engine_chdir_datadir(argv[0]))
+	{
+		dbg_msg("server", "fatal error: data-dir cannot be found");
+		return -1;
+	}
+	
 	/* run the server */
 	server_run();
 	return 0;
diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp
index d13524cd..9dc2447a 100644
--- a/src/game/client/components/mapimages.cpp
+++ b/src/game/client/components/mapimages.cpp
@@ -31,7 +31,7 @@ void MAPIMAGES::on_reset()
 		{
 			char buf[256];
 			char *name = (char *)map_get_data(img->image_name);
-			str_format(buf, sizeof(buf), "data/mapres/%s.png", name);
+			str_format(buf, sizeof(buf), "mapres/%s.png", name);
 			textures[i] = gfx_load_texture(buf, IMG_AUTO, 0);
 		}
 		else
diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp
index f28a3197..5fe2bbaa 100644
--- a/src/game/client/components/menus.cpp
+++ b/src/game/client/components/menus.cpp
@@ -1030,7 +1030,7 @@ void MENUS::render_background()
 	//gfx_clear(1,1,1);
 	//render_sunrays(0,0);
 	if(texture_blob == -1)
-		texture_blob = gfx_load_texture("data/blob.png", IMG_AUTO, 0);
+		texture_blob = gfx_load_texture("blob.png", IMG_AUTO, 0);
 
 
 	float sw = 300*gfx_screenaspect();
diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp
index eae45c4d..b12bc1cf 100644
--- a/src/game/client/components/skins.cpp
+++ b/src/game/client/components/skins.cpp
@@ -24,7 +24,7 @@ void SKINS::skinscan(const char *name, int is_dir, void *user)
 		return;
 		
 	char buf[512];
-	str_format(buf, sizeof(buf), "data/skins/%s", name);
+	str_format(buf, sizeof(buf), "skins/%s", name);
 	IMAGE_INFO info;
 	if(!gfx_load_png(&info, buf))
 	{
@@ -119,7 +119,7 @@ void SKINS::init()
 {
 	// load skins
 	num_skins = 0;
-	fs_listdir("data/skins", skinscan, this);
+	fs_listdir("skins", skinscan, this);
 }
 
 int SKINS::num()
diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp
index 2696e185..3aed1cd1 100644
--- a/src/game/client/gameclient.cpp
+++ b/src/game/client/gameclient.cpp
@@ -179,7 +179,7 @@ void GAMECLIENT::on_init()
 	int64 start = time_get();
 	
 	int before = gfx_memory_usage();
-	font_set_load(&default_font, "data/fonts/default_font%d.tfnt", "data/fonts/default_font%d.png", "data/fonts/default_font%d_b.png", 14, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 36);
+	font_set_load(&default_font, "fonts/default_font%d.tfnt", "fonts/default_font%d.png", "fonts/default_font%d_b.png", 14, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 36);
 	dbg_msg("font", "gfx memory used for font textures: %d", gfx_memory_usage()-before);
 	
 	gfx_text_set_default_font(&default_font);
diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp
index 54b8fcb6..ca4f354f 100644
--- a/src/game/editor/ed_editor.cpp
+++ b/src/game/editor/ed_editor.cpp
@@ -541,11 +541,11 @@ static void do_toolbar(RECT toolbar)
 	
 	// ctrl+o to open
 	if(inp_key_down('O') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL)))
-		editor.invoke_file_dialog("Open Map", "Open", "data/maps/", "", callback_open_map);
+		editor.invoke_file_dialog("Open Map", "Open", "maps/", "", callback_open_map);
 	
 	// ctrl+s to save
 	if(inp_key_down('S') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL)))
-		editor.invoke_file_dialog("Save Map", "Save", "data/maps/", "", callback_save_map);
+		editor.invoke_file_dialog("Save Map", "Save", "maps/", "", callback_save_map);
 
 	// animate button
 	ui_vsplit_l(&toolbar, 30.0f, &button, &toolbar);
@@ -1670,7 +1670,7 @@ static int popup_image(RECT view)
 	ui_hsplit_t(&view, 12.0f, &slot, &view);
 	if(do_editor_button(&replace_button, "Replace", 0, &slot, draw_editor_button_menuitem, 0, "Replaces the image with a new one"))
 	{
-		editor.invoke_file_dialog("Replace Image", "Replace", "data/mapres/", "", replace_image);
+		editor.invoke_file_dialog("Replace Image", "Replace", "mapres/", "", replace_image);
 		return 1;
 	}
 
@@ -1751,7 +1751,7 @@ static void render_images(RECT toolbox, RECT toolbar, RECT view)
 	ui_hsplit_t(&toolbox, 10.0f, &slot, &toolbox);
 	ui_hsplit_t(&toolbox, 12.0f, &slot, &toolbox);
 	if(do_editor_button(&new_image_button, "Add", 0, &slot, draw_editor_button, 0, "Load a new image to use in the map"))
-		editor.invoke_file_dialog("Add Image", "Add", "data/mapres/", "", add_image);
+		editor.invoke_file_dialog("Add Image", "Add", "mapres/", "", add_image);
 }
 
 
@@ -2288,7 +2288,7 @@ static int popup_menu_file(RECT view)
 	ui_hsplit_t(&view, 12.0f, &slot, &view);
 	if(do_editor_button(&open_button, "Open", 0, &slot, draw_editor_button_menuitem, 0, "Opens a map for editing"))
 	{
-		editor.invoke_file_dialog("Open Map", "Open", "data/maps/", "", callback_open_map);
+		editor.invoke_file_dialog("Open Map", "Open", "maps/", "", callback_open_map);
 		return 1;
 	}
 
@@ -2296,7 +2296,7 @@ static int popup_menu_file(RECT view)
 	ui_hsplit_t(&view, 12.0f, &slot, &view);
 	if(do_editor_button(&append_button, "Append", 0, &slot, draw_editor_button_menuitem, 0, "Opens a map and adds everything from that map to the current one"))
 	{
-		editor.invoke_file_dialog("Append Map", "Append", "data/maps/", "", callback_append_map);
+		editor.invoke_file_dialog("Append Map", "Append", "maps/", "", callback_append_map);
 		return 1;
 	}
 
@@ -2311,7 +2311,7 @@ static int popup_menu_file(RECT view)
 	ui_hsplit_t(&view, 12.0f, &slot, &view);
 	if(do_editor_button(&save_as_button, "Save As", 0, &slot, draw_editor_button_menuitem, 0, "Saves the current map under a new name"))
 	{
-		editor.invoke_file_dialog("Save Map", "Save", "data/maps/", "", callback_save_map);
+		editor.invoke_file_dialog("Save Map", "Save", "maps/", "", callback_save_map);
 		return 1;
 	}
 		
@@ -2523,10 +2523,10 @@ void MAP::create_default(int entities_texture)
 
 extern "C" void editor_init()
 {
-	checker_texture = gfx_load_texture("data/editor/checker.png", IMG_AUTO, 0);
-	background_texture = gfx_load_texture("data/editor/background.png", IMG_AUTO, 0);
-	cursor_texture = gfx_load_texture("data/editor/cursor.png", IMG_AUTO, 0);
-	entities_texture = gfx_load_texture("data/editor/entities.png", IMG_AUTO, 0);
+	checker_texture = gfx_load_texture("editor/checker.png", IMG_AUTO, 0);
+	background_texture = gfx_load_texture("editor/background.png", IMG_AUTO, 0);
+	cursor_texture = gfx_load_texture("editor/cursor.png", IMG_AUTO, 0);
+	entities_texture = gfx_load_texture("editor/entities.png", IMG_AUTO, 0);
 	
 	tileset_picker.make_palette();
 	tileset_picker.readonly = true;
@@ -2599,13 +2599,13 @@ extern "C" void editor_update_and_render()
 		editor.gui_active = !editor.gui_active;
 
 	if(inp_key_down(KEY_F5))
-		editor.save("data/maps/debug_test2.map");
+		editor.save("maps/debug_test2.map");
 
 	if(inp_key_down(KEY_F6))
-		editor.load("data/maps/debug_test2.map");
+		editor.load("maps/debug_test2.map");
 	
 	if(inp_key_down(KEY_F8))
-		editor.load("data/maps/debug_test.map");
+		editor.load("maps/debug_test.map");
 	
 	if(inp_key_down(KEY_F10))
 		editor.show_mouse_pointer = false;
diff --git a/src/game/editor/ed_io.cpp b/src/game/editor/ed_io.cpp
index b27dd25e..dfaa0e2c 100644
--- a/src/game/editor/ed_io.cpp
+++ b/src/game/editor/ed_io.cpp
@@ -398,7 +398,7 @@ int MAP::load(const char *filename)
 				if(item->external)
 				{
 					char buf[256];
-					sprintf(buf, "data/mapres/%s.png", name);
+					sprintf(buf, "mapres/%s.png", name);
 					
 					// load external
 					EDITOR_IMAGE imginfo;