about summary refs log tree commit diff
path: root/src/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/client/ec_client.c21
-rw-r--r--src/engine/client/ec_font.c3
-rw-r--r--src/engine/client/ec_gfx.c46
-rw-r--r--src/engine/e_config.c16
-rw-r--r--src/engine/e_config.h19
-rw-r--r--src/engine/e_config_variables.h111
-rw-r--r--src/engine/e_console.c7
-rw-r--r--src/engine/e_datafile.c7
-rw-r--r--src/engine/e_demorec.c5
-rw-r--r--src/engine/e_engine.c209
-rw-r--r--src/engine/e_engine.h5
-rw-r--r--src/engine/e_network.c5
-rw-r--r--src/engine/e_network_server.c35
-rw-r--r--src/engine/server/es_server.c28
14 files changed, 314 insertions, 203 deletions
diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c
index 8ef6cf51..1c499e85 100644
--- a/src/engine/client/ec_client.c
+++ b/src/engine/client/ec_client.c
@@ -727,7 +727,6 @@ static const char *client_load_map_search(const char *mapname, int wanted_crc)
 {
 	const char *error = 0;
 	char buf[512];
-	char buf2[512];
 	dbg_msg("client", "loading map, map=%s wanted crc=%08x", mapname, wanted_crc);
 	client_set_state(CLIENTSTATE_LOADING);
 	
@@ -738,8 +737,7 @@ static const char *client_load_map_search(const char *mapname, int wanted_crc)
 		return error;
 
 	/* try the downloaded maps */
-	str_format(buf2, sizeof(buf2), "maps/%s_%8x.map", mapname, wanted_crc);
-	engine_savepath(buf2, buf, sizeof(buf));
+	str_format(buf, sizeof(buf), "maps/%s_%8x.map", mapname, wanted_crc);
 	error = client_load_map(mapname, buf, wanted_crc);
 	return error;
 }
@@ -896,15 +894,13 @@ static void client_process_packet(NETCHUNK *packet)
 					}
 					else
 					{
-						char buf[512];
-						str_format(buf, sizeof(buf), "maps/%s_%08x.map", map, map_crc);
-						engine_savepath(buf, mapdownload_filename, sizeof(mapdownload_filename));
+						str_format(mapdownload_filename, sizeof(mapdownload_filename), "maps/%s_%08x.map", map, map_crc);
 
 						dbg_msg("client/network", "starting to download map to '%s'", mapdownload_filename);
 						
 						mapdownload_chunk = 0;
 						str_copy(mapdownload_name, map, sizeof(mapdownload_name));
-						mapdownload_file = io_open(mapdownload_filename, IOFLAG_WRITE);
+						mapdownload_file = engine_openfile(mapdownload_filename, IOFLAG_WRITE);
 						mapdownload_crc = map_crc;
 						mapdownload_totalsize = -1;
 						mapdownload_amount = 0;
@@ -1857,14 +1853,9 @@ 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;
-	}
+
+	/* execute config file */
+	console_execute_file("settings.cfg");
 	
 	/* run the client*/
 	client_run();
diff --git a/src/engine/client/ec_font.c b/src/engine/client/ec_font.c
index af9c612a..f8760d41 100644
--- a/src/engine/client/ec_font.c
+++ b/src/engine/client/ec_font.c
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <base/system.h>
 #include <engine/e_client_interface.h>
+#include <engine/e_engine.h>
 #include "ec_font.h"
 
 typedef struct
@@ -32,7 +33,7 @@ int font_load(FONT *font, const char *filename)
     FONT_DATA font_data;
 	IOHANDLE file;
 
-	file = io_open(filename, IOFLAG_READ);
+	file = engine_openfile(filename, IOFLAG_READ);
 	
 	if(file)
 	{
diff --git a/src/engine/client/ec_gfx.c b/src/engine/client/ec_gfx.c
index 1f9ec642..35e43e41 100644
--- a/src/engine/client/ec_gfx.c
+++ b/src/engine/client/ec_gfx.c
@@ -796,21 +796,24 @@ int gfx_load_texture(const char *filename, int store_format, int flags)
 
 int gfx_load_png(IMAGE_INFO *img, const char *filename)
 {
+	char completefilename[512];
 	unsigned char *buffer;
 	png_t png;
 	
 	/* open file for reading */
 	png_init(0,0);
 
-	if(png_open_file(&png, filename) != PNG_NO_ERROR)
+	engine_getpath(completefilename, sizeof(completefilename), filename, IOFLAG_READ);
+	
+	if(png_open_file(&png, completefilename) != PNG_NO_ERROR)
 	{
-		dbg_msg("game/png", "failed to open file. filename='%s'", filename);
+		dbg_msg("game/png", "failed to open file. filename='%s'", completefilename);
 		return 0;
 	}
 	
 	if(png.depth != 8 || (png.color_type != PNG_TRUECOLOR && png.color_type != PNG_TRUECOLOR_ALPHA))
 	{
-		dbg_msg("game/png", "invalid format. filename='%s'", filename);
+		dbg_msg("game/png", "invalid format. filename='%s'", completefilename);
 		png_close_file(&png);
         return 0;
 	}
@@ -865,22 +868,24 @@ void gfx_swap()
 			IOHANDLE io;
 			char filename[128];
 			char header[18] = {0};
-			sprintf(filename, "capture/frame%04d.tga", record);
+			str_format(filename, sizeof(filename), "capture/frame%04d.tga", record);
 			record++;
 			
-			io = io_open(filename, IOFLAG_WRITE);
-
-			header[2] = 2; /* rgb */
-			header[12] = w&255; /* width */
-			header[13] = w>>8; 
-			header[14] = h&255; /* height */
-			header[15] = h>>8; 
-			header[16] = 24;
-			
-			io_write(io, header, sizeof(header));
-			io_write(io, pixel_data, w*h*3);
-			
-			io_close(io);
+			io = engine_openfile(filename, IOFLAG_WRITE);
+			if(io)
+			{
+				header[2] = 2; /* rgb */
+				header[12] = w&255; /* width */
+				header[13] = w>>8; 
+				header[14] = h&255; /* height */
+				header[15] = h>>8; 
+				header[16] = 24;
+				
+				io_write(io, header, sizeof(header));
+				io_write(io, pixel_data, w*h*3);
+				
+				io_close(io);
+			}
 		}
 		
 
@@ -899,17 +904,14 @@ void gfx_swap()
 	if(do_screenshot)
 	{
 		/* find filename */
-		char wholepath[1024];
 		char filename[128];
 		static int index = 1;
 
 		for(; index < 1000; index++)
 		{
 			IOHANDLE io;
-			sprintf(filename, "screenshots/screenshot%04d.png", index);
-			engine_savepath(filename, wholepath, sizeof(wholepath));
-			
-			io = io_open(wholepath, IOFLAG_READ);
+			str_format(filename, sizeof(filename), "screenshots/screenshot%04d.png", index);
+			io = engine_openfile(filename, IOFLAG_READ);
 			if(io)
 				io_close(io);
 			else
diff --git a/src/engine/e_config.c b/src/engine/e_config.c
index 1746b682..67a4c81a 100644
--- a/src/engine/e_config.c
+++ b/src/engine/e_config.c
@@ -14,8 +14,8 @@ CONFIGURATION config;
 
 void config_reset()
 {
-    #define MACRO_CONFIG_INT(name,def,min,max) config.name = def;
-    #define MACRO_CONFIG_STR(name,len,def) str_copy(config.name, def, len);
+    #define MACRO_CONFIG_INT(name,def,min,max,flags,desc) config.name = def;
+    #define MACRO_CONFIG_STR(name,len,def,flags,desc) str_copy(config.name, def, len);
  
     #include "e_config_variables.h" 
  
@@ -27,8 +27,8 @@ void config_save()
 {
 	char linebuf[1024*2];
 	
-	#define MACRO_CONFIG_INT(name,def,min,max) { str_format(linebuf, sizeof(linebuf), "%s %i", #name, config.name); engine_config_write_line(linebuf); }
-	#define MACRO_CONFIG_STR(name,len,def) { str_format(linebuf, sizeof(linebuf), "%s %s", #name, config.name); engine_config_write_line(linebuf); }
+	#define MACRO_CONFIG_INT(name,def,min,max,flags,desc) if((flags)&CFGFLAG_SAVE){ str_format(linebuf, sizeof(linebuf), "%s %i", #name, config.name); engine_config_write_line(linebuf); }
+	#define MACRO_CONFIG_STR(name,len,def,flags,desc) if((flags)&CFGFLAG_SAVE){ str_format(linebuf, sizeof(linebuf), "%s %s", #name, config.name); engine_config_write_line(linebuf); }
 
 	#include "e_config_variables.h" 
 
@@ -36,14 +36,14 @@ void config_save()
 	#undef MACRO_CONFIG_STR 
 }
 
-#define MACRO_CONFIG_INT(name,def,min,max) int config_get_ ## name (CONFIGURATION *c) { return c->name; }
-#define MACRO_CONFIG_STR(name,len,def) const char *config_get_ ## name (CONFIGURATION *c) { return c->name; }
+#define MACRO_CONFIG_INT(name,def,min,max,flags,desc) int config_get_ ## name (CONFIGURATION *c) { return c->name; }
+#define MACRO_CONFIG_STR(name,len,def,flags,desc) const char *config_get_ ## name (CONFIGURATION *c) { return c->name; }
 #include "e_config_variables.h"
 #undef MACRO_CONFIG_INT
 #undef MACRO_CONFIG_STR
 
-#define MACRO_CONFIG_INT(name,def,min,max) void config_set_ ## name (CONFIGURATION *c, int val) { if(min != max) { if (val < min) val = min; if (max != 0 && val > max) val = max; } c->name = val; }
-#define MACRO_CONFIG_STR(name,len,def) void config_set_ ## name (CONFIGURATION *c, const char *str) { str_copy(c->name, str, len-1); c->name[sizeof(c->name)-1] = 0; }
+#define MACRO_CONFIG_INT(name,def,min,max,flags,desc) void config_set_ ## name (CONFIGURATION *c, int val) { if(min != max) { if (val < min) val = min; if (max != 0 && val > max) val = max; } c->name = val; }
+#define MACRO_CONFIG_STR(name,len,def,flags,desc) void config_set_ ## name (CONFIGURATION *c, const char *str) { str_copy(c->name, str, len-1); c->name[sizeof(c->name)-1] = 0; }
 #include "e_config_variables.h"
 #undef MACRO_CONFIG_INT
 #undef MACRO_CONFIG_STR
diff --git a/src/engine/e_config.h b/src/engine/e_config.h
index 6d56b026..965e08f0 100644
--- a/src/engine/e_config.h
+++ b/src/engine/e_config.h
@@ -8,8 +8,8 @@ extern "C"{
 
 typedef struct
 { 
-    #define MACRO_CONFIG_INT(name,def,min,max) int name;
-    #define MACRO_CONFIG_STR(name,len,def) char name[len]; /* Flawfinder: ignore */
+    #define MACRO_CONFIG_INT(name,def,min,max,save,desc) int name;
+    #define MACRO_CONFIG_STR(name,len,def,save,desc) char name[len]; /* Flawfinder: ignore */
     #include "e_config_variables.h" 
     #undef MACRO_CONFIG_INT 
     #undef MACRO_CONFIG_STR 
@@ -21,19 +21,26 @@ void config_init();
 void config_reset();
 void config_save();
 
+enum
+{
+	CFGFLAG_SAVE=1,
+	CFGFLAG_CLIENT=2,
+	CFGFLAG_SERVER=4
+};
+
 typedef int (*CONFIG_INT_GETTER)(CONFIGURATION *c);
 typedef const char *(*CONFIG_STR_GETTER)(CONFIGURATION *c);
 typedef void (*CONFIG_INT_SETTER)(CONFIGURATION *c, int val);
 typedef void (*CONFIG_STR_SETTER)(CONFIGURATION *c, const char *str);
 
-#define MACRO_CONFIG_INT(name,def,min,max) int config_get_ ## name (CONFIGURATION *c);
-#define MACRO_CONFIG_STR(name,len,def) const char *config_get_ ## name (CONFIGURATION *c);
+#define MACRO_CONFIG_INT(name,def,min,max,flags,desc) int config_get_ ## name (CONFIGURATION *c);
+#define MACRO_CONFIG_STR(name,len,def,flags,desc) const char *config_get_ ## name (CONFIGURATION *c);
 #include "e_config_variables.h"
 #undef MACRO_CONFIG_INT
 #undef MACRO_CONFIG_STR
 
-#define MACRO_CONFIG_INT(name,def,min,max) void config_set_ ## name (CONFIGURATION *c, int val);
-#define MACRO_CONFIG_STR(name,len,def) void config_set_ ## name (CONFIGURATION *c, const char *str);
+#define MACRO_CONFIG_INT(name,def,min,max,flags,desc) void config_set_ ## name (CONFIGURATION *c, int val);
+#define MACRO_CONFIG_STR(name,len,def,flags,desc) void config_set_ ## name (CONFIGURATION *c, const char *str);
 #include "e_config_variables.h"
 #undef MACRO_CONFIG_INT
 #undef MACRO_CONFIG_STR
diff --git a/src/engine/e_config_variables.h b/src/engine/e_config_variables.h
index 7eca3b04..32dcad0f 100644
--- a/src/engine/e_config_variables.h
+++ b/src/engine/e_config_variables.h
@@ -4,70 +4,69 @@
 #include "../game/variables.hpp"
 
 
-MACRO_CONFIG_STR(player_name, 32, "nameless tee")
-MACRO_CONFIG_STR(clan_name, 32, "")
-MACRO_CONFIG_STR(password, 32, "")
-MACRO_CONFIG_STR(logfile, 128, "")
+MACRO_CONFIG_STR(player_name, 32, "nameless tee", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Name of the player")
+MACRO_CONFIG_STR(clan_name, 32, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "(not used)")
+MACRO_CONFIG_STR(password, 32, "", CFGFLAG_CLIENT, "Password to the server")
+MACRO_CONFIG_STR(logfile, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filename to log all output to")
 
-MACRO_CONFIG_INT(cl_cpu_throttle, 0, 0, 1)
-MACRO_CONFIG_INT(cl_editor, 0, 0, 1)
+MACRO_CONFIG_INT(cl_cpu_throttle, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "")
 
-MACRO_CONFIG_STR(b_filter_string, 64, "")
+MACRO_CONFIG_STR(b_filter_string, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Server browser filtering string")
 
-MACRO_CONFIG_INT(b_filter_full, 0, 0, 1)
-MACRO_CONFIG_INT(b_filter_empty, 0, 0, 1)
-MACRO_CONFIG_INT(b_filter_pw, 0, 0, 1)
-MACRO_CONFIG_INT(b_filter_ping, 999, 0, 999)
-MACRO_CONFIG_STR(b_filter_gametype, 128, "")
-MACRO_CONFIG_INT(b_filter_tuned, 1, 0, 1)
-MACRO_CONFIG_INT(b_filter_compatversion, 1, 0, 1)
+MACRO_CONFIG_INT(b_filter_full, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out full server in browser")
+MACRO_CONFIG_INT(b_filter_empty, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out empty server in browser")
+MACRO_CONFIG_INT(b_filter_pw, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out password protected servers in browser")
+MACRO_CONFIG_INT(b_filter_ping, 999, 0, 999, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Ping to filter by in the server browser")
+MACRO_CONFIG_STR(b_filter_gametype, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Game types to filter")
+MACRO_CONFIG_INT(b_filter_tuned, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out tuned servers in browser")
+MACRO_CONFIG_INT(b_filter_compatversion, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-compatible servers in browser")
 
-MACRO_CONFIG_INT(b_sort, 0, 0, 256)
-MACRO_CONFIG_INT(b_sort_order, 0, 0, 1)
-MACRO_CONFIG_INT(b_max_requests, 10, 0, 1000)
+MACRO_CONFIG_INT(b_sort, 0, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(b_sort_order, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(b_max_requests, 10, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Number of requests to use when refreshing server browser")
 
-MACRO_CONFIG_INT(snd_rate, 48000, 0, 0)
-MACRO_CONFIG_INT(snd_enable, 1, 0, 1)
-MACRO_CONFIG_INT(snd_volume, 100, 0, 100)
-MACRO_CONFIG_INT(snd_device, -1, 0, 0)
+MACRO_CONFIG_INT(snd_rate, 48000, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound mixing rate")
+MACRO_CONFIG_INT(snd_enable, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound enable")
+MACRO_CONFIG_INT(snd_volume, 100, 0, 100, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound volume")
+MACRO_CONFIG_INT(snd_device, -1, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "(deprecated) Sound device to use")
 
-MACRO_CONFIG_INT(snd_nonactive_mute, 0, 0, 1)
+MACRO_CONFIG_INT(snd_nonactive_mute, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
 
-MACRO_CONFIG_INT(gfx_screen_width, 800, 0, 0)
-MACRO_CONFIG_INT(gfx_screen_height, 600, 0, 0)
-MACRO_CONFIG_INT(gfx_fullscreen, 1, 0, 1)
-MACRO_CONFIG_INT(gfx_alphabits, 0, 0, 0)
-MACRO_CONFIG_INT(gfx_color_depth, 24, 16, 24)
-MACRO_CONFIG_INT(gfx_clear, 0, 0, 1)
-MACRO_CONFIG_INT(gfx_vsync, 1, 0, 1)
-MACRO_CONFIG_INT(gfx_display_all_modes, 0, 0, 1)
-MACRO_CONFIG_INT(gfx_texture_compression, 0, 0, 1)
-MACRO_CONFIG_INT(gfx_high_detail, 1, 0, 1)
-MACRO_CONFIG_INT(gfx_texture_quality, 1, 0, 1)
-MACRO_CONFIG_INT(gfx_fsaa_samples, 0, 0, 16)
-MACRO_CONFIG_INT(gfx_refresh_rate, 0, 0, 0)
-MACRO_CONFIG_INT(gfx_debug_resizable, 0, 0, 0)
-MACRO_CONFIG_INT(gfx_finish, 1, 0, 1)
+MACRO_CONFIG_INT(gfx_screen_width, 800, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
+MACRO_CONFIG_INT(gfx_screen_height, 600, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
+MACRO_CONFIG_INT(gfx_fullscreen, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Fullscreen")
+MACRO_CONFIG_INT(gfx_alphabits, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Alpha bits for framebuffer  (fullscreen only)")
+MACRO_CONFIG_INT(gfx_color_depth, 24, 16, 24, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Colors bits for framebuffer (fullscreen only)")
+MACRO_CONFIG_INT(gfx_clear, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Clear screen before rendering")
+MACRO_CONFIG_INT(gfx_vsync, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Vertical sync")
+MACRO_CONFIG_INT(gfx_display_all_modes, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(gfx_texture_compression, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use texture compression")
+MACRO_CONFIG_INT(gfx_high_detail, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "High detail")
+MACRO_CONFIG_INT(gfx_texture_quality, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(gfx_fsaa_samples, 0, 0, 16, CFGFLAG_SAVE|CFGFLAG_CLIENT, "FSAA Samples")
+MACRO_CONFIG_INT(gfx_refresh_rate, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen refresh rate")
+MACRO_CONFIG_INT(gfx_debug_resizable, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(gfx_finish, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
 
+MACRO_CONFIG_INT(inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity")
 
-MACRO_CONFIG_INT(inp_mousesens, 100, 5, 100000)
+MACRO_CONFIG_STR(sv_name, 128, "unnamed server", CFGFLAG_SERVER, "Server name")
+MACRO_CONFIG_STR(sv_bindaddr, 128, "", CFGFLAG_SERVER, "Address to bind the server to")
+MACRO_CONFIG_INT(sv_port, 8303, 0, 0, CFGFLAG_SERVER, "Port to use for the server")
+MACRO_CONFIG_INT(sv_external_port, 0, 0, 0, CFGFLAG_SERVER, "External port to report to the master servers")
+MACRO_CONFIG_STR(sv_map, 128, "dm1", CFGFLAG_SERVER, "Map to use on the server")
+MACRO_CONFIG_INT(sv_max_clients, 8, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum number of clients that are allowed on a server")
+MACRO_CONFIG_INT(sv_high_bandwidth, 0, 0, 1, CFGFLAG_SERVER, "Use high bandwidth mode. Doubles the bandwidth required for the server. LAN use only")
+MACRO_CONFIG_INT(sv_register, 1, 0, 1, CFGFLAG_SERVER, "Register server with master server for public listing")
+MACRO_CONFIG_STR(sv_rcon_password, 32, "", CFGFLAG_SERVER, "Remote console password")
 
-MACRO_CONFIG_STR(sv_name, 128, "unnamed server")
-MACRO_CONFIG_STR(sv_bindaddr, 128, "")
-MACRO_CONFIG_INT(sv_port, 8303, 0, 0)
-MACRO_CONFIG_INT(sv_external_port, 0, 0, 0)
-MACRO_CONFIG_STR(sv_map, 128, "dm1")
-MACRO_CONFIG_INT(sv_max_clients, 8, 1, MAX_CLIENTS)
-MACRO_CONFIG_INT(sv_high_bandwidth, 0, 0, 1)
-MACRO_CONFIG_INT(sv_register, 1, 0, 1)
-MACRO_CONFIG_STR(sv_rcon_password, 32, "")
+MACRO_CONFIG_INT(debug, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Debug mode")
+MACRO_CONFIG_INT(dbg_stress, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress systems")
+MACRO_CONFIG_INT(dbg_stress_network, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress network")
+MACRO_CONFIG_INT(dbg_pref, 0, 0, 1, CFGFLAG_SERVER, "Performance outputs")
+MACRO_CONFIG_INT(dbg_graphs, 0, 0, 1, CFGFLAG_CLIENT, "Performance graphs")
+MACRO_CONFIG_INT(dbg_hitch, 0, 0, 0, CFGFLAG_SERVER, "Hitch warnings")
+MACRO_CONFIG_STR(dbg_stress_server, 32, "localhost", CFGFLAG_CLIENT, "Server to stress")
 
-MACRO_CONFIG_INT(debug, 0, 0, 1)
-MACRO_CONFIG_INT(dbg_stress, 0, 0, 0)
-MACRO_CONFIG_INT(dbg_stress_network, 0, 0, 0)
-MACRO_CONFIG_INT(dbg_pref, 0, 0, 1)
-MACRO_CONFIG_INT(dbg_graphs, 0, 0, 1)
-MACRO_CONFIG_INT(dbg_hitch, 0, 0, 0)
-MACRO_CONFIG_STR(dbg_stress_server, 32, "localhost")
-
-MACRO_CONFIG_INT(sv_map_reload, 0, 0, 1)
+MACRO_CONFIG_INT(sv_map_reload, 0, 0, 1, CFGFLAG_SERVER, "Reload the current map")
diff --git a/src/engine/e_console.c b/src/engine/e_console.c
index 2879e75b..1c68c2e7 100644
--- a/src/engine/e_console.c
+++ b/src/engine/e_console.c
@@ -2,6 +2,7 @@
 #include "e_if_other.h"
 #include "e_console.h"
 #include "e_config.h"
+#include "e_engine.h"
 #include "e_linereader.h"
 #include <stdio.h>
 #include <string.h>
@@ -299,7 +300,7 @@ void console_execute_line(const char *str)
 static void console_execute_file_real(const char *filename)
 {
 	IOHANDLE file;
-	file = io_open(filename, IOFLAG_READ);
+	file = engine_openfile(filename, IOFLAG_READ);
 	
 	if(file)
 	{
@@ -406,8 +407,8 @@ void console_init()
 	MACRO_REGISTER_COMMAND("echo", "r", con_echo, 0x0);
 	MACRO_REGISTER_COMMAND("exec", "r", con_exec, 0x0);
 
-	#define MACRO_CONFIG_INT(name,def,min,max) { static INT_VARIABLE_DATA data = { &config_get_ ## name, &config_set_ ## name }; MACRO_REGISTER_COMMAND(#name, "?i", int_variable_command, &data) }
-	#define MACRO_CONFIG_STR(name,len,def) { static STR_VARIABLE_DATA data = { &config_get_ ## name, &config_set_ ## name }; MACRO_REGISTER_COMMAND(#name, "?r", str_variable_command, &data) }
+	#define MACRO_CONFIG_INT(name,def,min,max,flags,desc) { static INT_VARIABLE_DATA data = { &config_get_ ## name, &config_set_ ## name }; MACRO_REGISTER_COMMAND(#name, "?i", int_variable_command, &data) }
+	#define MACRO_CONFIG_STR(name,len,def,flags,desc) { static STR_VARIABLE_DATA data = { &config_get_ ## name, &config_set_ ## name }; MACRO_REGISTER_COMMAND(#name, "?r", str_variable_command, &data) }
 
 	#include "e_config_variables.h" 
 
diff --git a/src/engine/e_datafile.c b/src/engine/e_datafile.c
index 49154567..0317f9d0 100644
--- a/src/engine/e_datafile.c
+++ b/src/engine/e_datafile.c
@@ -1,6 +1,7 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 #include <base/system.h>
 #include "e_datafile.h"
+#include "e_engine.h"
 #include <zlib.h>
 
 static const int DEBUG=0;
@@ -82,7 +83,7 @@ DATAFILE *datafile_load(const char *filename)
 	
 	dbg_msg("datafile", "datafile loading. filename='%s'", filename);
 
-	file = io_open(filename, IOFLAG_READ);
+	file = engine_openfile(filename, IOFLAG_READ);
 	if(!file)
 		return 0;
 	
@@ -393,7 +394,7 @@ DATAFILE_OUT *datafile_create(const char *filename)
 {
 	int i;
 	DATAFILE_OUT *df = (DATAFILE_OUT*)mem_alloc(sizeof(DATAFILE_OUT), 1);
-	df->file = io_open(filename, IOFLAG_WRITE);
+	df->file = engine_openfile(filename, IOFLAG_WRITE);
 	if(!df->file)
 	{
 		mem_free(df);
@@ -658,7 +659,7 @@ int datafile_crc(const char *filename)
 	int crc = 0;
 	unsigned bytes = 0;
 	
-	file = io_open(filename, IOFLAG_READ);
+	file = engine_openfile(filename, IOFLAG_READ);
 	if(!file)
 		return 0;
 		
diff --git a/src/engine/e_demorec.c b/src/engine/e_demorec.c
index aa60f924..5b8885ad 100644
--- a/src/engine/e_demorec.c
+++ b/src/engine/e_demorec.c
@@ -5,6 +5,7 @@
 #include "e_snapshot.h"
 #include "e_compression.h"
 #include "e_network.h"
+#include "e_engine.h"
 #include "e_if_other.h"
 
 static IOHANDLE record_file = 0;
@@ -23,7 +24,7 @@ int demorec_record_start(const char *filename, const char *netversion, const cha
 	if(record_file)
 		return -1;
 
-	record_file = io_open(filename, IOFLAG_WRITE);
+	record_file = engine_openfile(filename, IOFLAG_WRITE);
 	
 	if(!record_file)
 	{
@@ -466,7 +467,7 @@ void demorec_playback_unpause()
 
 int demorec_playback_load(const char *filename)
 {
-	play_file = io_open(filename, IOFLAG_READ);
+	play_file = engine_openfile(filename, IOFLAG_READ);
 	if(!play_file)
 	{
 		dbg_msg("demorec/playback", "could not open '%s'", filename);
diff --git a/src/engine/e_engine.c b/src/engine/e_engine.c
index 2d3992d3..d73082db 100644
--- a/src/engine/e_engine.c
+++ b/src/engine/e_engine.c
@@ -6,7 +6,6 @@
 #include <base/system.h>
 
 #include <engine/e_server_interface.h>
-/*#include <engine/e_client_interface.h>*/
 #include <engine/e_config.h>
 #include <engine/e_console.h>
 #include <engine/e_engine.h>
@@ -17,6 +16,7 @@
 #define DATA_DIR "data"
 
 static JOBPOOL hostlookuppool;
+static int engine_find_datadir(char *argv0);
 
 static void con_dbg_dumpmem(void *result, void *user_data)
 {
@@ -30,7 +30,7 @@ static void con_dbg_lognetwork(void *result, void *user_data)
 
 
 static char application_save_path[512] = {0};
-static char *datadir_override = 0;
+static char datadir[512] = {0};
 
 const char *engine_savepath(const char *filename, char *buffer, int max)
 {
@@ -87,33 +87,130 @@ void engine_init(const char *appname)
 	config_reset();
 }
 
+
+void engine_listdir(const char *path, FS_LISTDIR_CALLBACK cb, void *user)
+{
+	char buffer[1024];
+	
+	/* list current directory */
+	fs_listdir(path, cb, user);
+	
+	/* list users directory */
+	engine_savepath(path, buffer, sizeof(buffer));
+	fs_listdir(buffer, cb, user);
+	
+	/* list datadir directory */
+	str_format(buffer, sizeof(buffer), "%s/%s", datadir, path);
+	fs_listdir(buffer, cb, user);
+}
+
+void engine_getpath(char *buffer, int buffer_size, const char *filename, int flags)
+{
+	if(flags&IOFLAG_WRITE)
+		engine_savepath(filename, buffer, buffer_size);
+	else
+	{
+		IOHANDLE handle = 0;
+		
+		/* check current directory */
+		handle = io_open(filename, flags);
+		if(handle)
+		{
+			str_copy(buffer, filename, buffer_size);
+			io_close(handle);
+			return;
+		}
+			
+		/* check user directory */
+		engine_savepath(filename, buffer, buffer_size);
+		handle = io_open(buffer, flags);
+		if(handle)
+		{
+			io_close(handle);
+			return;
+		}
+			
+		/* check normal data directory */
+		str_format(buffer, buffer_size, "%s/%s", datadir, filename);
+		handle = io_open(buffer, flags);
+		if(handle)
+		{
+			io_close(handle);
+			return;
+		}
+	}
+	
+	buffer[0] = 0;
+}
+
+IOHANDLE engine_openfile(const char *filename, int flags)
+{
+	char buffer[1024];
+	
+	if(flags&IOFLAG_WRITE)
+	{
+		engine_savepath(filename, buffer, sizeof(buffer));
+		return io_open(buffer, flags);
+	}
+	else
+	{
+		IOHANDLE handle = 0;
+		
+		/* check current directory */
+		handle = io_open(filename, flags);
+		if(handle)
+			return handle;
+			
+		/* check user directory */
+		engine_savepath(filename, buffer, sizeof(buffer));
+		handle = io_open(buffer, flags);
+		if(handle)
+			return handle;
+			
+		/* check normal data directory */
+		str_format(buffer, sizeof(buffer), "%s/%s", datadir, filename);
+		handle = io_open(buffer, flags);
+		if(handle)
+			return handle;
+	}
+	return 0;		
+}
+
 void engine_parse_arguments(int argc, char **argv)
 {
 	/* load the configuration */
 	int i;
-	int abs = 0;
-	const char *config_filename = "settings.cfg";
-	char buf[1024];
+	
+	/* check for datadir override */
 	for(i = 1; i < argc; i++)
 	{
-		if(argv[i][0] == '-' && argv[i][1] == 'f' && argv[i][2] == 0 && argc - i > 1)
+		if(argv[i][0] == '-' && argv[i][1] == 'd' && argv[i][2] == 0 && argc - i > 1)
 		{
-			config_filename = argv[i+1];
-			abs = 1;
+			str_copy(datadir, argv[i+1], sizeof(datadir));
 			i++;
 		}
-		else if(argv[i][0] == '-' && argv[i][1] == 'd' && argv[i][2] == 0 && argc - i > 1)
+	}
+	
+	/* search for data directory */
+	engine_find_datadir(argv[0]);
+	
+	dbg_msg("engine/datadir", "paths used:");
+	dbg_msg("engine/datadir", "\t.");
+	dbg_msg("engine/datadir", "\t%s", application_save_path);
+	dbg_msg("engine/datadir", "\t%s", datadir);
+	dbg_msg("engine/datadir", "saving files to: %s", application_save_path);
+
+
+	/* check for scripts to execute */
+	for(i = 1; i < argc; i++)
+	{
+		if(argv[i][0] == '-' && argv[i][1] == 'f' && argv[i][2] == 0 && argc - i > 1)
 		{
-			datadir_override = argv[i+1];
+			console_execute_file(argv[i+1]);
 			i++;
 		}
 	}
 
-	if(abs)
-		console_execute_file(config_filename);
-	else
-		console_execute_file(engine_savepath(config_filename, buf, sizeof(buf)));
-	
 	/* search arguments for overrides */
 	{
 		int i;
@@ -121,7 +218,7 @@ void engine_parse_arguments(int argc, char **argv)
 			console_execute_line(argv[i]);
 	}
 
-	console_execute_file(engine_savepath("autoexec.cfg", buf, sizeof(buf)));
+	console_execute_file("autoexec.cfg");
 
 	/* open logfile if needed */
 	if(config.logfile[0])
@@ -137,10 +234,8 @@ static IOHANDLE config_file = 0;
 
 int engine_config_write_start()
 {
-	char filename[1024];
-	config_save(engine_savepath("settings.cfg", filename, sizeof(filename)));
-	
-	config_file = io_open(filename, IOFLAG_WRITE);
+	config_save("settings.cfg");
+	config_file = engine_openfile("settings.cfg", IOFLAG_WRITE);
 	if(config_file == 0)
 		return -1;
 	return 0;
@@ -340,12 +435,9 @@ int mastersrv_load()
 	LINEREADER lr;
 	IOHANDLE file;
 	int count = 0;
-	char filename[1024];
-	
-	engine_savepath("masters.cfg", filename, sizeof(filename));
 	
 	/* try to open file */
-	file = io_open(filename, IOFLAG_READ);
+	file = engine_openfile("masters.cfg", IOFLAG_READ);
 	if(!file)
 		return -1;
 	
@@ -386,12 +478,9 @@ int mastersrv_save()
 {
 	IOHANDLE file;
 	int i;
-	char filename[1024];
 
-	engine_savepath("masters.cfg", filename, sizeof(filename));
-	
 	/* try to open file */
-	file = io_open(filename, IOFLAG_WRITE);
+	file = engine_openfile("masters.cfg", IOFLAG_WRITE);
 	if(!file)
 		return -1;
 
@@ -423,64 +512,52 @@ void engine_hostlookup(HOSTLOOKUP *lookup, const char *hostname)
 	jobs_add(&hostlookuppool, &lookup->job, hostlookup_thread, lookup);
 }
 
-int engine_chdir_datadir(char *argv0)
+static int engine_find_datadir(char *argv0)
 {
-	int found = 0;
-	char data_dir[1024*2];
-	
 	/* 1) use provided data-dir override */
-	if (datadir_override)
+	if(datadir[0])
 	{
-		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;
-		}
+		if(fs_is_dir(datadir))
+			return 0;
 		else
 		{
-			dbg_msg("engine/datadir",
-				"specified data-dir '%s' does not exist",
-				datadir_override);
-			return 0;
+			dbg_msg("engine/datadir", "specified data-dir '%s' does not exist", datadir);
+			return -1;
 		}
 	}
 	
 	/* 2) use data-dir in PWD if present */
-	if (!found && fs_is_dir("data"))
+	if(fs_is_dir("data"))
 	{
-		strcpy(data_dir, "data");
-		found = 1;
+		strcpy(datadir, "data");
+		return 0;
 	}
 	
 	/* 3) use compiled-in data-dir if present */
-	if (!found && fs_is_dir(DATA_DIR))
+	if (fs_is_dir(DATA_DIR))
 	{
-		strcpy(data_dir, DATA_DIR);
-		found = 1;
+		strcpy(datadir, DATA_DIR);
+		return 0;
 	}
 	
 	/* 4) check for usable path in argv[0] */
-	if (!found)
 	{
 		unsigned int pos = strrchr(argv0, '/') - argv0;
 		
-		if (pos < sizeof(data_dir))
+		if (pos < sizeof(datadir))
 		{
-			char basedir[sizeof(data_dir)];
+			char basedir[sizeof(datadir)];
 			strncpy(basedir, argv0, pos);
 			basedir[pos] = '\0';
-			str_format(data_dir, sizeof(data_dir),
-				"%s/data", basedir);
+			str_format(datadir, sizeof(datadir), "%s/data", basedir);
 			
-			if (fs_is_dir(data_dir))
-				found = 1;
+			if (fs_is_dir(datadir))
+				return 0;
 		}
 	}
 	
 #if defined(CONF_FAMILY_UNIX)
 	/* 5) check for all default locations */
-	if (!found)
 	{
 		const char *sdirs[] = {
 			"/usr/share/teeworlds",
@@ -493,22 +570,14 @@ int engine_chdir_datadir(char *argv0)
 		{
 			if (fs_is_dir(sdirs[i]))
 			{
-				strcpy(data_dir, sdirs[i]);
-				found = 1;
-				break;
+				strcpy(datadir, sdirs[i]);
+				return 0;
 			}
 		}
 	}
 #endif
 	
-	/* data-dir exists */
-	if (found)
-	{
-		dbg_msg("engine/datadir", "using '%s'", data_dir);
-		
-		/* change working directory to data-dir */
-		fs_chdir(data_dir);
-	}
-	
-	return found;
+	/* no data-dir found */
+	dbg_msg("engine/datadir", "warning no data directory found");
+	return -1;
 }
diff --git a/src/engine/e_engine.h b/src/engine/e_engine.h
index 5db7a4dd..f11ba5c5 100644
--- a/src/engine/e_engine.h
+++ b/src/engine/e_engine.h
@@ -10,7 +10,10 @@ int engine_config_write_start();
 void engine_config_write_line(const char *line);
 void engine_config_write_stop();
 
-int engine_chdir_datadir(char *argv0);
+
+void engine_listdir(const char *path, FS_LISTDIR_CALLBACK cb, void *user);
+IOHANDLE engine_openfile(const char *filename, int flags);
+void engine_getpath(char *buffer, int buffer_size, const char *filename, int flags);
 
 int engine_stress(float probability);
 
diff --git a/src/engine/e_network.c b/src/engine/e_network.c
index 5d9037e3..6a555d78 100644
--- a/src/engine/e_network.c
+++ b/src/engine/e_network.c
@@ -4,6 +4,7 @@
 #include <string.h> /* strlen */
 
 #include "e_config.h"
+#include "e_engine.h"
 #include "e_network.h"
 #include "e_network_internal.h"
 #include "e_huffman.h"
@@ -259,7 +260,7 @@ void netcommon_openlog(const char *sentlog, const char *recvlog)
 {
 	if(sentlog)
 	{
-		datalog_sent = io_open(sentlog, IOFLAG_WRITE);
+		datalog_sent = engine_openfile(sentlog, IOFLAG_WRITE);
 		if(datalog_sent)
 			dbg_msg("network", "logging sent packages to '%s'", sentlog);
 		else
@@ -268,7 +269,7 @@ void netcommon_openlog(const char *sentlog, const char *recvlog)
 	
 	if(recvlog)
 	{
-		datalog_recv = io_open(recvlog, IOFLAG_WRITE);
+		datalog_recv = engine_openfile(recvlog, IOFLAG_WRITE);
 		if(recvlog)
 			dbg_msg("network", "logging recv packages to '%s'", recvlog);
 		else
diff --git a/src/engine/e_network_server.c b/src/engine/e_network_server.c
index a22bcbf8..7e60a9ce 100644
--- a/src/engine/e_network_server.c
+++ b/src/engine/e_network_server.c
@@ -162,8 +162,11 @@ int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds)
 	s->banpool_firstfree->prev = 0;
 	ban->next = 0;
 	ban->prev = 0;
-	ban->info.expires = stamp;
+	ban->info.expires = 0;
+	if(seconds)
+		ban->info.expires = stamp;
 	ban->info.type = type;
+	ban->info.addr = addr;
 	
 	/* add it to the ban hash */
 	if(s->bans[iphash])
@@ -174,7 +177,7 @@ int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds)
 	
 	/* insert it into the used list */
 	insert_after = s->banpool_firstused;
-	while(1)
+	while(insert_after)
 	{
 		if(!insert_after->next)
 			break;
@@ -186,7 +189,6 @@ int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds)
 	if(!insert_after || insert_after->info.expires > stamp)
 	{
 		/* insert first */
-		insert_after->prev = ban;
 		s->banpool_firstused = ban;
 		ban->next = insert_after;
 		ban->prev = 0;
@@ -200,6 +202,27 @@ int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds)
 			ban->next->prev = ban;
 		insert_after->next = ban;
 	}
+
+	/* drop banned clients */	
+	{
+		char buf[128];
+		int i;
+		NETADDR banaddr;
+		
+		if(seconds)
+			str_format(buf, sizeof(buf), "you have been banned for %d seconds", seconds);
+		else
+			str_format(buf, sizeof(buf), "you have been banned");
+		
+		for(i = 0; i < s->max_clients; i++)
+		{
+			banaddr = s->slots[i].conn.peeraddr;
+			banaddr.port = 0;
+			
+			if(net_addr_comp(&addr, &banaddr) == 0)
+				netserver_drop(s, i, buf);
+		}
+	}	
 	
 	return 0;
 }
@@ -242,18 +265,20 @@ int netserver_recv(NETSERVER *s, NETCHUNK *chunk)
 		if(unpack_packet(s->recv.buffer, bytes, &s->recv.data) == 0)
 		{
 			NETBAN *ban = 0;
+			NETADDR banaddr = addr;
 			int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff;
 			found = 0;
+			banaddr.port = 0;
 			
 			/* search a ban */
 			for(ban = s->bans[iphash]; ban; ban = ban->hashnext)
 			{
-				if(net_addr_comp(&ban->info.addr, &addr) == 0)
+				if(net_addr_comp(&ban->info.addr, &banaddr) == 0)
 					break;
 			}
 			
 			/* check if we just should drop the packet */
-			if(ban && ban->info.type == NETBANTYPE_DROP && ban->info.expires > now)
+			if(ban && ban->info.type == NETBANTYPE_DROP && (!ban->info.expires || ban->info.expires > now))
 				continue;
 			
 			if(s->recv.data.flags&NET_PACKETFLAG_CONNLESS)
diff --git a/src/engine/server/es_server.c b/src/engine/server/es_server.c
index 1797adac..d5e8dacb 100644
--- a/src/engine/server/es_server.c
+++ b/src/engine/server/es_server.c
@@ -964,7 +964,7 @@ static int server_load_map(const char *mapname)
 	
 	/* load compelate map into memory for download */
 	{
-		IOHANDLE file = io_open(buf, IOFLAG_READ);
+		IOHANDLE file = engine_openfile(buf, IOFLAG_READ);
 		current_map_size = (int)io_length(file);
 		if(current_map_data)
 			mem_free(current_map_data);
@@ -1185,7 +1185,23 @@ static void con_ban(void *result, void *user_data)
 	const char *str = console_arg_string(result, 0);
 	
 	if(net_addr_from_str(&addr, str) == 0)
-		server_ban_add(addr, 1, 60);
+		server_ban_add(addr, 2, 60);
+}
+
+
+static void con_bans(void *result, void *user_data)
+{
+	int i;
+	NETBANINFO info;
+	NETADDR addr;
+	int num = netserver_ban_num(net);
+	for(i = 0; i < num; i++)
+	{
+		netserver_ban_get(net, i, &info);
+		addr = info.addr;
+		
+		dbg_msg("server", "#%d %d.%d.%d.%d", i, addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3]);
+	}
 }
 
 static void con_status(void *result, void *user_data)
@@ -1223,6 +1239,7 @@ static void server_register_commands()
 {
 	MACRO_REGISTER_COMMAND("kick", "i", con_kick, 0);
 	MACRO_REGISTER_COMMAND("ban", "r", con_ban, 0);
+	MACRO_REGISTER_COMMAND("bans", "", con_bans, 0);
 	MACRO_REGISTER_COMMAND("status", "", con_status, 0);
 	MACRO_REGISTER_COMMAND("shutdown", "", con_shutdown, 0);
 
@@ -1255,13 +1272,6 @@ 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;